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 {...@@ -459,6 +459,28 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
459 return self.items[prev_len..][0..n];459 return self.items[prev_len..][0..n];
460 }460 }
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
462 /// Remove and return the last element from the list.484 /// Remove and return the last element from the list.
463 /// Asserts the list has at least one item.485 /// Asserts the list has at least one item.
464 /// Invalidates pointers to the removed element.486 /// Invalidates pointers to the removed element.
...@@ -949,6 +971,28 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ...@@ -949,6 +971,28 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
949 return self.items[prev_len..][0..n];971 return self.items[prev_len..][0..n];
950 }972 }
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
952 /// Remove and return the last element from the list.996 /// Remove and return the last element from the list.
953 /// Asserts the list has at least one item.997 /// Asserts the list has at least one item.
954 /// Invalidates pointers to last element.998 /// Invalidates pointers to last element.
src/Air.zig+3-3
...@@ -901,8 +901,8 @@ pub const Inst = struct {...@@ -901,8 +901,8 @@ pub const Inst = struct {
901 manyptr_const_u8_type = @enumToInt(InternPool.Index.manyptr_const_u8_type),901 manyptr_const_u8_type = @enumToInt(InternPool.Index.manyptr_const_u8_type),
902 manyptr_const_u8_sentinel_0_type = @enumToInt(InternPool.Index.manyptr_const_u8_sentinel_0_type),902 manyptr_const_u8_sentinel_0_type = @enumToInt(InternPool.Index.manyptr_const_u8_sentinel_0_type),
903 single_const_pointer_to_comptime_int_type = @enumToInt(InternPool.Index.single_const_pointer_to_comptime_int_type),903 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),904 slice_const_u8_type = @enumToInt(InternPool.Index.slice_const_u8_type),
905 const_slice_u8_sentinel_0_type = @enumToInt(InternPool.Index.const_slice_u8_sentinel_0_type),905 slice_const_u8_sentinel_0_type = @enumToInt(InternPool.Index.slice_const_u8_sentinel_0_type),
906 anyerror_void_error_union_type = @enumToInt(InternPool.Index.anyerror_void_error_union_type),906 anyerror_void_error_union_type = @enumToInt(InternPool.Index.anyerror_void_error_union_type),
907 generic_poison_type = @enumToInt(InternPool.Index.generic_poison_type),907 generic_poison_type = @enumToInt(InternPool.Index.generic_poison_type),
908 inferred_alloc_const_type = @enumToInt(InternPool.Index.inferred_alloc_const_type),908 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 {...@@ -1382,7 +1382,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index, ip: InternPool) Type {
13821382
1383 .bool_to_int => return Type.u1,1383 .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
1387 .call, .call_always_tail, .call_never_tail, .call_never_inline => {1387 .call, .call_always_tail, .call_never_tail, .call_never_inline => {
1388 const callee_ty = air.typeOf(datas[inst].pl_op.operand, ip);1388 const callee_ty = air.typeOf(datas[inst].pl_op.operand, ip);
src/AstGen.zig+15-15
...@@ -3934,7 +3934,7 @@ fn fnDecl(...@@ -3934,7 +3934,7 @@ fn fnDecl(
3934 var section_gz = decl_gz.makeSubBlock(params_scope);3934 var section_gz = decl_gz.makeSubBlock(params_scope);
3935 defer section_gz.unstack();3935 defer section_gz.unstack();
3936 const section_ref: Zir.Inst.Ref = if (fn_proto.ast.section_expr == 0) .none else inst: {3936 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);
3938 if (section_gz.instructionsSlice().len == 0) {3938 if (section_gz.instructionsSlice().len == 0) {
3939 // In this case we will send a len=0 body which can be encoded more efficiently.3939 // In this case we will send a len=0 body which can be encoded more efficiently.
3940 break :inst inst;3940 break :inst inst;
...@@ -4137,7 +4137,7 @@ fn globalVarDecl(...@@ -4137,7 +4137,7 @@ fn globalVarDecl(
4137 break :inst try expr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = .address_space_type } }, var_decl.ast.addrspace_node);4137 break :inst try expr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = .address_space_type } }, var_decl.ast.addrspace_node);
4138 };4138 };
4139 const section_inst: Zir.Inst.Ref = if (var_decl.ast.section_node == 0) .none else inst: {4139 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);
4141 };4141 };
4142 const has_section_or_addrspace = section_inst != .none or addrspace_inst != .none;4142 const has_section_or_addrspace = section_inst != .none or addrspace_inst != .none;
4143 wip_members.nextDecl(is_pub, is_export, align_inst != .none, has_section_or_addrspace);4143 wip_members.nextDecl(is_pub, is_export, align_inst != .none, has_section_or_addrspace);
...@@ -7878,7 +7878,7 @@ fn unionInit(...@@ -7878,7 +7878,7 @@ fn unionInit(
7878 params: []const Ast.Node.Index,7878 params: []const Ast.Node.Index,
7879) InnerError!Zir.Inst.Ref {7879) InnerError!Zir.Inst.Ref {
7880 const union_type = try typeExpr(gz, scope, params[0]);7880 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]);
7882 const field_type = try gz.addPlNode(.field_type_ref, params[1], Zir.Inst.FieldTypeRef{7882 const field_type = try gz.addPlNode(.field_type_ref, params[1], Zir.Inst.FieldTypeRef{
7883 .container_type = union_type,7883 .container_type = union_type,
7884 .field_name = field_name,7884 .field_name = field_name,
...@@ -8100,12 +8100,12 @@ fn builtinCall(...@@ -8100,12 +8100,12 @@ fn builtinCall(
8100 if (ri.rl == .ref) {8100 if (ri.rl == .ref) {
8101 return gz.addPlNode(.field_ptr_named, node, Zir.Inst.FieldNamed{8101 return gz.addPlNode(.field_ptr_named, node, Zir.Inst.FieldNamed{
8102 .lhs = try expr(gz, scope, .{ .rl = .ref }, params[0]),8102 .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]),
8104 });8104 });
8105 }8105 }
8106 const result = try gz.addPlNode(.field_val_named, node, Zir.Inst.FieldNamed{8106 const result = try gz.addPlNode(.field_val_named, node, Zir.Inst.FieldNamed{
8107 .lhs = try expr(gz, scope, .{ .rl = .none }, params[0]),8107 .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]),
8109 });8109 });
8110 return rvalue(gz, ri, result, node);8110 return rvalue(gz, ri, result, node);
8111 },8111 },
...@@ -8271,11 +8271,11 @@ fn builtinCall(...@@ -8271,11 +8271,11 @@ fn builtinCall(
8271 .align_of => return simpleUnOpType(gz, scope, ri, node, params[0], .align_of),8271 .align_of => return simpleUnOpType(gz, scope, ri, node, params[0], .align_of),
82728272
8273 .ptr_to_int => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .ptr_to_int),8273 .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),
8275 .set_eval_branch_quota => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0], .set_eval_branch_quota),8275 .set_eval_branch_quota => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0], .set_eval_branch_quota),
8276 .enum_to_int => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .enum_to_int),8276 .enum_to_int => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .enum_to_int),
8277 .bool_to_int => return simpleUnOp(gz, scope, ri, node, bool_ri, params[0], .bool_to_int),8277 .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),
8279 .error_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .anyerror_type } }, params[0], .error_name),8279 .error_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .anyerror_type } }, params[0], .error_name),
8280 .set_runtime_safety => return simpleUnOp(gz, scope, ri, node, bool_ri, params[0], .set_runtime_safety),8280 .set_runtime_safety => return simpleUnOp(gz, scope, ri, node, bool_ri, params[0], .set_runtime_safety),
8281 .sqrt => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .sqrt),8281 .sqrt => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .sqrt),
...@@ -8334,7 +8334,7 @@ fn builtinCall(...@@ -8334,7 +8334,7 @@ fn builtinCall(
8334 },8334 },
8335 .panic => {8335 .panic => {
8336 try emitDbgNode(gz, node);8336 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);
8338 },8338 },
8339 .trap => {8339 .trap => {
8340 try emitDbgNode(gz, node);8340 try emitDbgNode(gz, node);
...@@ -8450,7 +8450,7 @@ fn builtinCall(...@@ -8450,7 +8450,7 @@ fn builtinCall(
8450 },8450 },
8451 .c_define => {8451 .c_define => {
8452 if (!gz.c_import) return gz.astgen.failNode(node, "C define valid only inside C import block", .{});8452 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]);
8454 const value = try comptimeExpr(gz, scope, .{ .rl = .none }, params[1]);8454 const value = try comptimeExpr(gz, scope, .{ .rl = .none }, params[1]);
8455 const result = try gz.addExtendedPayload(.c_define, Zir.Inst.BinNode{8455 const result = try gz.addExtendedPayload(.c_define, Zir.Inst.BinNode{
8456 .node = gz.nodeIndexToRelative(node),8456 .node = gz.nodeIndexToRelative(node),
...@@ -8546,7 +8546,7 @@ fn builtinCall(...@@ -8546,7 +8546,7 @@ fn builtinCall(
8546 },8546 },
8547 .field_parent_ptr => {8547 .field_parent_ptr => {
8548 const parent_type = try typeExpr(gz, scope, params[0]);8548 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]);
8550 const result = try gz.addPlNode(.field_parent_ptr, node, Zir.Inst.FieldParentPtr{8550 const result = try gz.addPlNode(.field_parent_ptr, node, Zir.Inst.FieldParentPtr{
8551 .parent_type = parent_type,8551 .parent_type = parent_type,
8552 .field_name = field_name,8552 .field_name = field_name,
...@@ -8701,7 +8701,7 @@ fn hasDeclOrField(...@@ -8701,7 +8701,7 @@ fn hasDeclOrField(
8701 tag: Zir.Inst.Tag,8701 tag: Zir.Inst.Tag,
8702) InnerError!Zir.Inst.Ref {8702) InnerError!Zir.Inst.Ref {
8703 const container_type = try typeExpr(gz, scope, lhs_node);8703 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);
8705 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{8705 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{
8706 .lhs = container_type,8706 .lhs = container_type,
8707 .rhs = name,8707 .rhs = name,
...@@ -8851,7 +8851,7 @@ fn simpleCBuiltin(...@@ -8851,7 +8851,7 @@ fn simpleCBuiltin(
8851) InnerError!Zir.Inst.Ref {8851) InnerError!Zir.Inst.Ref {
8852 const name: []const u8 = if (tag == .c_undef) "C undef" else "C include";8852 const name: []const u8 = if (tag == .c_undef) "C undef" else "C include";
8853 if (!gz.c_import) return gz.astgen.failNode(node, "{s} valid only inside C import block", .{name});8853 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);
8855 _ = try gz.addExtendedPayload(tag, Zir.Inst.UnNode{8855 _ = try gz.addExtendedPayload(tag, Zir.Inst.UnNode{
8856 .node = gz.nodeIndexToRelative(node),8856 .node = gz.nodeIndexToRelative(node),
8857 .operand = operand,8857 .operand = operand,
...@@ -8869,7 +8869,7 @@ fn offsetOf(...@@ -8869,7 +8869,7 @@ fn offsetOf(
8869 tag: Zir.Inst.Tag,8869 tag: Zir.Inst.Tag,
8870) InnerError!Zir.Inst.Ref {8870) InnerError!Zir.Inst.Ref {
8871 const type_inst = try typeExpr(gz, scope, lhs_node);8871 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);
8873 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{8873 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{
8874 .lhs = type_inst,8874 .lhs = type_inst,
8875 .rhs = field_name,8875 .rhs = field_name,
...@@ -10317,8 +10317,8 @@ fn rvalue(...@@ -10317,8 +10317,8 @@ fn rvalue(
10317 as_ty | @enumToInt(Zir.Inst.Ref.manyptr_const_u8_type),10317 as_ty | @enumToInt(Zir.Inst.Ref.manyptr_const_u8_type),
10318 as_ty | @enumToInt(Zir.Inst.Ref.manyptr_const_u8_sentinel_0_type),10318 as_ty | @enumToInt(Zir.Inst.Ref.manyptr_const_u8_sentinel_0_type),
10319 as_ty | @enumToInt(Zir.Inst.Ref.single_const_pointer_to_comptime_int_type),10319 as_ty | @enumToInt(Zir.Inst.Ref.single_const_pointer_to_comptime_int_type),
10320 as_ty | @enumToInt(Zir.Inst.Ref.const_slice_u8_type),10320 as_ty | @enumToInt(Zir.Inst.Ref.slice_const_u8_type),
10321 as_ty | @enumToInt(Zir.Inst.Ref.const_slice_u8_sentinel_0_type),10321 as_ty | @enumToInt(Zir.Inst.Ref.slice_const_u8_sentinel_0_type),
10322 as_ty | @enumToInt(Zir.Inst.Ref.anyerror_void_error_union_type),10322 as_ty | @enumToInt(Zir.Inst.Ref.anyerror_void_error_union_type),
10323 as_ty | @enumToInt(Zir.Inst.Ref.generic_poison_type),10323 as_ty | @enumToInt(Zir.Inst.Ref.generic_poison_type),
10324 as_ty | @enumToInt(Zir.Inst.Ref.empty_struct_type),10324 as_ty | @enumToInt(Zir.Inst.Ref.empty_struct_type),
src/Compilation.zig+3-2
...@@ -226,7 +226,7 @@ const Job = union(enum) {...@@ -226,7 +226,7 @@ const Job = union(enum) {
226 /// Write the constant value for a Decl to the output file.226 /// Write the constant value for a Decl to the output file.
227 codegen_decl: Module.Decl.Index,227 codegen_decl: Module.Decl.Index,
228 /// Write the machine code for a function to the output file.228 /// Write the machine code for a function to the output file.
229 codegen_func: *Module.Fn,229 codegen_func: Module.Fn.Index,
230 /// Render the .h file snippet for the Decl.230 /// Render the .h file snippet for the Decl.
231 emit_h_decl: Module.Decl.Index,231 emit_h_decl: Module.Decl.Index,
232 /// The Decl needs to be analyzed and possibly export itself.232 /// 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...@@ -3208,7 +3208,8 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v
3208 // Tests are always emitted in test binaries. The decl_refs are created by3208 // Tests are always emitted in test binaries. The decl_refs are created by
3209 // Module.populateTestFunctions, but this will not queue body analysis, so do3209 // Module.populateTestFunctions, but this will not queue body analysis, so do
3210 // that now.3210 // 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);
3212 }3213 }
3213 },3214 },
3214 .update_embed_file => |embed_file| {3215 .update_embed_file => |embed_file| {
src/InternPool.zig+667-160
...@@ -34,6 +34,12 @@ allocated_unions: std.SegmentedList(Module.Union, 0) = .{},...@@ -34,6 +34,12 @@ allocated_unions: std.SegmentedList(Module.Union, 0) = .{},
34/// When a Union object is freed from `allocated_unions`, it is pushed into this stack.34/// When a Union object is freed from `allocated_unions`, it is pushed into this stack.
35unions_free_list: std.ArrayListUnmanaged(Module.Union.Index) = .{},35unions_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
37/// InferredErrorSet objects are stored in this data structure because:43/// InferredErrorSet objects are stored in this data structure because:
38/// * They contain pointers such as the errors map and the set of other inferred error sets.44/// * They contain pointers such as the errors map and the set of other inferred error sets.
39/// * They need to be mutated after creation.45/// * They need to be mutated after creation.
...@@ -66,18 +72,18 @@ const Limb = std.math.big.Limb;...@@ -66,18 +72,18 @@ const Limb = std.math.big.Limb;
6672
67const InternPool = @This();73const InternPool = @This();
68const Module = @import("Module.zig");74const Module = @import("Module.zig");
75const Sema = @import("Sema.zig");
6976
70const KeyAdapter = struct {77const KeyAdapter = struct {
71 intern_pool: *const InternPool,78 intern_pool: *const InternPool,
7279
73 pub fn eql(ctx: @This(), a: Key, b_void: void, b_map_index: usize) bool {80 pub fn eql(ctx: @This(), a: Key, b_void: void, b_map_index: usize) bool {
74 _ = b_void;81 _ = 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);
76 }83 }
7784
78 pub fn hash(ctx: @This(), a: Key) u32 {85 pub fn hash(ctx: @This(), a: Key) u32 {
79 _ = ctx;86 return a.hash32(ctx.intern_pool);
80 return a.hash32();
81 }87 }
82};88};
8389
...@@ -111,10 +117,19 @@ pub const RuntimeIndex = enum(u32) {...@@ -111,10 +117,19 @@ pub const RuntimeIndex = enum(u32) {
111 }117 }
112};118};
113119
120/// An index into `string_bytes`.
121pub const String = enum(u32) {
122 _,
123};
124
114/// An index into `string_bytes`.125/// An index into `string_bytes`.
115pub const NullTerminatedString = enum(u32) {126pub const NullTerminatedString = enum(u32) {
116 _,127 _,
117128
129 pub fn toString(self: NullTerminatedString) String {
130 return @intToEnum(String, @enumToInt(self));
131 }
132
118 pub fn toOptional(self: NullTerminatedString) OptionalNullTerminatedString {133 pub fn toOptional(self: NullTerminatedString) OptionalNullTerminatedString {
119 return @intToEnum(OptionalNullTerminatedString, @enumToInt(self));134 return @intToEnum(OptionalNullTerminatedString, @enumToInt(self));
120 }135 }
...@@ -180,23 +195,20 @@ pub const Key = union(enum) {...@@ -180,23 +195,20 @@ pub const Key = union(enum) {
180 /// Typed `undefined`. This will never be `none`; untyped `undefined` is represented195 /// Typed `undefined`. This will never be `none`; untyped `undefined` is represented
181 /// via `simple_value` and has a named `Index` tag for it.196 /// via `simple_value` and has a named `Index` tag for it.
182 undef: Index,197 undef: Index,
198 runtime_value: TypeValue,
183 simple_value: SimpleValue,199 simple_value: SimpleValue,
184 extern_func: struct {200 variable: Key.Variable,
185 ty: Index,201 extern_func: ExternFunc,
186 /// The Decl that corresponds to the function itself.202 func: Func,
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 },
193 int: Key.Int,203 int: Key.Int,
204 err: Error,
205 error_union: ErrorUnion,
206 enum_literal: NullTerminatedString,
194 /// A specific enum tag, indicated by the integer tag value.207 /// A specific enum tag, indicated by the integer tag value.
195 enum_tag: Key.EnumTag,208 enum_tag: Key.EnumTag,
196 float: Key.Float,209 float: Key.Float,
197 ptr: Ptr,210 ptr: Ptr,
198 opt: Opt,211 opt: Opt,
199
200 /// An instance of a struct, array, or vector.212 /// An instance of a struct, array, or vector.
201 /// Each element/field stored as an `Index`.213 /// Each element/field stored as an `Index`.
202 /// In the case of sentinel-terminated arrays, the sentinel value *is* stored,214 /// In the case of sentinel-terminated arrays, the sentinel value *is* stored,
...@@ -261,7 +273,7 @@ pub const Key = union(enum) {...@@ -261,7 +273,7 @@ pub const Key = union(enum) {
261 pub const ArrayType = struct {273 pub const ArrayType = struct {
262 len: u64,274 len: u64,
263 child: Index,275 child: Index,
264 sentinel: Index,276 sentinel: Index = .none,
265 };277 };
266278
267 pub const VectorType = struct {279 pub const VectorType = struct {
...@@ -369,6 +381,7 @@ pub const Key = union(enum) {...@@ -369,6 +381,7 @@ pub const Key = union(enum) {
369 return @intCast(u32, x);381 return @intCast(u32, x);
370 },382 },
371 .i64, .big_int => return null, // out of range383 .i64, .big_int => return null, // out of range
384 .lazy_align, .lazy_size => unreachable,
372 }385 }
373 }386 }
374 };387 };
...@@ -441,6 +454,32 @@ pub const Key = union(enum) {...@@ -441,6 +454,32 @@ pub const Key = union(enum) {
441 }454 }
442 };455 };
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
444 pub const Int = struct {483 pub const Int = struct {
445 ty: Index,484 ty: Index,
446 storage: Storage,485 storage: Storage,
...@@ -449,6 +488,8 @@ pub const Key = union(enum) {...@@ -449,6 +488,8 @@ pub const Key = union(enum) {
449 u64: u64,488 u64: u64,
450 i64: i64,489 i64: i64,
451 big_int: BigIntConst,490 big_int: BigIntConst,
491 lazy_align: Index,
492 lazy_size: Index,
452493
453 /// Big enough to fit any non-BigInt value494 /// Big enough to fit any non-BigInt value
454 pub const BigIntSpace = struct {495 pub const BigIntSpace = struct {
...@@ -460,13 +501,26 @@ pub const Key = union(enum) {...@@ -460,13 +501,26 @@ pub const Key = union(enum) {
460 pub fn toBigInt(storage: Storage, space: *BigIntSpace) BigIntConst {501 pub fn toBigInt(storage: Storage, space: *BigIntSpace) BigIntConst {
461 return switch (storage) {502 return switch (storage) {
462 .big_int => |x| x,503 .big_int => |x| x,
463 .u64 => |x| BigIntMutable.init(&space.limbs, x).toConst(),504 inline .u64, .i64 => |x| BigIntMutable.init(&space.limbs, x).toConst(),
464 .i64 => |x| BigIntMutable.init(&space.limbs, x).toConst(),505 .lazy_align, .lazy_size => unreachable,
465 };506 };
466 }507 }
467 };508 };
468 };509 };
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
470 pub const EnumTag = struct {524 pub const EnumTag = struct {
471 /// The enum type.525 /// The enum type.
472 ty: Index,526 ty: Index,
...@@ -497,19 +551,8 @@ pub const Key = union(enum) {...@@ -497,19 +551,8 @@ pub const Key = union(enum) {
497 len: Index = .none,551 len: Index = .none,
498552
499 pub const Addr = union(enum) {553 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 },
508 decl: Module.Decl.Index,554 decl: Module.Decl.Index,
509 mut_decl: struct {555 mut_decl: MutDecl,
510 decl: Module.Decl.Index,
511 runtime_index: RuntimeIndex,
512 },
513 int: Index,556 int: Index,
514 eu_payload: Index,557 eu_payload: Index,
515 opt_payload: Index,558 opt_payload: Index,
...@@ -517,6 +560,10 @@ pub const Key = union(enum) {...@@ -517,6 +560,10 @@ pub const Key = union(enum) {
517 elem: BaseIndex,560 elem: BaseIndex,
518 field: BaseIndex,561 field: BaseIndex,
519562
563 pub const MutDecl = struct {
564 decl: Module.Decl.Index,
565 runtime_index: RuntimeIndex,
566 };
520 pub const BaseIndex = struct {567 pub const BaseIndex = struct {
521 base: Index,568 base: Index,
522 index: u64,569 index: u64,
...@@ -546,22 +593,31 @@ pub const Key = union(enum) {...@@ -546,22 +593,31 @@ pub const Key = union(enum) {
546 storage: Storage,593 storage: Storage,
547594
548 pub const Storage = union(enum) {595 pub const Storage = union(enum) {
596 bytes: []const u8,
549 elems: []const Index,597 elems: []const Index,
550 repeated_elem: Index,598 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 }
551 };607 };
552 };608 };
553609
554 pub fn hash32(key: Key) u32 {610 pub fn hash32(key: Key, ip: *const InternPool) u32 {
555 return @truncate(u32, key.hash64());611 return @truncate(u32, key.hash64(ip));
556 }612 }
557613
558 pub fn hash64(key: Key) u64 {614 pub fn hash64(key: Key, ip: *const InternPool) u64 {
559 var hasher = std.hash.Wyhash.init(0);615 var hasher = std.hash.Wyhash.init(0);
560 key.hashWithHasher(&hasher);616 key.hashWithHasher(&hasher, ip);
561 return hasher.final();617 return hasher.final();
562 }618 }
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 {
565 const KeyTag = @typeInfo(Key).Union.tag_type.?;621 const KeyTag = @typeInfo(Key).Union.tag_type.?;
566 const key_tag: KeyTag = key;622 const key_tag: KeyTag = key;
567 std.hash.autoHash(hasher, key_tag);623 std.hash.autoHash(hasher, key_tag);
...@@ -575,27 +631,45 @@ pub const Key = union(enum) {...@@ -575,27 +631,45 @@ pub const Key = union(enum) {
575 .error_union_type,631 .error_union_type,
576 .simple_type,632 .simple_type,
577 .simple_value,633 .simple_value,
578 .extern_func,
579 .opt,634 .opt,
580 .struct_type,635 .struct_type,
581 .union_type,636 .union_type,
582 .un,637 .un,
583 .undef,638 .undef,
639 .err,
640 .error_union,
641 .enum_literal,
584 .enum_tag,642 .enum_tag,
585 .inferred_error_set_type,643 .inferred_error_set_type,
586 => |info| std.hash.autoHash(hasher, info),644 => |info| std.hash.autoHash(hasher, info),
587645
646 .runtime_value => |runtime_value| std.hash.autoHash(hasher, runtime_value.val),
588 .opaque_type => |opaque_type| std.hash.autoHash(hasher, opaque_type.decl),647 .opaque_type => |opaque_type| std.hash.autoHash(hasher, opaque_type.decl),
589 .enum_type => |enum_type| std.hash.autoHash(hasher, enum_type.decl),648 .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
591 .int => |int| {654 .int => |int| {
592 // Canonicalize all integers by converting them to BigIntConst.655 // Canonicalize all integers by converting them to BigIntConst.
593 var buffer: Key.Int.Storage.BigIntSpace = undefined;656 switch (int.storage) {
594 const big_int = int.storage.toBigInt(&buffer);657 .u64, .i64, .big_int => {
595658 var buffer: Key.Int.Storage.BigIntSpace = undefined;
596 std.hash.autoHash(hasher, int.ty);659 const big_int = int.storage.toBigInt(&buffer);
597 std.hash.autoHash(hasher, big_int.positive);660
598 for (big_int.limbs) |limb| std.hash.autoHash(hasher, limb);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 }
599 },673 },
600674
601 .float => |float| {675 .float => |float| {
...@@ -615,7 +689,6 @@ pub const Key = union(enum) {...@@ -615,7 +689,6 @@ pub const Key = union(enum) {
615 // This is sound due to pointer provenance rules.689 // This is sound due to pointer provenance rules.
616 std.hash.autoHash(hasher, @as(@typeInfo(Key.Ptr.Addr).Union.tag_type.?, ptr.addr));690 std.hash.autoHash(hasher, @as(@typeInfo(Key.Ptr.Addr).Union.tag_type.?, ptr.addr));
617 switch (ptr.addr) {691 switch (ptr.addr) {
618 .@"var" => |@"var"| std.hash.autoHash(hasher, @"var".owner_decl),
619 .decl => |decl| std.hash.autoHash(hasher, decl),692 .decl => |decl| std.hash.autoHash(hasher, decl),
620 .mut_decl => |mut_decl| std.hash.autoHash(hasher, mut_decl),693 .mut_decl => |mut_decl| std.hash.autoHash(hasher, mut_decl),
621 .int => |int| std.hash.autoHash(hasher, int),694 .int => |int| std.hash.autoHash(hasher, int),
...@@ -629,13 +702,47 @@ pub const Key = union(enum) {...@@ -629,13 +702,47 @@ pub const Key = union(enum) {
629702
630 .aggregate => |aggregate| {703 .aggregate => |aggregate| {
631 std.hash.autoHash(hasher, aggregate.ty);704 std.hash.autoHash(hasher, aggregate.ty);
632 std.hash.autoHash(hasher, @as(705 switch (ip.indexToKey(aggregate.ty)) {
633 @typeInfo(Key.Aggregate.Storage).Union.tag_type.?,706 .array_type => |array_type| if (array_type.child == .u8_type) switch (aggregate.storage) {
634 aggregate.storage,707 .bytes => |bytes| for (bytes) |byte| std.hash.autoHash(hasher, byte),
635 ));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
636 switch (aggregate.storage) {728 switch (aggregate.storage) {
637 .elems => |elems| for (elems) |elem| std.hash.autoHash(hasher, elem),729 .bytes => unreachable,
638 .repeated_elem => |elem| std.hash.autoHash(hasher, elem),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 },
639 }746 }
640 },747 },
641748
...@@ -663,7 +770,7 @@ pub const Key = union(enum) {...@@ -663,7 +770,7 @@ pub const Key = union(enum) {
663 }770 }
664 }771 }
665772
666 pub fn eql(a: Key, b: Key) bool {773 pub fn eql(a: Key, b: Key, ip: *const InternPool) bool {
667 const KeyTag = @typeInfo(Key).Union.tag_type.?;774 const KeyTag = @typeInfo(Key).Union.tag_type.?;
668 const a_tag: KeyTag = a;775 const a_tag: KeyTag = a;
669 const b_tag: KeyTag = b;776 const b_tag: KeyTag = b;
...@@ -709,9 +816,9 @@ pub const Key = union(enum) {...@@ -709,9 +816,9 @@ pub const Key = union(enum) {
709 const b_info = b.undef;816 const b_info = b.undef;
710 return a_info == b_info;817 return a_info == b_info;
711 },818 },
712 .extern_func => |a_info| {819 .runtime_value => |a_info| {
713 const b_info = b.extern_func;820 const b_info = b.runtime_value;
714 return std.meta.eql(a_info, b_info);821 return a_info.val == b_info.val;
715 },822 },
716 .opt => |a_info| {823 .opt => |a_info| {
717 const b_info = b.opt;824 const b_info = b.opt;
...@@ -729,11 +836,36 @@ pub const Key = union(enum) {...@@ -729,11 +836,36 @@ pub const Key = union(enum) {
729 const b_info = b.un;836 const b_info = b.un;
730 return std.meta.eql(a_info, b_info);837 return std.meta.eql(a_info, b_info);
731 },838 },
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 },
732 .enum_tag => |a_info| {851 .enum_tag => |a_info| {
733 const b_info = b.enum_tag;852 const b_info = b.enum_tag;
734 return std.meta.eql(a_info, b_info);853 return std.meta.eql(a_info, b_info);
735 },854 },
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
737 .ptr => |a_info| {869 .ptr => |a_info| {
738 const b_info = b.ptr;870 const b_info = b.ptr;
739 if (a_info.ty != b_info.ty or a_info.len != b_info.len) return false;871 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) {...@@ -742,7 +874,6 @@ pub const Key = union(enum) {
742 if (@as(AddrTag, a_info.addr) != @as(AddrTag, b_info.addr)) return false;874 if (@as(AddrTag, a_info.addr) != @as(AddrTag, b_info.addr)) return false;
743875
744 return switch (a_info.addr) {876 return switch (a_info.addr) {
745 .@"var" => |a_var| a_var.owner_decl == b_info.addr.@"var".owner_decl,
746 .decl => |a_decl| a_decl == b_info.addr.decl,877 .decl => |a_decl| a_decl == b_info.addr.decl,
747 .mut_decl => |a_mut_decl| std.meta.eql(a_mut_decl, b_info.addr.mut_decl),878 .mut_decl => |a_mut_decl| std.meta.eql(a_mut_decl, b_info.addr.mut_decl),
748 .int => |a_int| a_int == b_info.addr.int,879 .int => |a_int| a_int == b_info.addr.int,
...@@ -765,16 +896,27 @@ pub const Key = union(enum) {...@@ -765,16 +896,27 @@ pub const Key = union(enum) {
765 .u64 => |bb| aa == bb,896 .u64 => |bb| aa == bb,
766 .i64 => |bb| aa == bb,897 .i64 => |bb| aa == bb,
767 .big_int => |bb| bb.orderAgainstScalar(aa) == .eq,898 .big_int => |bb| bb.orderAgainstScalar(aa) == .eq,
899 .lazy_align, .lazy_size => false,
768 },900 },
769 .i64 => |aa| switch (b_info.storage) {901 .i64 => |aa| switch (b_info.storage) {
770 .u64 => |bb| aa == bb,902 .u64 => |bb| aa == bb,
771 .i64 => |bb| aa == bb,903 .i64 => |bb| aa == bb,
772 .big_int => |bb| bb.orderAgainstScalar(aa) == .eq,904 .big_int => |bb| bb.orderAgainstScalar(aa) == .eq,
905 .lazy_align, .lazy_size => false,
773 },906 },
774 .big_int => |aa| switch (b_info.storage) {907 .big_int => |aa| switch (b_info.storage) {
775 .u64 => |bb| aa.orderAgainstScalar(bb) == .eq,908 .u64 => |bb| aa.orderAgainstScalar(bb) == .eq,
776 .i64 => |bb| aa.orderAgainstScalar(bb) == .eq,909 .i64 => |bb| aa.orderAgainstScalar(bb) == .eq,
777 .big_int => |bb| aa.eq(bb),910 .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,
778 },920 },
779 };921 };
780 },922 },
...@@ -818,12 +960,43 @@ pub const Key = union(enum) {...@@ -818,12 +960,43 @@ pub const Key = union(enum) {
818 if (a_info.ty != b_info.ty) return false;960 if (a_info.ty != b_info.ty) return false;
819961
820 const StorageTag = @typeInfo(Key.Aggregate.Storage).Union.tag_type.?;962 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) {986 switch (a_info.storage) {
824 .elems => |a_elems| std.mem.eql(Index, a_elems, b_info.storage.elems),987 .bytes => |a_bytes| {
825 .repeated_elem => |a_elem| a_elem == b_info.storage.repeated_elem,988 const b_bytes = b_info.storage.bytes;
826 };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 }
827 },1000 },
828 .anon_struct_type => |a_info| {1001 .anon_struct_type => |a_info| {
829 const b_info = b.anon_struct_type;1002 const b_info = b.anon_struct_type;
...@@ -876,16 +1049,23 @@ pub const Key = union(enum) {...@@ -876,16 +1049,23 @@ pub const Key = union(enum) {
876 .func_type,1049 .func_type,
877 => .type_type,1050 => .type_type,
8781051
879 inline .ptr,1052 inline .runtime_value,
1053 .ptr,
880 .int,1054 .int,
881 .float,1055 .float,
882 .opt,1056 .opt,
1057 .variable,
883 .extern_func,1058 .extern_func,
1059 .func,
1060 .err,
1061 .error_union,
884 .enum_tag,1062 .enum_tag,
885 .aggregate,1063 .aggregate,
886 .un,1064 .un,
887 => |x| x.ty,1065 => |x| x.ty,
8881066
1067 .enum_literal => .enum_literal_type,
1068
889 .undef => |x| x,1069 .undef => |x| x,
8901070
891 .simple_value => |s| switch (s) {1071 .simple_value => |s| switch (s) {
...@@ -977,8 +1157,8 @@ pub const Index = enum(u32) {...@@ -977,8 +1157,8 @@ pub const Index = enum(u32) {
977 manyptr_const_u8_type,1157 manyptr_const_u8_type,
978 manyptr_const_u8_sentinel_0_type,1158 manyptr_const_u8_sentinel_0_type,
979 single_const_pointer_to_comptime_int_type,1159 single_const_pointer_to_comptime_int_type,
980 const_slice_u8_type,1160 slice_const_u8_type,
981 const_slice_u8_sentinel_0_type,1161 slice_const_u8_sentinel_0_type,
982 anyerror_void_error_union_type,1162 anyerror_void_error_union_type,
983 generic_poison_type,1163 generic_poison_type,
984 inferred_alloc_const_type,1164 inferred_alloc_const_type,
...@@ -1128,11 +1308,11 @@ pub const Index = enum(u32) {...@@ -1128,11 +1308,11 @@ pub const Index = enum(u32) {
1128 },1308 },
11291309
1130 undef: DataIsIndex,1310 undef: DataIsIndex,
1311 runtime_value: DataIsIndex,
1131 simple_value: struct { data: SimpleValue },1312 simple_value: struct { data: SimpleValue },
1132 ptr_var: struct { data: *PtrVar },
1133 ptr_mut_decl: struct { data: *PtrMutDecl },1313 ptr_mut_decl: struct { data: *PtrMutDecl },
1134 ptr_decl: struct { data: *PtrDecl },1314 ptr_decl: struct { data: *PtrDecl },
1135 ptr_int: struct { data: *PtrInt },1315 ptr_int: struct { data: *PtrAddr },
1136 ptr_eu_payload: DataIsIndex,1316 ptr_eu_payload: DataIsIndex,
1137 ptr_opt_payload: DataIsIndex,1317 ptr_opt_payload: DataIsIndex,
1138 ptr_comptime_field: struct { data: *PtrComptimeField },1318 ptr_comptime_field: struct { data: *PtrComptimeField },
...@@ -1151,6 +1331,12 @@ pub const Index = enum(u32) {...@@ -1151,6 +1331,12 @@ pub const Index = enum(u32) {
1151 int_small: struct { data: *IntSmall },1331 int_small: struct { data: *IntSmall },
1152 int_positive: struct { data: u32 },1332 int_positive: struct { data: u32 },
1153 int_negative: struct { data: u32 },1333 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 },
1154 enum_tag: struct { data: *Key.EnumTag },1340 enum_tag: struct { data: *Key.EnumTag },
1155 float_f16: struct { data: f16 },1341 float_f16: struct { data: f16 },
1156 float_f32: struct { data: f32 },1342 float_f32: struct { data: f32 },
...@@ -1160,18 +1346,21 @@ pub const Index = enum(u32) {...@@ -1160,18 +1346,21 @@ pub const Index = enum(u32) {
1160 float_c_longdouble_f80: struct { data: *Float80 },1346 float_c_longdouble_f80: struct { data: *Float80 },
1161 float_c_longdouble_f128: struct { data: *Float128 },1347 float_c_longdouble_f128: struct { data: *Float128 },
1162 float_comptime_float: struct { data: *Float128 },1348 float_comptime_float: struct { data: *Float128 },
1349 variable: struct { data: *Variable },
1163 extern_func: struct { data: void },1350 extern_func: struct { data: void },
1164 func: struct { data: void },1351 func: struct { data: void },
1165 only_possible_value: DataIsIndex,1352 only_possible_value: DataIsIndex,
1166 union_value: struct { data: *Key.Union },1353 union_value: struct { data: *Key.Union },
1354 bytes: struct { data: *Bytes },
1167 aggregate: struct { data: *Aggregate },1355 aggregate: struct { data: *Aggregate },
1168 repeated: struct { data: *Repeated },1356 repeated: struct { data: *Repeated },
1169 }) void {1357 }) void {
1170 _ = self;1358 _ = self;
1171 @setEvalBranchQuota(10_000);1359 const map_fields = @typeInfo(@typeInfo(@TypeOf(tag_to_encoding_map)).Pointer.child).Struct.fields;
1172 inline for (@typeInfo(Tag).Enum.fields) |tag| {1360 @setEvalBranchQuota(2_000);
1173 inline for (@typeInfo(@typeInfo(@TypeOf(tag_to_encoding_map)).Pointer.child).Struct.fields) |entry| {1361 inline for (@typeInfo(Tag).Enum.fields, 0..) |tag, start| {
1174 if (comptime std.mem.eql(u8, tag.name, entry.name)) break;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;
1175 } else {1364 } else {
1176 @compileError(@typeName(Tag) ++ "." ++ tag.name ++ " missing dbHelper tag_to_encoding_map entry");1365 @compileError(@typeName(Tag) ++ "." ++ tag.name ++ " missing dbHelper tag_to_encoding_map entry");
1177 }1366 }
...@@ -1318,14 +1507,14 @@ pub const static_keys = [_]Key{...@@ -1318,14 +1507,14 @@ pub const static_keys = [_]Key{
1318 .is_const = true,1507 .is_const = true,
1319 } },1508 } },
13201509
1321 // const_slice_u8_type1510 // slice_const_u8_type
1322 .{ .ptr_type = .{1511 .{ .ptr_type = .{
1323 .elem_type = .u8_type,1512 .elem_type = .u8_type,
1324 .size = .Slice,1513 .size = .Slice,
1325 .is_const = true,1514 .is_const = true,
1326 } },1515 } },
13271516
1328 // const_slice_u8_sentinel_0_type1517 // slice_const_u8_sentinel_0_type
1329 .{ .ptr_type = .{1518 .{ .ptr_type = .{
1330 .elem_type = .u8_type,1519 .elem_type = .u8_type,
1331 .sentinel = .zero_u8,1520 .sentinel = .zero_u8,
...@@ -1505,12 +1694,13 @@ pub const Tag = enum(u8) {...@@ -1505,12 +1694,13 @@ pub const Tag = enum(u8) {
1505 /// `data` is `Index` of the type.1694 /// `data` is `Index` of the type.
1506 /// Untyped `undefined` is stored instead via `simple_value`.1695 /// Untyped `undefined` is stored instead via `simple_value`.
1507 undef,1696 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,
1508 /// A value that can be represented with only an enum tag.1701 /// A value that can be represented with only an enum tag.
1509 /// data is SimpleValue enum value.1702 /// data is SimpleValue enum value.
1510 simple_value,1703 simple_value,
1511 /// A pointer to a var.
1512 /// data is extra index of PtrVal, which contains the type and address.
1513 ptr_var,
1514 /// A pointer to a decl that can be mutated at comptime.1704 /// A pointer to a decl that can be mutated at comptime.
1515 /// data is extra index of PtrMutDecl, which contains the type and address.1705 /// data is extra index of PtrMutDecl, which contains the type and address.
1516 ptr_mut_decl,1706 ptr_mut_decl,
...@@ -1518,7 +1708,7 @@ pub const Tag = enum(u8) {...@@ -1518,7 +1708,7 @@ pub const Tag = enum(u8) {
1518 /// data is extra index of PtrDecl, which contains the type and address.1708 /// data is extra index of PtrDecl, which contains the type and address.
1519 ptr_decl,1709 ptr_decl,
1520 /// A pointer with an integer value.1710 /// 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.
1522 /// Only pointer types are allowed to have this encoding. Optional types must use1712 /// Only pointer types are allowed to have this encoding. Optional types must use
1523 /// `opt_payload` or `opt_null`.1713 /// `opt_payload` or `opt_null`.
1524 ptr_int,1714 ptr_int,
...@@ -1585,6 +1775,24 @@ pub const Tag = enum(u8) {...@@ -1585,6 +1775,24 @@ pub const Tag = enum(u8) {
1585 /// A negative integer value.1775 /// A negative integer value.
1586 /// data is a limbs index to `Int`.1776 /// data is a limbs index to `Int`.
1587 int_negative,1777 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,
1588 /// An enum tag value.1796 /// An enum tag value.
1589 /// data is extra index of `Key.EnumTag`.1797 /// data is extra index of `Key.EnumTag`.
1590 enum_tag,1798 enum_tag,
...@@ -1617,9 +1825,14 @@ pub const Tag = enum(u8) {...@@ -1617,9 +1825,14 @@ pub const Tag = enum(u8) {
1617 /// A comptime_float value.1825 /// A comptime_float value.
1618 /// data is extra index to Float128.1826 /// data is extra index to Float128.
1619 float_comptime_float,1827 float_comptime_float,
1828 /// A global variable.
1829 /// data is extra index to Variable.
1830 variable,
1620 /// An extern function.1831 /// An extern function.
1832 /// data is extra index to Key.ExternFunc.
1621 extern_func,1833 extern_func,
1622 /// A regular function.1834 /// A regular function.
1835 /// data is extra index to Key.Func.
1623 func,1836 func,
1624 /// This represents the only possible value for *some* types which have1837 /// This represents the only possible value for *some* types which have
1625 /// only one possible value. Not all only-possible-values are encoded this way;1838 /// only one possible value. Not all only-possible-values are encoded this way;
...@@ -1631,6 +1844,9 @@ pub const Tag = enum(u8) {...@@ -1631,6 +1844,9 @@ pub const Tag = enum(u8) {
1631 only_possible_value,1844 only_possible_value,
1632 /// data is extra index to Key.Union.1845 /// data is extra index to Key.Union.
1633 union_value,1846 union_value,
1847 /// An array of bytes.
1848 /// data is extra index to `Bytes`.
1849 bytes,
1634 /// An instance of a struct, array, or vector.1850 /// An instance of a struct, array, or vector.
1635 /// data is extra index to `Aggregate`.1851 /// data is extra index to `Aggregate`.
1636 aggregate,1852 aggregate,
...@@ -1670,6 +1886,13 @@ pub const TypeFunction = struct {...@@ -1670,6 +1886,13 @@ pub const TypeFunction = struct {
1670 };1886 };
1671};1887};
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
1673/// Trailing:1896/// Trailing:
1674/// 0. element: Index for each len1897/// 0. element: Index for each len
1675/// len is determined by the aggregate type.1898/// len is determined by the aggregate type.
...@@ -1843,6 +2066,11 @@ pub const Array = struct {...@@ -1843,6 +2066,11 @@ pub const Array = struct {
1843 }2066 }
1844};2067};
18452068
2069pub const TypeValue = struct {
2070 ty: Index,
2071 val: Index,
2072};
2073
1846/// Trailing:2074/// Trailing:
1847/// 0. field name: NullTerminatedString for each fields_len; declaration order2075/// 0. field name: NullTerminatedString for each fields_len; declaration order
1848/// 1. tag value: Index for each fields_len; declaration order2076/// 1. tag value: Index for each fields_len; declaration order
...@@ -1888,21 +2116,22 @@ pub const PackedU64 = packed struct(u64) {...@@ -1888,21 +2116,22 @@ pub const PackedU64 = packed struct(u64) {
1888 }2116 }
1889};2117};
18902118
1891pub const PtrVar = struct {2119pub const Variable = struct {
1892 ty: Index,2120 /// This is a value if has_init is true, otherwise a type.
1893 /// If flags.is_extern == true this is `none`.
1894 init: Index,2121 init: Index,
1895 owner_decl: Module.Decl.Index,2122 decl: Module.Decl.Index,
1896 /// Library name if specified.2123 /// Library name if specified.
1897 /// For example `extern "c" var stderrp = ...` would have 'c' as library name.2124 /// For example `extern "c" var stderrp = ...` would have 'c' as library name.
1898 lib_name: OptionalNullTerminatedString,2125 lib_name: OptionalNullTerminatedString,
1899 flags: Flags,2126 flags: Flags,
19002127
1901 pub const Flags = packed struct(u32) {2128 pub const Flags = packed struct(u32) {
2129 has_init: bool,
2130 is_extern: bool,
1902 is_const: bool,2131 is_const: bool,
1903 is_threadlocal: bool,2132 is_threadlocal: bool,
1904 is_weak_linkage: bool,2133 is_weak_linkage: bool,
1905 _: u29 = 0,2134 _: u27 = 0,
1906 };2135 };
1907};2136};
19082137
...@@ -1917,7 +2146,7 @@ pub const PtrMutDecl = struct {...@@ -1917,7 +2146,7 @@ pub const PtrMutDecl = struct {
1917 runtime_index: RuntimeIndex,2146 runtime_index: RuntimeIndex,
1918};2147};
19192148
1920pub const PtrInt = struct {2149pub const PtrAddr = struct {
1921 ty: Index,2150 ty: Index,
1922 addr: Index,2151 addr: Index,
1923};2152};
...@@ -1949,6 +2178,11 @@ pub const IntSmall = struct {...@@ -1949,6 +2178,11 @@ pub const IntSmall = struct {
1949 value: u32,2178 value: u32,
1950};2179};
19512180
2181pub const IntLazy = struct {
2182 ty: Index,
2183 lazy_ty: Index,
2184};
2185
1952/// A f64 value, broken up into 2 u32 parts.2186/// A f64 value, broken up into 2 u32 parts.
1953pub const Float64 = struct {2187pub const Float64 = struct {
1954 piece0: u32,2188 piece0: u32,
...@@ -2063,6 +2297,9 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void {...@@ -2063,6 +2297,9 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void {
2063 ip.unions_free_list.deinit(gpa);2297 ip.unions_free_list.deinit(gpa);
2064 ip.allocated_unions.deinit(gpa);2298 ip.allocated_unions.deinit(gpa);
20652299
2300 ip.funcs_free_list.deinit(gpa);
2301 ip.allocated_funcs.deinit(gpa);
2302
2066 ip.inferred_error_sets_free_list.deinit(gpa);2303 ip.inferred_error_sets_free_list.deinit(gpa);
2067 ip.allocated_inferred_error_sets.deinit(gpa);2304 ip.allocated_inferred_error_sets.deinit(gpa);
20682305
...@@ -2235,6 +2472,13 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {...@@ -2235,6 +2472,13 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
2235 .type_function => .{ .func_type = indexToKeyFuncType(ip, data) },2472 .type_function => .{ .func_type = indexToKeyFuncType(ip, data) },
22362473
2237 .undef => .{ .undef = @intToEnum(Index, data) },2474 .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 },
2238 .opt_null => .{ .opt = .{2482 .opt_null => .{ .opt = .{
2239 .ty = @intToEnum(Index, data),2483 .ty = @intToEnum(Index, data),
2240 .val = .none,2484 .val = .none,
...@@ -2251,18 +2495,11 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {...@@ -2251,18 +2495,11 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
2251 .val = payload_val,2495 .val = payload_val,
2252 } };2496 } };
2253 },2497 },
2254 .ptr_var => {2498 .ptr_decl => {
2255 const info = ip.extraData(PtrVar, data);2499 const info = ip.extraData(PtrDecl, data);
2256 return .{ .ptr = .{2500 return .{ .ptr = .{
2257 .ty = info.ty,2501 .ty = info.ty,
2258 .addr = .{ .@"var" = .{2502 .addr = .{ .decl = info.decl },
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 } },
2266 } };2503 } };
2267 },2504 },
2268 .ptr_mut_decl => {2505 .ptr_mut_decl => {
...@@ -2275,15 +2512,8 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {...@@ -2275,15 +2512,8 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
2275 } },2512 } },
2276 } };2513 } };
2277 },2514 },
2278 .ptr_decl => {
2279 const info = ip.extraData(PtrDecl, data);
2280 return .{ .ptr = .{
2281 .ty = info.ty,
2282 .addr = .{ .decl = info.decl },
2283 } };
2284 },
2285 .ptr_int => {2515 .ptr_int => {
2286 const info = ip.extraData(PtrInt, data);2516 const info = ip.extraData(PtrAddr, data);
2287 return .{ .ptr = .{2517 return .{ .ptr = .{
2288 .ty = info.ty,2518 .ty = info.ty,
2289 .addr = .{ .int = info.addr },2519 .addr = .{ .int = info.addr },
...@@ -2383,6 +2613,17 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {...@@ -2383,6 +2613,17 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
2383 .storage = .{ .u64 = info.value },2613 .storage = .{ .u64 = info.value },
2384 } };2614 } };
2385 },2615 },
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 },
2386 .float_f16 => .{ .float = .{2627 .float_f16 => .{ .float = .{
2387 .ty = .f16_type,2628 .ty = .f16_type,
2388 .storage = .{ .f16 = @bitCast(f16, @intCast(u16, data)) },2629 .storage = .{ .f16 = @bitCast(f16, @intCast(u16, data)) },
...@@ -2415,8 +2656,21 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {...@@ -2415,8 +2656,21 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
2415 .ty = .comptime_float_type,2656 .ty = .comptime_float_type,
2416 .storage = .{ .f128 = ip.extraData(Float128, data).get() },2657 .storage = .{ .f128 = ip.extraData(Float128, data).get() },
2417 } },2658 } },
2418 .extern_func => @panic("TODO"),2659 .variable => {
2419 .func => @panic("TODO"),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) },
2420 .only_possible_value => {2674 .only_possible_value => {
2421 const ty = @intToEnum(Index, data);2675 const ty = @intToEnum(Index, data);
2422 return switch (ip.indexToKey(ty)) {2676 return switch (ip.indexToKey(ty)) {
...@@ -2438,6 +2692,14 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {...@@ -2438,6 +2692,14 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
2438 else => unreachable,2692 else => unreachable,
2439 };2693 };
2440 },2694 },
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 },
2441 .aggregate => {2703 .aggregate => {
2442 const extra = ip.extraDataTrail(Aggregate, data);2704 const extra = ip.extraDataTrail(Aggregate, data);
2443 const len = @intCast(u32, ip.aggregateTypeLen(extra.data.ty));2705 const len = @intCast(u32, ip.aggregateTypeLen(extra.data.ty));
...@@ -2455,6 +2717,22 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {...@@ -2455,6 +2717,22 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
2455 } };2717 } };
2456 },2718 },
2457 .union_value => .{ .un = ip.extraData(Key.Union, data) },2719 .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) },
2458 .enum_tag => .{ .enum_tag = ip.extraData(Key.EnumTag, data) },2736 .enum_tag => .{ .enum_tag = ip.extraData(Key.EnumTag, data) },
2459 };2737 };
2460}2738}
...@@ -2547,7 +2825,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -2547,7 +2825,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
2547 _ = ip.map.pop();2825 _ = ip.map.pop();
2548 var new_key = key;2826 var new_key = key;
2549 new_key.ptr_type.size = .Many;2827 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);
2551 assert(!(try ip.map.getOrPutAdapted(gpa, key, adapter)).found_existing);2829 assert(!(try ip.map.getOrPutAdapted(gpa, key, adapter)).found_existing);
2552 try ip.items.ensureUnusedCapacity(gpa, 1);2830 try ip.items.ensureUnusedCapacity(gpa, 1);
2553 ip.items.appendAssumeCapacity(.{2831 ip.items.appendAssumeCapacity(.{
...@@ -2677,6 +2955,13 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -2677,6 +2955,13 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
2677 .data = @enumToInt(ty),2955 .data = @enumToInt(ty),
2678 });2956 });
2679 },2957 },
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
2681 .struct_type => |struct_type| {2966 .struct_type => |struct_type| {
2682 ip.items.appendAssumeCapacity(if (struct_type.index.unwrap()) |i| .{2967 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 {...@@ -2809,7 +3094,35 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
2809 ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, func_type.param_types));3094 ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, func_type.param_types));
2810 },3095 },
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
2814 .ptr => |ptr| {3127 .ptr => |ptr| {
2815 const ptr_type = ip.indexToKey(ptr.ty).ptr_type;3128 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 {...@@ -2817,20 +3130,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
2817 .none => {3130 .none => {
2818 assert(ptr_type.size != .Slice);3131 assert(ptr_type.size != .Slice);
2819 switch (ptr.addr) {3132 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 }),
2834 .decl => |decl| ip.items.appendAssumeCapacity(.{3133 .decl => |decl| ip.items.appendAssumeCapacity(.{
2835 .tag = .ptr_decl,3134 .tag = .ptr_decl,
2836 .data = try ip.addExtra(gpa, PtrDecl{3135 .data = try ip.addExtra(gpa, PtrDecl{
...@@ -2846,31 +3145,41 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -2846,31 +3145,41 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
2846 .runtime_index = mut_decl.runtime_index,3145 .runtime_index = mut_decl.runtime_index,
2847 }),3146 }),
2848 }),3147 }),
2849 .int => |int| ip.items.appendAssumeCapacity(.{3148 .int => |int| {
2850 .tag = .ptr_int,3149 assert(int != .none);
2851 .data = try ip.addExtra(gpa, PtrInt{3150 ip.items.appendAssumeCapacity(.{
2852 .ty = ptr.ty,3151 .tag = .ptr_int,
2853 .addr = int,3152 .data = try ip.addExtra(gpa, PtrAddr{
2854 }),3153 .ty = ptr.ty,
2855 }),3154 .addr = int,
2856 .eu_payload, .opt_payload => |data| ip.items.appendAssumeCapacity(.{3155 }),
2857 .tag = switch (ptr.addr) {3156 });
2858 .eu_payload => .ptr_eu_payload,3157 },
2859 .opt_payload => .ptr_opt_payload,3158 .eu_payload, .opt_payload => |data| {
2860 else => unreachable,3159 assert(data != .none);
2861 },3160 ip.items.appendAssumeCapacity(.{
2862 .data = @enumToInt(data),3161 .tag = switch (ptr.addr) {
2863 }),3162 .eu_payload => .ptr_eu_payload,
2864 .comptime_field => |field_val| ip.items.appendAssumeCapacity(.{3163 .opt_payload => .ptr_opt_payload,
2865 .tag = .ptr_comptime_field,3164 else => unreachable,
2866 .data = try ip.addExtra(gpa, PtrComptimeField{3165 },
2867 .ty = ptr.ty,3166 .data = @enumToInt(data),
2868 .field_val = field_val,3167 });
2869 }),3168 },
2870 }),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 },
2871 .elem, .field => |base_index| {3179 .elem, .field => |base_index| {
3180 assert(base_index.base != .none);
2872 _ = ip.map.pop();3181 _ = ip.map.pop();
2873 const index_index = try get(ip, gpa, .{ .int = .{3182 const index_index = try ip.get(gpa, .{ .int = .{
2874 .ty = .usize_type,3183 .ty = .usize_type,
2875 .storage = .{ .u64 = base_index.index },3184 .storage = .{ .u64 = base_index.index },
2876 } });3185 } });
...@@ -2894,7 +3203,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -2894,7 +3203,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
2894 new_key.ptr.ty = ip.slicePtrType(ptr.ty);3203 new_key.ptr.ty = ip.slicePtrType(ptr.ty);
2895 new_key.ptr.len = .none;3204 new_key.ptr.len = .none;
2896 assert(ip.indexToKey(new_key.ptr.ty).ptr_type.size == .Many);3205 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);
2898 assert(!(try ip.map.getOrPutAdapted(gpa, key, adapter)).found_existing);3207 assert(!(try ip.map.getOrPutAdapted(gpa, key, adapter)).found_existing);
2899 try ip.items.ensureUnusedCapacity(gpa, 1);3208 try ip.items.ensureUnusedCapacity(gpa, 1);
2900 ip.items.appendAssumeCapacity(.{3209 ip.items.appendAssumeCapacity(.{
...@@ -2921,8 +3230,25 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -2921,8 +3230,25 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
2921 },3230 },
29223231
2923 .int => |int| b: {3232 .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 }
2924 switch (int.ty) {3251 switch (int.ty) {
2925 .none => unreachable,
2926 .u8_type => switch (int.storage) {3252 .u8_type => switch (int.storage) {
2927 .big_int => |big_int| {3253 .big_int => |big_int| {
2928 ip.items.appendAssumeCapacity(.{3254 ip.items.appendAssumeCapacity(.{
...@@ -2938,6 +3264,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -2938,6 +3264,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
2938 });3264 });
2939 break :b;3265 break :b;
2940 },3266 },
3267 .lazy_align, .lazy_size => unreachable,
2941 },3268 },
2942 .u16_type => switch (int.storage) {3269 .u16_type => switch (int.storage) {
2943 .big_int => |big_int| {3270 .big_int => |big_int| {
...@@ -2954,6 +3281,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -2954,6 +3281,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
2954 });3281 });
2955 break :b;3282 break :b;
2956 },3283 },
3284 .lazy_align, .lazy_size => unreachable,
2957 },3285 },
2958 .u32_type => switch (int.storage) {3286 .u32_type => switch (int.storage) {
2959 .big_int => |big_int| {3287 .big_int => |big_int| {
...@@ -2970,6 +3298,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -2970,6 +3298,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
2970 });3298 });
2971 break :b;3299 break :b;
2972 },3300 },
3301 .lazy_align, .lazy_size => unreachable,
2973 },3302 },
2974 .i32_type => switch (int.storage) {3303 .i32_type => switch (int.storage) {
2975 .big_int => |big_int| {3304 .big_int => |big_int| {
...@@ -2987,6 +3316,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -2987,6 +3316,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
2987 });3316 });
2988 break :b;3317 break :b;
2989 },3318 },
3319 .lazy_align, .lazy_size => unreachable,
2990 },3320 },
2991 .usize_type => switch (int.storage) {3321 .usize_type => switch (int.storage) {
2992 .big_int => |big_int| {3322 .big_int => |big_int| {
...@@ -3007,6 +3337,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -3007,6 +3337,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3007 break :b;3337 break :b;
3008 }3338 }
3009 },3339 },
3340 .lazy_align, .lazy_size => unreachable,
3010 },3341 },
3011 .comptime_int_type => switch (int.storage) {3342 .comptime_int_type => switch (int.storage) {
3012 .big_int => |big_int| {3343 .big_int => |big_int| {
...@@ -3041,6 +3372,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -3041,6 +3372,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3041 break :b;3372 break :b;
3042 }3373 }
3043 },3374 },
3375 .lazy_align, .lazy_size => unreachable,
3044 },3376 },
3045 else => {},3377 else => {},
3046 }3378 }
...@@ -3077,9 +3409,37 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -3077,9 +3409,37 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3077 const tag: Tag = if (big_int.positive) .int_positive else .int_negative;3409 const tag: Tag = if (big_int.positive) .int_positive else .int_negative;
3078 try addInt(ip, gpa, int.ty, tag, big_int.limbs);3410 try addInt(ip, gpa, int.ty, tag, big_int.limbs);
3079 },3411 },
3412 .lazy_align, .lazy_size => unreachable,
3080 }3413 }
3081 },3414 },
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
3083 .enum_tag => |enum_tag| {3443 .enum_tag => |enum_tag| {
3084 assert(enum_tag.ty != .none);3444 assert(enum_tag.ty != .none);
3085 assert(enum_tag.int != .none);3445 assert(enum_tag.int != .none);
...@@ -3131,9 +3491,12 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -3131,9 +3491,12 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3131 },3491 },
31323492
3133 .aggregate => |aggregate| {3493 .aggregate => |aggregate| {
3134 assert(aggregate.ty != .none);3494 const ty_key = ip.indexToKey(aggregate.ty);
3135 const aggregate_len = ip.aggregateTypeLen(aggregate.ty);3495 const aggregate_len = ip.aggregateTypeLen(aggregate.ty);
3136 switch (aggregate.storage) {3496 switch (aggregate.storage) {
3497 .bytes => {
3498 assert(ty_key.array_type.child == .u8_type);
3499 },
3137 .elems => |elems| {3500 .elems => |elems| {
3138 assert(elems.len == aggregate_len);3501 assert(elems.len == aggregate_len);
3139 for (elems) |elem| assert(elem != .none);3502 for (elems) |elem| assert(elem != .none);
...@@ -3151,9 +3514,15 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -3151,9 +3514,15 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3151 return @intToEnum(Index, ip.items.len - 1);3514 return @intToEnum(Index, ip.items.len - 1);
3152 }3515 }
31533516
3154 switch (ip.indexToKey(aggregate.ty)) {3517 switch (ty_key) {
3155 .anon_struct_type => |anon_struct_type| {3518 .anon_struct_type => |anon_struct_type| {
3156 if (switch (aggregate.storage) {3519 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,
3157 .elems => |elems| std.mem.eql(Index, anon_struct_type.values, elems),3526 .elems => |elems| std.mem.eql(Index, anon_struct_type.values, elems),
3158 .repeated_elem => |elem| for (anon_struct_type.values) |value| {3527 .repeated_elem => |elem| for (anon_struct_type.values) |value| {
3159 if (value != elem) break false;3528 if (value != elem) break false;
...@@ -3173,34 +3542,80 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -3173,34 +3542,80 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3173 }3542 }
31743543
3175 if (switch (aggregate.storage) {3544 if (switch (aggregate.storage) {
3545 .bytes => |bytes| for (bytes[1..]) |byte| {
3546 if (byte != bytes[0]) break false;
3547 } else true,
3176 .elems => |elems| for (elems[1..]) |elem| {3548 .elems => |elems| for (elems[1..]) |elem| {
3177 if (elem != elems[0]) break false;3549 if (elem != elems[0]) break false;
3178 } else true,3550 } else true,
3179 .repeated_elem => true,3551 .repeated_elem => true,
3180 }) {3552 }) {
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
3181 try ip.extra.ensureUnusedCapacity(3568 try ip.extra.ensureUnusedCapacity(
3182 gpa,3569 gpa,
3183 @typeInfo(Repeated).Struct.fields.len,3570 @typeInfo(Repeated).Struct.fields.len,
3184 );3571 );
3185
3186 ip.items.appendAssumeCapacity(.{3572 ip.items.appendAssumeCapacity(.{
3187 .tag = .repeated,3573 .tag = .repeated,
3188 .data = ip.addExtraAssumeCapacity(Repeated{3574 .data = ip.addExtraAssumeCapacity(Repeated{
3189 .ty = aggregate.ty,3575 .ty = aggregate.ty,
3190 .elem_val = switch (aggregate.storage) {3576 .elem_val = elem,
3191 .elems => |elems| elems[0],
3192 .repeated_elem => |elem| elem,
3193 },
3194 }),3577 }),
3195 });3578 });
3196 return @intToEnum(Index, ip.items.len - 1);3579 return @intToEnum(Index, ip.items.len - 1);
3197 }3580 }
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
3199 try ip.extra.ensureUnusedCapacity(3615 try ip.extra.ensureUnusedCapacity(
3200 gpa,3616 gpa,
3201 @typeInfo(Aggregate).Struct.fields.len + aggregate_len,3617 @typeInfo(Aggregate).Struct.fields.len + aggregate_len,
3202 );3618 );
3203
3204 ip.items.appendAssumeCapacity(.{3619 ip.items.appendAssumeCapacity(.{
3205 .tag = .aggregate,3620 .tag = .aggregate,
3206 .data = ip.addExtraAssumeCapacity(Aggregate{3621 .data = ip.addExtraAssumeCapacity(Aggregate{
...@@ -3423,12 +3838,16 @@ pub fn finishGetEnum(...@@ -3423,12 +3838,16 @@ pub fn finishGetEnum(
3423 return @intToEnum(Index, ip.items.len - 1);3838 return @intToEnum(Index, ip.items.len - 1);
3424}3839}
34253840
3426pub fn getAssumeExists(ip: *const InternPool, key: Key) Index {3841pub fn getIfExists(ip: *const InternPool, key: Key) ?Index {
3427 const adapter: KeyAdapter = .{ .intern_pool = ip };3842 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;
3429 return @intToEnum(Index, index);3844 return @intToEnum(Index, index);
3430}3845}
34313846
3847pub fn getAssumeExists(ip: *const InternPool, key: Key) Index {
3848 return ip.getIfExists(key).?;
3849}
3850
3432fn addStringsToMap(3851fn addStringsToMap(
3433 ip: *InternPool,3852 ip: *InternPool,
3434 gpa: Allocator,3853 gpa: Allocator,
...@@ -3500,9 +3919,11 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {...@@ -3500,9 +3919,11 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {
3500 Module.Decl.Index => @enumToInt(@field(extra, field.name)),3919 Module.Decl.Index => @enumToInt(@field(extra, field.name)),
3501 Module.Namespace.Index => @enumToInt(@field(extra, field.name)),3920 Module.Namespace.Index => @enumToInt(@field(extra, field.name)),
3502 Module.Namespace.OptionalIndex => @enumToInt(@field(extra, field.name)),3921 Module.Namespace.OptionalIndex => @enumToInt(@field(extra, field.name)),
3922 Module.Fn.Index => @enumToInt(@field(extra, field.name)),
3503 MapIndex => @enumToInt(@field(extra, field.name)),3923 MapIndex => @enumToInt(@field(extra, field.name)),
3504 OptionalMapIndex => @enumToInt(@field(extra, field.name)),3924 OptionalMapIndex => @enumToInt(@field(extra, field.name)),
3505 RuntimeIndex => @enumToInt(@field(extra, field.name)),3925 RuntimeIndex => @enumToInt(@field(extra, field.name)),
3926 String => @enumToInt(@field(extra, field.name)),
3506 NullTerminatedString => @enumToInt(@field(extra, field.name)),3927 NullTerminatedString => @enumToInt(@field(extra, field.name)),
3507 OptionalNullTerminatedString => @enumToInt(@field(extra, field.name)),3928 OptionalNullTerminatedString => @enumToInt(@field(extra, field.name)),
3508 i32 => @bitCast(u32, @field(extra, field.name)),3929 i32 => @bitCast(u32, @field(extra, field.name)),
...@@ -3510,7 +3931,7 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {...@@ -3510,7 +3931,7 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {
3510 TypeFunction.Flags => @bitCast(u32, @field(extra, field.name)),3931 TypeFunction.Flags => @bitCast(u32, @field(extra, field.name)),
3511 Pointer.PackedOffset => @bitCast(u32, @field(extra, field.name)),3932 Pointer.PackedOffset => @bitCast(u32, @field(extra, field.name)),
3512 Pointer.VectorIndex => @enumToInt(@field(extra, field.name)),3933 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)),
3514 else => @compileError("bad field type: " ++ @typeName(field.type)),3935 else => @compileError("bad field type: " ++ @typeName(field.type)),
3515 });3936 });
3516 }3937 }
...@@ -3566,9 +3987,11 @@ fn extraDataTrail(ip: InternPool, comptime T: type, index: usize) struct { data:...@@ -3566,9 +3987,11 @@ fn extraDataTrail(ip: InternPool, comptime T: type, index: usize) struct { data:
3566 Module.Decl.Index => @intToEnum(Module.Decl.Index, int32),3987 Module.Decl.Index => @intToEnum(Module.Decl.Index, int32),
3567 Module.Namespace.Index => @intToEnum(Module.Namespace.Index, int32),3988 Module.Namespace.Index => @intToEnum(Module.Namespace.Index, int32),
3568 Module.Namespace.OptionalIndex => @intToEnum(Module.Namespace.OptionalIndex, int32),3989 Module.Namespace.OptionalIndex => @intToEnum(Module.Namespace.OptionalIndex, int32),
3990 Module.Fn.Index => @intToEnum(Module.Fn.Index, int32),
3569 MapIndex => @intToEnum(MapIndex, int32),3991 MapIndex => @intToEnum(MapIndex, int32),
3570 OptionalMapIndex => @intToEnum(OptionalMapIndex, int32),3992 OptionalMapIndex => @intToEnum(OptionalMapIndex, int32),
3571 RuntimeIndex => @intToEnum(RuntimeIndex, int32),3993 RuntimeIndex => @intToEnum(RuntimeIndex, int32),
3994 String => @intToEnum(String, int32),
3572 NullTerminatedString => @intToEnum(NullTerminatedString, int32),3995 NullTerminatedString => @intToEnum(NullTerminatedString, int32),
3573 OptionalNullTerminatedString => @intToEnum(OptionalNullTerminatedString, int32),3996 OptionalNullTerminatedString => @intToEnum(OptionalNullTerminatedString, int32),
3574 i32 => @bitCast(i32, int32),3997 i32 => @bitCast(i32, int32),
...@@ -3576,7 +3999,7 @@ fn extraDataTrail(ip: InternPool, comptime T: type, index: usize) struct { data:...@@ -3576,7 +3999,7 @@ fn extraDataTrail(ip: InternPool, comptime T: type, index: usize) struct { data:
3576 TypeFunction.Flags => @bitCast(TypeFunction.Flags, int32),3999 TypeFunction.Flags => @bitCast(TypeFunction.Flags, int32),
3577 Pointer.PackedOffset => @bitCast(Pointer.PackedOffset, int32),4000 Pointer.PackedOffset => @bitCast(Pointer.PackedOffset, int32),
3578 Pointer.VectorIndex => @intToEnum(Pointer.VectorIndex, int32),4001 Pointer.VectorIndex => @intToEnum(Pointer.VectorIndex, int32),
3579 PtrVar.Flags => @bitCast(PtrVar.Flags, int32),4002 Variable.Flags => @bitCast(Variable.Flags, int32),
3580 else => @compileError("bad field type: " ++ @typeName(field.type)),4003 else => @compileError("bad field type: " ++ @typeName(field.type)),
3581 };4004 };
3582 }4005 }
...@@ -3700,8 +4123,8 @@ pub fn childType(ip: InternPool, i: Index) Index {...@@ -3700,8 +4123,8 @@ pub fn childType(ip: InternPool, i: Index) Index {
3700/// Given a slice type, returns the type of the ptr field.4123/// Given a slice type, returns the type of the ptr field.
3701pub fn slicePtrType(ip: InternPool, i: Index) Index {4124pub fn slicePtrType(ip: InternPool, i: Index) Index {
3702 switch (i) {4125 switch (i) {
3703 .const_slice_u8_type => return .manyptr_const_u8_type,4126 .slice_const_u8_type => return .manyptr_const_u8_type,
3704 .const_slice_u8_sentinel_0_type => return .manyptr_const_u8_sentinel_0_type,4127 .slice_const_u8_sentinel_0_type => return .manyptr_const_u8_sentinel_0_type,
3705 else => {},4128 else => {},
3706 }4129 }
3707 const item = ip.items.get(@enumToInt(i));4130 const item = ip.items.get(@enumToInt(i));
...@@ -3830,6 +4253,8 @@ pub fn getCoercedInts(ip: *InternPool, gpa: Allocator, int: Key.Int, new_ty: Ind...@@ -3830,6 +4253,8 @@ pub fn getCoercedInts(ip: *InternPool, gpa: Allocator, int: Key.Int, new_ty: Ind
3830 } },4253 } },
3831 } });4254 } });
3832 },4255 },
4256
4257 .lazy_align, .lazy_size => unreachable,
3833 }4258 }
3834}4259}
38354260
...@@ -3862,6 +4287,14 @@ pub fn indexToFuncType(ip: InternPool, val: Index) ?Key.FuncType {...@@ -3862,6 +4287,14 @@ pub fn indexToFuncType(ip: InternPool, val: Index) ?Key.FuncType {
3862 }4287 }
3863}4288}
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
3865pub fn indexToInferredErrorSetType(ip: InternPool, val: Index) Module.Fn.InferredErrorSet.OptionalIndex {4298pub fn indexToInferredErrorSetType(ip: InternPool, val: Index) Module.Fn.InferredErrorSet.OptionalIndex {
3866 assert(val != .none);4299 assert(val != .none);
3867 const tags = ip.items.items(.tag);4300 const tags = ip.items.items(.tag);
...@@ -3891,6 +4324,15 @@ pub fn isInferredErrorSetType(ip: InternPool, ty: Index) bool {...@@ -3891,6 +4324,15 @@ pub fn isInferredErrorSetType(ip: InternPool, ty: Index) bool {
3891 return tags[@enumToInt(ty)] == .type_inferred_error_set;4324 return tags[@enumToInt(ty)] == .type_inferred_error_set;
3892}4325}
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
3894pub fn dump(ip: InternPool) void {4336pub fn dump(ip: InternPool) void {
3895 dumpFallible(ip, std.heap.page_allocator) catch return;4337 dumpFallible(ip, std.heap.page_allocator) catch return;
3896}4338}
...@@ -3903,10 +4345,12 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {...@@ -3903,10 +4345,12 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {
3903 (@sizeOf(Module.Struct) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl));4345 (@sizeOf(Module.Struct) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl));
3904 const unions_size = ip.allocated_unions.len *4346 const unions_size = ip.allocated_unions.len *
3905 (@sizeOf(Module.Union) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl));4347 (@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
3907 // TODO: map overhead size is not taken into account4351 // TODO: map overhead size is not taken into account
3908 const total_size = @sizeOf(InternPool) + items_size + extra_size + limbs_size +4352 const total_size = @sizeOf(InternPool) + items_size + extra_size + limbs_size +
3909 structs_size + unions_size;4353 structs_size + unions_size + funcs_size;
39104354
3911 std.debug.print(4355 std.debug.print(
3912 \\InternPool size: {d} bytes4356 \\InternPool size: {d} bytes
...@@ -3915,6 +4359,7 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {...@@ -3915,6 +4359,7 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {
3915 \\ {d} limbs: {d} bytes4359 \\ {d} limbs: {d} bytes
3916 \\ {d} structs: {d} bytes4360 \\ {d} structs: {d} bytes
3917 \\ {d} unions: {d} bytes4361 \\ {d} unions: {d} bytes
4362 \\ {d} funcs: {d} bytes
3918 \\4363 \\
3919 , .{4364 , .{
3920 total_size,4365 total_size,
...@@ -3928,6 +4373,8 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {...@@ -3928,6 +4373,8 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {
3928 structs_size,4373 structs_size,
3929 ip.allocated_unions.len,4374 ip.allocated_unions.len,
3930 unions_size,4375 unions_size,
4376 ip.allocated_funcs.len,
4377 funcs_size,
3931 });4378 });
39324379
3933 const tags = ip.items.items(.tag);4380 const tags = ip.items.items(.tag);
...@@ -3982,12 +4429,12 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {...@@ -3982,12 +4429,12 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {
3982 },4429 },
39834430
3984 .undef => 0,4431 .undef => 0,
4432 .runtime_value => 0,
3985 .simple_type => 0,4433 .simple_type => 0,
3986 .simple_value => 0,4434 .simple_value => 0,
3987 .ptr_var => @sizeOf(PtrVar),
3988 .ptr_decl => @sizeOf(PtrDecl),4435 .ptr_decl => @sizeOf(PtrDecl),
3989 .ptr_mut_decl => @sizeOf(PtrMutDecl),4436 .ptr_mut_decl => @sizeOf(PtrMutDecl),
3990 .ptr_int => @sizeOf(PtrInt),4437 .ptr_int => @sizeOf(PtrAddr),
3991 .ptr_eu_payload => 0,4438 .ptr_eu_payload => 0,
3992 .ptr_opt_payload => 0,4439 .ptr_opt_payload => 0,
3993 .ptr_comptime_field => @sizeOf(PtrComptimeField),4440 .ptr_comptime_field => @sizeOf(PtrComptimeField),
...@@ -4011,8 +4458,20 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {...@@ -4011,8 +4458,20 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {
4011 const int = ip.limbData(Int, data);4458 const int = ip.limbData(Int, data);
4012 break :b @sizeOf(Int) + int.limbs_len * 8;4459 break :b @sizeOf(Int) + int.limbs_len * 8;
4013 },4460 },
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,
4014 .enum_tag => @sizeOf(Key.EnumTag),4467 .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 },
4016 .aggregate => b: {4475 .aggregate => b: {
4017 const info = ip.extraData(Aggregate, data);4476 const info = ip.extraData(Aggregate, data);
4018 const fields_len = @intCast(u32, ip.aggregateTypeLen(info.ty));4477 const fields_len = @intCast(u32, ip.aggregateTypeLen(info.ty));
...@@ -4028,8 +4487,9 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {...@@ -4028,8 +4487,9 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {
4028 .float_c_longdouble_f80 => @sizeOf(Float80),4487 .float_c_longdouble_f80 => @sizeOf(Float80),
4029 .float_c_longdouble_f128 => @sizeOf(Float128),4488 .float_c_longdouble_f128 => @sizeOf(Float128),
4030 .float_comptime_float => @sizeOf(Float128),4489 .float_comptime_float => @sizeOf(Float128),
4031 .extern_func => @panic("TODO"),4490 .variable => @sizeOf(Variable) + @sizeOf(Module.Decl),
4032 .func => @panic("TODO"),4491 .extern_func => @sizeOf(Key.ExternFunc) + @sizeOf(Module.Decl),
4492 .func => @sizeOf(Key.Func) + @sizeOf(Module.Fn) + @sizeOf(Module.Decl),
4033 .only_possible_value => 0,4493 .only_possible_value => 0,
4034 .union_value => @sizeOf(Key.Union),4494 .union_value => @sizeOf(Key.Union),
4035 });4495 });
...@@ -4071,6 +4531,14 @@ pub fn unionPtrConst(ip: InternPool, index: Module.Union.Index) *const Module.Un...@@ -4071,6 +4531,14 @@ pub fn unionPtrConst(ip: InternPool, index: Module.Union.Index) *const Module.Un
4071 return ip.allocated_unions.at(@enumToInt(index));4531 return ip.allocated_unions.at(@enumToInt(index));
4072}4532}
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
4074pub fn inferredErrorSetPtr(ip: *InternPool, index: Module.Fn.InferredErrorSet.Index) *Module.Fn.InferredErrorSet {4542pub fn inferredErrorSetPtr(ip: *InternPool, index: Module.Fn.InferredErrorSet.Index) *Module.Fn.InferredErrorSet {
4075 return ip.allocated_inferred_error_sets.at(@enumToInt(index));4543 return ip.allocated_inferred_error_sets.at(@enumToInt(index));
4076}4544}
...@@ -4117,6 +4585,25 @@ pub fn destroyUnion(ip: *InternPool, gpa: Allocator, index: Module.Union.Index)...@@ -4117,6 +4585,25 @@ pub fn destroyUnion(ip: *InternPool, gpa: Allocator, index: Module.Union.Index)
4117 };4585 };
4118}4586}
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
4120pub fn createInferredErrorSet(4607pub fn createInferredErrorSet(
4121 ip: *InternPool,4608 ip: *InternPool,
4122 gpa: Allocator,4609 gpa: Allocator,
...@@ -4142,9 +4629,25 @@ pub fn getOrPutString(...@@ -4142,9 +4629,25 @@ pub fn getOrPutString(
4142 s: []const u8,4629 s: []const u8,
4143) Allocator.Error!NullTerminatedString {4630) Allocator.Error!NullTerminatedString {
4144 const string_bytes = &ip.string_bytes;4631 const string_bytes = &ip.string_bytes;
4145 const str_index = @intCast(u32, string_bytes.items.len);
4146 try string_bytes.ensureUnusedCapacity(gpa, s.len + 1);4632 try string_bytes.ensureUnusedCapacity(gpa, s.len + 1);
4147 string_bytes.appendSliceAssumeCapacity(s);4633 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 }
4148 const key: []const u8 = string_bytes.items[str_index..];4651 const key: []const u8 = string_bytes.items[str_index..];
4149 const gop = try ip.string_table.getOrPutContextAdapted(gpa, key, std.hash_map.StringIndexAdapter{4652 const gop = try ip.string_table.getOrPutContextAdapted(gpa, key, std.hash_map.StringIndexAdapter{
4150 .bytes = string_bytes,4653 .bytes = string_bytes,
...@@ -4179,6 +4682,10 @@ pub fn stringToSlice(ip: InternPool, s: NullTerminatedString) [:0]const u8 {...@@ -4179,6 +4682,10 @@ pub fn stringToSlice(ip: InternPool, s: NullTerminatedString) [:0]const u8 {
4179 return string_bytes[start..end :0];4682 return string_bytes[start..end :0];
4180}4683}
41814684
4685pub fn stringToSliceUnwrap(ip: InternPool, s: OptionalNullTerminatedString) ?[:0]const u8 {
4686 return ip.stringToSlice(s.unwrap() orelse return null);
4687}
4688
4182pub fn typeOf(ip: InternPool, index: Index) Index {4689pub fn typeOf(ip: InternPool, index: Index) Index {
4183 return ip.indexToKey(index).typeOf();4690 return ip.indexToKey(index).typeOf();
4184}4691}
...@@ -4199,7 +4706,7 @@ pub fn aggregateTypeLen(ip: InternPool, ty: Index) u64 {...@@ -4199,7 +4706,7 @@ pub fn aggregateTypeLen(ip: InternPool, ty: Index) u64 {
4199 };4706 };
4200}4707}
42014708
4202pub fn isNoReturn(ip: InternPool, ty: InternPool.Index) bool {4709pub fn isNoReturn(ip: InternPool, ty: Index) bool {
4203 return switch (ty) {4710 return switch (ty) {
4204 .noreturn_type => true,4711 .noreturn_type => true,
4205 else => switch (ip.indexToKey(ty)) {4712 else => switch (ip.indexToKey(ty)) {
src/Module.zig+201-208
...@@ -109,7 +109,7 @@ memoized_calls: MemoizedCallSet = .{},...@@ -109,7 +109,7 @@ memoized_calls: MemoizedCallSet = .{},
109/// Contains the values from `@setAlignStack`. A sparse table is used here109/// Contains the values from `@setAlignStack`. A sparse table is used here
110/// instead of a field of `Fn` because usage of `@setAlignStack` is rare, while110/// instead of a field of `Fn` because usage of `@setAlignStack` is rare, while
111/// functions are many.111/// functions are many.
112align_stack_fns: std.AutoHashMapUnmanaged(*const Fn, SetAlignStack) = .{},112align_stack_fns: std.AutoHashMapUnmanaged(Fn.Index, SetAlignStack) = .{},
113113
114/// We optimize memory usage for a compilation with no compile errors by storing the114/// We optimize memory usage for a compilation with no compile errors by storing the
115/// error messages and mapping outside of `Decl`.115/// error messages and mapping outside of `Decl`.
...@@ -242,22 +242,23 @@ pub const StringLiteralAdapter = struct {...@@ -242,22 +242,23 @@ pub const StringLiteralAdapter = struct {
242};242};
243243
244const MonomorphedFuncsSet = std.HashMapUnmanaged(244const MonomorphedFuncsSet = std.HashMapUnmanaged(
245 *Fn,245 Fn.Index,
246 void,246 void,
247 MonomorphedFuncsContext,247 MonomorphedFuncsContext,
248 std.hash_map.default_max_load_percentage,248 std.hash_map.default_max_load_percentage,
249);249);
250250
251const MonomorphedFuncsContext = struct {251const 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 {
253 _ = ctx;255 _ = ctx;
254 return a == b;256 return a == b;
255 }257 }
256258
257 /// Must match `Sema.GenericCallAdapter.hash`.259 /// Must match `Sema.GenericCallAdapter.hash`.
258 pub fn hash(ctx: @This(), key: *Fn) u64 {260 pub fn hash(ctx: @This(), key: Fn.Index) u64 {
259 _ = ctx;261 return ctx.mod.funcPtr(key).hash;
260 return key.hash;
261 }262 }
262};263};
263264
...@@ -272,7 +273,7 @@ pub const MemoizedCall = struct {...@@ -272,7 +273,7 @@ pub const MemoizedCall = struct {
272 module: *Module,273 module: *Module,
273274
274 pub const Key = struct {275 pub const Key = struct {
275 func: *Fn,276 func: Fn.Index,
276 args: []TypedValue,277 args: []TypedValue,
277 };278 };
278279
...@@ -652,21 +653,12 @@ pub const Decl = struct {...@@ -652,21 +653,12 @@ pub const Decl = struct {
652653
653 pub fn clearValues(decl: *Decl, mod: *Module) void {654 pub fn clearValues(decl: *Decl, mod: *Module) void {
654 const gpa = mod.gpa;655 const gpa = mod.gpa;
655 if (decl.getExternFn()) |extern_fn| {656 if (decl.getFunctionIndex(mod).unwrap()) |func| {
656 extern_fn.deinit(gpa);
657 gpa.destroy(extern_fn);
658 }
659 if (decl.getFunction()) |func| {
660 _ = mod.align_stack_fns.remove(func);657 _ = mod.align_stack_fns.remove(func);
661 if (func.comptime_args != null) {658 if (mod.funcPtr(func).comptime_args != null) {
662 _ = mod.monomorphed_funcs.remove(func);659 _ = mod.monomorphed_funcs.removeContext(func, .{ .mod = mod });
663 }660 }
664 func.deinit(gpa);661 mod.destroyFunc(func);
665 gpa.destroy(func);
666 }
667 if (decl.getVariable()) |variable| {
668 variable.deinit(gpa);
669 gpa.destroy(variable);
670 }662 }
671 if (decl.value_arena) |value_arena| {663 if (decl.value_arena) |value_arena| {
672 if (decl.owns_tv) {664 if (decl.owns_tv) {
...@@ -835,11 +827,11 @@ pub const Decl = struct {...@@ -835,11 +827,11 @@ pub const Decl = struct {
835827
836 /// If the Decl has a value and it is a struct, return it,828 /// If the Decl has a value and it is a struct, return it,
837 /// otherwise null.829 /// otherwise null.
838 pub fn getStruct(decl: *Decl, mod: *Module) ?*Struct {830 pub fn getStruct(decl: Decl, mod: *Module) ?*Struct {
839 return mod.structPtrUnwrap(getStructIndex(decl, mod));831 return mod.structPtrUnwrap(decl.getStructIndex(mod));
840 }832 }
841833
842 pub fn getStructIndex(decl: *Decl, mod: *Module) Struct.OptionalIndex {834 pub fn getStructIndex(decl: Decl, mod: *Module) Struct.OptionalIndex {
843 if (!decl.owns_tv) return .none;835 if (!decl.owns_tv) return .none;
844 if (decl.val.ip_index == .none) return .none;836 if (decl.val.ip_index == .none) return .none;
845 return mod.intern_pool.indexToStructType(decl.val.ip_index);837 return mod.intern_pool.indexToStructType(decl.val.ip_index);
...@@ -847,7 +839,7 @@ pub const Decl = struct {...@@ -847,7 +839,7 @@ pub const Decl = struct {
847839
848 /// If the Decl has a value and it is a union, return it,840 /// If the Decl has a value and it is a union, return it,
849 /// otherwise null.841 /// otherwise null.
850 pub fn getUnion(decl: *Decl, mod: *Module) ?*Union {842 pub fn getUnion(decl: Decl, mod: *Module) ?*Union {
851 if (!decl.owns_tv) return null;843 if (!decl.owns_tv) return null;
852 if (decl.val.ip_index == .none) return null;844 if (decl.val.ip_index == .none) return null;
853 return mod.typeToUnion(decl.val.toType());845 return mod.typeToUnion(decl.val.toType());
...@@ -855,32 +847,30 @@ pub const Decl = struct {...@@ -855,32 +847,30 @@ pub const Decl = struct {
855847
856 /// If the Decl has a value and it is a function, return it,848 /// If the Decl has a value and it is a function, return it,
857 /// otherwise null.849 /// otherwise null.
858 pub fn getFunction(decl: *const Decl) ?*Fn {850 pub fn getFunction(decl: Decl, mod: *Module) ?*Fn {
859 if (!decl.owns_tv) return null;851 return mod.funcPtrUnwrap(decl.getFunctionIndex(mod));
860 const func = (decl.val.castTag(.function) orelse return null).data;852 }
861 return func;853
854 pub fn getFunctionIndex(decl: Decl, mod: *Module) Fn.OptionalIndex {
855 return if (decl.owns_tv) decl.val.getFunctionIndex(mod) else .none;
862 }856 }
863857
864 /// If the Decl has a value and it is an extern function, returns it,858 /// If the Decl has a value and it is an extern function, returns it,
865 /// otherwise null.859 /// otherwise null.
866 pub fn getExternFn(decl: *const Decl) ?*ExternFn {860 pub fn getExternFunc(decl: Decl, mod: *Module) ?InternPool.Key.ExternFunc {
867 if (!decl.owns_tv) return null;861 return if (decl.owns_tv) decl.val.getExternFunc(mod) else null;
868 const extern_fn = (decl.val.castTag(.extern_fn) orelse return null).data;
869 return extern_fn;
870 }862 }
871863
872 /// If the Decl has a value and it is a variable, returns it,864 /// If the Decl has a value and it is a variable, returns it,
873 /// otherwise null.865 /// otherwise null.
874 pub fn getVariable(decl: *const Decl) ?*Var {866 pub fn getVariable(decl: Decl, mod: *Module) ?InternPool.Key.Variable {
875 if (!decl.owns_tv) return null;867 return if (decl.owns_tv) decl.val.getVariable(mod) else null;
876 const variable = (decl.val.castTag(.variable) orelse return null).data;
877 return variable;
878 }868 }
879869
880 /// Gets the namespace that this Decl creates by being a struct, union,870 /// Gets the namespace that this Decl creates by being a struct, union,
881 /// enum, or opaque.871 /// enum, or opaque.
882 /// Only returns it if the Decl is the owner.872 /// 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 {
884 if (!decl.owns_tv) return .none;874 if (!decl.owns_tv) return .none;
885 return switch (decl.val.ip_index) {875 return switch (decl.val.ip_index) {
886 .empty_struct_type => .none,876 .empty_struct_type => .none,
...@@ -896,8 +886,8 @@ pub const Decl = struct {...@@ -896,8 +886,8 @@ pub const Decl = struct {
896 }886 }
897887
898 /// Same as `getInnerNamespaceIndex` but additionally obtains the pointer.888 /// Same as `getInnerNamespaceIndex` but additionally obtains the pointer.
899 pub fn getInnerNamespace(decl: *Decl, mod: *Module) ?*Namespace {889 pub fn getInnerNamespace(decl: Decl, mod: *Module) ?*Namespace {
900 return if (getInnerNamespaceIndex(decl, mod).unwrap()) |i| mod.namespacePtr(i) else null;890 return if (decl.getInnerNamespaceIndex(mod).unwrap()) |i| mod.namespacePtr(i) else null;
901 }891 }
902892
903 pub fn dump(decl: *Decl) void {893 pub fn dump(decl: *Decl) void {
...@@ -927,14 +917,11 @@ pub const Decl = struct {...@@ -927,14 +917,11 @@ pub const Decl = struct {
927 assert(decl.dependencies.swapRemove(other));917 assert(decl.dependencies.swapRemove(other));
928 }918 }
929919
930 pub fn isExtern(decl: Decl) bool {920 pub fn isExtern(decl: Decl, mod: *Module) bool {
931 assert(decl.has_tv);921 assert(decl.has_tv);
932 return switch (decl.val.ip_index) {922 return switch (mod.intern_pool.indexToKey(decl.val.ip_index)) {
933 .none => switch (decl.val.tag()) {923 .variable => |variable| variable.is_extern,
934 .extern_fn => true,924 .extern_func => true,
935 .variable => decl.val.castTag(.variable).?.data.init.ip_index == .unreachable_value,
936 else => false,
937 },
938 else => false,925 else => false,
939 };926 };
940 }927 }
...@@ -1494,6 +1481,28 @@ pub const Fn = struct {...@@ -1494,6 +1481,28 @@ pub const Fn = struct {
1494 is_noinline: bool,1481 is_noinline: bool,
1495 calls_or_awaits_errorable_fn: bool = false,1482 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
1497 pub const Analysis = enum {1506 pub const Analysis = enum {
1498 /// This function has not yet undergone analysis, because we have not1507 /// This function has not yet undergone analysis, because we have not
1499 /// seen a potential runtime call. It may be analyzed in future.1508 /// seen a potential runtime call. It may be analyzed in future.
...@@ -1519,7 +1528,7 @@ pub const Fn = struct {...@@ -1519,7 +1528,7 @@ pub const Fn = struct {
1519 /// or comptime functions.1528 /// or comptime functions.
1520 pub const InferredErrorSet = struct {1529 pub const InferredErrorSet = struct {
1521 /// The function from which this error set originates.1530 /// The function from which this error set originates.
1522 func: *Fn,1531 func: Fn.Index,
15231532
1524 /// All currently known errors that this error set contains. This includes1533 /// All currently known errors that this error set contains. This includes
1525 /// direct additions via `return error.Foo;`, and possibly also errors that1534 /// direct additions via `return error.Foo;`, and possibly also errors that
...@@ -1543,8 +1552,8 @@ pub const Fn = struct {...@@ -1543,8 +1552,8 @@ pub const Fn = struct {
1543 pub const Index = enum(u32) {1552 pub const Index = enum(u32) {
1544 _,1553 _,
15451554
1546 pub fn toOptional(i: Index) OptionalIndex {1555 pub fn toOptional(i: InferredErrorSet.Index) InferredErrorSet.OptionalIndex {
1547 return @intToEnum(OptionalIndex, @enumToInt(i));1556 return @intToEnum(InferredErrorSet.OptionalIndex, @enumToInt(i));
1548 }1557 }
1549 };1558 };
15501559
...@@ -1552,13 +1561,13 @@ pub const Fn = struct {...@@ -1552,13 +1561,13 @@ pub const Fn = struct {
1552 none = std.math.maxInt(u32),1561 none = std.math.maxInt(u32),
1553 _,1562 _,
15541563
1555 pub fn init(oi: ?Index) OptionalIndex {1564 pub fn init(oi: ?InferredErrorSet.Index) InferredErrorSet.OptionalIndex {
1556 return @intToEnum(OptionalIndex, @enumToInt(oi orelse return .none));1565 return @intToEnum(InferredErrorSet.OptionalIndex, @enumToInt(oi orelse return .none));
1557 }1566 }
15581567
1559 pub fn unwrap(oi: OptionalIndex) ?Index {1568 pub fn unwrap(oi: InferredErrorSet.OptionalIndex) ?InferredErrorSet.Index {
1560 if (oi == .none) return null;1569 if (oi == .none) return null;
1561 return @intToEnum(Index, @enumToInt(oi));1570 return @intToEnum(InferredErrorSet.Index, @enumToInt(oi));
1562 }1571 }
1563 };1572 };
15641573
...@@ -1587,12 +1596,6 @@ pub const Fn = struct {...@@ -1587,12 +1596,6 @@ pub const Fn = struct {
1587 }1596 }
1588 };1597 };
15891598
1590 /// TODO: remove this function
1591 pub fn deinit(func: *Fn, gpa: Allocator) void {
1592 _ = func;
1593 _ = gpa;
1594 }
1595
1596 pub fn isAnytypeParam(func: Fn, mod: *Module, index: u32) bool {1599 pub fn isAnytypeParam(func: Fn, mod: *Module, index: u32) bool {
1597 const file = mod.declPtr(func.owner_decl).getFileScope(mod);1600 const file = mod.declPtr(func.owner_decl).getFileScope(mod);
15981601
...@@ -1647,28 +1650,6 @@ pub const Fn = struct {...@@ -1647,28 +1650,6 @@ pub const Fn = struct {
1647 }1650 }
1648};1651};
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
1672pub const DeclAdapter = struct {1653pub const DeclAdapter = struct {
1673 mod: *Module,1654 mod: *Module,
16741655
...@@ -3472,6 +3453,10 @@ pub fn structPtr(mod: *Module, index: Struct.Index) *Struct {...@@ -3472,6 +3453,10 @@ pub fn structPtr(mod: *Module, index: Struct.Index) *Struct {
3472 return mod.intern_pool.structPtr(index);3453 return mod.intern_pool.structPtr(index);
3473}3454}
34743455
3456pub fn funcPtr(mod: *Module, index: Fn.Index) *Fn {
3457 return mod.intern_pool.funcPtr(index);
3458}
3459
3475pub fn inferredErrorSetPtr(mod: *Module, index: Fn.InferredErrorSet.Index) *Fn.InferredErrorSet {3460pub fn inferredErrorSetPtr(mod: *Module, index: Fn.InferredErrorSet.Index) *Fn.InferredErrorSet {
3476 return mod.intern_pool.inferredErrorSetPtr(index);3461 return mod.intern_pool.inferredErrorSetPtr(index);
3477}3462}
...@@ -3479,7 +3464,11 @@ pub fn inferredErrorSetPtr(mod: *Module, index: Fn.InferredErrorSet.Index) *Fn.I...@@ -3479,7 +3464,11 @@ pub fn inferredErrorSetPtr(mod: *Module, index: Fn.InferredErrorSet.Index) *Fn.I
3479/// This one accepts an index from the InternPool and asserts that it is not3464/// This one accepts an index from the InternPool and asserts that it is not
3480/// the anonymous empty struct type.3465/// the anonymous empty struct type.
3481pub fn structPtrUnwrap(mod: *Module, index: Struct.OptionalIndex) ?*Struct {3466pub 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);
3483}3472}
34843473
3485/// Returns true if and only if the Decl is the top level struct associated with a File.3474/// 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 {...@@ -3952,7 +3941,7 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void {
3952 };3941 };
3953 }3942 }
39543943
3955 if (decl.getFunction()) |func| {3944 if (decl.getFunction(mod)) |func| {
3956 func.zir_body_inst = inst_map.get(func.zir_body_inst) orelse {3945 func.zir_body_inst = inst_map.get(func.zir_body_inst) orelse {
3957 try file.deleted_decls.append(gpa, decl_index);3946 try file.deleted_decls.append(gpa, decl_index);
3958 continue;3947 continue;
...@@ -4139,7 +4128,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {...@@ -4139,7 +4128,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
4139 try mod.deleteDeclExports(decl_index);4128 try mod.deleteDeclExports(decl_index);
41404129
4141 // Similarly, `@setAlignStack` invocations will be re-discovered.4130 // Similarly, `@setAlignStack` invocations will be re-discovered.
4142 if (decl.getFunction()) |func| {4131 if (decl.getFunctionIndex(mod).unwrap()) |func| {
4143 _ = mod.align_stack_fns.remove(func);4132 _ = mod.align_stack_fns.remove(func);
4144 }4133 }
41454134
...@@ -4229,10 +4218,11 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {...@@ -4229,10 +4218,11 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
4229 }4218 }
4230}4219}
42314220
4232pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void {4221pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void {
4233 const tracy = trace(@src());4222 const tracy = trace(@src());
4234 defer tracy.end();4223 defer tracy.end();
42354224
4225 const func = mod.funcPtr(func_index);
4236 const decl_index = func.owner_decl;4226 const decl_index = func.owner_decl;
4237 const decl = mod.declPtr(decl_index);4227 const decl = mod.declPtr(decl_index);
42384228
...@@ -4264,7 +4254,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void {...@@ -4264,7 +4254,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void {
4264 defer tmp_arena.deinit();4254 defer tmp_arena.deinit();
4265 const sema_arena = tmp_arena.allocator();4255 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) {
4268 error.AnalysisFail => {4258 error.AnalysisFail => {
4269 if (func.state == .in_progress) {4259 if (func.state == .in_progress) {
4270 // If this decl caused the compile error, the analysis field would4260 // If this decl caused the compile error, the analysis field would
...@@ -4333,7 +4323,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void {...@@ -4333,7 +4323,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void {
43334323
4334 if (no_bin_file and !dump_llvm_ir) return;4324 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) {
4337 error.OutOfMemory => return error.OutOfMemory,4327 error.OutOfMemory => return error.OutOfMemory,
4338 error.AnalysisFail => {4328 error.AnalysisFail => {
4339 decl.analysis = .codegen_failure;4329 decl.analysis = .codegen_failure;
...@@ -4363,7 +4353,8 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void {...@@ -4363,7 +4353,8 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void {
4363/// analyzed, and for ensuring it can exist at runtime (see4353/// analyzed, and for ensuring it can exist at runtime (see
4364/// `sema.fnHasRuntimeBits`). This function does *not* guarantee that the body4354/// `sema.fnHasRuntimeBits`). This function does *not* guarantee that the body
4365/// will be analyzed when it returns: for that, see `ensureFuncBodyAnalyzed`.4355/// 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);
4367 const decl_index = func.owner_decl;4358 const decl_index = func.owner_decl;
4368 const decl = mod.declPtr(decl_index);4359 const decl = mod.declPtr(decl_index);
43694360
...@@ -4401,7 +4392,7 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func: *Fn) !void {...@@ -4401,7 +4392,7 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func: *Fn) !void {
44014392
4402 // Decl itself is safely analyzed, and body analysis is not yet queued4393 // 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 });
4405 if (mod.emit_h != null) {4396 if (mod.emit_h != null) {
4406 // TODO: we ideally only want to do this if the function's type changed4397 // TODO: we ideally only want to do this if the function's type changed
4407 // since the last update4398 // since the last update
...@@ -4532,8 +4523,10 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {...@@ -4532,8 +4523,10 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
4532 .owner_decl = new_decl,4523 .owner_decl = new_decl,
4533 .owner_decl_index = new_decl_index,4524 .owner_decl_index = new_decl_index,
4534 .func = null,4525 .func = null,
4526 .func_index = .none,
4535 .fn_ret_ty = Type.void,4527 .fn_ret_ty = Type.void,
4536 .owner_func = null,4528 .owner_func = null,
4529 .owner_func_index = .none,
4537 };4530 };
4538 defer sema.deinit();4531 defer sema.deinit();
45394532
...@@ -4628,8 +4621,10 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {...@@ -4628,8 +4621,10 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
4628 .owner_decl = decl,4621 .owner_decl = decl,
4629 .owner_decl_index = decl_index,4622 .owner_decl_index = decl_index,
4630 .func = null,4623 .func = null,
4624 .func_index = .none,
4631 .fn_ret_ty = Type.void,4625 .fn_ret_ty = Type.void,
4632 .owner_func = null,4626 .owner_func = null,
4627 .owner_func_index = .none,
4633 };4628 };
4634 defer sema.deinit();4629 defer sema.deinit();
46354630
...@@ -4707,8 +4702,8 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {...@@ -4707,8 +4702,8 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
4707 return true;4702 return true;
4708 }4703 }
47094704
4710 if (decl_tv.val.castTag(.function)) |fn_payload| {4705 if (mod.intern_pool.indexToFunc(decl_tv.val.ip_index).unwrap()) |func_index| {
4711 const func = fn_payload.data;4706 const func = mod.funcPtr(func_index);
4712 const owns_tv = func.owner_decl == decl_index;4707 const owns_tv = func.owner_decl == decl_index;
4713 if (owns_tv) {4708 if (owns_tv) {
4714 var prev_type_has_bits = false;4709 var prev_type_has_bits = false;
...@@ -4718,7 +4713,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {...@@ -4718,7 +4713,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
4718 if (decl.has_tv) {4713 if (decl.has_tv) {
4719 prev_type_has_bits = decl.ty.isFnOrHasRuntimeBits(mod);4714 prev_type_has_bits = decl.ty.isFnOrHasRuntimeBits(mod);
4720 type_changed = !decl.ty.eql(decl_tv.ty, mod);4715 type_changed = !decl.ty.eql(decl_tv.ty, mod);
4721 if (decl.getFunction()) |prev_func| {4716 if (decl.getFunction(mod)) |prev_func| {
4722 prev_is_inline = prev_func.state == .inline_only;4717 prev_is_inline = prev_func.state == .inline_only;
4723 }4718 }
4724 }4719 }
...@@ -4757,38 +4752,25 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {...@@ -4757,38 +4752,25 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
4757 switch (decl_tv.val.ip_index) {4752 switch (decl_tv.val.ip_index) {
4758 .generic_poison => unreachable,4753 .generic_poison => unreachable,
4759 .unreachable_value => unreachable,4754 .unreachable_value => unreachable,
47604755 else => switch (mod.intern_pool.indexToKey(decl_tv.val.ip_index)) {
4761 .none => switch (decl_tv.val.tag()) {4756 .variable => |variable| if (variable.decl == decl_index) {
4762 .variable => {4757 decl.owns_tv = true;
4763 const variable = decl_tv.val.castTag(.variable).?.data;4758 queue_linker_work = true;
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 }
4771 },4759 },
4772 .extern_fn => {4760
4773 const extern_fn = decl_tv.val.castTag(.extern_fn).?.data;4761 .extern_func => |extern_fn| if (extern_fn.decl == decl_index) {
4774 if (extern_fn.owner_decl == decl_index) {4762 decl.owns_tv = true;
4775 decl.owns_tv = true;4763 queue_linker_work = true;
4776 queue_linker_work = true;4764 is_extern = true;
4777 is_extern = true;
4778 }
4779 },4765 },
47804766
4781 .function => {},4767 .func => {},
47824768
4783 else => {4769 else => {
4784 log.debug("send global const to linker: {*} ({s})", .{ decl, decl.name });4770 log.debug("send global const to linker: {*} ({s})", .{ decl, decl.name });
4785 queue_linker_work = true;4771 queue_linker_work = true;
4786 },4772 },
4787 },4773 },
4788 else => {
4789 log.debug("send global const to linker: {*} ({s})", .{ decl, decl.name });
4790 queue_linker_work = true;
4791 },
4792 }4774 }
47934775
4794 decl.ty = decl_tv.ty;4776 decl.ty = decl_tv.ty;
...@@ -4810,12 +4792,9 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {...@@ -4810,12 +4792,9 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
4810 break :blk (try decl_arena_allocator.dupeZ(u8, bytes)).ptr;4792 break :blk (try decl_arena_allocator.dupeZ(u8, bytes)).ptr;
4811 };4793 };
4812 decl.@"addrspace" = blk: {4794 decl.@"addrspace" = blk: {
4813 const addrspace_ctx: Sema.AddressSpaceContext = switch (decl_tv.val.ip_index) {4795 const addrspace_ctx: Sema.AddressSpaceContext = switch (mod.intern_pool.indexToKey(decl_tv.val.ip_index)) {
4814 .none => switch (decl_tv.val.tag()) {4796 .variable => .variable,
4815 .function, .extern_fn => .function,4797 .extern_func, .func => .function,
4816 .variable => .variable,
4817 else => .constant,
4818 },
4819 else => .constant,4798 else => .constant,
4820 };4799 };
48214800
...@@ -5388,7 +5367,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err...@@ -5388,7 +5367,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
5388 decl.has_align = has_align;5367 decl.has_align = has_align;
5389 decl.has_linksection_or_addrspace = has_linksection_or_addrspace;5368 decl.has_linksection_or_addrspace = has_linksection_or_addrspace;
5390 decl.zir_decl_index = @intCast(u32, decl_sub_index);5369 decl.zir_decl_index = @intCast(u32, decl_sub_index);
5391 if (decl.getFunction()) |_| {5370 if (decl.getFunctionIndex(mod) != .none) {
5392 switch (comp.bin_file.tag) {5371 switch (comp.bin_file.tag) {
5393 .coff, .elf, .macho, .plan9 => {5372 .coff, .elf, .macho, .plan9 => {
5394 // TODO Look into detecting when this would be unnecessary by storing enough state5373 // 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...@@ -5572,11 +5551,12 @@ fn deleteDeclExports(mod: *Module, decl_index: Decl.Index) Allocator.Error!void
5572 export_owners.deinit(mod.gpa);5551 export_owners.deinit(mod.gpa);
5573}5552}
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 {
5576 const tracy = trace(@src());5555 const tracy = trace(@src());
5577 defer tracy.end();5556 defer tracy.end();
55785557
5579 const gpa = mod.gpa;5558 const gpa = mod.gpa;
5559 const func = mod.funcPtr(func_index);
5580 const decl_index = func.owner_decl;5560 const decl_index = func.owner_decl;
5581 const decl = mod.declPtr(decl_index);5561 const decl = mod.declPtr(decl_index);
55825562
...@@ -5597,8 +5577,10 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {...@@ -5597,8 +5577,10 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
5597 .owner_decl = decl,5577 .owner_decl = decl,
5598 .owner_decl_index = decl_index,5578 .owner_decl_index = decl_index,
5599 .func = func,5579 .func = func,
5580 .func_index = func_index.toOptional(),
5600 .fn_ret_ty = fn_ty_info.return_type.toType(),5581 .fn_ret_ty = fn_ty_info.return_type.toType(),
5601 .owner_func = func,5582 .owner_func = func,
5583 .owner_func_index = func_index.toOptional(),
5602 .branch_quota = @max(func.branch_quota, Sema.default_branch_quota),5584 .branch_quota = @max(func.branch_quota, Sema.default_branch_quota),
5603 };5585 };
5604 defer sema.deinit();5586 defer sema.deinit();
...@@ -5807,8 +5789,7 @@ fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void {...@@ -5807,8 +5789,7 @@ fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void {
5807 for (kv.value) |err| err.deinit(mod.gpa);5789 for (kv.value) |err| err.deinit(mod.gpa);
5808 }5790 }
5809 if (decl.has_tv and decl.owns_tv) {5791 if (decl.has_tv and decl.owns_tv) {
5810 if (decl.val.castTag(.function)) |payload| {5792 if (decl.getFunctionIndex(mod).unwrap()) |func| {
5811 const func = payload.data;
5812 _ = mod.align_stack_fns.remove(func);5793 _ = mod.align_stack_fns.remove(func);
5813 }5794 }
5814 }5795 }
...@@ -5852,6 +5833,14 @@ pub fn destroyUnion(mod: *Module, index: Union.Index) void {...@@ -5852,6 +5833,14 @@ pub fn destroyUnion(mod: *Module, index: Union.Index) void {
5852 return mod.intern_pool.destroyUnion(mod.gpa, index);5833 return mod.intern_pool.destroyUnion(mod.gpa, index);
5853}5834}
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
5855pub fn allocateNewDecl(5844pub fn allocateNewDecl(
5856 mod: *Module,5845 mod: *Module,
5857 namespace: Namespace.Index,5846 namespace: Namespace.Index,
...@@ -6499,7 +6488,11 @@ pub fn populateTestFunctions(...@@ -6499,7 +6488,11 @@ pub fn populateTestFunctions(
6499 try mod.ensureDeclAnalyzed(decl_index);6488 try mod.ensureDeclAnalyzed(decl_index);
6500 }6489 }
6501 const decl = mod.declPtr(decl_index);6490 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
6504 const array_decl_index = d: {6497 const array_decl_index = d: {
6505 // Add mod.test_functions to an array decl then make the test_functions6498 // Add mod.test_functions to an array decl then make the test_functions
...@@ -6512,7 +6505,7 @@ pub fn populateTestFunctions(...@@ -6512,7 +6505,7 @@ pub fn populateTestFunctions(
6512 const array_decl_index = try mod.createAnonymousDeclFromDecl(decl, decl.src_namespace, null, .{6505 const array_decl_index = try mod.createAnonymousDeclFromDecl(decl, decl.src_namespace, null, .{
6513 .ty = try mod.arrayType(.{6506 .ty = try mod.arrayType(.{
6514 .len = test_fn_vals.len,6507 .len = test_fn_vals.len,
6515 .child = tmp_test_fn_ty.ip_index,6508 .child = test_fn_ty.ip_index,
6516 .sentinel = .none,6509 .sentinel = .none,
6517 }),6510 }),
6518 .val = try Value.Tag.aggregate.create(arena, test_fn_vals),6511 .val = try Value.Tag.aggregate.create(arena, test_fn_vals),
...@@ -6530,7 +6523,7 @@ pub fn populateTestFunctions(...@@ -6530,7 +6523,7 @@ pub fn populateTestFunctions(
6530 errdefer name_decl_arena.deinit();6523 errdefer name_decl_arena.deinit();
6531 const bytes = try name_decl_arena.allocator().dupe(u8, test_name_slice);6524 const bytes = try name_decl_arena.allocator().dupe(u8, test_name_slice);
6532 const test_name_decl_index = try mod.createAnonymousDeclFromDecl(array_decl, array_decl.src_namespace, null, .{6525 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 }),
6534 .val = try Value.Tag.bytes.create(name_decl_arena.allocator(), bytes),6527 .val = try Value.Tag.bytes.create(name_decl_arena.allocator(), bytes),
6535 });6528 });
6536 try mod.declPtr(test_name_decl_index).finalizeNewArena(&name_decl_arena);6529 try mod.declPtr(test_name_decl_index).finalizeNewArena(&name_decl_arena);
...@@ -6540,16 +6533,24 @@ pub fn populateTestFunctions(...@@ -6540,16 +6533,24 @@ pub fn populateTestFunctions(
6540 array_decl.dependencies.putAssumeCapacityNoClobber(test_name_decl_index, .normal);6533 array_decl.dependencies.putAssumeCapacityNoClobber(test_name_decl_index, .normal);
6541 try mod.linkerUpdateDecl(test_name_decl_index);6534 try mod.linkerUpdateDecl(test_name_decl_index);
65426535
6543 const field_vals = try arena.create([3]Value);6536 const test_fn_fields = .{
6544 field_vals.* = .{6537 // name
6545 try Value.Tag.slice.create(arena, .{6538 try mod.intern(.{ .ptr = .{
6546 .ptr = try Value.Tag.decl_ref.create(arena, test_name_decl_index),6539 .ty = .slice_const_u8_type,
6547 .len = try mod.intValue(Type.usize, test_name_slice.len),6540 .addr = .{ .decl = test_name_decl_index },
6548 }), // name6541 } }),
6549 try Value.Tag.decl_ref.create(arena, test_decl_index), // func6542 // func
6550 Value.null, // async_frame_size6543 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,
6551 };6549 };
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();
6553 }6554 }
65546555
6555 try array_decl.finalizeNewArena(&new_decl_arena);6556 try array_decl.finalizeNewArena(&new_decl_arena);
...@@ -6558,36 +6559,25 @@ pub fn populateTestFunctions(...@@ -6558,36 +6559,25 @@ pub fn populateTestFunctions(
6558 try mod.linkerUpdateDecl(array_decl_index);6559 try mod.linkerUpdateDecl(array_decl_index);
65596560
6560 {6561 {
6561 var new_decl_arena = std.heap.ArenaAllocator.init(gpa);6562 const new_ty = try mod.ptrType(.{
6562 errdefer new_decl_arena.deinit();6563 .elem_type = test_fn_ty.ip_index,
6563 const arena = new_decl_arena.allocator();6564 .is_const = true,
65646565 .size = .Slice,
6565 {6566 });
6566 // This copy accesses the old Decl Type/Value so it must be done before `clearValues`.6567 const new_val = decl.val;
6567 const new_ty = try Type.ptr(arena, mod, .{6568 const new_init = try mod.intern(.{ .ptr = .{
6568 .size = .Slice,6569 .ty = new_ty.ip_index,
6569 .pointee_type = tmp_test_fn_ty,6570 .addr = .{ .decl = array_decl_index },
6570 .mutable = false,6571 .len = (try mod.intValue(Type.usize, mod.test_functions.count())).ip_index,
6571 .@"addrspace" = .generic,6572 } });
6572 });6573 mod.intern_pool.mutateVarInit(decl.val.ip_index, new_init);
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 }
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;
6591 }6581 }
6592 try mod.linkerUpdateDecl(decl_index);6582 try mod.linkerUpdateDecl(decl_index);
6593}6583}
...@@ -6660,50 +6650,47 @@ fn reportRetryableFileError(...@@ -6660,50 +6650,47 @@ fn reportRetryableFileError(
6660}6650}
66616651
6662pub fn markReferencedDeclsAlive(mod: *Module, val: Value) void {6652pub fn markReferencedDeclsAlive(mod: *Module, val: Value) void {
6663 if (val.ip_index != .none) return;6653 switch (val.ip_index) {
6664 switch (val.tag()) {6654 .none => switch (val.tag()) {
6665 .decl_ref_mut => return mod.markDeclIndexAlive(val.castTag(.decl_ref_mut).?.data.decl_index),6655 .aggregate => {
6666 .extern_fn => return mod.markDeclIndexAlive(val.castTag(.extern_fn).?.data.owner_decl),6656 for (val.castTag(.aggregate).?.data) |field_val| {
6667 .function => return mod.markDeclIndexAlive(val.castTag(.function).?.data.owner_decl),6657 mod.markReferencedDeclsAlive(field_val);
6668 .variable => return mod.markDeclIndexAlive(val.castTag(.variable).?.data.owner_decl),6658 }
6669 .decl_ref => return mod.markDeclIndexAlive(val.cast(Value.Payload.Decl).?.data),6659 },
66706660 .@"union" => {
6671 .repeated,6661 const data = val.castTag(.@"union").?.data;
6672 .eu_payload,6662 mod.markReferencedDeclsAlive(data.tag);
6673 .opt_payload,6663 mod.markReferencedDeclsAlive(data.val);
6674 .empty_array_sentinel,6664 },
6675 => return mod.markReferencedDeclsAlive(val.cast(Value.Payload.SubValue).?.data),6665 else => {},
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 }
6699 },6666 },
6700 .@"union" => {6667 else => switch (mod.intern_pool.indexToKey(val.ip_index)) {
6701 const data = val.cast(Value.Payload.Union).?.data;6668 .variable => |variable| mod.markDeclIndexAlive(variable.decl),
6702 mod.markReferencedDeclsAlive(data.tag);6669 .extern_func => |extern_func| mod.markDeclIndexAlive(extern_func.decl),
6703 mod.markReferencedDeclsAlive(data.val);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 => {},
6704 },6693 },
6705
6706 else => {},
6707 }6694 }
6708}6695}
67096696
...@@ -7075,6 +7062,12 @@ pub fn intBitsForValue(mod: *Module, val: Value, sign: bool) u16 {...@@ -7075,6 +7062,12 @@ pub fn intBitsForValue(mod: *Module, val: Value, sign: bool) u16 {
70757062
7076 return @intCast(u16, big.bitCountTwosComp());7063 return @intCast(u16, big.bitCountTwosComp());
7077 },7064 },
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 },
7078 }7071 }
7079}7072}
70807073
src/Sema.zig+1338-1544
...@@ -28,10 +28,12 @@ owner_decl_index: Decl.Index,...@@ -28,10 +28,12 @@ owner_decl_index: Decl.Index,
28/// For an inline or comptime function call, this will be the root parent function28/// For an inline or comptime function call, this will be the root parent function
29/// which contains the callsite. Corresponds to `owner_decl`.29/// which contains the callsite. Corresponds to `owner_decl`.
30owner_func: ?*Module.Fn,30owner_func: ?*Module.Fn,
31owner_func_index: Module.Fn.OptionalIndex,
31/// The function this ZIR code is the body of, according to the source code.32/// The function this ZIR code is the body of, according to the source code.
32/// This starts out the same as `owner_func` and then diverges in the case of33/// This starts out the same as `owner_func` and then diverges in the case of
33/// an inline or comptime function call.34/// an inline or comptime function call.
34func: ?*Module.Fn,35func: ?*Module.Fn,
36func_index: Module.Fn.OptionalIndex,
35/// Used to restore the error return trace when returning a non-error from a function.37/// Used to restore the error return trace when returning a non-error from a function.
36error_return_trace_index_on_fn_entry: Air.Inst.Ref = .none,38error_return_trace_index_on_fn_entry: Air.Inst.Ref = .none,
37/// When semantic analysis needs to know the return type of the function whose body39/// 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,...@@ -65,7 +67,7 @@ comptime_args_fn_inst: Zir.Inst.Index = 0,
65/// to use this instead of allocating a fresh one. This avoids an unnecessary67/// to use this instead of allocating a fresh one. This avoids an unnecessary
66/// extra hash table lookup in the `monomorphed_funcs` set.68/// extra hash table lookup in the `monomorphed_funcs` set.
67/// Sema will set this to null when it takes ownership.69/// Sema will set this to null when it takes ownership.
68preallocated_new_func: ?*Module.Fn = null,70preallocated_new_func: Module.Fn.OptionalIndex = .none,
69/// The key is types that must be fully resolved prior to machine code71/// The key is types that must be fully resolved prior to machine code
70/// generation pass. Types are added to this set when resolving them72/// generation pass. Types are added to this set when resolving them
71/// immediately could cause a dependency loop, but they do need to be resolved73/// 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) = .{}...@@ -92,7 +94,7 @@ unresolved_inferred_allocs: std.AutoHashMapUnmanaged(Air.Inst.Index, void) = .{}
92const std = @import("std");94const std = @import("std");
93const math = std.math;95const math = std.math;
94const mem = std.mem;96const mem = std.mem;
95const Allocator = std.mem.Allocator;97const Allocator = mem.Allocator;
96const assert = std.debug.assert;98const assert = std.debug.assert;
97const log = std.log.scoped(.sema);99const log = std.log.scoped(.sema);
98100
...@@ -1777,7 +1779,7 @@ pub fn resolveConstString(...@@ -1777,7 +1779,7 @@ pub fn resolveConstString(
1777 reason: []const u8,1779 reason: []const u8,
1778) ![]u8 {1780) ![]u8 {
1779 const air_inst = try sema.resolveInst(zir_ref);1781 const air_inst = try sema.resolveInst(zir_ref);
1780 const wanted_type = Type.const_slice_u8;1782 const wanted_type = Type.slice_const_u8;
1781 const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src);1783 const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src);
1782 const val = try sema.resolveConstValue(block, src, coerced_inst, reason);1784 const val = try sema.resolveConstValue(block, src, coerced_inst, reason);
1783 return val.toAllocatedBytes(wanted_type, sema.arena, sema.mod);1785 return val.toAllocatedBytes(wanted_type, sema.arena, sema.mod);
...@@ -1866,11 +1868,10 @@ fn resolveConstMaybeUndefVal(...@@ -1866,11 +1868,10 @@ fn resolveConstMaybeUndefVal(
1866 if (try sema.resolveMaybeUndefValAllowVariables(inst)) |val| {1868 if (try sema.resolveMaybeUndefValAllowVariables(inst)) |val| {
1867 switch (val.ip_index) {1869 switch (val.ip_index) {
1868 .generic_poison => return error.GenericPoison,1870 .generic_poison => return error.GenericPoison,
1869 .none => switch (val.tag()) {1871 else => switch (sema.mod.intern_pool.indexToKey(val.ip_index)) {
1870 .variable => return sema.failWithNeededComptime(block, src, reason),1872 .variable => return sema.failWithNeededComptime(block, src, reason),
1871 else => return val,1873 else => return val,
1872 },1874 },
1873 else => return val,
1874 }1875 }
1875 }1876 }
1876 return sema.failWithNeededComptime(block, src, reason);1877 return sema.failWithNeededComptime(block, src, reason);
...@@ -1889,11 +1890,11 @@ fn resolveConstValue(...@@ -1889,11 +1890,11 @@ fn resolveConstValue(
1889 switch (val.ip_index) {1890 switch (val.ip_index) {
1890 .generic_poison => return error.GenericPoison,1891 .generic_poison => return error.GenericPoison,
1891 .undef => return sema.failWithUseOfUndef(block, src),1892 .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),
1893 .variable => return sema.failWithNeededComptime(block, src, reason),1895 .variable => return sema.failWithNeededComptime(block, src, reason),
1894 else => return val,1896 else => return val,
1895 },1897 },
1896 else => return val,
1897 }1898 }
1898 }1899 }
1899 return sema.failWithNeededComptime(block, src, reason);1900 return sema.failWithNeededComptime(block, src, reason);
...@@ -1928,11 +1929,11 @@ fn resolveMaybeUndefVal(...@@ -1928,11 +1929,11 @@ fn resolveMaybeUndefVal(
1928 const val = (try sema.resolveMaybeUndefValAllowVariables(inst)) orelse return null;1929 const val = (try sema.resolveMaybeUndefValAllowVariables(inst)) orelse return null;
1929 switch (val.ip_index) {1930 switch (val.ip_index) {
1930 .generic_poison => return error.GenericPoison,1931 .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)) {
1932 .variable => return null,1934 .variable => return null,
1933 else => return val,1935 else => return val,
1934 },1936 },
1935 else => return val,
1936 }1937 }
1937}1938}
19381939
...@@ -1948,21 +1949,20 @@ fn resolveMaybeUndefValIntable(...@@ -1948,21 +1949,20 @@ fn resolveMaybeUndefValIntable(
1948 var check = val;1949 var check = val;
1949 while (true) switch (check.ip_index) {1950 while (true) switch (check.ip_index) {
1950 .generic_poison => return error.GenericPoison,1951 .generic_poison => return error.GenericPoison,
1951 .none => switch (check.tag()) {1952 .none => break,
1952 .variable, .decl_ref, .decl_ref_mut, .comptime_field_ptr => return null,1953 else => switch (sema.mod.intern_pool.indexToKey(check.ip_index)) {
1953 .field_ptr => check = check.castTag(.field_ptr).?.data.container_ptr,1954 .variable => return null,
1954 .elem_ptr => check = check.castTag(.elem_ptr).?.data.array_ptr,1955 .ptr => |ptr| switch (ptr.addr) {
1955 .eu_payload_ptr, .opt_payload_ptr => check = check.cast(Value.Payload.PayloadPtr).?.data.container_ptr,1956 .decl, .mut_decl, .comptime_field => return null,
1956 else => {1957 .int => break,
1957 try sema.resolveLazyValue(val);1958 .eu_payload, .opt_payload => |base| check = base.toValue(),
1958 return val;1959 .elem, .field => |base_index| check = base_index.base.toValue(),
1959 },1960 },
1960 },1961 else => break,
1961 else => {
1962 try sema.resolveLazyValue(val);
1963 return val;
1964 },1962 },
1965 };1963 };
1964 try sema.resolveLazyValue(val);
1965 return val;
1966}1966}
19671967
1968/// Returns all Value tags including `variable` and `undef`.1968/// Returns all Value tags including `variable` and `undef`.
...@@ -1994,7 +1994,7 @@ fn resolveMaybeUndefValAllowVariablesMaybeRuntime(...@@ -1994,7 +1994,7 @@ fn resolveMaybeUndefValAllowVariablesMaybeRuntime(
1994 if (air_tags[i] == .constant) {1994 if (air_tags[i] == .constant) {
1995 const ty_pl = sema.air_instructions.items(.data)[i].ty_pl;1995 const ty_pl = sema.air_instructions.items(.data)[i].ty_pl;
1996 const val = sema.air_values.items[ty_pl.payload];1996 const val = sema.air_values.items[ty_pl.payload];
1997 if (val.tagIsVariable()) return val;1997 if (val.getVariable(sema.mod) != null) return val;
1998 }1998 }
1999 return opv;1999 return opv;
2000 }2000 }
...@@ -2003,7 +2003,7 @@ fn resolveMaybeUndefValAllowVariablesMaybeRuntime(...@@ -2003,7 +2003,7 @@ fn resolveMaybeUndefValAllowVariablesMaybeRuntime(
2003 .constant => {2003 .constant => {
2004 const ty_pl = air_datas[i].ty_pl;2004 const ty_pl = air_datas[i].ty_pl;
2005 const val = sema.air_values.items[ty_pl.payload];2005 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;
2007 if (val.isPtrToThreadLocal(sema.mod)) make_runtime.* = true;2007 if (val.isPtrToThreadLocal(sema.mod)) make_runtime.* = true;
2008 return val;2008 return val;
2009 },2009 },
...@@ -2489,13 +2489,13 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -2489,13 +2489,13 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
2489 .@"addrspace" = addr_space,2489 .@"addrspace" = addr_space,
2490 });2490 });
2491 try sema.maybeQueueFuncBodyAnalysis(iac.data.decl_index);2491 try sema.maybeQueueFuncBodyAnalysis(iac.data.decl_index);
2492 return sema.addConstant(2492 return sema.addConstant(ptr_ty, (try sema.mod.intern(.{ .ptr = .{
2493 ptr_ty,2493 .ty = ptr_ty.ip_index,
2494 try Value.Tag.decl_ref_mut.create(sema.arena, .{2494 .addr = .{ .mut_decl = .{
2495 .decl_index = iac.data.decl_index,2495 .decl = iac.data.decl_index,
2496 .runtime_index = block.runtime_index,2496 .runtime_index = block.runtime_index,
2497 }),2497 } },
2498 );2498 } })).toValue());
2499 },2499 },
2500 else => {},2500 else => {},
2501 }2501 }
...@@ -2949,12 +2949,18 @@ fn zirEnumDecl(...@@ -2949,12 +2949,18 @@ fn zirEnumDecl(
2949 }2949 }
29502950
2951 const prev_owner_func = sema.owner_func;2951 const prev_owner_func = sema.owner_func;
2952 const prev_owner_func_index = sema.owner_func_index;
2952 sema.owner_func = null;2953 sema.owner_func = null;
2954 sema.owner_func_index = .none;
2953 defer sema.owner_func = prev_owner_func;2955 defer sema.owner_func = prev_owner_func;
2956 defer sema.owner_func_index = prev_owner_func_index;
29542957
2955 const prev_func = sema.func;2958 const prev_func = sema.func;
2959 const prev_func_index = sema.func_index;
2956 sema.func = null;2960 sema.func = null;
2961 sema.func_index = .none;
2957 defer sema.func = prev_func;2962 defer sema.func = prev_func;
2963 defer sema.func_index = prev_func_index;
29582964
2959 var wip_captures = try WipCaptureScope.init(gpa, sema.perm_arena, new_decl.src_scope);2965 var wip_captures = try WipCaptureScope.init(gpa, sema.perm_arena, new_decl.src_scope);
2960 defer wip_captures.deinit();2966 defer wip_captures.deinit();
...@@ -3735,14 +3741,13 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -3735,14 +3741,13 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
3735 sema.air_instructions.items(.data)[ptr_inst].ty_pl.ty = final_ptr_ty_inst;3741 sema.air_instructions.items(.data)[ptr_inst].ty_pl.ty = final_ptr_ty_inst;
37363742
3737 try sema.maybeQueueFuncBodyAnalysis(decl_index);3743 try sema.maybeQueueFuncBodyAnalysis(decl_index);
3738 if (var_is_mut) {3744 sema.air_values.items[value_index] = (try sema.mod.intern(.{ .ptr = .{
3739 sema.air_values.items[value_index] = try Value.Tag.decl_ref_mut.create(sema.arena, .{3745 .ty = final_ptr_ty.ip_index,
3740 .decl_index = decl_index,3746 .addr = if (var_is_mut) .{ .mut_decl = .{
3747 .decl = decl_index,
3741 .runtime_index = block.runtime_index,3748 .runtime_index = block.runtime_index,
3742 });3749 } } else .{ .decl = decl_index },
3743 } else {3750 } })).toValue();
3744 sema.air_values.items[value_index] = try Value.Tag.decl_ref.create(sema.arena, decl_index);
3745 }
3746 },3751 },
3747 .inferred_alloc => {3752 .inferred_alloc => {
3748 assert(sema.unresolved_inferred_allocs.remove(ptr_inst));3753 assert(sema.unresolved_inferred_allocs.remove(ptr_inst));
...@@ -3836,7 +3841,10 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -3836,7 +3841,10 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
3836 // block so that codegen does not see it.3841 // block so that codegen does not see it.
3837 block.instructions.shrinkRetainingCapacity(search_index);3842 block.instructions.shrinkRetainingCapacity(search_index);
3838 try sema.maybeQueueFuncBodyAnalysis(new_decl_index);3843 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();
3840 // if bitcast ty ref needs to be made const, make_ptr_const3848 // if bitcast ty ref needs to be made const, make_ptr_const
3841 // ZIR handles it later, so we can just use the ty ref here.3849 // ZIR handles it later, so we can just use the ty ref here.
3842 air_datas[ptr_inst].ty_pl.ty = air_datas[bitcast_inst].ty_op.ty;3850 air_datas[ptr_inst].ty_pl.ty = air_datas[bitcast_inst].ty_op.ty;
...@@ -4332,12 +4340,16 @@ fn validateUnionInit(...@@ -4332,12 +4340,16 @@ fn validateUnionInit(
4332 // instead a single `store` to the result ptr with a comptime union value.4340 // instead a single `store` to the result ptr with a comptime union value.
4333 block.instructions.shrinkRetainingCapacity(first_block_index);4341 block.instructions.shrinkRetainingCapacity(first_block_index);
43344342
4335 var union_val = try Value.Tag.@"union".create(sema.arena, .{4343 var union_val = try mod.intern(.{ .un = .{
4336 .tag = tag_val,4344 .ty = union_ty.ip_index,
4337 .val = val,4345 .tag = tag_val.ip_index,
4338 });4346 .val = val.ip_index,
4339 if (make_runtime) union_val = try Value.Tag.runtime_value.create(sema.arena, union_val);4347 } });
4340 const union_init = try sema.addConstant(union_ty, union_val);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());
4341 try sema.storePtr2(block, init_src, union_ptr, init_src, union_init, init_src, .store);4353 try sema.storePtr2(block, init_src, union_ptr, init_src, union_init, init_src, .store);
4342 return;4354 return;
4343 } else if (try sema.typeRequiresComptime(union_ty)) {4355 } else if (try sema.typeRequiresComptime(union_ty)) {
...@@ -4464,14 +4476,15 @@ fn validateStructInit(...@@ -4464,14 +4476,15 @@ fn validateStructInit(
44644476
4465 // We collect the comptime field values in case the struct initialization4477 // We collect the comptime field values in case the struct initialization
4466 // ends up being comptime-known.4478 // 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
4469 field: for (found_fields, 0..) |field_ptr, i| {4482 field: for (found_fields, 0..) |field_ptr, i| {
4470 if (field_ptr != 0) {4483 if (field_ptr != 0) {
4471 // Determine whether the value stored to this pointer is comptime-known.4484 // Determine whether the value stored to this pointer is comptime-known.
4472 const field_ty = struct_ty.structFieldType(i, mod);4485 const field_ty = struct_ty.structFieldType(i, mod);
4473 if (try sema.typeHasOnePossibleValue(field_ty)) |opv| {4486 if (try sema.typeHasOnePossibleValue(field_ty)) |opv| {
4474 field_values[i] = opv;4487 field_values[i] = opv.ip_index;
4475 continue;4488 continue;
4476 }4489 }
44774490
...@@ -4536,7 +4549,7 @@ fn validateStructInit(...@@ -4536,7 +4549,7 @@ fn validateStructInit(
4536 first_block_index = @min(first_block_index, block_index);4549 first_block_index = @min(first_block_index, block_index);
4537 }4550 }
4538 if (try sema.resolveMaybeUndefValAllowVariablesMaybeRuntime(bin_op.rhs, &make_runtime)) |val| {4551 if (try sema.resolveMaybeUndefValAllowVariablesMaybeRuntime(bin_op.rhs, &make_runtime)) |val| {
4539 field_values[i] = val;4552 field_values[i] = val.ip_index;
4540 } else if (require_comptime) {4553 } else if (require_comptime) {
4541 const field_ptr_data = sema.code.instructions.items(.data)[field_ptr].pl_node;4554 const field_ptr_data = sema.code.instructions.items(.data)[field_ptr].pl_node;
4542 return sema.failWithNeededComptime(block, field_ptr_data.src(), "initializer of comptime only struct must be comptime-known");4555 return sema.failWithNeededComptime(block, field_ptr_data.src(), "initializer of comptime only struct must be comptime-known");
...@@ -4570,7 +4583,7 @@ fn validateStructInit(...@@ -4570,7 +4583,7 @@ fn validateStructInit(
4570 }4583 }
4571 continue;4584 continue;
4572 }4585 }
4573 field_values[i] = default_val;4586 field_values[i] = default_val.ip_index;
4574 }4587 }
45754588
4576 if (root_msg) |msg| {4589 if (root_msg) |msg| {
...@@ -4593,9 +4606,15 @@ fn validateStructInit(...@@ -4593,9 +4606,15 @@ fn validateStructInit(
4593 // instead a single `store` to the struct_ptr with a comptime struct value.4606 // instead a single `store` to the struct_ptr with a comptime struct value.
45944607
4595 block.instructions.shrinkRetainingCapacity(first_block_index);4608 block.instructions.shrinkRetainingCapacity(first_block_index);
4596 var struct_val = try Value.Tag.aggregate.create(sema.arena, field_values);4609 var struct_val = try mod.intern(.{ .aggregate = .{
4597 if (make_runtime) struct_val = try Value.Tag.runtime_value.create(sema.arena, struct_val);4610 .ty = struct_ty.ip_index,
4598 const struct_init = try sema.addConstant(struct_ty, struct_val);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());
4599 try sema.storePtr2(block, init_src, struct_ptr, init_src, struct_init, init_src, .store);4618 try sema.storePtr2(block, init_src, struct_ptr, init_src, struct_init, init_src, .store);
4600 return;4619 return;
4601 }4620 }
...@@ -4611,7 +4630,7 @@ fn validateStructInit(...@@ -4611,7 +4630,7 @@ fn validateStructInit(
4611 else4630 else
4612 try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty, true);4631 try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty, true);
4613 const field_ty = sema.typeOf(default_field_ptr).childType(mod);4632 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());
4615 try sema.storePtr2(block, init_src, default_field_ptr, init_src, init, field_src, .store);4634 try sema.storePtr2(block, init_src, default_field_ptr, init_src, init, field_src, .store);
4616 }4635 }
4617}4636}
...@@ -4691,7 +4710,8 @@ fn zirValidateArrayInit(...@@ -4691,7 +4710,8 @@ fn zirValidateArrayInit(
4691 // Collect the comptime element values in case the array literal ends up4710 // Collect the comptime element values in case the array literal ends up
4692 // being comptime-known.4711 // being comptime-known.
4693 const array_len_s = try sema.usizeCast(block, init_src, array_ty.arrayLenIncludingSentinel(mod));4712 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);
4695 const opt_opv = try sema.typeHasOnePossibleValue(array_ty);4715 const opt_opv = try sema.typeHasOnePossibleValue(array_ty);
4696 const air_tags = sema.air_instructions.items(.tag);4716 const air_tags = sema.air_instructions.items(.tag);
4697 const air_datas = sema.air_instructions.items(.data);4717 const air_datas = sema.air_instructions.items(.data);
...@@ -4701,13 +4721,13 @@ fn zirValidateArrayInit(...@@ -4701,13 +4721,13 @@ fn zirValidateArrayInit(
47014721
4702 if (array_ty.isTuple(mod)) {4722 if (array_ty.isTuple(mod)) {
4703 if (try array_ty.structFieldValueComptime(mod, i)) |opv| {4723 if (try array_ty.structFieldValueComptime(mod, i)) |opv| {
4704 element_vals[i] = opv;4724 element_vals[i] = opv.ip_index;
4705 continue;4725 continue;
4706 }4726 }
4707 } else {4727 } else {
4708 // Array has one possible value, so value is always comptime-known4728 // Array has one possible value, so value is always comptime-known
4709 if (opt_opv) |opv| {4729 if (opt_opv) |opv| {
4710 element_vals[i] = opv;4730 element_vals[i] = opv.ip_index;
4711 continue;4731 continue;
4712 }4732 }
4713 }4733 }
...@@ -4768,7 +4788,7 @@ fn zirValidateArrayInit(...@@ -4768,7 +4788,7 @@ fn zirValidateArrayInit(
4768 first_block_index = @min(first_block_index, block_index);4788 first_block_index = @min(first_block_index, block_index);
4769 }4789 }
4770 if (try sema.resolveMaybeUndefValAllowVariablesMaybeRuntime(bin_op.rhs, &make_runtime)) |val| {4790 if (try sema.resolveMaybeUndefValAllowVariablesMaybeRuntime(bin_op.rhs, &make_runtime)) |val| {
4771 element_vals[i] = val;4791 element_vals[i] = val.ip_index;
4772 } else {4792 } else {
4773 array_is_comptime = false;4793 array_is_comptime = false;
4774 }4794 }
...@@ -4780,9 +4800,12 @@ fn zirValidateArrayInit(...@@ -4780,9 +4800,12 @@ fn zirValidateArrayInit(
47804800
4781 if (array_is_comptime) {4801 if (array_is_comptime) {
4782 if (try sema.resolveDefinedValue(block, init_src, array_ptr)) |ptr_val| {4802 if (try sema.resolveDefinedValue(block, init_src, array_ptr)) |ptr_val| {
4783 if (ptr_val.tag() == .comptime_field_ptr) {4803 switch (mod.intern_pool.indexToKey(ptr_val.ip_index)) {
4784 // This store was validated by the individual elem ptrs.4804 .ptr => |ptr| switch (ptr.addr) {
4785 return;4805 .comptime_field => return, // This store was validated by the individual elem ptrs.
4806 else => {},
4807 },
4808 else => {},
4786 }4809 }
4787 }4810 }
47884811
...@@ -4790,14 +4813,20 @@ fn zirValidateArrayInit(...@@ -4790,14 +4813,20 @@ fn zirValidateArrayInit(
4790 // instead a single `store` to the array_ptr with a comptime struct value.4813 // instead a single `store` to the array_ptr with a comptime struct value.
4791 // Also to populate the sentinel value, if any.4814 // Also to populate the sentinel value, if any.
4792 if (array_ty.sentinel(mod)) |sentinel_val| {4815 if (array_ty.sentinel(mod)) |sentinel_val| {
4793 element_vals[instrs.len] = sentinel_val;4816 element_vals[instrs.len] = sentinel_val.ip_index;
4794 }4817 }
47954818
4796 block.instructions.shrinkRetainingCapacity(first_block_index);4819 block.instructions.shrinkRetainingCapacity(first_block_index);
47974820
4798 var array_val = try Value.Tag.aggregate.create(sema.arena, element_vals);4821 var array_val = try mod.intern(.{ .aggregate = .{
4799 if (make_runtime) array_val = try Value.Tag.runtime_value.create(sema.arena, array_val);4822 .ty = array_ty.ip_index,
4800 const array_init = try sema.addConstant(array_ty, array_val);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());
4801 try sema.storePtr2(block, init_src, array_ptr, init_src, array_init, init_src, .store);4830 try sema.storePtr2(block, init_src, array_ptr, init_src, array_init, init_src, .store);
4802 }4831 }
4803}4832}
...@@ -5029,7 +5058,7 @@ fn storeToInferredAllocComptime(...@@ -5029,7 +5058,7 @@ fn storeToInferredAllocComptime(
5029 // There will be only one store_to_inferred_ptr because we are running at comptime.5058 // There will be only one store_to_inferred_ptr because we are running at comptime.
5030 // The alloc will turn into a Decl.5059 // The alloc will turn into a Decl.
5031 if (try sema.resolveMaybeUndefValAllowVariables(operand)) |operand_val| store: {5060 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;
5033 var anon_decl = try block.startAnonDecl();5062 var anon_decl = try block.startAnonDecl();
5034 defer anon_decl.deinit();5063 defer anon_decl.deinit();
5035 iac.data.decl_index = try anon_decl.finish(5064 iac.data.decl_index = try anon_decl.finish(
...@@ -5717,8 +5746,8 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void...@@ -5717,8 +5746,8 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
5717 {5746 {
5718 try mod.ensureDeclAnalyzed(decl_index);5747 try mod.ensureDeclAnalyzed(decl_index);
5719 const exported_decl = mod.declPtr(decl_index);5748 const exported_decl = mod.declPtr(decl_index);
5720 if (exported_decl.val.castTag(.function)) |some| {5749 if (exported_decl.getFunction(mod)) |function| {
5721 return sema.analyzeExport(block, src, options, some.data.owner_decl);5750 return sema.analyzeExport(block, src, options, function.owner_decl);
5722 }5751 }
5723 }5752 }
5724 try sema.analyzeExport(block, src, options, decl_index);5753 try sema.analyzeExport(block, src, options, decl_index);
...@@ -5741,17 +5770,14 @@ fn zirExportValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -5741,17 +5770,14 @@ fn zirExportValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
5741 },5770 },
5742 else => |e| return e,5771 else => |e| return e,
5743 };5772 };
5744 const decl_index = switch (operand.val.tag()) {5773 const decl_index = if (operand.val.getFunction(sema.mod)) |function| function.owner_decl else blk: {
5745 .function => operand.val.castTag(.function).?.data.owner_decl,5774 var anon_decl = try block.startAnonDecl();
5746 else => blk: {5775 defer anon_decl.deinit();
5747 var anon_decl = try block.startAnonDecl();5776 break :blk try anon_decl.finish(
5748 defer anon_decl.deinit();5777 operand.ty,
5749 break :blk try anon_decl.finish(5778 try operand.val.copy(anon_decl.arena()),
5750 operand.ty,5779 0,
5751 try operand.val.copy(anon_decl.arena()),5780 );
5752 0,
5753 );
5754 },
5755 };5781 };
5756 try sema.analyzeExport(block, src, options, decl_index);5782 try sema.analyzeExport(block, src, options, decl_index);
5757}5783}
...@@ -5788,7 +5814,7 @@ pub fn analyzeExport(...@@ -5788,7 +5814,7 @@ pub fn analyzeExport(
5788 }5814 }
57895815
5790 // TODO: some backends might support re-exporting extern decls5816 // TODO: some backends might support re-exporting extern decls
5791 if (exported_decl.isExtern()) {5817 if (exported_decl.isExtern(mod)) {
5792 return sema.fail(block, src, "export target cannot be extern", .{});5818 return sema.fail(block, src, "export target cannot be extern", .{});
5793 }5819 }
57945820
...@@ -5796,7 +5822,7 @@ pub fn analyzeExport(...@@ -5796,7 +5822,7 @@ pub fn analyzeExport(
5796 mod.markDeclAlive(exported_decl);5822 mod.markDeclAlive(exported_decl);
5797 try sema.maybeQueueFuncBodyAnalysis(exported_decl_index);5823 try sema.maybeQueueFuncBodyAnalysis(exported_decl_index);
57985824
5799 const gpa = mod.gpa;5825 const gpa = sema.gpa;
58005826
5801 try mod.decl_exports.ensureUnusedCapacity(gpa, 1);5827 try mod.decl_exports.ensureUnusedCapacity(gpa, 1);
5802 try mod.export_owners.ensureUnusedCapacity(gpa, 1);5828 try mod.export_owners.ensureUnusedCapacity(gpa, 1);
...@@ -5852,8 +5878,9 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst...@@ -5852,8 +5878,9 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst
5852 alignment,5878 alignment,
5853 });5879 });
5854 }5880 }
5855 const func = sema.func orelse5881 const func_index = sema.func_index.unwrap() orelse
5856 return sema.fail(block, src, "@setAlignStack outside function body", .{});5882 return sema.fail(block, src, "@setAlignStack outside function body", .{});
5883 const func = mod.funcPtr(func_index);
58575884
5858 const fn_owner_decl = mod.declPtr(func.owner_decl);5885 const fn_owner_decl = mod.declPtr(func.owner_decl);
5859 switch (fn_owner_decl.ty.fnCallingConvention(mod)) {5886 switch (fn_owner_decl.ty.fnCallingConvention(mod)) {
...@@ -5864,7 +5891,7 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst...@@ -5864,7 +5891,7 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst
5864 },5891 },
5865 }5892 }
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);
5868 if (gop.found_existing) {5895 if (gop.found_existing) {
5869 const msg = msg: {5896 const msg = msg: {
5870 const msg = try sema.errMsg(block, src, "multiple @setAlignStack in the same function body", .{});5897 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 {...@@ -6191,10 +6218,13 @@ fn funcDeclSrc(sema: *Sema, func_inst: Air.Inst.Ref) !?*Decl {
6191 const mod = sema.mod;6218 const mod = sema.mod;
6192 const func_val = (try sema.resolveMaybeUndefVal(func_inst)) orelse return null;6219 const func_val = (try sema.resolveMaybeUndefVal(func_inst)) orelse return null;
6193 if (func_val.isUndef(mod)) return null;6220 if (func_val.isUndef(mod)) return null;
6194 const owner_decl_index = switch (func_val.tag()) {6221 const owner_decl_index = switch (mod.intern_pool.indexToKey(func_val.ip_index)) {
6195 .extern_fn => func_val.castTag(.extern_fn).?.data.owner_decl,6222 .extern_func => |extern_func| extern_func.decl,
6196 .function => func_val.castTag(.function).?.data.owner_decl,6223 .func => |func| mod.funcPtr(func.index).owner_decl,
6197 .decl_ref => mod.declPtr(func_val.castTag(.decl_ref).?.data).val.castTag(.function).?.data.owner_decl,6224 .ptr => |ptr| switch (ptr.addr) {
6225 .decl => |decl| decl,
6226 else => return null,
6227 },
6198 else => return null,6228 else => return null,
6199 };6229 };
6200 return mod.declPtr(owner_decl_index);6230 return mod.declPtr(owner_decl_index);
...@@ -6576,20 +6606,22 @@ const GenericCallAdapter = struct {...@@ -6576,20 +6606,22 @@ const GenericCallAdapter = struct {
6576 is_anytype: bool,6606 is_anytype: bool,
6577 };6607 };
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 {
6580 _ = adapted_key;6610 _ = adapted_key;
6611 const other_func = ctx.module.funcPtr(other_key);
6612
6581 // Checking for equality may happen on an item that has been inserted6613 // Checking for equality may happen on an item that has been inserted
6582 // into the map but is not yet fully initialized. In such case, the6614 // into the map but is not yet fully initialized. In such case, the
6583 // two initialized fields are `hash` and `generic_owner_decl`.6615 // 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.?;
6587 for (other_comptime_args[0..ctx.func_ty_info.param_types.len], 0..) |other_arg, i| {6619 for (other_comptime_args[0..ctx.func_ty_info.param_types.len], 0..) |other_arg, i| {
6588 const this_arg = ctx.args[i];6620 const this_arg = ctx.args[i];
6589 const this_is_comptime = !this_arg.val.isGenericPoison();6621 const this_is_comptime = !this_arg.val.isGenericPoison();
6590 const other_is_comptime = !other_arg.val.isGenericPoison();6622 const other_is_comptime = !other_arg.val.isGenericPoison();
6591 const this_is_anytype = this_arg.is_anytype;6623 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
6594 if (other_is_anytype != this_is_anytype) return false;6626 if (other_is_anytype != this_is_anytype) return false;
6595 if (other_is_comptime != this_is_comptime) return false;6627 if (other_is_comptime != this_is_comptime) return false;
...@@ -6663,7 +6695,7 @@ fn analyzeCall(...@@ -6663,7 +6695,7 @@ fn analyzeCall(
6663 );6695 );
6664 errdefer msg.destroy(sema.gpa);6696 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", .{});
6667 break :msg msg;6699 break :msg msg;
6668 };6700 };
6669 return sema.failWithOwnedErrorMsg(msg);6701 return sema.failWithOwnedErrorMsg(msg);
...@@ -6760,18 +6792,21 @@ fn analyzeCall(...@@ -6760,18 +6792,21 @@ fn analyzeCall(
6760 if (err == error.AnalysisFail and comptime_reason != null) try comptime_reason.?.explain(sema, sema.err);6792 if (err == error.AnalysisFail and comptime_reason != null) try comptime_reason.?.explain(sema, sema.err);
6761 return err;6793 return err;
6762 };6794 };
6763 const module_fn = switch (func_val.tag()) {6795 const module_fn_index = switch (mod.intern_pool.indexToKey(func_val.ip_index)) {
6764 .decl_ref => mod.declPtr(func_val.castTag(.decl_ref).?.data).val.castTag(.function).?.data,6796 .extern_func => return sema.fail(block, call_src, "{s} call of extern function", .{
6765 .function => func_val.castTag(.function).?.data,
6766 .extern_fn => return sema.fail(block, call_src, "{s} call of extern function", .{
6767 @as([]const u8, if (is_comptime_call) "comptime" else "inline"),6797 @as([]const u8, if (is_comptime_call) "comptime" else "inline"),
6768 }),6798 }),
6769 else => {6799 .func => |function| function.index,
6770 assert(callee_ty.isPtrAtRuntime(mod));6800 .ptr => |ptr| switch (ptr.addr) {
6771 return sema.fail(block, call_src, "{s} call of function pointer", .{6801 .decl => |decl| mod.declPtr(decl).getFunctionIndex(mod).unwrap().?,
6772 @as([]const u8, if (is_comptime_call) "comptime" else "inline"),6802 else => {
6773 });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 },
6774 },6808 },
6809 else => unreachable,
6775 };6810 };
6776 if (func_ty_info.is_var_args) {6811 if (func_ty_info.is_var_args) {
6777 return sema.fail(block, call_src, "{s} call of variadic function", .{6812 return sema.fail(block, call_src, "{s} call of variadic function", .{
...@@ -6804,6 +6839,7 @@ fn analyzeCall(...@@ -6804,6 +6839,7 @@ fn analyzeCall(
6804 // In order to save a bit of stack space, directly modify Sema rather6839 // In order to save a bit of stack space, directly modify Sema rather
6805 // than create a child one.6840 // than create a child one.
6806 const parent_zir = sema.code;6841 const parent_zir = sema.code;
6842 const module_fn = mod.funcPtr(module_fn_index);
6807 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);6843 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
6808 sema.code = fn_owner_decl.getFileScope(mod).zir;6844 sema.code = fn_owner_decl.getFileScope(mod).zir;
6809 defer sema.code = parent_zir;6845 defer sema.code = parent_zir;
...@@ -6819,8 +6855,11 @@ fn analyzeCall(...@@ -6819,8 +6855,11 @@ fn analyzeCall(
6819 }6855 }
68206856
6821 const parent_func = sema.func;6857 const parent_func = sema.func;
6858 const parent_func_index = sema.func_index;
6822 sema.func = module_fn;6859 sema.func = module_fn;
6860 sema.func_index = module_fn_index.toOptional();
6823 defer sema.func = parent_func;6861 defer sema.func = parent_func;
6862 defer sema.func_index = parent_func_index;
68246863
6825 const parent_err_ret_index = sema.error_return_trace_index_on_fn_entry;6864 const parent_err_ret_index = sema.error_return_trace_index_on_fn_entry;
6826 sema.error_return_trace_index_on_fn_entry = block.error_return_trace_index;6865 sema.error_return_trace_index_on_fn_entry = block.error_return_trace_index;
...@@ -6856,7 +6895,7 @@ fn analyzeCall(...@@ -6856,7 +6895,7 @@ fn analyzeCall(
6856 defer if (delete_memoized_call_key) gpa.free(memoized_call_key.args);6895 defer if (delete_memoized_call_key) gpa.free(memoized_call_key.args);
6857 if (is_comptime_call) {6896 if (is_comptime_call) {
6858 memoized_call_key = .{6897 memoized_call_key = .{
6859 .func = module_fn,6898 .func = module_fn_index,
6860 .args = try gpa.alloc(TypedValue, func_ty_info.param_types.len),6899 .args = try gpa.alloc(TypedValue, func_ty_info.param_types.len),
6861 };6900 };
6862 delete_memoized_call_key = true;6901 delete_memoized_call_key = true;
...@@ -6889,7 +6928,7 @@ fn analyzeCall(...@@ -6889,7 +6928,7 @@ fn analyzeCall(
6889 &child_block,6928 &child_block,
6890 .unneeded,6929 .unneeded,
6891 inst,6930 inst,
6892 new_fn_info,6931 &new_fn_info,
6893 &arg_i,6932 &arg_i,
6894 uncasted_args,6933 uncasted_args,
6895 is_comptime_call,6934 is_comptime_call,
...@@ -6907,7 +6946,7 @@ fn analyzeCall(...@@ -6907,7 +6946,7 @@ fn analyzeCall(
6907 &child_block,6946 &child_block,
6908 mod.argSrc(call_src.node_offset.x, decl, arg_i, bound_arg_src),6947 mod.argSrc(call_src.node_offset.x, decl, arg_i, bound_arg_src),
6909 inst,6948 inst,
6910 new_fn_info,6949 &new_fn_info,
6911 &arg_i,6950 &arg_i,
6912 uncasted_args,6951 uncasted_args,
6913 is_comptime_call,6952 is_comptime_call,
...@@ -6950,7 +6989,7 @@ fn analyzeCall(...@@ -6950,7 +6989,7 @@ fn analyzeCall(
6950 const fn_ret_ty = blk: {6989 const fn_ret_ty = blk: {
6951 if (module_fn.hasInferredErrorSet(mod)) {6990 if (module_fn.hasInferredErrorSet(mod)) {
6952 const ies_index = try mod.intern_pool.createInferredErrorSet(gpa, .{6991 const ies_index = try mod.intern_pool.createInferredErrorSet(gpa, .{
6953 .func = module_fn,6992 .func = module_fn_index,
6954 });6993 });
6955 const error_set_ty = try mod.intern(.{ .inferred_error_set_type = ies_index });6994 const error_set_ty = try mod.intern(.{ .inferred_error_set_type = ies_index });
6956 break :blk try mod.errorUnionType(error_set_ty.toType(), bare_return_type);6995 break :blk try mod.errorUnionType(error_set_ty.toType(), bare_return_type);
...@@ -6982,7 +7021,7 @@ fn analyzeCall(...@@ -6982,7 +7021,7 @@ fn analyzeCall(
69827021
6983 const new_func_resolved_ty = try mod.funcType(new_fn_info);7022 const new_func_resolved_ty = try mod.funcType(new_fn_info);
6984 if (!is_comptime_call and !block.is_typeof) {7023 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
6987 const zir_tags = sema.code.instructions.items(.tag);7026 const zir_tags = sema.code.instructions.items(.tag);
6988 for (fn_info.param_body) |param| switch (zir_tags[param]) {7027 for (fn_info.param_body) |param| switch (zir_tags[param]) {
...@@ -7014,7 +7053,7 @@ fn analyzeCall(...@@ -7014,7 +7053,7 @@ fn analyzeCall(
7014 error.ComptimeReturn => break :result inlining.comptime_result,7053 error.ComptimeReturn => break :result inlining.comptime_result,
7015 error.AnalysisFail => {7054 error.AnalysisFail => {
7016 const err_msg = sema.err orelse return err;7055 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;
7018 try sema.errNote(block, call_src, err_msg, "called from here", .{});7057 try sema.errNote(block, call_src, err_msg, "called from here", .{});
7019 err_msg.clearTrace(sema.gpa);7058 err_msg.clearTrace(sema.gpa);
7020 return err;7059 return err;
...@@ -7027,8 +7066,8 @@ fn analyzeCall(...@@ -7027,8 +7066,8 @@ fn analyzeCall(
7027 if (!is_comptime_call and !block.is_typeof and sema.typeOf(result).zigTypeTag(mod) != .NoReturn) {7066 if (!is_comptime_call and !block.is_typeof and sema.typeOf(result).zigTypeTag(mod) != .NoReturn) {
7028 try sema.emitDbgInline(7067 try sema.emitDbgInline(
7029 block,7068 block,
7030 module_fn,7069 module_fn_index,
7031 parent_func.?,7070 parent_func_index.unwrap().?,
7032 mod.declPtr(parent_func.?.owner_decl).ty,7071 mod.declPtr(parent_func.?.owner_decl).ty,
7033 .dbg_inline_end,7072 .dbg_inline_end,
7034 );7073 );
...@@ -7120,8 +7159,8 @@ fn analyzeCall(...@@ -7120,8 +7159,8 @@ fn analyzeCall(
7120 }7159 }
71217160
7122 if (try sema.resolveMaybeUndefVal(func)) |func_val| {7161 if (try sema.resolveMaybeUndefVal(func)) |func_val| {
7123 if (func_val.castTag(.function)) |func_obj| {7162 if (mod.intern_pool.indexToFunc(func_val.toIntern()).unwrap()) |func_index| {
7124 try sema.mod.ensureFuncBodyAnalysisQueued(func_obj.data);7163 try sema.mod.ensureFuncBodyAnalysisQueued(func_index);
7125 }7164 }
7126 }7165 }
71277166
...@@ -7147,9 +7186,9 @@ fn analyzeCall(...@@ -7147,9 +7186,9 @@ fn analyzeCall(
7147 // Function pointers and extern functions aren't guaranteed to7186 // Function pointers and extern functions aren't guaranteed to
7148 // actually be noreturn so we add a safety check for them.7187 // actually be noreturn so we add a safety check for them.
7149 check: {7188 check: {
7150 var func_val = (try sema.resolveMaybeUndefVal(func)) orelse break :check;7189 const func_val = (try sema.resolveMaybeUndefVal(func)) orelse break :check;
7151 switch (func_val.tag()) {7190 switch (mod.intern_pool.indexToKey(func_val.toIntern())) {
7152 .function, .decl_ref => {7191 .func, .extern_func, .ptr => {
7153 _ = try block.addNoOp(.unreach);7192 _ = try block.addNoOp(.unreach);
7154 return Air.Inst.Ref.unreachable_value;7193 return Air.Inst.Ref.unreachable_value;
7155 },7194 },
...@@ -7196,7 +7235,7 @@ fn analyzeInlineCallArg(...@@ -7196,7 +7235,7 @@ fn analyzeInlineCallArg(
7196 param_block: *Block,7235 param_block: *Block,
7197 arg_src: LazySrcLoc,7236 arg_src: LazySrcLoc,
7198 inst: Zir.Inst.Index,7237 inst: Zir.Inst.Index,
7199 new_fn_info: InternPool.Key.FuncType,7238 new_fn_info: *InternPool.Key.FuncType,
7200 arg_i: *usize,7239 arg_i: *usize,
7201 uncasted_args: []const Air.Inst.Ref,7240 uncasted_args: []const Air.Inst.Ref,
7202 is_comptime_call: bool,7241 is_comptime_call: bool,
...@@ -7263,7 +7302,7 @@ fn analyzeInlineCallArg(...@@ -7263,7 +7302,7 @@ fn analyzeInlineCallArg(
7263 try sema.resolveLazyValue(arg_val);7302 try sema.resolveLazyValue(arg_val);
7264 },7303 },
7265 }7304 }
7266 should_memoize.* = should_memoize.* and !arg_val.canMutateComptimeVarState();7305 should_memoize.* = should_memoize.* and !arg_val.canMutateComptimeVarState(sema.mod);
7267 memoized_call_key.args[arg_i.*] = .{7306 memoized_call_key.args[arg_i.*] = .{
7268 .ty = param_ty.toType(),7307 .ty = param_ty.toType(),
7269 .val = arg_val,7308 .val = arg_val,
...@@ -7302,7 +7341,7 @@ fn analyzeInlineCallArg(...@@ -7302,7 +7341,7 @@ fn analyzeInlineCallArg(
7302 try sema.resolveLazyValue(arg_val);7341 try sema.resolveLazyValue(arg_val);
7303 },7342 },
7304 }7343 }
7305 should_memoize.* = should_memoize.* and !arg_val.canMutateComptimeVarState();7344 should_memoize.* = should_memoize.* and !arg_val.canMutateComptimeVarState(sema.mod);
7306 memoized_call_key.args[arg_i.*] = .{7345 memoized_call_key.args[arg_i.*] = .{
7307 .ty = sema.typeOf(uncasted_arg),7346 .ty = sema.typeOf(uncasted_arg),
7308 .val = arg_val,7347 .val = arg_val,
...@@ -7387,11 +7426,11 @@ fn instantiateGenericCall(...@@ -7387,11 +7426,11 @@ fn instantiateGenericCall(
7387 const gpa = sema.gpa;7426 const gpa = sema.gpa;
73887427
7389 const func_val = try sema.resolveConstValue(block, func_src, func, "generic function being called must be comptime-known");7428 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()) {7429 const module_fn = mod.funcPtr(switch (mod.intern_pool.indexToKey(func_val.ip_index)) {
7391 .function => func_val.castTag(.function).?.data,7430 .func => |function| function.index,
7392 .decl_ref => mod.declPtr(func_val.castTag(.decl_ref).?.data).val.castTag(.function).?.data,7431 .ptr => |ptr| mod.declPtr(ptr.addr.decl).getFunctionIndex(mod).unwrap().?,
7393 else => unreachable,7432 else => unreachable,
7394 };7433 });
7395 // Check the Module's generic function map with an adapted context, so that we7434 // Check the Module's generic function map with an adapted context, so that we
7396 // can match against `uncasted_args` rather than doing the work below to create a7435 // can match against `uncasted_args` rather than doing the work below to create a
7397 // generic Scope only to junk it if it matches an existing instantiation.7436 // generic Scope only to junk it if it matches an existing instantiation.
...@@ -7496,16 +7535,17 @@ fn instantiateGenericCall(...@@ -7496,16 +7535,17 @@ fn instantiateGenericCall(
7496 .args = generic_args,7535 .args = generic_args,
7497 .module = mod,7536 .module = mod,
7498 };7537 };
7499 const gop = try mod.monomorphed_funcs.getOrPutAdapted(gpa, {}, adapter);7538 const gop = try mod.monomorphed_funcs.getOrPutContextAdapted(gpa, {}, adapter, .{ .mod = mod });
7500 const callee = if (!gop.found_existing) callee: {7539 const callee_index = if (!gop.found_existing) callee: {
7501 const new_module_func = try gpa.create(Module.Fn);7540 const new_module_func_index = try mod.createFunc(undefined);
7541 const new_module_func = mod.funcPtr(new_module_func_index);
75027542
7503 // This ensures that we can operate on the hash map before the Module.Fn7543 // This ensures that we can operate on the hash map before the Module.Fn
7504 // struct is fully initialized.7544 // struct is fully initialized.
7505 new_module_func.hash = precomputed_hash;7545 new_module_func.hash = precomputed_hash;
7506 new_module_func.generic_owner_decl = module_fn.owner_decl.toOptional();7546 new_module_func.generic_owner_decl = module_fn.owner_decl.toOptional();
7507 new_module_func.comptime_args = null;7547 new_module_func.comptime_args = null;
7508 gop.key_ptr.* = new_module_func;7548 gop.key_ptr.* = new_module_func_index;
75097549
7510 try namespace.anon_decls.ensureUnusedCapacity(gpa, 1);7550 try namespace.anon_decls.ensureUnusedCapacity(gpa, 1);
75117551
...@@ -7549,7 +7589,7 @@ fn instantiateGenericCall(...@@ -7549,7 +7589,7 @@ fn instantiateGenericCall(
7549 new_decl_index,7589 new_decl_index,
7550 uncasted_args,7590 uncasted_args,
7551 module_fn,7591 module_fn,
7552 new_module_func,7592 new_module_func_index,
7553 namespace_index,7593 namespace_index,
7554 func_ty_info,7594 func_ty_info,
7555 call_src,7595 call_src,
...@@ -7565,12 +7605,12 @@ fn instantiateGenericCall(...@@ -7565,12 +7605,12 @@ fn instantiateGenericCall(
7565 }7605 }
7566 assert(namespace.anon_decls.orderedRemove(new_decl_index));7606 assert(namespace.anon_decls.orderedRemove(new_decl_index));
7567 mod.destroyDecl(new_decl_index);7607 mod.destroyDecl(new_decl_index);
7568 assert(mod.monomorphed_funcs.remove(new_module_func));7608 assert(mod.monomorphed_funcs.removeContext(new_module_func_index, .{ .mod = mod }));
7569 gpa.destroy(new_module_func);7609 mod.destroyFunc(new_module_func_index);
7570 return err;7610 return err;
7571 },7611 },
7572 else => {7612 else => {
7573 assert(mod.monomorphed_funcs.remove(new_module_func));7613 assert(mod.monomorphed_funcs.removeContext(new_module_func_index, .{ .mod = mod }));
7574 {7614 {
7575 errdefer new_decl_arena.deinit();7615 errdefer new_decl_arena.deinit();
7576 try new_decl.finalizeNewArena(&new_decl_arena);7616 try new_decl.finalizeNewArena(&new_decl_arena);
...@@ -7590,6 +7630,7 @@ fn instantiateGenericCall(...@@ -7590,6 +7630,7 @@ fn instantiateGenericCall(
7590 try new_decl.finalizeNewArena(&new_decl_arena);7630 try new_decl.finalizeNewArena(&new_decl_arena);
7591 break :callee new_func;7631 break :callee new_func;
7592 } else gop.key_ptr.*;7632 } else gop.key_ptr.*;
7633 const callee = mod.funcPtr(callee_index);
75937634
7594 callee.branch_quota = @max(callee.branch_quota, sema.branch_quota);7635 callee.branch_quota = @max(callee.branch_quota, sema.branch_quota);
75957636
...@@ -7645,7 +7686,7 @@ fn instantiateGenericCall(...@@ -7645,7 +7686,7 @@ fn instantiateGenericCall(
7645 sema.owner_func.?.calls_or_awaits_errorable_fn = true;7686 sema.owner_func.?.calls_or_awaits_errorable_fn = true;
7646 }7687 }
76477688
7648 try sema.mod.ensureFuncBodyAnalysisQueued(callee);7689 try sema.mod.ensureFuncBodyAnalysisQueued(callee_index);
76497690
7650 try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Call).Struct.fields.len +7691 try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Call).Struct.fields.len +
7651 runtime_args_len);7692 runtime_args_len);
...@@ -7682,12 +7723,12 @@ fn resolveGenericInstantiationType(...@@ -7682,12 +7723,12 @@ fn resolveGenericInstantiationType(
7682 new_decl_index: Decl.Index,7723 new_decl_index: Decl.Index,
7683 uncasted_args: []const Air.Inst.Ref,7724 uncasted_args: []const Air.Inst.Ref,
7684 module_fn: *Module.Fn,7725 module_fn: *Module.Fn,
7685 new_module_func: *Module.Fn,7726 new_module_func: Module.Fn.Index,
7686 namespace: Namespace.Index,7727 namespace: Namespace.Index,
7687 func_ty_info: InternPool.Key.FuncType,7728 func_ty_info: InternPool.Key.FuncType,
7688 call_src: LazySrcLoc,7729 call_src: LazySrcLoc,
7689 bound_arg_src: ?LazySrcLoc,7730 bound_arg_src: ?LazySrcLoc,
7690) !*Module.Fn {7731) !Module.Fn.Index {
7691 const mod = sema.mod;7732 const mod = sema.mod;
7692 const gpa = sema.gpa;7733 const gpa = sema.gpa;
76937734
...@@ -7707,11 +7748,13 @@ fn resolveGenericInstantiationType(...@@ -7707,11 +7748,13 @@ fn resolveGenericInstantiationType(
7707 .owner_decl = new_decl,7748 .owner_decl = new_decl,
7708 .owner_decl_index = new_decl_index,7749 .owner_decl_index = new_decl_index,
7709 .func = null,7750 .func = null,
7751 .func_index = .none,
7710 .fn_ret_ty = Type.void,7752 .fn_ret_ty = Type.void,
7711 .owner_func = null,7753 .owner_func = null,
7754 .owner_func_index = .none,
7712 .comptime_args = try new_decl_arena_allocator.alloc(TypedValue, uncasted_args.len),7755 .comptime_args = try new_decl_arena_allocator.alloc(TypedValue, uncasted_args.len),
7713 .comptime_args_fn_inst = module_fn.zir_body_inst,7756 .comptime_args_fn_inst = module_fn.zir_body_inst,
7714 .preallocated_new_func = new_module_func,7757 .preallocated_new_func = new_module_func.toOptional(),
7715 .is_generic_instantiation = true,7758 .is_generic_instantiation = true,
7716 .branch_quota = sema.branch_quota,7759 .branch_quota = sema.branch_quota,
7717 .branch_count = sema.branch_count,7760 .branch_count = sema.branch_count,
...@@ -7802,8 +7845,8 @@ fn resolveGenericInstantiationType(...@@ -7802,8 +7845,8 @@ fn resolveGenericInstantiationType(
78027845
7803 const new_func_inst = try child_sema.resolveBody(&child_block, fn_info.param_body, fn_info.param_body_inst);7846 const new_func_inst = try child_sema.resolveBody(&child_block, fn_info.param_body, fn_info.param_body_inst);
7804 const new_func_val = child_sema.resolveConstValue(&child_block, .unneeded, new_func_inst, undefined) catch unreachable;7847 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;7848 const new_func = new_func_val.getFunctionIndex(mod).unwrap().?;
7806 errdefer new_func.deinit(gpa);7849 errdefer mod.destroyFunc(new_func);
7807 assert(new_func == new_module_func);7850 assert(new_func == new_module_func);
78087851
7809 arg_i = 0;7852 arg_i = 0;
...@@ -7867,7 +7910,10 @@ fn resolveGenericInstantiationType(...@@ -7867,7 +7910,10 @@ fn resolveGenericInstantiationType(
7867 return error.GenericPoison;7910 return error.GenericPoison;
7868 }7911 }
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();
7871 new_decl.@"align" = 0;7917 new_decl.@"align" = 0;
7872 new_decl.has_tv = true;7918 new_decl.has_tv = true;
7873 new_decl.owns_tv = true;7919 new_decl.owns_tv = true;
...@@ -7900,8 +7946,8 @@ fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type)...@@ -7900,8 +7946,8 @@ fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type)
7900fn emitDbgInline(7946fn emitDbgInline(
7901 sema: *Sema,7947 sema: *Sema,
7902 block: *Block,7948 block: *Block,
7903 old_func: *Module.Fn,7949 old_func: Module.Fn.Index,
7904 new_func: *Module.Fn,7950 new_func: Module.Fn.Index,
7905 new_func_ty: Type,7951 new_func_ty: Type,
7906 tag: Air.Inst.Tag,7952 tag: Air.Inst.Tag,
7907) CompileError!void {7953) CompileError!void {
...@@ -7910,7 +7956,10 @@ fn emitDbgInline(...@@ -7910,7 +7956,10 @@ fn emitDbgInline(
7910 // Recursive inline call; no dbg_inline needed.7956 // Recursive inline call; no dbg_inline needed.
7911 if (old_func == new_func) return;7957 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());
7914 _ = try block.addInst(.{7963 _ = try block.addInst(.{
7915 .tag = tag,7964 .tag = tag,
7916 .data = .{ .ty_pl = .{7965 .data = .{ .ty_pl = .{
...@@ -8078,12 +8127,11 @@ fn zirErrorValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -8078,12 +8127,11 @@ fn zirErrorValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
8078 const name = inst_data.get(sema.code);8127 const name = inst_data.get(sema.code);
8079 // Create an error set type with only this error value, and return the value.8128 // Create an error set type with only this error value, and return the value.
8080 const kv = try sema.mod.getErrorValue(name);8129 const kv = try sema.mod.getErrorValue(name);
8081 return sema.addConstant(8130 const error_set_type = try mod.singleErrorSetType(kv.key);
8082 try mod.singleErrorSetType(kv.key),8131 return sema.addConstant(error_set_type, (try mod.intern(.{ .err = .{
8083 try Value.Tag.@"error".create(sema.arena, .{8132 .ty = error_set_type.ip_index,
8084 .name = kv.key,8133 .name = try mod.intern_pool.getOrPutString(sema.gpa, kv.key),
8085 }),8134 } })).toValue());
8086 );
8087}8135}
80888136
8089fn zirErrorToInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {8137fn 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...@@ -8101,23 +8149,11 @@ fn zirErrorToInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
8101 if (val.isUndef(mod)) {8149 if (val.isUndef(mod)) {
8102 return sema.addConstUndef(Type.err_int);8150 return sema.addConstUndef(Type.err_int);
8103 }8151 }
8104 switch (val.tag()) {8152 const err_name = mod.intern_pool.indexToKey(val.ip_index).err.name;
8105 .@"error" => {8153 return sema.addConstant(Type.err_int, try mod.intValue(
8106 return sema.addConstant(8154 Type.err_int,
8107 Type.err_int,8155 (try mod.getErrorValue(mod.intern_pool.stringToSlice(err_name))).value,
8108 try mod.intValue(8156 ));
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 }
8121 }8157 }
81228158
8123 const op_ty = sema.typeOf(uncasted_operand);8159 const op_ty = sema.typeOf(uncasted_operand);
...@@ -8142,23 +8178,21 @@ fn zirIntToError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat...@@ -8142,23 +8178,21 @@ fn zirIntToError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
8142 const tracy = trace(@src());8178 const tracy = trace(@src());
8143 defer tracy.end();8179 defer tracy.end();
81448180
8181 const mod = sema.mod;
8145 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;8182 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
8146 const src = LazySrcLoc.nodeOffset(extra.node);8183 const src = LazySrcLoc.nodeOffset(extra.node);
8147 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };8184 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
8148 const uncasted_operand = try sema.resolveInst(extra.operand);8185 const uncasted_operand = try sema.resolveInst(extra.operand);
8149 const operand = try sema.coerce(block, Type.err_int, uncasted_operand, operand_src);8186 const operand = try sema.coerce(block, Type.err_int, uncasted_operand, operand_src);
8150 const mod = sema.mod;
81518187
8152 if (try sema.resolveDefinedValue(block, operand_src, operand)) |value| {8188 if (try sema.resolveDefinedValue(block, operand_src, operand)) |value| {
8153 const int = try sema.usizeCast(block, operand_src, value.toUnsignedInt(mod));8189 const int = try sema.usizeCast(block, operand_src, value.toUnsignedInt(mod));
8154 if (int > sema.mod.global_error_set.count() or int == 0)8190 if (int > sema.mod.global_error_set.count() or int == 0)
8155 return sema.fail(block, operand_src, "integer value '{d}' represents no error", .{int});8191 return sema.fail(block, operand_src, "integer value '{d}' represents no error", .{int});
8156 const payload = try sema.arena.create(Value.Payload.Error);8192 return sema.addConstant(Type.anyerror, (try mod.intern(.{ .err = .{
8157 payload.* = .{8193 .ty = .anyerror_type,
8158 .base = .{ .tag = .@"error" },8194 .name = mod.intern_pool.getString(sema.mod.error_name_list.items[int]).unwrap().?,
8159 .data = .{ .name = sema.mod.error_name_list.items[int] },8195 } })).toValue());
8160 };
8161 return sema.addConstant(Type.anyerror, Value.initPayload(&payload.base));
8162 }8196 }
8163 try sema.requireRuntimeBlock(block, src, operand_src);8197 try sema.requireRuntimeBlock(block, src, operand_src);
8164 if (block.wantSafety()) {8198 if (block.wantSafety()) {
...@@ -8234,12 +8268,12 @@ fn zirEnumLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -8234,12 +8268,12 @@ fn zirEnumLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
8234 const tracy = trace(@src());8268 const tracy = trace(@src());
8235 defer tracy.end();8269 defer tracy.end();
82368270
8271 const mod = sema.mod;
8237 const inst_data = sema.code.instructions.items(.data)[inst].str_tok;8272 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));8273 const name = inst_data.get(sema.code);
8239 return sema.addConstant(8274 return sema.addConstant(.{ .ip_index = .enum_literal_type }, (try mod.intern(.{
8240 .{ .ip_index = .enum_literal_type },8275 .enum_literal = try mod.intern_pool.getOrPutString(sema.gpa, name),
8241 try Value.Tag.enum_literal.create(sema.arena, duped_name),8276 })).toValue());
8242 );
8243}8277}
82448278
8245fn zirEnumToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {8279fn zirEnumToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
...@@ -8404,32 +8438,26 @@ fn analyzeOptionalPayloadPtr(...@@ -8404,32 +8438,26 @@ fn analyzeOptionalPayloadPtr(
84048438
8405 if (try sema.resolveDefinedValue(block, src, optional_ptr)) |ptr_val| {8439 if (try sema.resolveDefinedValue(block, src, optional_ptr)) |ptr_val| {
8406 if (initializing) {8440 if (initializing) {
8407 if (!ptr_val.isComptimeMutablePtr()) {8441 if (!ptr_val.isComptimeMutablePtr(mod)) {
8408 // If the pointer resulting from this function was stored at comptime,8442 // If the pointer resulting from this function was stored at comptime,
8409 // the optional non-null bit would be set that way. But in this case,8443 // the optional non-null bit would be set that way. But in this case,
8410 // we need to emit a runtime instruction to do it.8444 // we need to emit a runtime instruction to do it.
8411 _ = try block.addTyOp(.optional_payload_ptr_set, child_pointer, optional_ptr);8445 _ = try block.addTyOp(.optional_payload_ptr_set, child_pointer, optional_ptr);
8412 }8446 }
8413 return sema.addConstant(8447 return sema.addConstant(child_pointer, (try mod.intern(.{ .ptr = .{
8414 child_pointer,8448 .ty = child_pointer.ip_index,
8415 try Value.Tag.opt_payload_ptr.create(sema.arena, .{8449 .addr = .{ .opt_payload = ptr_val.ip_index },
8416 .container_ptr = ptr_val,8450 } })).toValue());
8417 .container_ty = optional_ptr_ty.childType(mod),
8418 }),
8419 );
8420 }8451 }
8421 if (try sema.pointerDeref(block, src, ptr_val, optional_ptr_ty)) |val| {8452 if (try sema.pointerDeref(block, src, ptr_val, optional_ptr_ty)) |val| {
8422 if (val.isNull(mod)) {8453 if (val.isNull(mod)) {
8423 return sema.fail(block, src, "unable to unwrap null", .{});8454 return sema.fail(block, src, "unable to unwrap null", .{});
8424 }8455 }
8425 // The same Value represents the pointer to the optional and the payload.8456 // The same Value represents the pointer to the optional and the payload.
8426 return sema.addConstant(8457 return sema.addConstant(child_pointer, (try mod.intern(.{ .ptr = .{
8427 child_pointer,8458 .ty = child_pointer.ip_index,
8428 try Value.Tag.opt_payload_ptr.create(sema.arena, .{8459 .addr = .{ .opt_payload = ptr_val.ip_index },
8429 .container_ptr = ptr_val,8460 } })).toValue());
8430 .container_ty = optional_ptr_ty.childType(mod),
8431 }),
8432 );
8433 }8461 }
8434 }8462 }
84358463
...@@ -8532,11 +8560,13 @@ fn analyzeErrUnionPayload(...@@ -8532,11 +8560,13 @@ fn analyzeErrUnionPayload(
8532 const mod = sema.mod;8560 const mod = sema.mod;
8533 const payload_ty = err_union_ty.errorUnionPayload(mod);8561 const payload_ty = err_union_ty.errorUnionPayload(mod);
8534 if (try sema.resolveDefinedValue(block, operand_src, operand)) |val| {8562 if (try sema.resolveDefinedValue(block, operand_src, operand)) |val| {
8535 if (val.getError()) |name| {8563 if (val.getError(mod)) |name| {
8536 return sema.fail(block, src, "caught unexpected error '{s}'", .{name});8564 return sema.fail(block, src, "caught unexpected error '{s}'", .{name});
8537 }8565 }
8538 const data = val.castTag(.eu_payload).?.data;8566 return sema.addConstant(
8539 return sema.addConstant(payload_ty, data);8567 payload_ty,
8568 mod.intern_pool.indexToKey(val.ip_index).error_union.val.payload.toValue(),
8569 );
8540 }8570 }
85418571
8542 try sema.requireRuntimeBlock(block, src, null);8572 try sema.requireRuntimeBlock(block, src, null);
...@@ -8595,33 +8625,26 @@ fn analyzeErrUnionPayloadPtr(...@@ -8595,33 +8625,26 @@ fn analyzeErrUnionPayloadPtr(
85958625
8596 if (try sema.resolveDefinedValue(block, src, operand)) |ptr_val| {8626 if (try sema.resolveDefinedValue(block, src, operand)) |ptr_val| {
8597 if (initializing) {8627 if (initializing) {
8598 if (!ptr_val.isComptimeMutablePtr()) {8628 if (!ptr_val.isComptimeMutablePtr(mod)) {
8599 // If the pointer resulting from this function was stored at comptime,8629 // If the pointer resulting from this function was stored at comptime,
8600 // the error union error code would be set that way. But in this case,8630 // the error union error code would be set that way. But in this case,
8601 // we need to emit a runtime instruction to do it.8631 // we need to emit a runtime instruction to do it.
8602 try sema.requireRuntimeBlock(block, src, null);8632 try sema.requireRuntimeBlock(block, src, null);
8603 _ = try block.addTyOp(.errunion_payload_ptr_set, operand_pointer_ty, operand);8633 _ = try block.addTyOp(.errunion_payload_ptr_set, operand_pointer_ty, operand);
8604 }8634 }
8605 return sema.addConstant(8635 return sema.addConstant(operand_pointer_ty, (try mod.intern(.{ .ptr = .{
8606 operand_pointer_ty,8636 .ty = operand_pointer_ty.ip_index,
8607 try Value.Tag.eu_payload_ptr.create(sema.arena, .{8637 .addr = .{ .eu_payload = ptr_val.ip_index },
8608 .container_ptr = ptr_val,8638 } })).toValue());
8609 .container_ty = operand_ty.childType(mod),
8610 }),
8611 );
8612 }8639 }
8613 if (try sema.pointerDeref(block, src, ptr_val, operand_ty)) |val| {8640 if (try sema.pointerDeref(block, src, ptr_val, operand_ty)) |val| {
8614 if (val.getError()) |name| {8641 if (val.getError(mod)) |name| {
8615 return sema.fail(block, src, "caught unexpected error '{s}'", .{name});8642 return sema.fail(block, src, "caught unexpected error '{s}'", .{name});
8616 }8643 }
86178644 return sema.addConstant(operand_pointer_ty, (try mod.intern(.{ .ptr = .{
8618 return sema.addConstant(8645 .ty = operand_pointer_ty.ip_index,
8619 operand_pointer_ty,8646 .addr = .{ .eu_payload = ptr_val.ip_index },
8620 try Value.Tag.eu_payload_ptr.create(sema.arena, .{8647 } })).toValue());
8621 .container_ptr = ptr_val,
8622 .container_ty = operand_ty.childType(mod),
8623 }),
8624 );
8625 }8648 }
8626 }8649 }
86278650
...@@ -8664,7 +8687,7 @@ fn analyzeErrUnionCode(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air...@@ -8664,7 +8687,7 @@ fn analyzeErrUnionCode(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air
8664 const result_ty = operand_ty.errorUnionSet(mod);8687 const result_ty = operand_ty.errorUnionSet(mod);
86658688
8666 if (try sema.resolveDefinedValue(block, src, operand)) |val| {8689 if (try sema.resolveDefinedValue(block, src, operand)) |val| {
8667 assert(val.getError() != null);8690 assert(val.getError(mod) != null);
8668 return sema.addConstant(result_ty, val);8691 return sema.addConstant(result_ty, val);
8669 }8692 }
86708693
...@@ -8694,7 +8717,7 @@ fn zirErrUnionCodePtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -8694,7 +8717,7 @@ fn zirErrUnionCodePtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
86948717
8695 if (try sema.resolveDefinedValue(block, src, operand)) |pointer_val| {8718 if (try sema.resolveDefinedValue(block, src, operand)) |pointer_val| {
8696 if (try sema.pointerDeref(block, src, pointer_val, operand_ty)) |val| {8719 if (try sema.pointerDeref(block, src, pointer_val, operand_ty)) |val| {
8697 assert(val.getError() != null);8720 assert(val.getError(mod) != null);
8698 return sema.addConstant(result_ty, val);8721 return sema.addConstant(result_ty, val);
8699 }8722 }
8700 }8723 }
...@@ -8931,20 +8954,21 @@ fn funcCommon(...@@ -8931,20 +8954,21 @@ fn funcCommon(
8931 }8954 }
89328955
8933 var destroy_fn_on_error = false;8956 var destroy_fn_on_error = false;
8934 const new_func: *Module.Fn = new_func: {8957 const new_func_index = new_func: {
8935 if (!has_body) break :new_func undefined;8958 if (!has_body) break :new_func undefined;
8936 if (sema.comptime_args_fn_inst == func_inst) {8959 if (sema.comptime_args_fn_inst == func_inst) {
8937 const new_func = sema.preallocated_new_func.?;8960 const new_func_index = sema.preallocated_new_func.unwrap().?;
8938 sema.preallocated_new_func = null; // take ownership8961 sema.preallocated_new_func = .none; // take ownership
8939 break :new_func new_func;8962 break :new_func new_func_index;
8940 }8963 }
8941 destroy_fn_on_error = true;8964 destroy_fn_on_error = true;
8942 const new_func = try gpa.create(Module.Fn);8965 var new_func: Module.Fn = undefined;
8943 // Set this here so that the inferred return type can be printed correctly if it appears in an error.8966 // Set this here so that the inferred return type can be printed correctly if it appears in an error.
8944 new_func.owner_decl = sema.owner_decl_index;8967 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;
8946 };8970 };
8947 errdefer if (destroy_fn_on_error) gpa.destroy(new_func);8971 errdefer if (destroy_fn_on_error) mod.destroyFunc(new_func_index);
89488972
8949 const target = sema.mod.getTarget();8973 const target = sema.mod.getTarget();
8950 const fn_ty: Type = fn_ty: {8974 const fn_ty: Type = fn_ty: {
...@@ -9008,7 +9032,7 @@ fn funcCommon(...@@ -9008,7 +9032,7 @@ fn funcCommon(
9008 else blk: {9032 else blk: {
9009 try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src);9033 try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src);
9010 const ies_index = try mod.intern_pool.createInferredErrorSet(gpa, .{9034 const ies_index = try mod.intern_pool.createInferredErrorSet(gpa, .{
9011 .func = new_func,9035 .func = new_func_index,
9012 });9036 });
9013 const error_set_ty = try mod.intern(.{ .inferred_error_set_type = ies_index });9037 const error_set_ty = try mod.intern(.{ .inferred_error_set_type = ies_index });
9014 break :blk try mod.errorUnionType(error_set_ty.toType(), bare_return_type);9038 break :blk try mod.errorUnionType(error_set_ty.toType(), bare_return_type);
...@@ -9158,26 +9182,16 @@ fn funcCommon(...@@ -9158,26 +9182,16 @@ fn funcCommon(
9158 sema.owner_decl.@"addrspace" = address_space orelse .generic;9182 sema.owner_decl.@"addrspace" = address_space orelse .generic;
91599183
9160 if (is_extern) {9184 if (is_extern) {
9161 const new_extern_fn = try gpa.create(Module.ExternFn);9185 return sema.addConstant(fn_ty, (try mod.intern(.{ .extern_func = .{
9162 errdefer gpa.destroy(new_extern_fn);9186 .ty = fn_ty.ip_index,
91639187 .decl = sema.owner_decl_index,
9164 new_extern_fn.* = Module.ExternFn{9188 .lib_name = if (opt_lib_name) |lib_name| (try mod.intern_pool.getOrPutString(
9165 .owner_decl = sema.owner_decl_index,9189 gpa,
9166 .lib_name = null,9190 try sema.handleExternLibName(block, .{
9167 };9191 .node_offset_lib_name = src_node_offset,
91689192 }, lib_name),
9169 if (opt_lib_name) |lib_name| {9193 )).toOptional() else .none,
9170 new_extern_fn.lib_name = try sema.handleExternLibName(block, .{9194 } })).toValue());
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));
9181 }9195 }
91829196
9183 if (!has_body) {9197 if (!has_body) {
...@@ -9191,9 +9205,9 @@ fn funcCommon(...@@ -9191,9 +9205,9 @@ fn funcCommon(
9191 break :blk if (sema.comptime_args.len == 0) null else sema.comptime_args.ptr;9205 break :blk if (sema.comptime_args.len == 0) null else sema.comptime_args.ptr;
9192 } else null;9206 } else null;
91939207
9208 const new_func = mod.funcPtr(new_func_index);
9194 const hash = new_func.hash;9209 const hash = new_func.hash;
9195 const generic_owner_decl = if (comptime_args == null) .none else new_func.generic_owner_decl;9210 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);
9197 new_func.* = .{9211 new_func.* = .{
9198 .state = anal_state,9212 .state = anal_state,
9199 .zir_body_inst = func_inst,9213 .zir_body_inst = func_inst,
...@@ -9208,11 +9222,10 @@ fn funcCommon(...@@ -9208,11 +9222,10 @@ fn funcCommon(
9208 .branch_quota = default_branch_quota,9222 .branch_quota = default_branch_quota,
9209 .is_noinline = is_noinline,9223 .is_noinline = is_noinline,
9210 };9224 };
9211 fn_payload.* = .{9225 return sema.addConstant(fn_ty, (try mod.intern(.{ .func = .{
9212 .base = .{ .tag = .function },9226 .ty = fn_ty.ip_index,
9213 .data = new_func,9227 .index = new_func_index,
9214 };9228 } })).toValue());
9215 return sema.addConstant(fn_ty, Value.initPayload(&fn_payload.base));
9216}9229}
92179230
9218fn analyzeParameter(9231fn analyzeParameter(
...@@ -9312,7 +9325,7 @@ fn zirParam(...@@ -9312,7 +9325,7 @@ fn zirParam(
9312 const prev_preallocated_new_func = sema.preallocated_new_func;9325 const prev_preallocated_new_func = sema.preallocated_new_func;
9313 const prev_no_partial_func_type = sema.no_partial_func_ty;9326 const prev_no_partial_func_type = sema.no_partial_func_ty;
9314 block.params = .{};9327 block.params = .{};
9315 sema.preallocated_new_func = null;9328 sema.preallocated_new_func = .none;
9316 sema.no_partial_func_ty = true;9329 sema.no_partial_func_ty = true;
9317 defer {9330 defer {
9318 block.params.deinit(sema.gpa);9331 block.params.deinit(sema.gpa);
...@@ -9369,7 +9382,7 @@ fn zirParam(...@@ -9369,7 +9382,7 @@ fn zirParam(
9369 else => |e| return e,9382 else => |e| return e,
9370 } or comptime_syntax;9383 } or comptime_syntax;
9371 if (sema.inst_map.get(inst)) |arg| {9384 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) {
9373 // We have a comptime value for this parameter so it should be elided from the9386 // We have a comptime value for this parameter so it should be elided from the
9374 // function type of the function instruction in this block.9387 // function type of the function instruction in this block.
9375 const coerced_arg = sema.coerce(block, param_ty, arg, .unneeded) catch |err| switch (err) {9388 const coerced_arg = sema.coerce(block, param_ty, arg, .unneeded) catch |err| switch (err) {
...@@ -9392,7 +9405,7 @@ fn zirParam(...@@ -9392,7 +9405,7 @@ fn zirParam(
9392 assert(sema.inst_map.remove(inst));9405 assert(sema.inst_map.remove(inst));
9393 }9406 }
93949407
9395 if (sema.preallocated_new_func != null) {9408 if (sema.preallocated_new_func != .none) {
9396 if (try sema.typeHasOnePossibleValue(param_ty)) |opv| {9409 if (try sema.typeHasOnePossibleValue(param_ty)) |opv| {
9397 // In this case we are instantiating a generic function call with a non-comptime9410 // In this case we are instantiating a generic function call with a non-comptime
9398 // non-anytype parameter that ended up being a one-possible-type.9411 // non-anytype parameter that ended up being a one-possible-type.
...@@ -9640,8 +9653,8 @@ fn intCast(...@@ -9640,8 +9653,8 @@ fn intCast(
96409653
9641 if (wanted_bits == 0) {9654 if (wanted_bits == 0) {
9642 const ok = if (is_vector) ok: {9655 const ok = if (is_vector) ok: {
9643 const zeros = try Value.Tag.repeated.create(sema.arena, try mod.intValue(operand_scalar_ty, 0));9656 const zeros = try sema.splat(operand_ty, try mod.intValue(operand_scalar_ty, 0));
9644 const zero_inst = try sema.addConstant(sema.typeOf(operand), zeros);9657 const zero_inst = try sema.addConstant(operand_ty, zeros);
9645 const is_in_range = try block.addCmpVector(operand, zero_inst, .eq);9658 const is_in_range = try block.addCmpVector(operand, zero_inst, .eq);
9646 const all_in_range = try block.addInst(.{9659 const all_in_range = try block.addInst(.{
9647 .tag = .reduce,9660 .tag = .reduce,
...@@ -9649,7 +9662,7 @@ fn intCast(...@@ -9649,7 +9662,7 @@ fn intCast(
9649 });9662 });
9650 break :ok all_in_range;9663 break :ok all_in_range;
9651 } else ok: {9664 } 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));
9653 const is_in_range = try block.addBinOp(.cmp_lte, operand, zero_inst);9666 const is_in_range = try block.addBinOp(.cmp_lte, operand, zero_inst);
9654 break :ok is_in_range;9667 break :ok is_in_range;
9655 };9668 };
...@@ -9673,10 +9686,7 @@ fn intCast(...@@ -9673,10 +9686,7 @@ fn intCast(
9673 // requirement: int value fits into target type9686 // requirement: int value fits into target type
9674 if (wanted_value_bits < actual_value_bits) {9687 if (wanted_value_bits < actual_value_bits) {
9675 const dest_max_val_scalar = try dest_scalar_ty.maxIntScalar(mod, operand_ty);9688 const dest_max_val_scalar = try dest_scalar_ty.maxIntScalar(mod, operand_ty);
9676 const dest_max_val = if (is_vector)9689 const dest_max_val = try sema.splat(operand_ty, dest_max_val_scalar);
9677 try Value.Tag.repeated.create(sema.arena, dest_max_val_scalar)
9678 else
9679 dest_max_val_scalar;
9680 const dest_max = try sema.addConstant(operand_ty, dest_max_val);9690 const dest_max = try sema.addConstant(operand_ty, dest_max_val);
9681 const diff = try block.addBinOp(.subwrap, dest_max, operand);9691 const diff = try block.addBinOp(.subwrap, dest_max, operand);
96829692
...@@ -9732,7 +9742,8 @@ fn intCast(...@@ -9732,7 +9742,8 @@ fn intCast(
9732 // no shrinkage, yes sign loss9742 // no shrinkage, yes sign loss
9733 // requirement: signed to unsigned >= 09743 // requirement: signed to unsigned >= 0
9734 const ok = if (is_vector) ok: {9744 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);
9736 const zero_inst = try sema.addConstant(operand_ty, zero_val);9747 const zero_inst = try sema.addConstant(operand_ty, zero_val);
9737 const is_in_range = try block.addCmpVector(operand, zero_inst, .gte);9748 const is_in_range = try block.addCmpVector(operand, zero_inst, .gte);
9738 const all_in_range = try block.addInst(.{9749 const all_in_range = try block.addInst(.{
...@@ -10139,17 +10150,18 @@ fn zirSwitchCapture(...@@ -10139,17 +10150,18 @@ fn zirSwitchCapture(
10139 .@"volatile" = operand_ptr_ty.isVolatilePtr(mod),10150 .@"volatile" = operand_ptr_ty.isVolatilePtr(mod),
10140 .@"addrspace" = operand_ptr_ty.ptrAddressSpace(mod),10151 .@"addrspace" = operand_ptr_ty.ptrAddressSpace(mod),
10141 });10152 });
10142 return sema.addConstant(10153 return sema.addConstant(ptr_field_ty, (try mod.intern(.{ .ptr = .{
10143 ptr_field_ty,10154 .ty = ptr_field_ty.ip_index,
10144 try Value.Tag.field_ptr.create(sema.arena, .{10155 .addr = .{ .field = .{
10145 .container_ptr = union_val,10156 .base = union_val.ip_index,
10146 .container_ty = operand_ty,10157 .index = field_index,
10147 .field_index = field_index,10158 } },
10148 }),10159 } })).toValue());
10149 );
10150 }10160 }
10151 const tag_and_val = union_val.castTag(.@"union").?.data;10161 return sema.addConstant(
10152 return sema.addConstant(field_ty, tag_and_val.val);10162 field_ty,
10163 mod.intern_pool.indexToKey(union_val.ip_index).un.val.toValue(),
10164 );
10153 }10165 }
10154 if (is_ref) {10166 if (is_ref) {
10155 const ptr_field_ty = try Type.ptr(sema.arena, sema.mod, .{10167 const ptr_field_ty = try Type.ptr(sema.arena, sema.mod, .{
...@@ -10243,14 +10255,13 @@ fn zirSwitchCapture(...@@ -10243,14 +10255,13 @@ fn zirSwitchCapture(
10243 });10255 });
1024410256
10245 if (try sema.resolveDefinedValue(block, operand_src, operand_ptr)) |op_ptr_val| {10257 if (try sema.resolveDefinedValue(block, operand_src, operand_ptr)) |op_ptr_val| {
10246 return sema.addConstant(10258 return sema.addConstant(field_ty_ptr, (try mod.intern(.{ .ptr = .{
10247 field_ty_ptr,10259 .ty = field_ty_ptr.ip_index,
10248 try Value.Tag.field_ptr.create(sema.arena, .{10260 .addr = .{ .field = .{
10249 .container_ptr = op_ptr_val,10261 .base = op_ptr_val.ip_index,
10250 .container_ty = operand_ty,10262 .index = first_field_index,
10251 .field_index = first_field_index,10263 } },
10252 }),10264 } })).toValue());
10253 );
10254 }10265 }
10255 try sema.requireRuntimeBlock(block, operand_src, null);10266 try sema.requireRuntimeBlock(block, operand_src, null);
10256 return block.addStructFieldPtr(operand_ptr, first_field_index, field_ty_ptr);10267 return block.addStructFieldPtr(operand_ptr, first_field_index, field_ty_ptr);
...@@ -10273,7 +10284,7 @@ fn zirSwitchCapture(...@@ -10273,7 +10284,7 @@ fn zirSwitchCapture(
10273 const item_ref = try sema.resolveInst(item);10284 const item_ref = try sema.resolveInst(item);
10274 // Previous switch validation ensured this will succeed10285 // Previous switch validation ensured this will succeed
10275 const item_val = sema.resolveConstValue(block, .unneeded, item_ref, "") catch unreachable;10286 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).?);
10277 names.putAssumeCapacityNoClobber(name_ip, {});10288 names.putAssumeCapacityNoClobber(name_ip, {});
10278 }10289 }
10279 const else_error_ty = try mod.errorSetFromUnsortedNames(names.keys());10290 const else_error_ty = try mod.errorSetFromUnsortedNames(names.keys());
...@@ -10284,7 +10295,7 @@ fn zirSwitchCapture(...@@ -10284,7 +10295,7 @@ fn zirSwitchCapture(
10284 // Previous switch validation ensured this will succeed10295 // Previous switch validation ensured this will succeed
10285 const item_val = sema.resolveConstValue(block, .unneeded, item_ref, "") catch unreachable;10296 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).?);
10288 return sema.bitCast(block, item_ty, operand, operand_src, null);10299 return sema.bitCast(block, item_ty, operand, operand_src, null);
10289 }10300 }
10290 },10301 },
...@@ -10809,10 +10820,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10809,10 +10820,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1080910820
10810 check_range: {10821 check_range: {
10811 if (operand_ty.zigTypeTag(mod) == .Int) {10822 if (operand_ty.zigTypeTag(mod) == .Int) {
10812 var arena = std.heap.ArenaAllocator.init(gpa);10823 const min_int = try operand_ty.minInt(mod);
10813 defer arena.deinit();
10814
10815 const min_int = try operand_ty.minInt(arena.allocator(), mod);
10816 const max_int = try operand_ty.maxIntScalar(mod, Type.comptime_int);10824 const max_int = try operand_ty.maxIntScalar(mod, Type.comptime_int);
10817 if (try range_set.spans(min_int, max_int, operand_ty)) {10825 if (try range_set.spans(min_int, max_int, operand_ty)) {
10818 if (special_prong == .@"else") {10826 if (special_prong == .@"else") {
...@@ -11493,8 +11501,11 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11493,8 +11501,11 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11493 if (seen_errors.contains(error_name)) continue;11501 if (seen_errors.contains(error_name)) continue;
11494 cases_len += 1;11502 cases_len += 1;
1149511503
11496 const item_val = try Value.Tag.@"error".create(sema.arena, .{ .name = error_name });11504 const item_val = try mod.intern(.{ .err = .{
11497 const item_ref = try sema.addConstant(operand_ty, item_val);11505 .ty = operand_ty.ip_index,
11506 .name = error_name_ip,
11507 } });
11508 const item_ref = try sema.addConstant(operand_ty, item_val.toValue());
11498 case_block.inline_case_capture = item_ref;11509 case_block.inline_case_capture = item_ref;
1149911510
11500 case_block.instructions.shrinkRetainingCapacity(0);11511 case_block.instructions.shrinkRetainingCapacity(0);
...@@ -11665,7 +11676,7 @@ const RangeSetUnhandledIterator = struct {...@@ -11665,7 +11676,7 @@ const RangeSetUnhandledIterator = struct {
1166511676
11666 fn init(sema: *Sema, ty: Type, range_set: RangeSet) !RangeSetUnhandledIterator {11677 fn init(sema: *Sema, ty: Type, range_set: RangeSet) !RangeSetUnhandledIterator {
11667 const mod = sema.mod;11678 const mod = sema.mod;
11668 const min = try ty.minInt(sema.arena, mod);11679 const min = try ty.minInt(mod);
11669 const max = try ty.maxIntScalar(mod, Type.comptime_int);11680 const max = try ty.maxIntScalar(mod, Type.comptime_int);
1167011681
11671 return RangeSetUnhandledIterator{11682 return RangeSetUnhandledIterator{
...@@ -11788,9 +11799,10 @@ fn validateSwitchItemError(...@@ -11788,9 +11799,10 @@ fn validateSwitchItemError(
11788 src_node_offset: i32,11799 src_node_offset: i32,
11789 switch_prong_src: Module.SwitchProngSrc,11800 switch_prong_src: Module.SwitchProngSrc,
11790) CompileError!void {11801) CompileError!void {
11802 const ip = &sema.mod.intern_pool;
11791 const item_tv = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);11803 const item_tv = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);
11792 // TODO: Do i need to typecheck here?11804 // 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);
11794 const maybe_prev_src = if (try seen_errors.fetchPut(error_name, switch_prong_src)) |prev|11806 const maybe_prev_src = if (try seen_errors.fetchPut(error_name, switch_prong_src)) |prev|
11795 prev.value11807 prev.value
11796 else11808 else
...@@ -11983,7 +11995,7 @@ fn maybeErrorUnwrapCondbr(sema: *Sema, block: *Block, body: []const Zir.Inst.Ind...@@ -11983,7 +11995,7 @@ fn maybeErrorUnwrapCondbr(sema: *Sema, block: *Block, body: []const Zir.Inst.Ind
11983 }11995 }
11984 if (try sema.resolveDefinedValue(block, cond_src, err_operand)) |val| {11996 if (try sema.resolveDefinedValue(block, cond_src, err_operand)) |val| {
11985 if (!operand_ty.isError(mod)) return;11997 if (!operand_ty.isError(mod)) return;
11986 if (val.getError() == null) return;11998 if (val.getError(mod) == null) return;
11987 try sema.maybeErrorUnwrapComptime(block, body, err_operand);11999 try sema.maybeErrorUnwrapComptime(block, body, err_operand);
11988 }12000 }
11989}12001}
...@@ -12005,7 +12017,7 @@ fn maybeErrorUnwrapComptime(sema: *Sema, block: *Block, body: []const Zir.Inst.I...@@ -12005,7 +12017,7 @@ fn maybeErrorUnwrapComptime(sema: *Sema, block: *Block, body: []const Zir.Inst.I
12005 const src = inst_data.src();12017 const src = inst_data.src();
1200612018
12007 if (try sema.resolveDefinedValue(block, src, operand)) |val| {12019 if (try sema.resolveDefinedValue(block, src, operand)) |val| {
12008 if (val.getError()) |name| {12020 if (val.getError(sema.mod)) |name| {
12009 return sema.fail(block, src, "caught unexpected error '{s}'", .{name});12021 return sema.fail(block, src, "caught unexpected error '{s}'", .{name});
12010 }12022 }
12011 }12023 }
...@@ -12172,11 +12184,11 @@ fn zirRetErrValueCode(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.R...@@ -12172,11 +12184,11 @@ fn zirRetErrValueCode(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.R
1217212184
12173 // Return the error code from the function.12185 // Return the error code from the function.
12174 const kv = try mod.getErrorValue(err_name);12186 const kv = try mod.getErrorValue(err_name);
12175 const result_inst = try sema.addConstant(12187 const error_set_type = try mod.singleErrorSetType(kv.key);
12176 try mod.singleErrorSetType(kv.key),12188 return sema.addConstant(error_set_type, (try mod.intern(.{ .err = .{
12177 try Value.Tag.@"error".create(sema.arena, .{ .name = kv.key }),12189 .ty = error_set_type.ip_index,
12178 );12190 .name = mod.intern_pool.getString(kv.key).unwrap().?,
12179 return result_inst;12191 } })).toValue());
12180}12192}
1218112193
12182fn zirShl(12194fn zirShl(
...@@ -12301,7 +12313,7 @@ fn zirShl(...@@ -12301,7 +12313,7 @@ fn zirShl(
12301 {12313 {
12302 const max_int = try sema.addConstant(12314 const max_int = try sema.addConstant(
12303 lhs_ty,12315 lhs_ty,
12304 try lhs_ty.maxInt(sema.arena, mod, lhs_ty),12316 try lhs_ty.maxInt(mod, lhs_ty),
12305 );12317 );
12306 const rhs_limited = try sema.analyzeMinMax(block, rhs_src, .min, &.{ rhs, max_int }, &.{ rhs_src, rhs_src });12318 const rhs_limited = try sema.analyzeMinMax(block, rhs_src, .min, &.{ rhs, max_int }, &.{ rhs_src, rhs_src });
12307 break :rhs try sema.intCast(block, src, lhs_ty, rhs_src, rhs_limited, rhs_src, false);12319 break :rhs try sema.intCast(block, src, lhs_ty, rhs_src, rhs_limited, rhs_src, false);
...@@ -12316,7 +12328,7 @@ fn zirShl(...@@ -12316,7 +12328,7 @@ fn zirShl(
12316 if (!std.math.isPowerOfTwo(bit_count)) {12328 if (!std.math.isPowerOfTwo(bit_count)) {
12317 const bit_count_val = try mod.intValue(scalar_rhs_ty, bit_count);12329 const bit_count_val = try mod.intValue(scalar_rhs_ty, bit_count);
12318 const ok = if (rhs_ty.zigTypeTag(mod) == .Vector) ok: {12330 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));
12320 const lt = try block.addCmpVector(rhs, bit_count_inst, .lt);12332 const lt = try block.addCmpVector(rhs, bit_count_inst, .lt);
12321 break :ok try block.addInst(.{12333 break :ok try block.addInst(.{
12322 .tag = .reduce,12334 .tag = .reduce,
...@@ -12466,7 +12478,7 @@ fn zirShr(...@@ -12466,7 +12478,7 @@ fn zirShr(
12466 const bit_count_val = try mod.intValue(scalar_ty, bit_count);12478 const bit_count_val = try mod.intValue(scalar_ty, bit_count);
1246712479
12468 const ok = if (rhs_ty.zigTypeTag(mod) == .Vector) ok: {12480 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));
12470 const lt = try block.addCmpVector(rhs, bit_count_inst, .lt);12482 const lt = try block.addCmpVector(rhs, bit_count_inst, .lt);
12471 break :ok try block.addInst(.{12483 break :ok try block.addInst(.{
12472 .tag = .reduce,12484 .tag = .reduce,
...@@ -13179,11 +13191,7 @@ fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -13179,11 +13191,7 @@ fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
13179 return block.addUnOp(if (block.float_mode == .Optimized) .neg_optimized else .neg, rhs);13191 return block.addUnOp(if (block.float_mode == .Optimized) .neg_optimized else .neg, rhs);
13180 }13192 }
1318113193
13182 const lhs = if (rhs_ty.zigTypeTag(mod) == .Vector)13194 const lhs = try sema.addConstant(rhs_ty, try sema.splat(rhs_ty, try mod.intValue(rhs_scalar_ty, 0)));
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
13187 return sema.analyzeArithmetic(block, .sub, lhs, rhs, src, lhs_src, rhs_src, true);13195 return sema.analyzeArithmetic(block, .sub, lhs, rhs, src, lhs_src, rhs_src, true);
13188}13196}
1318913197
...@@ -13203,11 +13211,7 @@ fn zirNegateWrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -13203,11 +13211,7 @@ fn zirNegateWrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
13203 else => return sema.fail(block, src, "negation of type '{}'", .{rhs_ty.fmt(sema.mod)}),13211 else => return sema.fail(block, src, "negation of type '{}'", .{rhs_ty.fmt(sema.mod)}),
13204 }13212 }
1320513213
13206 const lhs = if (rhs_ty.zigTypeTag(mod) == .Vector)13214 const lhs = try sema.addConstant(rhs_ty, try sema.splat(rhs_ty, try mod.intValue(rhs_scalar_ty, 0)));
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
13211 return sema.analyzeArithmetic(block, .subwrap, lhs, rhs, src, lhs_src, rhs_src, true);13215 return sema.analyzeArithmetic(block, .subwrap, lhs, rhs, src, lhs_src, rhs_src, true);
13212}13216}
1321313217
...@@ -13254,8 +13258,6 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -13254,8 +13258,6 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
13254 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },13258 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
13255 });13259 });
1325613260
13257 const is_vector = resolved_type.zigTypeTag(mod) == .Vector;
13258
13259 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);13261 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
13260 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);13262 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...@@ -13325,9 +13327,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
13325 .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),13327 .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
13326 else => unreachable,13328 else => unreachable,
13327 };13329 };
13328 const zero_val = if (is_vector) b: {13330 const zero_val = try sema.splat(resolved_type, scalar_zero);
13329 break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
13330 } else scalar_zero;
13331 return sema.addConstant(resolved_type, zero_val);13331 return sema.addConstant(resolved_type, zero_val);
13332 }13332 }
13333 }13333 }
...@@ -13427,8 +13427,6 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13427,8 +13427,6 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13427 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },13427 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
13428 });13428 });
1342913429
13430 const is_vector = resolved_type.zigTypeTag(mod) == .Vector;
13431
13432 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);13430 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
13433 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);13431 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...@@ -13469,9 +13467,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13469 .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),13467 .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
13470 else => unreachable,13468 else => unreachable,
13471 };13469 };
13472 const zero_val = if (is_vector) b: {13470 const zero_val = try sema.splat(resolved_type, scalar_zero);
13473 break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
13474 } else scalar_zero;
13475 return sema.addConstant(resolved_type, zero_val);13471 return sema.addConstant(resolved_type, zero_val);
13476 }13472 }
13477 }13473 }
...@@ -13555,7 +13551,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13555,7 +13551,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13555 else => unreachable,13551 else => unreachable,
13556 };13552 };
13557 if (resolved_type.zigTypeTag(mod) == .Vector) {13553 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);
13559 const zero = try sema.addConstant(resolved_type, zero_val);13555 const zero = try sema.addConstant(resolved_type, zero_val);
13560 const eql = try block.addCmpVector(remainder, zero, .eq);13556 const eql = try block.addCmpVector(remainder, zero, .eq);
13561 break :ok try block.addInst(.{13557 break :ok try block.addInst(.{
...@@ -13600,8 +13596,6 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13600,8 +13596,6 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13600 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },13596 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
13601 });13597 });
1360213598
13603 const is_vector = resolved_type.zigTypeTag(mod) == .Vector;
13604
13605 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);13599 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
13606 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);13600 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...@@ -13644,9 +13638,7 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13644 .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),13638 .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
13645 else => unreachable,13639 else => unreachable,
13646 };13640 };
13647 const zero_val = if (is_vector) b: {13641 const zero_val = try sema.splat(resolved_type, scalar_zero);
13648 break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
13649 } else scalar_zero;
13650 return sema.addConstant(resolved_type, zero_val);13642 return sema.addConstant(resolved_type, zero_val);
13651 }13643 }
13652 }13644 }
...@@ -13721,8 +13713,6 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13721,8 +13713,6 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13721 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },13713 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
13722 });13714 });
1372313715
13724 const is_vector = resolved_type.zigTypeTag(mod) == .Vector;
13725
13726 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);13716 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
13727 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);13717 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...@@ -13765,9 +13755,7 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13765 .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),13755 .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
13766 else => unreachable,13756 else => unreachable,
13767 };13757 };
13768 const zero_val = if (is_vector) b: {13758 const zero_val = try sema.splat(resolved_type, scalar_zero);
13769 break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
13770 } else scalar_zero;
13771 return sema.addConstant(resolved_type, zero_val);13759 return sema.addConstant(resolved_type, zero_val);
13772 }13760 }
13773 }13761 }
...@@ -13843,12 +13831,9 @@ fn addDivIntOverflowSafety(...@@ -13843,12 +13831,9 @@ fn addDivIntOverflowSafety(
13843 return;13831 return;
13844 }13832 }
1384513833
13846 const min_int = try resolved_type.minInt(sema.arena, mod);13834 const min_int = try resolved_type.minInt(mod);
13847 const neg_one_scalar = try mod.intValue(lhs_scalar_ty, -1);13835 const neg_one_scalar = try mod.intValue(lhs_scalar_ty, -1);
13848 const neg_one = if (resolved_type.zigTypeTag(mod) == .Vector)13836 const neg_one = try sema.splat(resolved_type, neg_one_scalar);
13849 try Value.Tag.repeated.create(sema.arena, neg_one_scalar)
13850 else
13851 neg_one_scalar;
1385213837
13853 // If the LHS is comptime-known to be not equal to the min int,13838 // If the LHS is comptime-known to be not equal to the min int,
13854 // no overflow is possible.13839 // no overflow is possible.
...@@ -13924,7 +13909,7 @@ fn addDivByZeroSafety(...@@ -13924,7 +13909,7 @@ fn addDivByZeroSafety(
13924 else13909 else
13925 try mod.floatValue(resolved_type.scalarType(mod), 0);13910 try mod.floatValue(resolved_type.scalarType(mod), 0);
13926 const ok = if (resolved_type.zigTypeTag(mod) == .Vector) ok: {13911 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);
13928 const zero = try sema.addConstant(resolved_type, zero_val);13913 const zero = try sema.addConstant(resolved_type, zero_val);
13929 const ok = try block.addCmpVector(casted_rhs, zero, .neq);13914 const ok = try block.addCmpVector(casted_rhs, zero, .neq);
13930 break :ok try block.addInst(.{13915 break :ok try block.addInst(.{
...@@ -14012,9 +13997,10 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -14012,9 +13997,10 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
14012 .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),13997 .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
14013 else => unreachable,13998 else => unreachable,
14014 };13999 };
14015 const zero_val = if (is_vector) b: {14000 const zero_val = if (is_vector) (try mod.intern(.{ .aggregate = .{
14016 break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);14001 .ty = resolved_type.ip_index,
14017 } else scalar_zero;14002 .storage = .{ .repeated_elem = scalar_zero.ip_index },
14003 } })).toValue() else scalar_zero;
14018 return sema.addConstant(resolved_type, zero_val);14004 return sema.addConstant(resolved_type, zero_val);
14019 }14005 }
14020 } else if (lhs_scalar_ty.isSignedInt(mod)) {14006 } else if (lhs_scalar_ty.isSignedInt(mod)) {
...@@ -14399,12 +14385,12 @@ fn zirOverflowArithmetic(...@@ -14399,12 +14385,12 @@ fn zirOverflowArithmetic(
14399 // Otherwise, if either of the argument is undefined, undefined is returned.14385 // Otherwise, if either of the argument is undefined, undefined is returned.
14400 if (maybe_lhs_val) |lhs_val| {14386 if (maybe_lhs_val) |lhs_val| {
14401 if (!lhs_val.isUndef(mod) and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema))) {14387 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 };
14403 }14389 }
14404 }14390 }
14405 if (maybe_rhs_val) |rhs_val| {14391 if (maybe_rhs_val) |rhs_val| {
14406 if (!rhs_val.isUndef(mod) and (try rhs_val.compareAllWithZeroAdvanced(.eq, sema))) {14392 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 };
14408 }14394 }
14409 }14395 }
14410 if (maybe_lhs_val) |lhs_val| {14396 if (maybe_lhs_val) |lhs_val| {
...@@ -14425,7 +14411,7 @@ fn zirOverflowArithmetic(...@@ -14425,7 +14411,7 @@ fn zirOverflowArithmetic(
14425 if (rhs_val.isUndef(mod)) {14411 if (rhs_val.isUndef(mod)) {
14426 break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef };14412 break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef };
14427 } else if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {14413 } 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 };
14429 } else if (maybe_lhs_val) |lhs_val| {14415 } else if (maybe_lhs_val) |lhs_val| {
14430 if (lhs_val.isUndef(mod)) {14416 if (lhs_val.isUndef(mod)) {
14431 break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef };14417 break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef };
...@@ -14444,9 +14430,9 @@ fn zirOverflowArithmetic(...@@ -14444,9 +14430,9 @@ fn zirOverflowArithmetic(
14444 if (maybe_lhs_val) |lhs_val| {14430 if (maybe_lhs_val) |lhs_val| {
14445 if (!lhs_val.isUndef(mod)) {14431 if (!lhs_val.isUndef(mod)) {
14446 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {14432 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
14447 break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, zero), .inst = lhs };14433 break :result .{ .overflow_bit = try sema.splat(dest_ty, zero), .inst = lhs };
14448 } else if (try sema.compareAll(lhs_val, .eq, try maybeRepeated(sema, dest_ty, scalar_one), dest_ty)) {14434 } else if (try sema.compareAll(lhs_val, .eq, try sema.splat(dest_ty, scalar_one), dest_ty)) {
14449 break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, zero), .inst = rhs };14435 break :result .{ .overflow_bit = try sema.splat(dest_ty, zero), .inst = rhs };
14450 }14436 }
14451 }14437 }
14452 }14438 }
...@@ -14454,9 +14440,9 @@ fn zirOverflowArithmetic(...@@ -14454,9 +14440,9 @@ fn zirOverflowArithmetic(
14454 if (maybe_rhs_val) |rhs_val| {14440 if (maybe_rhs_val) |rhs_val| {
14455 if (!rhs_val.isUndef(mod)) {14441 if (!rhs_val.isUndef(mod)) {
14456 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {14442 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
14457 break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, zero), .inst = rhs };14443 break :result .{ .overflow_bit = try sema.splat(dest_ty, zero), .inst = rhs };
14458 } else if (try sema.compareAll(rhs_val, .eq, try maybeRepeated(sema, dest_ty, scalar_one), dest_ty)) {14444 } else if (try sema.compareAll(rhs_val, .eq, try sema.splat(dest_ty, scalar_one), dest_ty)) {
14459 break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, zero), .inst = lhs };14445 break :result .{ .overflow_bit = try sema.splat(dest_ty, zero), .inst = lhs };
14460 }14446 }
14461 }14447 }
14462 }14448 }
...@@ -14478,12 +14464,12 @@ fn zirOverflowArithmetic(...@@ -14478,12 +14464,12 @@ fn zirOverflowArithmetic(
14478 // Oterhwise if either of the arguments is undefined, both results are undefined.14464 // Oterhwise if either of the arguments is undefined, both results are undefined.
14479 if (maybe_lhs_val) |lhs_val| {14465 if (maybe_lhs_val) |lhs_val| {
14480 if (!lhs_val.isUndef(mod) and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema))) {14466 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 };
14482 }14468 }
14483 }14469 }
14484 if (maybe_rhs_val) |rhs_val| {14470 if (maybe_rhs_val) |rhs_val| {
14485 if (!rhs_val.isUndef(mod) and (try rhs_val.compareAllWithZeroAdvanced(.eq, sema))) {14471 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 };
14487 }14473 }
14488 }14474 }
14489 if (maybe_lhs_val) |lhs_val| {14475 if (maybe_lhs_val) |lhs_val| {
...@@ -14544,10 +14530,14 @@ fn zirOverflowArithmetic(...@@ -14544,10 +14530,14 @@ fn zirOverflowArithmetic(
14544 return block.addAggregateInit(tuple_ty, element_refs);14530 return block.addAggregateInit(tuple_ty, element_refs);
14545}14531}
1454614532
14547fn maybeRepeated(sema: *Sema, ty: Type, val: Value) !Value {14533fn splat(sema: *Sema, ty: Type, val: Value) !Value {
14548 const mod = sema.mod;14534 const mod = sema.mod;
14549 if (ty.zigTypeTag(mod) != .Vector) return val;14535 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();
14551}14541}
1455214542
14553fn overflowArithmeticTupleType(sema: *Sema, ty: Type) !Type {14543fn overflowArithmeticTupleType(sema: *Sema, ty: Type) !Type {
...@@ -14603,8 +14593,6 @@ fn analyzeArithmetic(...@@ -14603,8 +14593,6 @@ fn analyzeArithmetic(
14603 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },14593 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
14604 });14594 });
1460514595
14606 const is_vector = resolved_type.zigTypeTag(mod) == .Vector;
14607
14608 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);14596 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
14609 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);14597 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
1461014598
...@@ -14853,9 +14841,7 @@ fn analyzeArithmetic(...@@ -14853,9 +14841,7 @@ fn analyzeArithmetic(
14853 } else if (resolved_type.isAnyFloat()) {14841 } else if (resolved_type.isAnyFloat()) {
14854 break :lz;14842 break :lz;
14855 }14843 }
14856 const zero_val = if (is_vector) b: {14844 const zero_val = try sema.splat(resolved_type, scalar_zero);
14857 break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
14858 } else scalar_zero;
14859 return sema.addConstant(resolved_type, zero_val);14845 return sema.addConstant(resolved_type, zero_val);
14860 }14846 }
14861 if (try sema.compareAll(lhs_val, .eq, try mod.intValue(resolved_type, 1), resolved_type)) {14847 if (try sema.compareAll(lhs_val, .eq, try mod.intValue(resolved_type, 1), resolved_type)) {
...@@ -14886,9 +14872,7 @@ fn analyzeArithmetic(...@@ -14886,9 +14872,7 @@ fn analyzeArithmetic(
14886 } else if (resolved_type.isAnyFloat()) {14872 } else if (resolved_type.isAnyFloat()) {
14887 break :rz;14873 break :rz;
14888 }14874 }
14889 const zero_val = if (is_vector) b: {14875 const zero_val = try sema.splat(resolved_type, scalar_zero);
14890 break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
14891 } else scalar_zero;
14892 return sema.addConstant(resolved_type, zero_val);14876 return sema.addConstant(resolved_type, zero_val);
14893 }14877 }
14894 if (try sema.compareAll(rhs_val, .eq, try mod.intValue(resolved_type, 1), resolved_type)) {14878 if (try sema.compareAll(rhs_val, .eq, try mod.intValue(resolved_type, 1), resolved_type)) {
...@@ -14931,9 +14915,7 @@ fn analyzeArithmetic(...@@ -14931,9 +14915,7 @@ fn analyzeArithmetic(
14931 if (maybe_lhs_val) |lhs_val| {14915 if (maybe_lhs_val) |lhs_val| {
14932 if (!lhs_val.isUndef(mod)) {14916 if (!lhs_val.isUndef(mod)) {
14933 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {14917 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
14934 const zero_val = if (is_vector) b: {14918 const zero_val = try sema.splat(resolved_type, scalar_zero);
14935 break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
14936 } else scalar_zero;
14937 return sema.addConstant(resolved_type, zero_val);14919 return sema.addConstant(resolved_type, zero_val);
14938 }14920 }
14939 if (try sema.compareAll(lhs_val, .eq, try mod.intValue(resolved_type, 1), resolved_type)) {14921 if (try sema.compareAll(lhs_val, .eq, try mod.intValue(resolved_type, 1), resolved_type)) {
...@@ -14947,9 +14929,7 @@ fn analyzeArithmetic(...@@ -14947,9 +14929,7 @@ fn analyzeArithmetic(
14947 return sema.addConstUndef(resolved_type);14929 return sema.addConstUndef(resolved_type);
14948 }14930 }
14949 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {14931 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
14950 const zero_val = if (is_vector) b: {14932 const zero_val = try sema.splat(resolved_type, scalar_zero);
14951 break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
14952 } else scalar_zero;
14953 return sema.addConstant(resolved_type, zero_val);14933 return sema.addConstant(resolved_type, zero_val);
14954 }14934 }
14955 if (try sema.compareAll(rhs_val, .eq, try mod.intValue(resolved_type, 1), resolved_type)) {14935 if (try sema.compareAll(rhs_val, .eq, try mod.intValue(resolved_type, 1), resolved_type)) {
...@@ -14979,9 +14959,7 @@ fn analyzeArithmetic(...@@ -14979,9 +14959,7 @@ fn analyzeArithmetic(
14979 if (maybe_lhs_val) |lhs_val| {14959 if (maybe_lhs_val) |lhs_val| {
14980 if (!lhs_val.isUndef(mod)) {14960 if (!lhs_val.isUndef(mod)) {
14981 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {14961 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
14982 const zero_val = if (is_vector) b: {14962 const zero_val = try sema.splat(resolved_type, scalar_zero);
14983 break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
14984 } else scalar_zero;
14985 return sema.addConstant(resolved_type, zero_val);14963 return sema.addConstant(resolved_type, zero_val);
14986 }14964 }
14987 if (try sema.compareAll(lhs_val, .eq, try mod.intValue(resolved_type, 1), resolved_type)) {14965 if (try sema.compareAll(lhs_val, .eq, try mod.intValue(resolved_type, 1), resolved_type)) {
...@@ -14994,9 +14972,7 @@ fn analyzeArithmetic(...@@ -14994,9 +14972,7 @@ fn analyzeArithmetic(
14994 return sema.addConstUndef(resolved_type);14972 return sema.addConstUndef(resolved_type);
14995 }14973 }
14996 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {14974 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
14997 const zero_val = if (is_vector) b: {14975 const zero_val = try sema.splat(resolved_type, scalar_zero);
14998 break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
14999 } else scalar_zero;
15000 return sema.addConstant(resolved_type, zero_val);14976 return sema.addConstant(resolved_type, zero_val);
15001 }14977 }
15002 if (try sema.compareAll(rhs_val, .eq, try mod.intValue(resolved_type, 1), resolved_type)) {14978 if (try sema.compareAll(rhs_val, .eq, try mod.intValue(resolved_type, 1), resolved_type)) {
...@@ -15138,7 +15114,7 @@ fn analyzePtrArithmetic(...@@ -15138,7 +15114,7 @@ fn analyzePtrArithmetic(
15138 if (air_tag == .ptr_sub) {15114 if (air_tag == .ptr_sub) {
15139 return sema.fail(block, op_src, "TODO implement Sema comptime pointer subtraction", .{});15115 return sema.fail(block, op_src, "TODO implement Sema comptime pointer subtraction", .{});
15140 }15116 }
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);
15142 return sema.addConstant(new_ptr_ty, new_ptr_val);15118 return sema.addConstant(new_ptr_ty, new_ptr_val);
15143 } else break :rs offset_src;15119 } else break :rs offset_src;
15144 } else break :rs ptr_src;15120 } else break :rs ptr_src;
...@@ -15184,7 +15160,7 @@ fn zirAsm(...@@ -15184,7 +15160,7 @@ fn zirAsm(
15184 const inputs_len = @truncate(u5, extended.small >> 5);15160 const inputs_len = @truncate(u5, extended.small >> 5);
15185 const clobbers_len = @truncate(u5, extended.small >> 10);15161 const clobbers_len = @truncate(u5, extended.small >> 10);
15186 const is_volatile = @truncate(u1, extended.small >> 15) != 0;15162 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
15189 const asm_source: []const u8 = if (tmpl_is_expr) blk: {15165 const asm_source: []const u8 = if (tmpl_is_expr) blk: {
15190 const tmpl = @intToEnum(Zir.Inst.Ref, extra.data.asm_source);15166 const tmpl = @intToEnum(Zir.Inst.Ref, extra.data.asm_source);
...@@ -15387,12 +15363,7 @@ fn zirCmpEq(...@@ -15387,12 +15363,7 @@ fn zirCmpEq(
15387 if (lval.isUndef(mod) or rval.isUndef(mod)) {15363 if (lval.isUndef(mod) or rval.isUndef(mod)) {
15388 return sema.addConstUndef(Type.bool);15364 return sema.addConstUndef(Type.bool);
15389 }15365 }
15390 // TODO optimisation opportunity: evaluate if mem.eql is faster with the names,15366 if (lval.toIntern() == rval.toIntern()) {
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)) {
15396 return Air.Inst.Ref.bool_true;15367 return Air.Inst.Ref.bool_true;
15397 } else {15368 } else {
15398 return Air.Inst.Ref.bool_false;15369 return Air.Inst.Ref.bool_false;
...@@ -15650,8 +15621,8 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -15650,8 +15621,8 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
15650 .AnyFrame,15621 .AnyFrame,
15651 => {},15622 => {},
15652 }15623 }
15653 const val = try ty.lazyAbiSize(mod, sema.arena);15624 const val = try ty.lazyAbiSize(mod);
15654 if (val.isLazySize()) {15625 if (val.isLazySize(mod)) {
15655 try sema.queueFullTypeResolution(ty);15626 try sema.queueFullTypeResolution(ty);
15656 }15627 }
15657 return sema.addConstant(Type.comptime_int, val);15628 return sema.addConstant(Type.comptime_int, val);
...@@ -15760,11 +15731,11 @@ fn zirClosureGet(...@@ -15760,11 +15731,11 @@ fn zirClosureGet(
15760 scope = scope.parent.?;15731 scope = scope.parent.?;
15761 };15732 };
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) {
15764 const msg = msg: {15735 const msg = msg: {
15765 const name = name: {15736 const name = name: {
15766 const file = sema.owner_decl.getFileScope(mod);15737 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| {
15768 // In this case we emit a warning + a less precise source location.15739 // In this case we emit a warning + a less precise source location.
15769 log.warn("unable to load {s}: {s}", .{15740 log.warn("unable to load {s}: {s}", .{
15770 file.sub_file_path, @errorName(err),15741 file.sub_file_path, @errorName(err),
...@@ -15788,11 +15759,11 @@ fn zirClosureGet(...@@ -15788,11 +15759,11 @@ fn zirClosureGet(
15788 return sema.failWithOwnedErrorMsg(msg);15759 return sema.failWithOwnedErrorMsg(msg);
15789 }15760 }
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) {
15792 const msg = msg: {15763 const msg = msg: {
15793 const name = name: {15764 const name = name: {
15794 const file = sema.owner_decl.getFileScope(mod);15765 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| {
15796 // In this case we emit a warning + a less precise source location.15767 // In this case we emit a warning + a less precise source location.
15797 log.warn("unable to load {s}: {s}", .{15768 log.warn("unable to load {s}: {s}", .{
15798 file.sub_file_path, @errorName(err),15769 file.sub_file_path, @errorName(err),
...@@ -15868,14 +15839,17 @@ fn zirBuiltinSrc(...@@ -15868,14 +15839,17 @@ fn zirBuiltinSrc(
15868 const func_name_val = blk: {15839 const func_name_val = blk: {
15869 var anon_decl = try block.startAnonDecl();15840 var anon_decl = try block.startAnonDecl();
15870 defer anon_decl.deinit();15841 defer anon_decl.deinit();
15871 const name = std.mem.span(fn_owner_decl.name);15842 const name = mem.span(fn_owner_decl.name);
15872 const bytes = try anon_decl.arena().dupe(u8, name[0 .. name.len + 1]);15843 const bytes = try anon_decl.arena().dupe(u8, name[0 .. name.len + 1]);
15873 const new_decl = try anon_decl.finish(15844 const new_decl = try anon_decl.finish(
15874 try Type.array(anon_decl.arena(), bytes.len - 1, try mod.intValue(Type.u8, 0), Type.u8, mod),15845 try Type.array(anon_decl.arena(), bytes.len - 1, try mod.intValue(Type.u8, 0), Type.u8, mod),
15875 try Value.Tag.bytes.create(anon_decl.arena(), bytes),15846 try Value.Tag.bytes.create(anon_decl.arena(), bytes),
15876 0, // default alignment15847 0, // default alignment
15877 );15848 );
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 } });
15879 };15853 };
1588015854
15881 const file_name_val = blk: {15855 const file_name_val = blk: {
...@@ -15888,27 +15862,35 @@ fn zirBuiltinSrc(...@@ -15888,27 +15862,35 @@ fn zirBuiltinSrc(
15888 try Value.Tag.bytes.create(anon_decl.arena(), name[0 .. name.len + 1]),15862 try Value.Tag.bytes.create(anon_decl.arena(), name[0 .. name.len + 1]),
15889 0, // default alignment15863 0, // default alignment
15890 );15864 );
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 } });
15892 };15869 };
1589315870
15894 const field_values = try sema.arena.alloc(Value, 4);15871 const src_loc_ty = try sema.getBuiltinType("SourceLocation");
15895 // file: [:0]const u8,15872 const fields = .{
15896 field_values[0] = file_name_val;15873 // file: [:0]const u8,
15897 // fn_name: [:0]const u8,15874 file_name_val,
15898 field_values[1] = func_name_val;15875 // fn_name: [:0]const u8,
15899 // line: u3215876 func_name_val,
15900 field_values[2] = try Value.Tag.runtime_value.create(sema.arena, try mod.intValue(Type.u32, extra.line + 1));15877 // line: u32,
15901 // column: u32,15878 try mod.intern(.{ .runtime_value = .{
15902 field_values[3] = try mod.intValue(Type.u32, extra.column + 1);15879 .ty = .u32_type,
1590315880 .val = (try mod.intValue(Type.u32, extra.line + 1)).ip_index,
15904 return sema.addConstant(15881 } }),
15905 try sema.getBuiltinType("SourceLocation"),15882 // column: u32,
15906 try Value.Tag.aggregate.create(sema.arena, field_values),15883 (try mod.intValue(Type.u32, extra.column + 1)).ip_index,
15907 );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());
15908}15889}
1590915890
15910fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {15891fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
15911 const mod = sema.mod;15892 const mod = sema.mod;
15893 const gpa = sema.gpa;
15912 const inst_data = sema.code.instructions.items(.data)[inst].un_node;15894 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
15913 const src = inst_data.src();15895 const src = inst_data.src();
15914 const ty = try sema.resolveType(block, src, inst_data.operand);15896 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...@@ -15916,69 +15898,20 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
15916 const type_info_tag_ty = type_info_ty.unionTagType(mod).?;15898 const type_info_tag_ty = type_info_ty.unionTagType(mod).?;
1591715899
15918 switch (ty.zigTypeTag(mod)) {15900 switch (ty.zigTypeTag(mod)) {
15919 .Type => return sema.addConstant(15901 .Type,
15920 type_info_ty,15902 .Void,
15921 try Value.Tag.@"union".create(sema.arena, .{15903 .Bool,
15922 .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Type)),15904 .NoReturn,
15923 .val = Value.void,15905 .ComptimeFloat,
15924 }),15906 .ComptimeInt,
15925 ),15907 .Undefined,
15926 .Void => return sema.addConstant(15908 .Null,
15927 type_info_ty,15909 .EnumLiteral,
15928 try Value.Tag.@"union".create(sema.arena, .{15910 => |type_info_tag| return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
15929 .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Void)),15911 .ty = type_info_ty.ip_index,
15930 .val = Value.void,15912 .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(type_info_tag))).ip_index,
15931 }),15913 .val = .void_value,
15932 ),15914 } })).toValue()),
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 ),
15982 .Fn => {15915 .Fn => {
15983 // TODO: look into memoizing this result.15916 // TODO: look into memoizing this result.
15984 const info = mod.typeToFunc(ty).?;15917 const info = mod.typeToFunc(ty).?;
...@@ -15986,11 +15919,34 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -15986,11 +15919,34 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
15986 var params_anon_decl = try block.startAnonDecl();15919 var params_anon_decl = try block.startAnonDecl();
15987 defer params_anon_decl.deinit();15920 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);
15990 for (param_vals, info.param_types, 0..) |*param_val, param_ty, i| {15946 for (param_vals, info.param_types, 0..) |*param_val, param_ty, i| {
15991 const is_generic = param_ty == .generic_poison_type;15947 const is_generic = param_ty == .generic_poison_type;
15992 const param_ty_val = try mod.intern_pool.get(mod.gpa, .{ .opt = .{15948 const param_ty_val = try mod.intern_pool.get(gpa, .{ .opt = .{
15993 .ty = try mod.intern_pool.get(mod.gpa, .{ .opt_type = .type_type }),15949 .ty = try mod.intern_pool.get(gpa, .{ .opt_type = .type_type }),
15994 .val = if (is_generic) .none else param_ty,15950 .val = if (is_generic) .none else param_ty,
15995 } });15951 } });
1599615952
...@@ -15999,87 +15955,74 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -15999,87 +15955,74 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
15999 break :blk @truncate(u1, info.noalias_bits >> index) != 0;15955 break :blk @truncate(u1, info.noalias_bits >> index) != 0;
16000 };15956 };
1600115957
16002 const param_fields = try params_anon_decl.arena().create([3]Value);15958 const param_fields = .{
16003 param_fields.* = .{
16004 // is_generic: bool,15959 // is_generic: bool,
16005 Value.makeBool(is_generic),15960 Value.makeBool(is_generic).ip_index,
16006 // is_noalias: bool,15961 // is_noalias: bool,
16007 Value.makeBool(is_noalias),15962 Value.makeBool(is_noalias).ip_index,
16008 // type: ?type,15963 // type: ?type,
16009 param_ty_val.toValue(),15964 param_ty_val,
16010 };15965 };
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 } });
16012 }15970 }
1601315971
16014 const args_val = v: {15972 const args_val = v: {
16015 const fn_info_decl_index = (try sema.namespaceLookup(15973 const args_slice_ty = try mod.ptrType(.{
16016 block,15974 .elem_type = param_info_ty.ip_index,
16017 src,15975 .size = .Slice,
16018 type_info_ty.getNamespaceIndex(mod).unwrap().?,15976 .is_const = true,
16019 "Fn",15977 });
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();
16035 const new_decl = try params_anon_decl.finish(15978 const new_decl = try params_anon_decl.finish(
16036 try mod.arrayType(.{15979 try mod.arrayType(.{
16037 .len = param_vals.len,15980 .len = param_vals.len,
16038 .child = param_ty.ip_index,15981 .child = param_info_ty.ip_index,
16039 .sentinel = .none,15982 .sentinel = .none,
16040 }),15983 }),
16041 try Value.Tag.aggregate.create(15984 (try mod.intern(.{ .aggregate = .{
16042 params_anon_decl.arena(),15985 .ty = args_slice_ty.ip_index,
16043 param_vals,15986 .storage = .{ .elems = param_vals },
16044 ),15987 } })).toValue(),
16045 0, // default alignment15988 0, // default alignment
16046 );15989 );
16047 break :v try Value.Tag.slice.create(sema.arena, .{15990 break :v try mod.intern(.{ .ptr = .{
16048 .ptr = try Value.Tag.decl_ref.create(sema.arena, new_decl),15991 .ty = args_slice_ty.ip_index,
16049 .len = try mod.intValue(Type.usize, param_vals.len),15992 .addr = .{ .decl = new_decl },
16050 });15993 .len = (try mod.intValue(Type.usize, param_vals.len)).ip_index,
15994 } });
16051 };15995 };
1605215996
16053 const ret_ty_opt = try mod.intern_pool.get(mod.gpa, .{ .opt = .{15997 const ret_ty_opt = try mod.intern(.{ .opt = .{
16054 .ty = try mod.intern_pool.get(mod.gpa, .{ .opt_type = .type_type }),15998 .ty = try mod.intern_pool.get(gpa, .{ .opt_type = .type_type }),
16055 .val = if (info.return_type == .generic_poison_type) .none else info.return_type,15999 .val = if (info.return_type == .generic_poison_type) .none else info.return_type,
16056 } });16000 } });
1605716001
16058 const callconv_ty = try sema.getBuiltinType("CallingConvention");16002 const callconv_ty = try sema.getBuiltinType("CallingConvention");
1605916003
16060 const field_values = try sema.arena.create([6]Value);16004 const field_values = .{
16061 field_values.* = .{
16062 // calling_convention: CallingConvention,16005 // calling_convention: CallingConvention,
16063 try mod.enumValueFieldIndex(callconv_ty, @enumToInt(info.cc)),16006 (try mod.enumValueFieldIndex(callconv_ty, @enumToInt(info.cc))).ip_index,
16064 // alignment: comptime_int,16007 // 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,
16066 // is_generic: bool,16009 // is_generic: bool,
16067 Value.makeBool(info.is_generic),16010 Value.makeBool(info.is_generic).ip_index,
16068 // is_var_args: bool,16011 // is_var_args: bool,
16069 Value.makeBool(info.is_var_args),16012 Value.makeBool(info.is_var_args).ip_index,
16070 // return_type: ?type,16013 // return_type: ?type,
16071 ret_ty_opt.toValue(),16014 ret_ty_opt,
16072 // args: []const Fn.Param,16015 // args: []const Fn.Param,
16073 args_val,16016 args_val,
16074 };16017 };
1607516018 return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
16076 return sema.addConstant(16019 .ty = type_info_ty.ip_index,
16077 type_info_ty,16020 .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Fn))).ip_index,
16078 try Value.Tag.@"union".create(sema.arena, .{16021 .val = try mod.intern(.{ .aggregate = .{
16079 .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Fn)),16022 .ty = fn_info_ty.ip_index,
16080 .val = try Value.Tag.aggregate.create(sema.arena, field_values),16023 .storage = .{ .elems = &field_values },
16081 }),16024 } }),
16082 );16025 } })).toValue());
16083 },16026 },
16084 .Int => {16027 .Int => {
16085 const signedness_ty = try sema.getBuiltinType("Signedness");16028 const signedness_ty = try sema.getBuiltinType("Signedness");
...@@ -16099,24 +16042,36 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16099,24 +16042,36 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16099 );16042 );
16100 },16043 },
16101 .Float => {16044 .Float => {
16102 const field_values = try sema.arena.alloc(Value, 1);16045 const float_info_decl_index = (try sema.namespaceLookup(
16103 // bits: u16,16046 block,
16104 field_values[0] = try mod.intValue(Type.u16, ty.bitSize(mod));16047 src,
1610516048 type_info_ty.getNamespaceIndex(mod).unwrap().?,
16106 return sema.addConstant(16049 "Float",
16107 type_info_ty,16050 )).?;
16108 try Value.Tag.@"union".create(sema.arena, .{16051 try mod.declareDeclDependency(sema.owner_decl_index, float_info_decl_index);
16109 .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Float)),16052 try sema.ensureDeclAnalyzed(float_info_decl_index);
16110 .val = try Value.Tag.aggregate.create(sema.arena, field_values),16053 const float_info_decl = mod.declPtr(float_info_decl_index);
16111 }),16054 const float_ty = float_info_decl.val.toType();
16112 );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());
16113 },16068 },
16114 .Pointer => {16069 .Pointer => {
16115 const info = ty.ptrInfo(mod);16070 const info = ty.ptrInfo(mod);
16116 const alignment = if (info.@"align" != 0)16071 const alignment = if (info.@"align" != 0)
16117 try mod.intValue(Type.comptime_int, info.@"align")16072 try mod.intValue(Type.comptime_int, info.@"align")
16118 else16073 else
16119 try info.pointee_type.lazyAbiAlignment(mod, sema.arena);16074 try info.pointee_type.lazyAbiAlignment(mod);
1612016075
16121 const addrspace_ty = try sema.getBuiltinType("AddressSpace");16076 const addrspace_ty = try sema.getBuiltinType("AddressSpace");
16122 const pointer_ty = t: {16077 const pointer_ty = t: {
...@@ -16245,9 +16200,10 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16245,9 +16200,10 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16245 // Build our list of Error values16200 // Build our list of Error values
16246 // Optional value is only null if anyerror16201 // Optional value is only null if anyerror
16247 // Value can be zero-length slice otherwise16202 // 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: {
16249 const names = ty.errorSetNames(mod);16204 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);
16251 for (vals, names) |*field_val, name_ip| {16207 for (vals, names) |*field_val, name_ip| {
16252 const name = mod.intern_pool.stringToSlice(name_ip);16208 const name = mod.intern_pool.stringToSlice(name_ip);
16253 const name_val = v: {16209 const name_val = v: {
...@@ -16259,70 +16215,91 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16259,70 +16215,91 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16259 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),16215 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
16260 0, // default alignment16216 0, // default alignment
16261 );16217 );
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 } });
16263 };16222 };
1626416223
16265 const error_field_fields = try fields_anon_decl.arena().create([1]Value);16224 const error_field_fields = .{
16266 error_field_fields.* = .{
16267 // name: []const u8,16225 // name: []const u8,
16268 name_val,16226 name_val,
16269 };16227 };
1627016228 field_val.* = try mod.intern(.{ .aggregate = .{
16271 field_val.* = try Value.Tag.aggregate.create(16229 .ty = error_field_ty.ip_index,
16272 fields_anon_decl.arena(),16230 .storage = .{ .elems = &error_field_fields },
16273 error_field_fields,16231 } });
16274 );
16275 }16232 }
1627616233
16277 break :blk vals;16234 break :blk vals;
16278 };16235 };
1627916236
16280 // Build our ?[]const Error value16237 // 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 });
16282 const new_decl = try fields_anon_decl.finish(16250 const new_decl = try fields_anon_decl.finish(
16283 try mod.arrayType(.{16251 array_errors_ty,
16284 .len = vals.len,16252 (try mod.intern(.{ .aggregate = .{
16285 .child = error_field_ty.ip_index,16253 .ty = array_errors_ty.ip_index,
16286 .sentinel = .none,16254 .storage = .{ .elems = vals },
16287 }),16255 } })).toValue(),
16288 try Value.Tag.aggregate.create(
16289 fields_anon_decl.arena(),
16290 vals,
16291 ),
16292 0, // default alignment16256 0, // default alignment
16293 );16257 );
1629416258 break :v try mod.intern(.{ .ptr = .{
16295 const new_decl_val = try Value.Tag.decl_ref.create(sema.arena, new_decl);16259 .ty = slice_errors_ty.ip_index,
16296 const slice_val = try Value.Tag.slice.create(sema.arena, .{16260 .addr = .{ .decl = new_decl },
16297 .ptr = new_decl_val,16261 } });
16298 .len = try mod.intValue(Type.usize, vals.len),16262 } else .none;
16299 });16263 const errors_val = try mod.intern(.{ .opt = .{
16300 break :v try Value.Tag.opt_payload.create(sema.arena, slice_val);16264 .ty = opt_slice_errors_ty.ip_index,
16301 } else Value.null;16265 .val = errors_payload_val,
16266 } });
1630216267
16303 // Construct Type{ .ErrorSet = errors_val }16268 // Construct Type{ .ErrorSet = errors_val }
16304 return sema.addConstant(16269 return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
16305 type_info_ty,16270 .ty = type_info_ty.ip_index,
16306 try Value.Tag.@"union".create(sema.arena, .{16271 .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.ErrorSet))).ip_index,
16307 .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.ErrorSet)),16272 .val = errors_val,
16308 .val = errors_val,16273 } })).toValue());
16309 }),
16310 );
16311 },16274 },
16312 .ErrorUnion => {16275 .ErrorUnion => {
16313 const field_values = try sema.arena.alloc(Value, 2);16276 const error_union_field_ty = t: {
16314 // error_set: type,16277 const error_union_field_ty_decl_index = (try sema.namespaceLookup(
16315 field_values[0] = ty.errorUnionSet(mod).toValue();16278 block,
16316 // payload: type,16279 src,
16317 field_values[1] = ty.errorUnionPayload(mod).toValue();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(16289 const field_values = .{
16320 type_info_ty,16290 // error_set: type,
16321 try Value.Tag.@"union".create(sema.arena, .{16291 ty.errorUnionSet(mod).ip_index,
16322 .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.ErrorUnion)),16292 // payload: type,
16323 .val = try Value.Tag.aggregate.create(sema.arena, field_values),16293 ty.errorUnionPayload(mod).ip_index,
16324 }),16294 };
16325 );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());
16326 },16303 },
16327 .Enum => {16304 .Enum => {
16328 // TODO: look into memoizing this result.16305 // TODO: look into memoizing this result.
...@@ -16346,7 +16323,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16346,7 +16323,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16346 break :t enum_field_ty_decl.val.toType();16323 break :t enum_field_ty_decl.val.toType();
16347 };16324 };
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
16351 for (enum_field_vals, 0..) |*field_val, i| {16329 for (enum_field_vals, 0..) |*field_val, i| {
16352 const name_ip = enum_type.names[i];16330 const name_ip = enum_type.names[i];
...@@ -16360,56 +16338,81 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16360,56 +16338,81 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16360 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),16338 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
16361 0, // default alignment16339 0, // default alignment
16362 );16340 );
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 } });
16364 };16345 };
1636516346
16366 const enum_field_fields = try fields_anon_decl.arena().create([2]Value);16347 const enum_field_fields = .{
16367 enum_field_fields.* = .{
16368 // name: []const u8,16348 // name: []const u8,
16369 name_val,16349 name_val,
16370 // value: comptime_int,16350 // value: comptime_int,
16371 try mod.intValue(Type.comptime_int, i),16351 (try mod.intValue(Type.comptime_int, i)).ip_index,
16372 };16352 };
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 } });
16374 }16357 }
1637516358
16376 const fields_val = v: {16359 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 });
16377 const new_decl = try fields_anon_decl.finish(16365 const new_decl = try fields_anon_decl.finish(
16378 try mod.arrayType(.{16366 fields_array_ty,
16379 .len = enum_field_vals.len,16367 (try mod.intern(.{ .aggregate = .{
16380 .child = enum_field_ty.ip_index,16368 .ty = fields_array_ty.ip_index,
16381 .sentinel = .none,16369 .storage = .{ .elems = enum_field_vals },
16382 }),16370 } })).toValue(),
16383 try Value.Tag.aggregate.create(
16384 fields_anon_decl.arena(),
16385 enum_field_vals,
16386 ),
16387 0, // default alignment16371 0, // default alignment
16388 );16372 );
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 } });
16390 };16381 };
1639116382
16392 const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, enum_type.namespace);16383 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);16385 const type_enum_ty = t: {
16395 field_values.* = .{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 = .{
16396 // tag_type: type,16399 // tag_type: type,
16397 enum_type.tag_ty.toValue(),16400 enum_type.tag_ty,
16398 // fields: []const EnumField,16401 // fields: []const EnumField,
16399 fields_val,16402 fields_val,
16400 // decls: []const Declaration,16403 // decls: []const Declaration,
16401 decls_val,16404 decls_val,
16402 // is_exhaustive: bool,16405 // is_exhaustive: bool,
16403 is_exhaustive,16406 is_exhaustive.ip_index,
16404 };16407 };
1640516408 return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
16406 return sema.addConstant(16409 .ty = type_info_ty.ip_index,
16407 type_info_ty,16410 .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Enum))).ip_index,
16408 try Value.Tag.@"union".create(sema.arena, .{16411 .val = try mod.intern(.{ .aggregate = .{
16409 .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Enum)),16412 .ty = type_enum_ty.ip_index,
16410 .val = try Value.Tag.aggregate.create(sema.arena, field_values),16413 .storage = .{ .elems = &field_values },
16411 }),16414 } }),
16412 );16415 } })).toValue());
16413 },16416 },
16414 .Union => {16417 .Union => {
16415 // TODO: look into memoizing this result.16418 // TODO: look into memoizing this result.
...@@ -16417,6 +16420,19 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16417,6 +16420,19 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16417 var fields_anon_decl = try block.startAnonDecl();16420 var fields_anon_decl = try block.startAnonDecl();
16418 defer fields_anon_decl.deinit();16421 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
16420 const union_field_ty = t: {16436 const union_field_ty = t: {
16421 const union_field_ty_decl_index = (try sema.namespaceLookup(16437 const union_field_ty_decl_index = (try sema.namespaceLookup(
16422 block,16438 block,
...@@ -16435,7 +16451,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16435,7 +16451,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16435 const layout = union_ty.containerLayout(mod);16451 const layout = union_ty.containerLayout(mod);
1643616452
16437 const union_fields = union_ty.unionFields(mod);16453 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
16440 for (union_field_vals, 0..) |*field_val, i| {16457 for (union_field_vals, 0..) |*field_val, i| {
16441 const field = union_fields.values()[i];16458 const field = union_fields.values()[i];
...@@ -16449,51 +16466,62 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16449,51 +16466,62 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16449 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),16466 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
16450 0, // default alignment16467 0, // default alignment
16451 );16468 );
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 } });
16453 };16473 };
1645416474
16455 const union_field_fields = try fields_anon_decl.arena().create([3]Value);
16456 const alignment = switch (layout) {16475 const alignment = switch (layout) {
16457 .Auto, .Extern => try sema.unionFieldAlignment(field),16476 .Auto, .Extern => try sema.unionFieldAlignment(field),
16458 .Packed => 0,16477 .Packed => 0,
16459 };16478 };
1646016479
16461 union_field_fields.* = .{16480 const union_field_fields = .{
16462 // name: []const u8,16481 // name: []const u8,
16463 name_val,16482 name_val,
16464 // type: type,16483 // type: type,
16465 field.ty.toValue(),16484 field.ty.ip_index,
16466 // alignment: comptime_int,16485 // alignment: comptime_int,
16467 try mod.intValue(Type.comptime_int, alignment),16486 (try mod.intValue(Type.comptime_int, alignment)).ip_index,
16468 };16487 };
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 } });
16470 }16492 }
1647116493
16472 const fields_val = v: {16494 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 });
16473 const new_decl = try fields_anon_decl.finish(16500 const new_decl = try fields_anon_decl.finish(
16474 try mod.arrayType(.{16501 array_fields_ty,
16475 .len = union_field_vals.len,16502 (try mod.intern(.{ .aggregate = .{
16476 .child = union_field_ty.ip_index,16503 .ty = array_fields_ty.ip_index,
16477 .sentinel = .none,16504 .storage = .{ .elems = union_field_vals },
16478 }),16505 } })).toValue(),
16479 try Value.Tag.aggregate.create(
16480 fields_anon_decl.arena(),
16481 try fields_anon_decl.arena().dupe(Value, union_field_vals),
16482 ),
16483 0, // default alignment16506 0, // default alignment
16484 );16507 );
16485 break :v try Value.Tag.slice.create(sema.arena, .{16508 break :v try mod.intern(.{ .ptr = .{
16486 .ptr = try Value.Tag.decl_ref.create(sema.arena, new_decl),16509 .ty = (try mod.ptrType(.{
16487 .len = try mod.intValue(Type.usize, union_field_vals.len),16510 .elem_type = union_field_ty.ip_index,
16488 });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 } });
16489 };16517 };
1649016518
16491 const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, union_ty.getNamespaceIndex(mod));16519 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: {16521 const enum_tag_ty_val = try mod.intern(.{ .opt = .{
16494 const ty_val = tag_ty.toValue();16522 .ty = (try mod.optionalType(.type_type)).ip_index,
16495 break :v try Value.Tag.opt_payload.create(sema.arena, ty_val);16523 .val = if (union_ty.unionTagType(mod)) |tag_ty| tag_ty.ip_index else .none,
16496 } else Value.null;16524 } });
1649716525
16498 const container_layout_ty = t: {16526 const container_layout_ty = t: {
16499 const decl_index = (try sema.namespaceLookup(16527 const decl_index = (try sema.namespaceLookup(
...@@ -16508,10 +16536,9 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16508,10 +16536,9 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16508 break :t decl.val.toType();16536 break :t decl.val.toType();
16509 };16537 };
1651016538
16511 const field_values = try sema.arena.create([4]Value);16539 const field_values = .{
16512 field_values.* = .{
16513 // layout: ContainerLayout,16540 // layout: ContainerLayout,
16514 try mod.enumValueFieldIndex(container_layout_ty, @enumToInt(layout)),16541 (try mod.enumValueFieldIndex(container_layout_ty, @enumToInt(layout))).ip_index,
1651516542
16516 // tag_type: ?type,16543 // tag_type: ?type,
16517 enum_tag_ty_val,16544 enum_tag_ty_val,
...@@ -16520,14 +16547,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16520,14 +16547,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16520 // decls: []const Declaration,16547 // decls: []const Declaration,
16521 decls_val,16548 decls_val,
16522 };16549 };
1652316550 return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
16524 return sema.addConstant(16551 .ty = type_info_ty.ip_index,
16525 type_info_ty,16552 .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Union))).ip_index,
16526 try Value.Tag.@"union".create(sema.arena, .{16553 .val = try mod.intern(.{ .aggregate = .{
16527 .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Union)),16554 .ty = type_union_ty.ip_index,
16528 .val = try Value.Tag.aggregate.create(sema.arena, field_values),16555 .storage = .{ .elems = &field_values },
16529 }),16556 } }),
16530 );16557 } })).toValue());
16531 },16558 },
16532 .Struct => {16559 .Struct => {
16533 // TODO: look into memoizing this result.16560 // TODO: look into memoizing this result.
...@@ -16535,6 +16562,19 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16535,6 +16562,19 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16535 var fields_anon_decl = try block.startAnonDecl();16562 var fields_anon_decl = try block.startAnonDecl();
16536 defer fields_anon_decl.deinit();16563 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
16538 const struct_field_ty = t: {16578 const struct_field_ty = t: {
16539 const struct_field_ty_decl_index = (try sema.namespaceLookup(16579 const struct_field_ty_decl_index = (try sema.namespaceLookup(
16540 block,16580 block,
...@@ -16547,14 +16587,17 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16547,14 +16587,17 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16547 const struct_field_ty_decl = mod.declPtr(struct_field_ty_decl_index);16587 const struct_field_ty_decl = mod.declPtr(struct_field_ty_decl_index);
16548 break :t struct_field_ty_decl.val.toType();16588 break :t struct_field_ty_decl.val.toType();
16549 };16589 };
16590
16550 const struct_ty = try sema.resolveTypeFields(ty);16591 const struct_ty = try sema.resolveTypeFields(ty);
16551 try sema.resolveTypeLayout(ty); // Getting alignment requires type layout16592 try sema.resolveTypeLayout(ty); // Getting alignment requires type layout
16552 const layout = struct_ty.containerLayout(mod);16593 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: {
16555 const struct_type = switch (mod.intern_pool.indexToKey(struct_ty.ip_index)) {16598 const struct_type = switch (mod.intern_pool.indexToKey(struct_ty.ip_index)) {
16556 .anon_struct_type => |tuple| {16599 .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);
16558 for (16601 for (
16559 tuple.types,16602 tuple.types,
16560 tuple.values,16603 tuple.values,
...@@ -16574,38 +16617,40 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16574,38 +16617,40 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16574 try Value.Tag.bytes.create(anon_decl.arena(), bytes.ptr[0 .. bytes.len + 1]),16617 try Value.Tag.bytes.create(anon_decl.arena(), bytes.ptr[0 .. bytes.len + 1]),
16575 0, // default alignment16618 0, // default alignment
16576 );16619 );
16577 break :v try Value.Tag.slice.create(fields_anon_decl.arena(), .{16620 break :v try mod.intern(.{ .ptr = .{
16578 .ptr = try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl),16621 .ty = .slice_const_u8_type,
16579 .len = try mod.intValue(Type.usize, bytes.len),16622 .addr = .{ .decl = new_decl },
16580 });16623 .len = (try mod.intValue(Type.usize, bytes.len)).ip_index,
16624 } });
16581 };16625 };
1658216626
16583 const struct_field_fields = try fields_anon_decl.arena().create([5]Value);
16584 const is_comptime = field_val != .none;16627 const is_comptime = field_val != .none;
16585 const opt_default_val = if (is_comptime) field_val.toValue() else null;16628 const opt_default_val = if (is_comptime) field_val.toValue() else null;
16586 const default_val_ptr = try sema.optRefValue(block, field_ty.toType(), opt_default_val);16629 const default_val_ptr = try sema.optRefValue(block, field_ty.toType(), opt_default_val);
16587 struct_field_fields.* = .{16630 const struct_field_fields = .{
16588 // name: []const u8,16631 // name: []const u8,
16589 name_val,16632 name_val,
16590 // type: type,16633 // type: type,
16591 field_ty.toValue(),16634 field_ty,
16592 // default_value: ?*const anyopaque,16635 // default_value: ?*const anyopaque,
16593 try default_val_ptr.copy(fields_anon_decl.arena()),16636 default_val_ptr.ip_index,
16594 // is_comptime: bool,16637 // is_comptime: bool,
16595 Value.makeBool(is_comptime),16638 Value.makeBool(is_comptime).ip_index,
16596 // alignment: comptime_int,16639 // 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,
16598 };16641 };
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 } });
16600 }16646 }
16601 break :fv struct_field_vals;16647 break :fv;
16602 },16648 },
16603 .struct_type => |s| s,16649 .struct_type => |s| s,
16604 else => unreachable,16650 else => unreachable,
16605 };16651 };
16606 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse16652 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse break :fv;
16607 break :fv &[0]Value{};16653 struct_field_vals = try gpa.alloc(InternPool.Index, struct_obj.fields.count());
16608 const struct_field_vals = try fields_anon_decl.arena().alloc(Value, struct_obj.fields.count());
1660916654
16610 for (16655 for (
16611 struct_field_vals,16656 struct_field_vals,
...@@ -16621,13 +16666,13 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16621,13 +16666,13 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16621 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),16666 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
16622 0, // default alignment16667 0, // default alignment
16623 );16668 );
16624 break :v try Value.Tag.slice.create(fields_anon_decl.arena(), .{16669 break :v try mod.intern(.{ .ptr = .{
16625 .ptr = try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl),16670 .ty = .slice_const_u8_type,
16626 .len = try mod.intValue(Type.usize, bytes.len),16671 .addr = .{ .decl = new_decl },
16627 });16672 .len = (try mod.intValue(Type.usize, bytes.len)).ip_index,
16673 } });
16628 };16674 };
1662916675
16630 const struct_field_fields = try fields_anon_decl.arena().create([5]Value);
16631 const opt_default_val = if (field.default_val.ip_index == .unreachable_value)16676 const opt_default_val = if (field.default_val.ip_index == .unreachable_value)
16632 null16677 null
16633 else16678 else
...@@ -16635,55 +16680,61 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16635,55 +16680,61 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16635 const default_val_ptr = try sema.optRefValue(block, field.ty, opt_default_val);16680 const default_val_ptr = try sema.optRefValue(block, field.ty, opt_default_val);
16636 const alignment = field.alignment(mod, layout);16681 const alignment = field.alignment(mod, layout);
1663716682
16638 struct_field_fields.* = .{16683 const struct_field_fields = .{
16639 // name: []const u8,16684 // name: []const u8,
16640 name_val,16685 name_val,
16641 // type: type,16686 // type: type,
16642 field.ty.toValue(),16687 field.ty.ip_index,
16643 // default_value: ?*const anyopaque,16688 // default_value: ?*const anyopaque,
16644 try default_val_ptr.copy(fields_anon_decl.arena()),16689 default_val_ptr.ip_index,
16645 // is_comptime: bool,16690 // is_comptime: bool,
16646 Value.makeBool(field.is_comptime),16691 Value.makeBool(field.is_comptime).ip_index,
16647 // alignment: comptime_int,16692 // alignment: comptime_int,
16648 try mod.intValue(Type.comptime_int, alignment),16693 (try mod.intValue(Type.comptime_int, alignment)).ip_index,
16649 };16694 };
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 } });
16651 }16699 }
16652 break :fv struct_field_vals;16700 }
16653 };
1665416701
16655 const fields_val = v: {16702 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 });
16656 const new_decl = try fields_anon_decl.finish(16708 const new_decl = try fields_anon_decl.finish(
16657 try mod.arrayType(.{16709 array_fields_ty,
16658 .len = struct_field_vals.len,16710 (try mod.intern(.{ .aggregate = .{
16659 .child = struct_field_ty.ip_index,16711 .ty = array_fields_ty.ip_index,
16660 .sentinel = .none,16712 .storage = .{ .elems = struct_field_vals },
16661 }),16713 } })).toValue(),
16662 try Value.Tag.aggregate.create(
16663 fields_anon_decl.arena(),
16664 try fields_anon_decl.arena().dupe(Value, struct_field_vals),
16665 ),
16666 0, // default alignment16714 0, // default alignment
16667 );16715 );
16668 break :v try Value.Tag.slice.create(sema.arena, .{16716 break :v try mod.intern(.{ .ptr = .{
16669 .ptr = try Value.Tag.decl_ref.create(sema.arena, new_decl),16717 .ty = (try mod.ptrType(.{
16670 .len = try mod.intValue(Type.usize, struct_field_vals.len),16718 .elem_type = struct_field_ty.ip_index,
16671 });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 } });
16672 };16725 };
1667316726
16674 const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, struct_ty.getNamespaceIndex(mod));16727 const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, struct_ty.getNamespaceIndex(mod));
1667516728
16676 const backing_integer_val = blk: {16729 const backing_integer_val = try mod.intern(.{ .opt = .{
16677 if (layout == .Packed) {16730 .ty = (try mod.optionalType(.type_type)).ip_index,
16731 .val = if (layout == .Packed) val: {
16678 const struct_obj = mod.typeToStruct(struct_ty).?;16732 const struct_obj = mod.typeToStruct(struct_ty).?;
16679 assert(struct_obj.haveLayout());16733 assert(struct_obj.haveLayout());
16680 assert(struct_obj.backing_int_ty.isInt(mod));16734 assert(struct_obj.backing_int_ty.isInt(mod));
16681 const backing_int_ty_val = struct_obj.backing_int_ty.toValue();16735 break :val struct_obj.backing_int_ty.ip_index;
16682 break :blk try Value.Tag.opt_payload.create(sema.arena, backing_int_ty_val);16736 } else .none,
16683 } else {16737 } });
16684 break :blk Value.null;
16685 }
16686 };
1668716738
16688 const container_layout_ty = t: {16739 const container_layout_ty = t: {
16689 const decl_index = (try sema.namespaceLookup(16740 const decl_index = (try sema.namespaceLookup(
...@@ -16698,10 +16749,9 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16698,10 +16749,9 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16698 break :t decl.val.toType();16749 break :t decl.val.toType();
16699 };16750 };
1670016751
16701 const field_values = try sema.arena.create([5]Value);16752 const field_values = [_]InternPool.Index{
16702 field_values.* = .{
16703 // layout: ContainerLayout,16753 // layout: ContainerLayout,
16704 try mod.enumValueFieldIndex(container_layout_ty, @enumToInt(layout)),16754 (try mod.enumValueFieldIndex(container_layout_ty, @enumToInt(layout))).ip_index,
16705 // backing_integer: ?type,16755 // backing_integer: ?type,
16706 backing_integer_val,16756 backing_integer_val,
16707 // fields: []const StructField,16757 // fields: []const StructField,
...@@ -16709,36 +16759,48 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16709,36 +16759,48 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16709 // decls: []const Declaration,16759 // decls: []const Declaration,
16710 decls_val,16760 decls_val,
16711 // is_tuple: bool,16761 // is_tuple: bool,
16712 Value.makeBool(struct_ty.isTuple(mod)),16762 Value.makeBool(struct_ty.isTuple(mod)).ip_index,
16713 };16763 };
1671416764 return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
16715 return sema.addConstant(16765 .ty = type_info_ty.ip_index,
16716 type_info_ty,16766 .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Struct))).ip_index,
16717 try Value.Tag.@"union".create(sema.arena, .{16767 .val = try mod.intern(.{ .aggregate = .{
16718 .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Struct)),16768 .ty = type_struct_ty.ip_index,
16719 .val = try Value.Tag.aggregate.create(sema.arena, field_values),16769 .storage = .{ .elems = &field_values },
16720 }),16770 } }),
16721 );16771 } })).toValue());
16722 },16772 },
16723 .Opaque => {16773 .Opaque => {
16724 // TODO: look into memoizing this result.16774 // 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
16726 const opaque_ty = try sema.resolveTypeFields(ty);16789 const opaque_ty = try sema.resolveTypeFields(ty);
16727 const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, opaque_ty.getNamespaceIndex(mod));16790 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);16792 const field_values = .{
16730 field_values.* = .{
16731 // decls: []const Declaration,16793 // decls: []const Declaration,
16732 decls_val,16794 decls_val,
16733 };16795 };
1673416796 return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
16735 return sema.addConstant(16797 .ty = type_info_ty.ip_index,
16736 type_info_ty,16798 .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Opaque))).ip_index,
16737 try Value.Tag.@"union".create(sema.arena, .{16799 .val = try mod.intern(.{ .aggregate = .{
16738 .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Opaque)),16800 .ty = type_opaque_ty.ip_index,
16739 .val = try Value.Tag.aggregate.create(sema.arena, field_values),16801 .storage = .{ .elems = &field_values },
16740 }),16802 } }),
16741 );16803 } })).toValue());
16742 },16804 },
16743 .Frame => return sema.failWithUseOfAsync(block, src),16805 .Frame => return sema.failWithUseOfAsync(block, src),
16744 .AnyFrame => return sema.failWithUseOfAsync(block, src),16806 .AnyFrame => return sema.failWithUseOfAsync(block, src),
...@@ -16751,7 +16813,7 @@ fn typeInfoDecls(...@@ -16751,7 +16813,7 @@ fn typeInfoDecls(
16751 src: LazySrcLoc,16813 src: LazySrcLoc,
16752 type_info_ty: Type,16814 type_info_ty: Type,
16753 opt_namespace: Module.Namespace.OptionalIndex,16815 opt_namespace: Module.Namespace.OptionalIndex,
16754) CompileError!Value {16816) CompileError!InternPool.Index {
16755 const mod = sema.mod;16817 const mod = sema.mod;
16756 var decls_anon_decl = try block.startAnonDecl();16818 var decls_anon_decl = try block.startAnonDecl();
16757 defer decls_anon_decl.deinit();16819 defer decls_anon_decl.deinit();
...@@ -16770,7 +16832,7 @@ fn typeInfoDecls(...@@ -16770,7 +16832,7 @@ fn typeInfoDecls(
16770 };16832 };
16771 try sema.queueFullTypeResolution(declaration_ty);16833 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);
16774 defer decl_vals.deinit();16836 defer decl_vals.deinit();
1677516837
16776 var seen_namespaces = std.AutoHashMap(*Namespace, void).init(sema.gpa);16838 var seen_namespaces = std.AutoHashMap(*Namespace, void).init(sema.gpa);
...@@ -16778,33 +16840,39 @@ fn typeInfoDecls(...@@ -16778,33 +16840,39 @@ fn typeInfoDecls(
1677816840
16779 if (opt_namespace.unwrap()) |namespace_index| {16841 if (opt_namespace.unwrap()) |namespace_index| {
16780 const namespace = mod.namespacePtr(namespace_index);16842 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);
16782 }16844 }
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 });
16784 const new_decl = try decls_anon_decl.finish(16851 const new_decl = try decls_anon_decl.finish(
16785 try mod.arrayType(.{16852 array_decl_ty,
16786 .len = decl_vals.items.len,16853 (try mod.intern(.{ .aggregate = .{
16787 .child = declaration_ty.ip_index,16854 .ty = array_decl_ty.ip_index,
16788 .sentinel = .none,16855 .storage = .{ .elems = decl_vals.items },
16789 }),16856 } })).toValue(),
16790 try Value.Tag.aggregate.create(
16791 decls_anon_decl.arena(),
16792 try decls_anon_decl.arena().dupe(Value, decl_vals.items),
16793 ),
16794 0, // default alignment16857 0, // default alignment
16795 );16858 );
16796 return try Value.Tag.slice.create(sema.arena, .{16859 return try mod.intern(.{ .ptr = .{
16797 .ptr = try Value.Tag.decl_ref.create(sema.arena, new_decl),16860 .ty = (try mod.ptrType(.{
16798 .len = try mod.intValue(Type.usize, decl_vals.items.len),16861 .elem_type = declaration_ty.ip_index,
16799 });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 } });
16800}16868}
1680116869
16802fn typeInfoNamespaceDecls(16870fn typeInfoNamespaceDecls(
16803 sema: *Sema,16871 sema: *Sema,
16804 block: *Block,16872 block: *Block,
16805 decls_anon_decl: Allocator,
16806 namespace: *Namespace,16873 namespace: *Namespace,
16807 decl_vals: *std.ArrayList(Value),16874 declaration_ty: Type,
16875 decl_vals: *std.ArrayList(InternPool.Index),
16808 seen_namespaces: *std.AutoHashMap(*Namespace, void),16876 seen_namespaces: *std.AutoHashMap(*Namespace, void),
16809) !void {16877) !void {
16810 const mod = sema.mod;16878 const mod = sema.mod;
...@@ -16817,7 +16885,7 @@ fn typeInfoNamespaceDecls(...@@ -16817,7 +16885,7 @@ fn typeInfoNamespaceDecls(
16817 if (decl.analysis == .in_progress) continue;16885 if (decl.analysis == .in_progress) continue;
16818 try mod.ensureDeclAnalyzed(decl_index);16886 try mod.ensureDeclAnalyzed(decl_index);
16819 const new_ns = decl.val.toType().getNamespace(mod).?;16887 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);
16821 continue;16889 continue;
16822 }16890 }
16823 if (decl.kind != .named) continue;16891 if (decl.kind != .named) continue;
...@@ -16830,20 +16898,23 @@ fn typeInfoNamespaceDecls(...@@ -16830,20 +16898,23 @@ fn typeInfoNamespaceDecls(
16830 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),16898 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
16831 0, // default alignment16899 0, // default alignment
16832 );16900 );
16833 break :v try Value.Tag.slice.create(decls_anon_decl, .{16901 break :v try mod.intern(.{ .ptr = .{
16834 .ptr = try Value.Tag.decl_ref.create(decls_anon_decl, new_decl),16902 .ty = .slice_const_u8_type,
16835 .len = try mod.intValue(Type.usize, bytes.len),16903 .addr = .{ .decl = new_decl },
16836 });16904 .len = (try mod.intValue(Type.usize, bytes.len)).ip_index,
16905 } });
16837 };16906 };
1683816907
16839 const fields = try decls_anon_decl.create([2]Value);16908 const fields = .{
16840 fields.* = .{
16841 //name: []const u8,16909 //name: []const u8,
16842 name_val,16910 name_val,
16843 //is_pub: bool,16911 //is_pub: bool,
16844 Value.makeBool(decl.is_pub),16912 Value.makeBool(decl.is_pub).ip_index,
16845 };16913 };
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 } }));
16847 }16918 }
16848}16919}
1684916920
...@@ -17454,10 +17525,11 @@ fn zirRetErrValue(...@@ -17454,10 +17525,11 @@ fn zirRetErrValue(
1745417525
17455 // Return the error code from the function.17526 // Return the error code from the function.
17456 const kv = try mod.getErrorValue(err_name);17527 const kv = try mod.getErrorValue(err_name);
17457 const result_inst = try sema.addConstant(17528 const error_set_type = try mod.singleErrorSetType(err_name);
17458 try mod.singleErrorSetType(err_name),17529 const result_inst = try sema.addConstant(error_set_type, (try mod.intern(.{ .err = .{
17459 try Value.Tag.@"error".create(sema.arena, .{ .name = kv.key }),17530 .ty = error_set_type.ip_index,
17460 );17531 .name = try mod.intern_pool.getOrPutString(sema.gpa, kv.key),
17532 } })).toValue());
17461 return sema.analyzeRet(block, result_inst, src);17533 return sema.analyzeRet(block, result_inst, src);
17462}17534}
1746317535
...@@ -17782,10 +17854,12 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -17782,10 +17854,12 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
17782 const val = try sema.resolveConstValue(block, align_src, coerced, "pointer alignment must be comptime-known");17854 const val = try sema.resolveConstValue(block, align_src, coerced, "pointer alignment must be comptime-known");
17783 // Check if this happens to be the lazy alignment of our element type, in17855 // Check if this happens to be the lazy alignment of our element type, in
17784 // which case we can make this 0 without resolving it.17856 // which case we can make this 0 without resolving it.
17785 if (val.castTag(.lazy_align)) |payload| {17857 switch (mod.intern_pool.indexToKey(val.ip_index)) {
17786 if (payload.data.eql(elem_ty, sema.mod)) {17858 .int => |int| switch (int.storage) {
17787 break :blk .none;17859 .lazy_align => |lazy_ty| if (lazy_ty == elem_ty.ip_index) break :blk .none,
17788 }17860 else => {},
17861 },
17862 else => {},
17789 }17863 }
17790 const abi_align = @intCast(u32, (try val.getUnsignedIntAdvanced(mod, sema)).?);17864 const abi_align = @intCast(u32, (try val.getUnsignedIntAdvanced(mod, sema)).?);
17791 try sema.validateAlign(block, align_src, abi_align);17865 try sema.validateAlign(block, align_src, abi_align);
...@@ -17910,12 +17984,10 @@ fn arrayInitEmpty(sema: *Sema, block: *Block, src: LazySrcLoc, obj_ty: Type) Com...@@ -17910,12 +17984,10 @@ fn arrayInitEmpty(sema: *Sema, block: *Block, src: LazySrcLoc, obj_ty: Type) Com
17910 return sema.fail(block, src, "expected {d} vector elements; found 0", .{arr_len});17984 return sema.fail(block, src, "expected {d} vector elements; found 0", .{arr_len});
17911 }17985 }
17912 }17986 }
17913 if (obj_ty.sentinel(mod)) |sentinel| {17987 return sema.addConstant(obj_ty, (try mod.intern(.{ .aggregate = .{
17914 const val = try Value.Tag.empty_array_sentinel.create(sema.arena, sentinel);17988 .ty = obj_ty.ip_index,
17915 return sema.addConstant(obj_ty, val);17989 .storage = .{ .elems = &.{} },
17916 } else {17990 } })).toValue());
17917 return sema.addConstant(obj_ty, Value.initTag(.empty_array));
17918 }
17919}17991}
1792017992
17921fn zirUnionInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {17993fn 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...@@ -18679,8 +18751,8 @@ fn zirAlignOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
18679 if (ty.isNoReturn(mod)) {18751 if (ty.isNoReturn(mod)) {
18680 return sema.fail(block, operand_src, "no align available for type '{}'", .{ty.fmt(sema.mod)});18752 return sema.fail(block, operand_src, "no align available for type '{}'", .{ty.fmt(sema.mod)});
18681 }18753 }
18682 const val = try ty.lazyAbiAlignment(mod, sema.arena);18754 const val = try ty.lazyAbiAlignment(mod);
18683 if (val.isLazyAlign()) {18755 if (val.isLazyAlign(mod)) {
18684 try sema.queueFullTypeResolution(ty);18756 try sema.queueFullTypeResolution(ty);
18685 }18757 }
18686 return sema.addConstant(Type.comptime_int, val);18758 return sema.addConstant(Type.comptime_int, val);
...@@ -18704,7 +18776,8 @@ fn zirErrorName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -18704,7 +18776,8 @@ fn zirErrorName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
18704 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };18776 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
1870518777
18706 if (try sema.resolveDefinedValue(block, operand_src, operand)) |val| {18778 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);
18708 return sema.addStrLit(block, bytes);18781 return sema.addStrLit(block, bytes);
18709 }18782 }
1871018783
...@@ -18794,7 +18867,8 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -18794,7 +18867,8 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
18794 const enum_ty = switch (operand_ty.zigTypeTag(mod)) {18867 const enum_ty = switch (operand_ty.zigTypeTag(mod)) {
18795 .EnumLiteral => {18868 .EnumLiteral => {
18796 const val = try sema.resolveConstValue(block, .unneeded, operand, "");18869 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);
18798 return sema.addStrLit(block, bytes);18872 return sema.addStrLit(block, bytes);
18799 },18873 },
18800 .Enum => operand_ty,18874 .Enum => operand_ty,
...@@ -18883,11 +18957,8 @@ fn zirReify(...@@ -18883,11 +18957,8 @@ fn zirReify(
18883 .EnumLiteral => return Air.Inst.Ref.enum_literal_type,18957 .EnumLiteral => return Air.Inst.Ref.enum_literal_type,
18884 .Int => {18958 .Int => {
18885 const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);18959 const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);
18886 const signedness_index = fields.getIndex("signedness").?;18960 const signedness_val = try union_val.val.fieldValue(mod, fields.getIndex("signedness").?);
18887 const bits_index = fields.getIndex("bits").?;18961 const bits_val = try union_val.val.fieldValue(mod, 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);
1889118962
18892 const signedness = mod.toEnum(std.builtin.Signedness, signedness_val);18963 const signedness = mod.toEnum(std.builtin.Signedness, signedness_val);
18893 const bits = @intCast(u16, bits_val.toUnsignedInt(mod));18964 const bits = @intCast(u16, bits_val.toUnsignedInt(mod));
...@@ -18896,11 +18967,8 @@ fn zirReify(...@@ -18896,11 +18967,8 @@ fn zirReify(
18896 },18967 },
18897 .Vector => {18968 .Vector => {
18898 const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);18969 const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);
18899 const len_index = fields.getIndex("len").?;18970 const len_val = try union_val.val.fieldValue(mod, fields.getIndex("len").?);
18900 const child_index = fields.getIndex("child").?;18971 const child_val = try union_val.val.fieldValue(mod, 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);
1890418972
18905 const len = @intCast(u32, len_val.toUnsignedInt(mod));18973 const len = @intCast(u32, len_val.toUnsignedInt(mod));
18906 const child_ty = child_val.toType();18974 const child_ty = child_val.toType();
...@@ -18915,9 +18983,7 @@ fn zirReify(...@@ -18915,9 +18983,7 @@ fn zirReify(
18915 },18983 },
18916 .Float => {18984 .Float => {
18917 const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);18985 const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);
18918 const bits_index = fields.getIndex("bits").?;18986 const bits_val = try union_val.val.fieldValue(mod, fields.getIndex("bits").?);
18919
18920 const bits_val = try union_val.val.fieldValue(fields.values()[bits_index].ty, mod, bits_index);
1892118987
18922 const bits = @intCast(u16, bits_val.toUnsignedInt(mod));18988 const bits = @intCast(u16, bits_val.toUnsignedInt(mod));
18923 const ty = switch (bits) {18989 const ty = switch (bits) {
...@@ -18932,23 +18998,14 @@ fn zirReify(...@@ -18932,23 +18998,14 @@ fn zirReify(
18932 },18998 },
18933 .Pointer => {18999 .Pointer => {
18934 const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);19000 const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);
18935 const size_index = fields.getIndex("size").?;19001 const size_val = try union_val.val.fieldValue(mod, fields.getIndex("size").?);
18936 const is_const_index = fields.getIndex("is_const").?;19002 const is_const_val = try union_val.val.fieldValue(mod, fields.getIndex("is_const").?);
18937 const is_volatile_index = fields.getIndex("is_volatile").?;19003 const is_volatile_val = try union_val.val.fieldValue(mod, fields.getIndex("is_volatile").?);
18938 const alignment_index = fields.getIndex("alignment").?;19004 const alignment_val = try union_val.val.fieldValue(mod, fields.getIndex("alignment").?);
18939 const address_space_index = fields.getIndex("address_space").?;19005 const address_space_val = try union_val.val.fieldValue(mod, fields.getIndex("address_space").?);
18940 const child_index = fields.getIndex("child").?;19006 const child_val = try union_val.val.fieldValue(mod, fields.getIndex("child").?);
18941 const is_allowzero_index = fields.getIndex("is_allowzero").?;19007 const is_allowzero_val = try union_val.val.fieldValue(mod, fields.getIndex("is_allowzero").?);
18942 const sentinel_index = fields.getIndex("sentinel").?;19008 const sentinel_val = try union_val.val.fieldValue(mod, 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);
1895219009
18953 if (!try sema.intFitsInType(alignment_val, Type.u32, null)) {19010 if (!try sema.intFitsInType(alignment_val, Type.u32, null)) {
18954 return sema.fail(block, src, "alignment must fit in 'u32'", .{});19011 return sema.fail(block, src, "alignment must fit in 'u32'", .{});
...@@ -19032,22 +19089,18 @@ fn zirReify(...@@ -19032,22 +19089,18 @@ fn zirReify(
19032 },19089 },
19033 .Array => {19090 .Array => {
19034 const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);19091 const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);
19035 const len_index = fields.getIndex("len").?;19092 const len_val = try union_val.val.fieldValue(mod, fields.getIndex("len").?);
19036 const child_index = fields.getIndex("child").?;19093 const child_val = try union_val.val.fieldValue(mod, fields.getIndex("child").?);
19037 const sentinel_index = fields.getIndex("sentinel").?;19094 const sentinel_val = try union_val.val.fieldValue(mod, 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);
1904219095
19043 const len = len_val.toUnsignedInt(mod);19096 const len = len_val.toUnsignedInt(mod);
19044 const child_ty = child_val.toType();19097 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: {
19046 const ptr_ty = try Type.ptr(sema.arena, mod, .{19099 const ptr_ty = try Type.ptr(sema.arena, mod, .{
19047 .@"addrspace" = .generic,19100 .@"addrspace" = .generic,
19048 .pointee_type = child_ty,19101 .pointee_type = child_ty,
19049 });19102 });
19050 break :blk (try sema.pointerDeref(block, src, p.data, ptr_ty)).?;19103 break :blk (try sema.pointerDeref(block, src, p, ptr_ty)).?;
19051 } else null;19104 } else null;
1905219105
19053 const ty = try Type.array(sema.arena, len, sentinel, child_ty, mod);19106 const ty = try Type.array(sema.arena, len, sentinel, child_ty, mod);
...@@ -19055,9 +19108,7 @@ fn zirReify(...@@ -19055,9 +19108,7 @@ fn zirReify(
19055 },19108 },
19056 .Optional => {19109 .Optional => {
19057 const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);19110 const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);
19058 const child_index = fields.getIndex("child").?;19111 const child_val = try union_val.val.fieldValue(mod, fields.getIndex("child").?);
19059
19060 const child_val = try union_val.val.fieldValue(fields.values()[child_index].ty, mod, child_index);
1906119112
19062 const child_ty = child_val.toType();19113 const child_ty = child_val.toType();
1906319114
...@@ -19066,11 +19117,8 @@ fn zirReify(...@@ -19066,11 +19117,8 @@ fn zirReify(
19066 },19117 },
19067 .ErrorUnion => {19118 .ErrorUnion => {
19068 const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);19119 const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);
19069 const error_set_index = fields.getIndex("error_set").?;19120 const error_set_val = try union_val.val.fieldValue(mod, fields.getIndex("error_set").?);
19070 const payload_index = fields.getIndex("payload").?;19121 const payload_val = try union_val.val.fieldValue(mod, 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);
1907419122
19075 const error_set_ty = error_set_val.toType();19123 const error_set_ty = error_set_val.toType();
19076 const payload_ty = payload_val.toType();19124 const payload_ty = payload_val.toType();
...@@ -19085,18 +19133,17 @@ fn zirReify(...@@ -19085,18 +19133,17 @@ fn zirReify(
19085 .ErrorSet => {19133 .ErrorSet => {
19086 const payload_val = union_val.val.optionalValue(mod) orelse19134 const payload_val = union_val.val.optionalValue(mod) orelse
19087 return sema.addType(Type.anyerror);19135 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));
19091 var names: Module.Fn.InferredErrorSet.NameMap = .{};19138 var names: Module.Fn.InferredErrorSet.NameMap = .{};
19092 try names.ensureUnusedCapacity(sema.arena, len);19139 try names.ensureUnusedCapacity(sema.arena, len);
19093 for (0..len) |i| {19140 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);
19095 const struct_val = elem_val.castTag(.aggregate).?.data;19142 const struct_val = elem_val.castTag(.aggregate).?.data;
19096 // TODO use reflection instead of magic numbers here19143 // TODO use reflection instead of magic numbers here
19097 // error_set: type,19144 // error_set: type,
19098 const name_val = struct_val[0];19145 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);
19100 const name_ip = try mod.intern_pool.getOrPutString(gpa, name_str);19147 const name_ip = try mod.intern_pool.getOrPutString(gpa, name_str);
19101 const gop = names.getOrPutAssumeCapacity(name_ip);19148 const gop = names.getOrPutAssumeCapacity(name_ip);
19102 if (gop.found_existing) {19149 if (gop.found_existing) {
...@@ -19109,17 +19156,11 @@ fn zirReify(...@@ -19109,17 +19156,11 @@ fn zirReify(
19109 },19156 },
19110 .Struct => {19157 .Struct => {
19111 const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);19158 const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);
19112 const layout_index = fields.getIndex("layout").?;19159 const layout_val = try union_val.val.fieldValue(mod, fields.getIndex("layout").?);
19113 const backing_integer_index = fields.getIndex("backing_integer").?;19160 const backing_integer_val = try union_val.val.fieldValue(mod, fields.getIndex("backing_integer").?);
19114 const fields_index = fields.getIndex("fields").?;19161 const fields_val = try union_val.val.fieldValue(mod, fields.getIndex("fields").?);
19115 const decls_index = fields.getIndex("decls").?;19162 const decls_val = try union_val.val.fieldValue(mod, fields.getIndex("decls").?);
19116 const is_tuple_index = fields.getIndex("is_tuple").?;19163 const is_tuple_val = try union_val.val.fieldValue(mod, 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);
1912319164
19124 const layout = mod.toEnum(std.builtin.Type.ContainerLayout, layout_val);19165 const layout = mod.toEnum(std.builtin.Type.ContainerLayout, layout_val);
1912519166
...@@ -19136,15 +19177,10 @@ fn zirReify(...@@ -19136,15 +19177,10 @@ fn zirReify(
19136 },19177 },
19137 .Enum => {19178 .Enum => {
19138 const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);19179 const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);
19139 const tag_type_index = fields.getIndex("tag_type").?;19180 const tag_type_val = try union_val.val.fieldValue(mod, fields.getIndex("tag_type").?);
19140 const fields_index = fields.getIndex("fields").?;19181 const fields_val = try union_val.val.fieldValue(mod, fields.getIndex("fields").?);
19141 const decls_index = fields.getIndex("decls").?;19182 const decls_val = try union_val.val.fieldValue(mod, fields.getIndex("decls").?);
19142 const is_exhaustive_index = fields.getIndex("is_exhaustive").?;19183 const is_exhaustive_val = try union_val.val.fieldValue(mod, 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);
1914819184
19149 // Decls19185 // Decls
19150 if (decls_val.sliceLen(mod) > 0) {19186 if (decls_val.sliceLen(mod) > 0) {
...@@ -19195,7 +19231,7 @@ fn zirReify(...@@ -19195,7 +19231,7 @@ fn zirReify(
19195 const value_val = field_struct_val[1];19231 const value_val = field_struct_val[1];
1919619232
19197 const field_name = try name_val.toAllocatedBytes(19233 const field_name = try name_val.toAllocatedBytes(
19198 Type.const_slice_u8,19234 Type.slice_const_u8,
19199 sema.arena,19235 sema.arena,
19200 mod,19236 mod,
19201 );19237 );
...@@ -19237,9 +19273,7 @@ fn zirReify(...@@ -19237,9 +19273,7 @@ fn zirReify(
19237 },19273 },
19238 .Opaque => {19274 .Opaque => {
19239 const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);19275 const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);
19240 const decls_index = fields.getIndex("decls").?;19276 const decls_val = try union_val.val.fieldValue(mod, fields.getIndex("decls").?);
19241
19242 const decls_val = try union_val.val.fieldValue(fields.values()[decls_index].ty, mod, decls_index);
1924319277
19244 // Decls19278 // Decls
19245 if (decls_val.sliceLen(mod) > 0) {19279 if (decls_val.sliceLen(mod) > 0) {
...@@ -19283,15 +19317,10 @@ fn zirReify(...@@ -19283,15 +19317,10 @@ fn zirReify(
19283 },19317 },
19284 .Union => {19318 .Union => {
19285 const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);19319 const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);
19286 const layout_index = fields.getIndex("layout").?;19320 const layout_val = try union_val.val.fieldValue(mod, fields.getIndex("layout").?);
19287 const tag_type_index = fields.getIndex("tag_type").?;19321 const tag_type_val = try union_val.val.fieldValue(mod, fields.getIndex("tag_type").?);
19288 const fields_index = fields.getIndex("fields").?;19322 const fields_val = try union_val.val.fieldValue(mod, fields.getIndex("fields").?);
19289 const decls_index = fields.getIndex("decls").?;19323 const decls_val = try union_val.val.fieldValue(mod, 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);
1929519324
19296 // Decls19325 // Decls
19297 if (decls_val.sliceLen(mod) > 0) {19326 if (decls_val.sliceLen(mod) > 0) {
...@@ -19386,7 +19415,7 @@ fn zirReify(...@@ -19386,7 +19415,7 @@ fn zirReify(
19386 const alignment_val = field_struct_val[2];19415 const alignment_val = field_struct_val[2];
1938719416
19388 const field_name = try name_val.toAllocatedBytes(19417 const field_name = try name_val.toAllocatedBytes(
19389 Type.const_slice_u8,19418 Type.slice_const_u8,
19390 new_decl_arena_allocator,19419 new_decl_arena_allocator,
19391 mod,19420 mod,
19392 );19421 );
...@@ -19489,19 +19518,12 @@ fn zirReify(...@@ -19489,19 +19518,12 @@ fn zirReify(
19489 },19518 },
19490 .Fn => {19519 .Fn => {
19491 const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);19520 const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);
19492 const calling_convention_index = fields.getIndex("calling_convention").?;19521 const calling_convention_val = try union_val.val.fieldValue(mod, fields.getIndex("calling_convention").?);
19493 const alignment_index = fields.getIndex("alignment").?;19522 const alignment_val = try union_val.val.fieldValue(mod, fields.getIndex("alignment").?);
19494 const is_generic_index = fields.getIndex("is_generic").?;19523 const is_generic_val = try union_val.val.fieldValue(mod, fields.getIndex("is_generic").?);
19495 const is_var_args_index = fields.getIndex("is_var_args").?;19524 const is_var_args_val = try union_val.val.fieldValue(mod, fields.getIndex("is_var_args").?);
19496 const return_type_index = fields.getIndex("return_type").?;19525 const return_type_val = try union_val.val.fieldValue(mod, fields.getIndex("return_type").?);
19497 const params_index = fields.getIndex("params").?;19526 const params_val = try union_val.val.fieldValue(mod, 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);
1950519527
19506 const is_generic = is_generic_val.toBool(mod);19528 const is_generic = is_generic_val.toBool(mod);
19507 if (is_generic) {19529 if (is_generic) {
...@@ -19528,14 +19550,12 @@ fn zirReify(...@@ -19528,14 +19550,12 @@ fn zirReify(
19528 const return_type = return_type_val.optionalValue(mod) orelse19550 const return_type = return_type_val.optionalValue(mod) orelse
19529 return sema.fail(block, src, "Type.Fn.return_type must be non-null for @Type", .{});19551 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;19553 const args_len = try sema.usizeCast(block, src, params_val.sliceLen(mod));
19532 const args_len = try sema.usizeCast(block, src, args_slice_val.len.toUnsignedInt(mod));
19533
19534 const param_types = try sema.arena.alloc(InternPool.Index, args_len);19554 const param_types = try sema.arena.alloc(InternPool.Index, args_len);
1953519555
19536 var noalias_bits: u32 = 0;19556 var noalias_bits: u32 = 0;
19537 for (param_types, 0..) |*param_type, i| {19557 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);
19539 const arg_val = arg.castTag(.aggregate).?.data;19559 const arg_val = arg.castTag(.aggregate).?.data;
19540 // TODO use reflection instead of magic numbers here19560 // TODO use reflection instead of magic numbers here
19541 // is_generic: bool,19561 // is_generic: bool,
...@@ -19676,7 +19696,7 @@ fn reifyStruct(...@@ -19676,7 +19696,7 @@ fn reifyStruct(
19676 }19696 }
1967719697
19678 const field_name = try name_val.toAllocatedBytes(19698 const field_name = try name_val.toAllocatedBytes(
19679 Type.const_slice_u8,19699 Type.slice_const_u8,
19680 new_decl_arena_allocator,19700 new_decl_arena_allocator,
19681 mod,19701 mod,
19682 );19702 );
...@@ -19707,7 +19727,7 @@ fn reifyStruct(...@@ -19707,7 +19727,7 @@ fn reifyStruct(
19707 }19727 }
1970819728
19709 const default_val = if (default_value_val.optionalValue(mod)) |opt_val| blk: {19729 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|
19711 mod.declPtr(opt_decl).val19731 mod.declPtr(opt_decl).val
19712 else19732 else
19713 opt_val;19733 opt_val;
...@@ -20137,7 +20157,7 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat...@@ -20137,7 +20157,7 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
2013720157
20138 if (maybe_operand_val) |val| {20158 if (maybe_operand_val) |val| {
20139 if (!dest_ty.isAnyError(mod)) {20159 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);
20141 if (!dest_ty.errorSetHasField(error_name, mod)) {20161 if (!dest_ty.errorSetHasField(error_name, mod)) {
20142 const msg = msg: {20162 const msg = msg: {
20143 const msg = try sema.errMsg(20163 const msg = try sema.errMsg(
...@@ -20279,7 +20299,10 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -20279,7 +20299,10 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
20279 return sema.fail(block, operand_src, "null pointer casted to type '{}'", .{dest_ty.fmt(sema.mod)});20299 return sema.fail(block, operand_src, "null pointer casted to type '{}'", .{dest_ty.fmt(sema.mod)});
20280 }20300 }
20281 if (dest_ty.zigTypeTag(mod) == .Optional and sema.typeOf(ptr).zigTypeTag(mod) != .Optional) {20301 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());
20283 }20306 }
20284 return sema.addConstant(aligned_dest_ty, operand_val);20307 return sema.addConstant(aligned_dest_ty, operand_val);
20285 }20308 }
...@@ -20944,7 +20967,7 @@ fn checkPtrIsNotComptimeMutable(...@@ -20944,7 +20967,7 @@ fn checkPtrIsNotComptimeMutable(
20944 operand_src: LazySrcLoc,20967 operand_src: LazySrcLoc,
20945) CompileError!void {20968) CompileError!void {
20946 _ = operand_src;20969 _ = operand_src;
20947 if (ptr_val.isComptimeMutablePtr()) {20970 if (ptr_val.isComptimeMutablePtr(sema.mod)) {
20948 return sema.fail(block, ptr_src, "cannot store runtime value in compile time variable", .{});20971 return sema.fail(block, ptr_src, "cannot store runtime value in compile time variable", .{});
20949 }20972 }
20950}20973}
...@@ -20953,7 +20976,7 @@ fn checkComptimeVarStore(...@@ -20953,7 +20976,7 @@ fn checkComptimeVarStore(
20953 sema: *Sema,20976 sema: *Sema,
20954 block: *Block,20977 block: *Block,
20955 src: LazySrcLoc,20978 src: LazySrcLoc,
20956 decl_ref_mut: Value.Payload.DeclRefMut.Data,20979 decl_ref_mut: InternPool.Key.Ptr.Addr.MutDecl,
20957) CompileError!void {20980) CompileError!void {
20958 if (@enumToInt(decl_ref_mut.runtime_index) < @enumToInt(block.runtime_index)) {20981 if (@enumToInt(decl_ref_mut.runtime_index) < @enumToInt(block.runtime_index)) {
20959 if (block.runtime_cond) |cond_src| {20982 if (block.runtime_cond) |cond_src| {
...@@ -21159,7 +21182,7 @@ fn resolveExportOptions(...@@ -21159,7 +21182,7 @@ fn resolveExportOptions(
2115921182
21160 const name_operand = try sema.fieldVal(block, src, options, "name", name_src);21183 const name_operand = try sema.fieldVal(block, src, options, "name", name_src);
21161 const name_val = try sema.resolveConstValue(block, name_src, name_operand, "name of exported value must be comptime-known");21184 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;
21163 const name = try name_val.toAllocatedBytes(name_ty, sema.arena, mod);21186 const name = try name_val.toAllocatedBytes(name_ty, sema.arena, mod);
2116421187
21165 const linkage_operand = try sema.fieldVal(block, src, options, "linkage", linkage_src);21188 const linkage_operand = try sema.fieldVal(block, src, options, "linkage", linkage_src);
...@@ -21168,7 +21191,7 @@ fn resolveExportOptions(...@@ -21168,7 +21191,7 @@ fn resolveExportOptions(
2116821191
21169 const section_operand = try sema.fieldVal(block, src, options, "section", section_src);21192 const section_operand = try sema.fieldVal(block, src, options, "section", section_src);
21170 const section_opt_val = try sema.resolveConstValue(block, section_src, section_operand, "linksection of exported value must be comptime-known");21193 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;
21172 const section = if (section_opt_val.optionalValue(mod)) |section_val|21195 const section = if (section_opt_val.optionalValue(mod)) |section_val|
21173 try section_val.toAllocatedBytes(section_ty, sema.arena, mod)21196 try section_val.toAllocatedBytes(section_ty, sema.arena, mod)
21174 else21197 else
...@@ -21298,12 +21321,14 @@ fn zirCmpxchg(...@@ -21298,12 +21321,14 @@ fn zirCmpxchg(
21298 }21321 }
21299 const ptr_ty = sema.typeOf(ptr);21322 const ptr_ty = sema.typeOf(ptr);
21300 const stored_val = (try sema.pointerDeref(block, ptr_src, ptr_val, ptr_ty)) orelse break :rs ptr_src;21323 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: {21324 const result_val = try mod.intern(.{ .opt = .{
21302 try sema.storePtr(block, src, ptr, new_value);21325 .ty = result_ty.ip_index,
21303 break :blk Value.null;21326 .val = if (stored_val.eql(expected_val, elem_ty, sema.mod)) blk: {
21304 } else try Value.Tag.opt_payload.create(sema.arena, stored_val);21327 try sema.storePtr(block, src, ptr, new_value);
2130521328 break :blk .none;
21306 return sema.addConstant(result_ty, result_val);21329 } else stored_val.toIntern(),
21330 } });
21331 return sema.addConstant(result_ty, result_val.toValue());
21307 } else break :rs new_value_src;21332 } else break :rs new_value_src;
21308 } else break :rs expected_src;21333 } else break :rs expected_src;
21309 } else ptr_src;21334 } else ptr_src;
...@@ -21342,11 +21367,7 @@ fn zirSplat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I...@@ -21342,11 +21367,7 @@ fn zirSplat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
21342 });21367 });
21343 if (try sema.resolveMaybeUndefVal(scalar)) |scalar_val| {21368 if (try sema.resolveMaybeUndefVal(scalar)) |scalar_val| {
21344 if (scalar_val.isUndef(mod)) return sema.addConstUndef(vector_ty);21369 if (scalar_val.isUndef(mod)) return sema.addConstUndef(vector_ty);
2134521370 return sema.addConstant(vector_ty, try sema.splat(vector_ty, scalar_val));
21346 return sema.addConstant(
21347 vector_ty,
21348 try Value.Tag.repeated.create(sema.arena, scalar_val),
21349 );
21350 }21371 }
2135121372
21352 try sema.requireRuntimeBlock(block, inst_data.src(), scalar_src);21373 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...@@ -21800,7 +21821,7 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
21800 try sema.checkPtrIsNotComptimeMutable(block, ptr_val, ptr_src, operand_src);21821 try sema.checkPtrIsNotComptimeMutable(block, ptr_val, ptr_src, operand_src);
21801 break :rs operand_src;21822 break :rs operand_src;
21802 };21823 };
21803 if (ptr_val.isComptimeMutablePtr()) {21824 if (ptr_val.isComptimeMutablePtr(mod)) {
21804 const ptr_ty = sema.typeOf(ptr);21825 const ptr_ty = sema.typeOf(ptr);
21805 const stored_val = (try sema.pointerDeref(block, ptr_src, ptr_val, ptr_ty)) orelse break :rs ptr_src;21826 const stored_val = (try sema.pointerDeref(block, ptr_src, ptr_val, ptr_ty)) orelse break :rs ptr_src;
21806 const new_val = switch (op) {21827 const new_val = switch (op) {
...@@ -22081,10 +22102,15 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr...@@ -22081,10 +22102,15 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
22081 const result_ptr = try Type.ptr(sema.arena, sema.mod, ptr_ty_data);22102 const result_ptr = try Type.ptr(sema.arena, sema.mod, ptr_ty_data);
2208222103
22083 if (try sema.resolveDefinedValue(block, src, casted_field_ptr)) |field_ptr_val| {22104 if (try sema.resolveDefinedValue(block, src, casted_field_ptr)) |field_ptr_val| {
22084 const payload = field_ptr_val.castTag(.field_ptr) orelse {22105 const field = switch (mod.intern_pool.indexToKey(field_ptr_val.ip_index)) {
22085 return sema.fail(block, ptr_src, "pointer value not based on parent struct", .{});22106 .ptr => |ptr| switch (ptr.addr) {
22086 };22107 .field => |field| field,
22087 if (payload.data.field_index != field_index) {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) {
22088 const msg = msg: {22114 const msg = msg: {
22089 const msg = try sema.errMsg(22115 const msg = try sema.errMsg(
22090 block,22116 block,
...@@ -22093,7 +22119,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr...@@ -22093,7 +22119,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
22093 .{22119 .{
22094 field_name,22120 field_name,
22095 field_index,22121 field_index,
22096 payload.data.field_index,22122 field.index,
22097 parent_ty.fmt(sema.mod),22123 parent_ty.fmt(sema.mod),
22098 },22124 },
22099 );22125 );
...@@ -22103,7 +22129,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr...@@ -22103,7 +22129,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
22103 };22129 };
22104 return sema.failWithOwnedErrorMsg(msg);22130 return sema.failWithOwnedErrorMsg(msg);
22105 }22131 }
22106 return sema.addConstant(result_ptr, payload.data.container_ptr);22132 return sema.addConstant(result_ptr, field.base.toValue());
22107 }22133 }
2210822134
22109 try sema.requireRuntimeBlock(block, src, ptr_src);22135 try sema.requireRuntimeBlock(block, src, ptr_src);
...@@ -22335,13 +22361,13 @@ fn analyzeMinMax(...@@ -22335,13 +22361,13 @@ fn analyzeMinMax(
2233522361
22336 // Compute the final bounds based on the runtime type and the comptime-known bound type22362 // Compute the final bounds based on the runtime type and the comptime-known bound type
22337 const min_val = switch (air_tag) {22363 const min_val = switch (air_tag) {
22338 .min => try unrefined_elem_ty.minInt(sema.arena, mod),22364 .min => try unrefined_elem_ty.minInt(mod),
22339 .max => try comptime_elem_ty.minInt(sema.arena, mod), // @max(ct, rt) >= ct22365 .max => try comptime_elem_ty.minInt(mod), // @max(ct, rt) >= ct
22340 else => unreachable,22366 else => unreachable,
22341 };22367 };
22342 const max_val = switch (air_tag) {22368 const max_val = switch (air_tag) {
22343 .min => try comptime_elem_ty.maxInt(sema.arena, mod, Type.comptime_int), // @min(ct, rt) <= ct22369 .min => try comptime_elem_ty.maxInt(mod, Type.comptime_int), // @min(ct, rt) <= ct
22344 .max => try unrefined_elem_ty.maxInt(sema.arena, mod, Type.comptime_int),22370 .max => try unrefined_elem_ty.maxInt(mod, Type.comptime_int),
22345 else => unreachable,22371 else => unreachable,
22346 };22372 };
2234722373
...@@ -22464,7 +22490,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void...@@ -22464,7 +22490,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
22464 }22490 }
2246522491
22466 const runtime_src = if (try sema.resolveDefinedValue(block, dest_src, dest_ptr)) |dest_ptr_val| rs: {22492 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;
22468 if (try sema.resolveDefinedValue(block, src_src, src_ptr)) |_| {22494 if (try sema.resolveDefinedValue(block, src_src, src_ptr)) |_| {
22469 const len_u64 = (try len_val.?.getUnsignedIntAdvanced(mod, sema)).?;22495 const len_u64 = (try len_val.?.getUnsignedIntAdvanced(mod, sema)).?;
22470 const len = try sema.usizeCast(block, dest_src, len_u64);22496 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...@@ -22618,7 +22644,7 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
22618 return;22644 return;
22619 }22645 }
2262022646
22621 if (!ptr_val.isComptimeMutablePtr()) break :rs dest_src;22647 if (!ptr_val.isComptimeMutablePtr(mod)) break :rs dest_src;
22622 if (try sema.resolveMaybeUndefVal(uncoerced_elem)) |_| {22648 if (try sema.resolveMaybeUndefVal(uncoerced_elem)) |_| {
22623 for (0..len) |i| {22649 for (0..len) |i| {
22624 const elem_index = try sema.addIntUnsigned(Type.usize, i);22650 const elem_index = try sema.addIntUnsigned(Type.usize, i);
...@@ -22696,6 +22722,7 @@ fn zirVarExtended(...@@ -22696,6 +22722,7 @@ fn zirVarExtended(
22696 block: *Block,22722 block: *Block,
22697 extended: Zir.Inst.Extended.InstData,22723 extended: Zir.Inst.Extended.InstData,
22698) CompileError!Air.Inst.Ref {22724) CompileError!Air.Inst.Ref {
22725 const mod = sema.mod;
22699 const extra = sema.code.extraData(Zir.Inst.ExtendedVar, extended.operand);22726 const extra = sema.code.extraData(Zir.Inst.ExtendedVar, extended.operand);
22700 const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = 0 };22727 const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = 0 };
22701 const init_src: LazySrcLoc = .{ .node_offset_var_decl_init = 0 };22728 const init_src: LazySrcLoc = .{ .node_offset_var_decl_init = 0 };
...@@ -22737,32 +22764,17 @@ fn zirVarExtended(...@@ -22737,32 +22764,17 @@ fn zirVarExtended(
2273722764
22738 try sema.validateVarType(block, ty_src, var_ty, small.is_extern);22765 try sema.validateVarType(block, ty_src, var_ty, small.is_extern);
2273922766
22740 const new_var = try sema.gpa.create(Module.Var);22767 return sema.addConstant(var_ty, (try mod.intern(.{ .variable = .{
22741 errdefer sema.gpa.destroy(new_var);22768 .ty = var_ty.ip_index,
2274222769 .init = init_val.toIntern(),
22743 log.debug("created variable {*} owner_decl: {*} ({s})", .{22770 .decl = sema.owner_decl_index,
22744 new_var, sema.owner_decl, sema.owner_decl.name,22771 .lib_name = if (lib_name) |lname| (try mod.intern_pool.getOrPutString(
22745 });22772 sema.gpa,
2274622773 try sema.handleExternLibName(block, ty_src, lname),
22747 new_var.* = .{22774 )).toOptional() else .none,
22748 .owner_decl = sema.owner_decl_index,
22749 .init = init_val,
22750 .is_extern = small.is_extern,22775 .is_extern = small.is_extern,
22751 .is_mutable = true,
22752 .is_threadlocal = small.is_threadlocal,22776 .is_threadlocal = small.is_threadlocal,
22753 .is_weak_linkage = false,22777 } })).toValue());
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;
22766}22778}
2276722779
22768fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {22780fn 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...@@ -22861,7 +22873,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
22861 const body = sema.code.extra[extra_index..][0..body_len];22873 const body = sema.code.extra[extra_index..][0..body_len];
22862 extra_index += body.len;22874 extra_index += body.len;
2286322875
22864 const ty = Type.const_slice_u8;22876 const ty = Type.slice_const_u8;
22865 const val = try sema.resolveGenericBody(block, section_src, body, inst, ty, "linksection must be comptime-known");22877 const val = try sema.resolveGenericBody(block, section_src, body, inst, ty, "linksection must be comptime-known");
22866 if (val.isGenericPoison()) {22878 if (val.isGenericPoison()) {
22867 break :blk FuncLinkSection{ .generic = {} };22879 break :blk FuncLinkSection{ .generic = {} };
...@@ -23133,10 +23145,10 @@ fn resolveExternOptions(...@@ -23133,10 +23145,10 @@ fn resolveExternOptions(
23133 src: LazySrcLoc,23145 src: LazySrcLoc,
23134 zir_ref: Zir.Inst.Ref,23146 zir_ref: Zir.Inst.Ref,
23135) CompileError!std.builtin.ExternOptions {23147) CompileError!std.builtin.ExternOptions {
23148 const mod = sema.mod;
23136 const options_inst = try sema.resolveInst(zir_ref);23149 const options_inst = try sema.resolveInst(zir_ref);
23137 const extern_options_ty = try sema.getBuiltinType("ExternOptions");23150 const extern_options_ty = try sema.getBuiltinType("ExternOptions");
23138 const options = try sema.coerce(block, extern_options_ty, options_inst, src);23151 const options = try sema.coerce(block, extern_options_ty, options_inst, src);
23139 const mod = sema.mod;
2314023152
23141 const name_src = sema.maybeOptionsSrc(block, src, "name");23153 const name_src = sema.maybeOptionsSrc(block, src, "name");
23142 const library_src = sema.maybeOptionsSrc(block, src, "library");23154 const library_src = sema.maybeOptionsSrc(block, src, "library");
...@@ -23145,7 +23157,7 @@ fn resolveExternOptions(...@@ -23145,7 +23157,7 @@ fn resolveExternOptions(
2314523157
23146 const name_ref = try sema.fieldVal(block, src, options, "name", name_src);23158 const name_ref = try sema.fieldVal(block, src, options, "name", name_src);
23147 const name_val = try sema.resolveConstValue(block, name_src, name_ref, "name of the extern symbol must be comptime-known");23159 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
23150 const library_name_inst = try sema.fieldVal(block, src, options, "library_name", library_src);23162 const library_name_inst = try sema.fieldVal(block, src, options, "library_name", library_src);
23151 const library_name_val = try sema.resolveConstValue(block, library_src, library_name_inst, "library in which extern symbol is must be comptime-known");23163 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(...@@ -23157,9 +23169,8 @@ fn resolveExternOptions(
23157 const is_thread_local = try sema.fieldVal(block, src, options, "is_thread_local", thread_local_src);23169 const is_thread_local = try sema.fieldVal(block, src, options, "is_thread_local", thread_local_src);
23158 const is_thread_local_val = try sema.resolveConstValue(block, thread_local_src, is_thread_local, "threadlocality of the extern symbol must be comptime-known");23170 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: {23172 const library_name = if (library_name_val.optionalValue(mod)) |payload| blk: {
23161 const payload = library_name_val.castTag(.opt_payload).?.data;23173 const library_name = try payload.toAllocatedBytes(Type.slice_const_u8, sema.arena, mod);
23162 const library_name = try payload.toAllocatedBytes(Type.const_slice_u8, sema.arena, mod);
23163 if (library_name.len == 0) {23174 if (library_name.len == 0) {
23164 return sema.fail(block, library_src, "library name cannot be empty", .{});23175 return sema.fail(block, library_src, "library name cannot be empty", .{});
23165 }23176 }
...@@ -23227,40 +23238,36 @@ fn zirBuiltinExtern(...@@ -23227,40 +23238,36 @@ fn zirBuiltinExtern(
23227 new_decl.name = try sema.gpa.dupeZ(u8, options.name);23238 new_decl.name = try sema.gpa.dupeZ(u8, options.name);
2322823239
23229 {23240 {
23230 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);23241 const new_var = try mod.intern(.{ .variable = .{
23231 errdefer new_decl_arena.deinit();23242 .ty = ty.ip_index,
23232 const new_decl_arena_allocator = new_decl_arena.allocator();23243 .init = .none,
2323323244 .decl = sema.owner_decl_index,
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",
23238 .is_extern = true,23245 .is_extern = true,
23239 .is_mutable = false,23246 .is_const = true,
23240 .is_threadlocal = options.is_thread_local,23247 .is_threadlocal = options.is_thread_local,
23241 .is_weak_linkage = options.linkage == .Weak,23248 .is_weak_linkage = options.linkage == .Weak,
23242 .lib_name = null,23249 } });
23243 };
2324423250
23245 new_decl.src_line = sema.owner_decl.src_line;23251 new_decl.src_line = sema.owner_decl.src_line;
23246 // We only access this decl through the decl_ref with the correct type created23252 // We only access this decl through the decl_ref with the correct type created
23247 // below, so this type doesn't matter23253 // below, so this type doesn't matter
23248 new_decl.ty = Type.anyopaque;23254 new_decl.ty = ty;
23249 new_decl.val = try Value.Tag.variable.create(new_decl_arena_allocator, new_var);23255 new_decl.val = new_var.toValue();
23250 new_decl.@"align" = 0;23256 new_decl.@"align" = 0;
23251 new_decl.@"linksection" = null;23257 new_decl.@"linksection" = null;
23252 new_decl.has_tv = true;23258 new_decl.has_tv = true;
23253 new_decl.analysis = .complete;23259 new_decl.analysis = .complete;
23254 new_decl.generation = mod.generation;23260 new_decl.generation = mod.generation;
23255
23256 try new_decl.finalizeNewArena(&new_decl_arena);
23257 }23261 }
2325823262
23259 try mod.declareDeclDependency(sema.owner_decl_index, new_decl_index);23263 try mod.declareDeclDependency(sema.owner_decl_index, new_decl_index);
23260 try sema.ensureDeclAnalyzed(new_decl_index);23264 try sema.ensureDeclAnalyzed(new_decl_index);
2326123265
23262 const ref = try Value.Tag.decl_ref.create(sema.arena, new_decl_index);23266 const ref = try mod.intern(.{ .ptr = .{
23263 return sema.addConstant(ty, ref);23267 .ty = (try mod.singleConstPtrType(ty)).ip_index,
23268 .addr = .{ .decl = new_decl_index },
23269 } });
23270 return sema.addConstant(ty, ref.toValue());
23264}23271}
2326523272
23266fn zirWorkItem(23273fn zirWorkItem(
...@@ -24117,7 +24124,6 @@ fn fieldVal(...@@ -24117,7 +24124,6 @@ fn fieldVal(
2411724124
24118 const mod = sema.mod;24125 const mod = sema.mod;
24119 const gpa = sema.gpa;24126 const gpa = sema.gpa;
24120 const arena = sema.arena;
24121 const ip = &mod.intern_pool;24127 const ip = &mod.intern_pool;
24122 const object_src = src; // TODO better source location24128 const object_src = src; // TODO better source location
24123 const object_ty = sema.typeOf(object);24129 const object_ty = sema.typeOf(object);
...@@ -24221,13 +24227,14 @@ fn fieldVal(...@@ -24221,13 +24227,14 @@ fn fieldVal(
24221 else => unreachable,24227 else => unreachable,
24222 }24228 }
2422324229
24224 return sema.addConstant(24230 const error_set_type = if (!child_type.isAnyError(mod))
24225 if (!child_type.isAnyError(mod))24231 child_type
24226 child_type24232 else
24227 else24233 try mod.singleErrorSetTypeNts(name);
24228 try mod.singleErrorSetTypeNts(name),24234 return sema.addConstant(error_set_type, (try mod.intern(.{ .err = .{
24229 try Value.Tag.@"error".create(arena, .{ .name = ip.stringToSlice(name) }),24235 .ty = error_set_type.ip_index,
24230 );24236 .name = name,
24237 } })).toValue());
24231 },24238 },
24232 .Union => {24239 .Union => {
24233 if (child_type.getNamespaceIndex(mod).unwrap()) |namespace| {24240 if (child_type.getNamespaceIndex(mod).unwrap()) |namespace| {
...@@ -24368,14 +24375,13 @@ fn fieldPtr(...@@ -24368,14 +24375,13 @@ fn fieldPtr(
24368 });24375 });
2436924376
24370 if (try sema.resolveDefinedValue(block, object_ptr_src, inner_ptr)) |val| {24377 if (try sema.resolveDefinedValue(block, object_ptr_src, inner_ptr)) |val| {
24371 return sema.addConstant(24378 return sema.addConstant(result_ty, (try mod.intern(.{ .ptr = .{
24372 result_ty,24379 .ty = result_ty.ip_index,
24373 try Value.Tag.field_ptr.create(sema.arena, .{24380 .addr = .{ .field = .{
24374 .container_ptr = val,24381 .base = val.ip_index,
24375 .container_ty = inner_ty,24382 .index = Value.slice_ptr_index,
24376 .field_index = Value.Payload.Slice.ptr_index,24383 } },
24377 }),24384 } })).toValue());
24378 );
24379 }24385 }
24380 try sema.requireRuntimeBlock(block, src, null);24386 try sema.requireRuntimeBlock(block, src, null);
2438124387
...@@ -24389,14 +24395,13 @@ fn fieldPtr(...@@ -24389,14 +24395,13 @@ fn fieldPtr(
24389 });24395 });
2439024396
24391 if (try sema.resolveDefinedValue(block, object_ptr_src, inner_ptr)) |val| {24397 if (try sema.resolveDefinedValue(block, object_ptr_src, inner_ptr)) |val| {
24392 return sema.addConstant(24398 return sema.addConstant(result_ty, (try mod.intern(.{ .ptr = .{
24393 result_ty,24399 .ty = result_ty.ip_index,
24394 try Value.Tag.field_ptr.create(sema.arena, .{24400 .addr = .{ .field = .{
24395 .container_ptr = val,24401 .base = val.ip_index,
24396 .container_ty = inner_ty,24402 .index = Value.slice_len_index,
24397 .field_index = Value.Payload.Slice.len_index,24403 } },
24398 }),24404 } })).toValue());
24399 );
24400 }24405 }
24401 try sema.requireRuntimeBlock(block, src, null);24406 try sema.requireRuntimeBlock(block, src, null);
2440224407
...@@ -24442,14 +24447,16 @@ fn fieldPtr(...@@ -24442,14 +24447,16 @@ fn fieldPtr(
2444224447
24443 var anon_decl = try block.startAnonDecl();24448 var anon_decl = try block.startAnonDecl();
24444 defer anon_decl.deinit();24449 defer anon_decl.deinit();
24450 const error_set_type = if (!child_type.isAnyError(mod))
24451 child_type
24452 else
24453 try mod.singleErrorSetTypeNts(name);
24445 return sema.analyzeDeclRef(try anon_decl.finish(24454 return sema.analyzeDeclRef(try anon_decl.finish(
24446 if (!child_type.isAnyError(mod))24455 error_set_type,
24447 child_type24456 (try mod.intern(.{ .err = .{
24448 else24457 .ty = error_set_type.ip_index,
24449 try mod.singleErrorSetTypeNts(name),24458 .name = name,
24450 try Value.Tag.@"error".create(anon_decl.arena(), .{24459 } })).toValue(),
24451 .name = ip.stringToSlice(name),
24452 }),
24453 0, // default alignment24460 0, // default alignment
24454 ));24461 ));
24455 },24462 },
...@@ -24714,14 +24721,13 @@ fn finishFieldCallBind(...@@ -24714,14 +24721,13 @@ fn finishFieldCallBind(
24714 }24721 }
2471524722
24716 if (try sema.resolveDefinedValue(block, src, object_ptr)) |struct_ptr_val| {24723 if (try sema.resolveDefinedValue(block, src, object_ptr)) |struct_ptr_val| {
24717 const pointer = try sema.addConstant(24724 const pointer = try sema.addConstant(ptr_field_ty, (try mod.intern(.{ .ptr = .{
24718 ptr_field_ty,24725 .ty = ptr_field_ty.ip_index,
24719 try Value.Tag.field_ptr.create(arena, .{24726 .addr = .{ .field = .{
24720 .container_ptr = struct_ptr_val,24727 .base = struct_ptr_val.ip_index,
24721 .container_ty = container_ty,24728 .index = field_index,
24722 .field_index = field_index,24729 } },
24723 }),24730 } })).toValue());
24724 );
24725 return .{ .direct = try sema.analyzeLoad(block, src, pointer, src) };24731 return .{ .direct = try sema.analyzeLoad(block, src, pointer, src) };
24726 }24732 }
2472724733
...@@ -24901,22 +24907,22 @@ fn structFieldPtrByIndex(...@@ -24901,22 +24907,22 @@ fn structFieldPtrByIndex(
24901 const ptr_field_ty = try Type.ptr(sema.arena, mod, ptr_ty_data);24907 const ptr_field_ty = try Type.ptr(sema.arena, mod, ptr_ty_data);
2490224908
24903 if (field.is_comptime) {24909 if (field.is_comptime) {
24904 const val = try Value.Tag.comptime_field_ptr.create(sema.arena, .{24910 const val = try mod.intern(.{ .ptr = .{
24905 .field_ty = field.ty,24911 .ty = ptr_field_ty.ip_index,
24906 .field_val = try field.default_val.copy(sema.arena),24912 .addr = .{ .comptime_field = try field.default_val.intern(field.ty, mod) },
24907 });24913 } });
24908 return sema.addConstant(ptr_field_ty, val);24914 return sema.addConstant(ptr_field_ty, val.toValue());
24909 }24915 }
2491024916
24911 if (try sema.resolveDefinedValue(block, src, struct_ptr)) |struct_ptr_val| {24917 if (try sema.resolveDefinedValue(block, src, struct_ptr)) |struct_ptr_val| {
24912 return sema.addConstant(24918 const val = try mod.intern(.{ .ptr = .{
24913 ptr_field_ty,24919 .ty = ptr_field_ty.ip_index,
24914 try Value.Tag.field_ptr.create(sema.arena, .{24920 .addr = .{ .field = .{
24915 .container_ptr = struct_ptr_val,24921 .base = try struct_ptr_val.intern(struct_ptr_ty, mod),
24916 .container_ty = struct_ptr_ty.childType(mod),24922 .index = field_index,
24917 .field_index = field_index,24923 } },
24918 }),24924 } });
24919 );24925 return sema.addConstant(ptr_field_ty, val.toValue());
24920 }24926 }
2492124927
24922 try sema.requireRuntimeBlock(block, src, null);24928 try sema.requireRuntimeBlock(block, src, null);
...@@ -24955,7 +24961,7 @@ fn structFieldVal(...@@ -24955,7 +24961,7 @@ fn structFieldVal(
24955 if ((try sema.typeHasOnePossibleValue(field.ty))) |opv| {24961 if ((try sema.typeHasOnePossibleValue(field.ty))) |opv| {
24956 return sema.addConstant(field.ty, opv);24962 return sema.addConstant(field.ty, opv);
24957 }24963 }
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));
24959 }24965 }
2496024966
24961 try sema.requireRuntimeBlock(block, src, null);24967 try sema.requireRuntimeBlock(block, src, null);
...@@ -24999,7 +25005,7 @@ fn tupleFieldIndex(...@@ -24999,7 +25005,7 @@ fn tupleFieldIndex(
24999 field_name_src: LazySrcLoc,25005 field_name_src: LazySrcLoc,
25000) CompileError!u32 {25006) CompileError!u32 {
25001 const mod = sema.mod;25007 const mod = sema.mod;
25002 assert(!std.mem.eql(u8, field_name, "len"));25008 assert(!mem.eql(u8, field_name, "len"));
25003 if (std.fmt.parseUnsigned(u32, field_name, 10)) |field_index| {25009 if (std.fmt.parseUnsigned(u32, field_name, 10)) |field_index| {
25004 if (field_index < tuple_ty.structFieldCount(mod)) return field_index;25010 if (field_index < tuple_ty.structFieldCount(mod)) return field_index;
25005 return sema.fail(block, field_name_src, "index '{s}' out of bounds of tuple '{}'", .{25011 return sema.fail(block, field_name_src, "index '{s}' out of bounds of tuple '{}'", .{
...@@ -25109,14 +25115,13 @@ fn unionFieldPtr(...@@ -25109,14 +25115,13 @@ fn unionFieldPtr(
25109 },25115 },
25110 .Packed, .Extern => {},25116 .Packed, .Extern => {},
25111 }25117 }
25112 return sema.addConstant(25118 return sema.addConstant(ptr_field_ty, (try mod.intern(.{ .ptr = .{
25113 ptr_field_ty,25119 .ty = ptr_field_ty.ip_index,
25114 try Value.Tag.field_ptr.create(arena, .{25120 .addr = .{ .field = .{
25115 .container_ptr = union_ptr_val,25121 .base = union_ptr_val.ip_index,
25116 .container_ty = union_ty,25122 .index = field_index,
25117 .field_index = field_index,25123 } },
25118 }),25124 } })).toValue());
25119 );
25120 }25125 }
2512125126
25122 try sema.requireRuntimeBlock(block, src, null);25127 try sema.requireRuntimeBlock(block, src, null);
...@@ -25267,7 +25272,7 @@ fn elemPtrOneLayerOnly(...@@ -25267,7 +25272,7 @@ fn elemPtrOneLayerOnly(
25267 const ptr_val = maybe_ptr_val orelse break :rs indexable_src;25272 const ptr_val = maybe_ptr_val orelse break :rs indexable_src;
25268 const index_val = maybe_index_val orelse break :rs elem_index_src;25273 const index_val = maybe_index_val orelse break :rs elem_index_src;
25269 const index = @intCast(usize, index_val.toUnsignedInt(mod));25274 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);
25271 const result_ty = try sema.elemPtrType(indexable_ty, index);25276 const result_ty = try sema.elemPtrType(indexable_ty, index);
25272 return sema.addConstant(result_ty, elem_ptr);25277 return sema.addConstant(result_ty, elem_ptr);
25273 };25278 };
...@@ -25313,7 +25318,7 @@ fn elemVal(...@@ -25313,7 +25318,7 @@ fn elemVal(
25313 const indexable_val = maybe_indexable_val orelse break :rs indexable_src;25318 const indexable_val = maybe_indexable_val orelse break :rs indexable_src;
25314 const index_val = maybe_index_val orelse break :rs elem_index_src;25319 const index_val = maybe_index_val orelse break :rs elem_index_src;
25315 const index = @intCast(usize, index_val.toUnsignedInt(mod));25320 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);
25317 if (try sema.pointerDeref(block, indexable_src, elem_ptr_val, indexable_ty)) |elem_val| {25322 if (try sema.pointerDeref(block, indexable_src, elem_ptr_val, indexable_ty)) |elem_val| {
25318 return sema.addConstant(indexable_ty.elemType2(mod), elem_val);25323 return sema.addConstant(indexable_ty.elemType2(mod), elem_val);
25319 }25324 }
...@@ -25407,22 +25412,20 @@ fn tupleFieldPtr(...@@ -25407,22 +25412,20 @@ fn tupleFieldPtr(
25407 });25412 });
2540825413
25409 if (try tuple_ty.structFieldValueComptime(mod, field_index)) |default_val| {25414 if (try tuple_ty.structFieldValueComptime(mod, field_index)) |default_val| {
25410 const val = try Value.Tag.comptime_field_ptr.create(sema.arena, .{25415 return sema.addConstant(ptr_field_ty, (try mod.intern(.{ .ptr = .{
25411 .field_ty = field_ty,25416 .ty = ptr_field_ty.ip_index,
25412 .field_val = default_val,25417 .addr = .{ .comptime_field = default_val.ip_index },
25413 });25418 } })).toValue());
25414 return sema.addConstant(ptr_field_ty, val);
25415 }25419 }
2541625420
25417 if (try sema.resolveMaybeUndefVal(tuple_ptr)) |tuple_ptr_val| {25421 if (try sema.resolveMaybeUndefVal(tuple_ptr)) |tuple_ptr_val| {
25418 return sema.addConstant(25422 return sema.addConstant(ptr_field_ty, (try mod.intern(.{ .ptr = .{
25419 ptr_field_ty,25423 .ty = ptr_field_ty.ip_index,
25420 try Value.Tag.field_ptr.create(sema.arena, .{25424 .addr = .{ .field = .{
25421 .container_ptr = tuple_ptr_val,25425 .base = tuple_ptr_val.ip_index,
25422 .container_ty = tuple_ty,25426 .index = field_index,
25423 .field_index = field_index,25427 } },
25424 }),25428 } })).toValue());
25425 );
25426 }25429 }
2542725430
25428 if (!init) {25431 if (!init) {
...@@ -25463,7 +25466,7 @@ fn tupleField(...@@ -25463,7 +25466,7 @@ fn tupleField(
2546325466
25464 if (try sema.resolveMaybeUndefVal(tuple)) |tuple_val| {25467 if (try sema.resolveMaybeUndefVal(tuple)) |tuple_val| {
25465 if (tuple_val.isUndef(mod)) return sema.addConstUndef(field_ty);25468 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));
25467 }25470 }
2546825471
25469 try sema.validateRuntimeElemAccess(block, field_index_src, field_ty, tuple_ty, tuple_src);25472 try sema.validateRuntimeElemAccess(block, field_index_src, field_ty, tuple_ty, tuple_src);
...@@ -25575,7 +25578,7 @@ fn elemPtrArray(...@@ -25575,7 +25578,7 @@ fn elemPtrArray(
25575 return sema.addConstUndef(elem_ptr_ty);25578 return sema.addConstUndef(elem_ptr_ty);
25576 }25579 }
25577 if (offset) |index| {25580 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);
25579 return sema.addConstant(elem_ptr_ty, elem_ptr);25582 return sema.addConstant(elem_ptr_ty, elem_ptr);
25580 }25583 }
25581 }25584 }
...@@ -25631,7 +25634,7 @@ fn elemValSlice(...@@ -25631,7 +25634,7 @@ fn elemValSlice(
25631 const sentinel_label: []const u8 = if (slice_sent) " +1 (sentinel)" else "";25634 const sentinel_label: []const u8 = if (slice_sent) " +1 (sentinel)" else "";
25632 return sema.fail(block, elem_index_src, "index {d} outside slice of length {d}{s}", .{ index, slice_len, sentinel_label });25635 return sema.fail(block, elem_index_src, "index {d} outside slice of length {d}{s}", .{ index, slice_len, sentinel_label });
25633 }25636 }
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);
25635 if (try sema.pointerDeref(block, slice_src, elem_ptr_val, slice_ty)) |elem_val| {25638 if (try sema.pointerDeref(block, slice_src, elem_ptr_val, slice_ty)) |elem_val| {
25636 return sema.addConstant(elem_ty, elem_val);25639 return sema.addConstant(elem_ty, elem_val);
25637 }25640 }
...@@ -25691,7 +25694,7 @@ fn elemPtrSlice(...@@ -25691,7 +25694,7 @@ fn elemPtrSlice(
25691 const sentinel_label: []const u8 = if (slice_sent) " +1 (sentinel)" else "";25694 const sentinel_label: []const u8 = if (slice_sent) " +1 (sentinel)" else "";
25692 return sema.fail(block, elem_index_src, "index {d} outside slice of length {d}{s}", .{ index, slice_len, sentinel_label });25695 return sema.fail(block, elem_index_src, "index {d} outside slice of length {d}{s}", .{ index, slice_len, sentinel_label });
25693 }25696 }
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);
25695 return sema.addConstant(elem_ptr_ty, elem_ptr_val);25698 return sema.addConstant(elem_ptr_ty, elem_ptr_val);
25696 }25699 }
25697 }25700 }
...@@ -25851,7 +25854,7 @@ fn coerceExtra(...@@ -25851,7 +25854,7 @@ fn coerceExtra(
25851 // Function body to function pointer.25854 // Function body to function pointer.
25852 if (inst_ty.zigTypeTag(mod) == .Fn) {25855 if (inst_ty.zigTypeTag(mod) == .Fn) {
25853 const fn_val = try sema.resolveConstValue(block, .unneeded, inst, "");25856 const fn_val = try sema.resolveConstValue(block, .unneeded, inst, "");
25854 const fn_decl = fn_val.pointerDecl().?;25857 const fn_decl = fn_val.pointerDecl(mod).?;
25855 const inst_as_ptr = try sema.analyzeDeclRef(fn_decl);25858 const inst_as_ptr = try sema.analyzeDeclRef(fn_decl);
25856 return sema.coerce(block, dest_ty, inst_as_ptr, inst_src);25859 return sema.coerce(block, dest_ty, inst_as_ptr, inst_src);
25857 }25860 }
...@@ -26080,14 +26083,14 @@ fn coerceExtra(...@@ -26080,14 +26083,14 @@ fn coerceExtra(
26080 if (inst_child_ty.structFieldCount(mod) == 0) {26083 if (inst_child_ty.structFieldCount(mod) == 0) {
26081 // Optional slice is represented with a null pointer so26084 // Optional slice is represented with a null pointer so
26082 // we use a dummy pointer value with the required alignment.26085 // we use a dummy pointer value with the required alignment.
26083 const slice_val = try Value.Tag.slice.create(sema.arena, .{26086 return sema.addConstant(dest_ty, (try mod.intern(.{ .ptr = .{
26084 .ptr = if (dest_info.@"align" != 0)26087 .ty = dest_ty.ip_index,
26088 .addr = .{ .int = (if (dest_info.@"align" != 0)
26085 try mod.intValue(Type.usize, dest_info.@"align")26089 try mod.intValue(Type.usize, dest_info.@"align")
26086 else26090 else
26087 try dest_info.pointee_type.lazyAbiAlignment(mod, sema.arena),26091 try dest_info.pointee_type.lazyAbiAlignment(mod)).ip_index },
26088 .len = try mod.intValue(Type.usize, 0),26092 .len = (try mod.intValue(Type.usize, 0)).ip_index,
26089 });26093 } })).toValue());
26090 return sema.addConstant(dest_ty, slice_val);
26091 }26094 }
2609226095
26093 // pointer to tuple to slice26096 // pointer to tuple to slice
...@@ -26255,7 +26258,8 @@ fn coerceExtra(...@@ -26255,7 +26258,8 @@ fn coerceExtra(
26255 .EnumLiteral => {26258 .EnumLiteral => {
26256 // enum literal to enum26259 // enum literal to enum
26257 const val = try sema.resolveConstValue(block, .unneeded, inst, "");26260 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);
26259 const field_index = dest_ty.enumFieldIndex(bytes, mod) orelse {26263 const field_index = dest_ty.enumFieldIndex(bytes, mod) orelse {
26260 const msg = msg: {26264 const msg = msg: {
26261 const msg = try sema.errMsg(26265 const msg = try sema.errMsg(
...@@ -26292,26 +26296,30 @@ fn coerceExtra(...@@ -26292,26 +26296,30 @@ fn coerceExtra(
26292 if (maybe_inst_val) |inst_val| {26296 if (maybe_inst_val) |inst_val| {
26293 switch (inst_val.ip_index) {26297 switch (inst_val.ip_index) {
26294 .undef => return sema.addConstUndef(dest_ty),26298 .undef => return sema.addConstUndef(dest_ty),
26295 .none => switch (inst_val.tag()) {26299 else => switch (mod.intern_pool.indexToKey(inst_val.ip_index)) {
26296 .eu_payload => {26300 .error_union => |error_union| switch (error_union.val) {
26297 const payload = try sema.addConstant(26301 .err_name => |err_name| {
26298 inst_ty.errorUnionPayload(mod),26302 const error_set_ty = inst_ty.errorUnionSet(mod);
26299 inst_val.castTag(.eu_payload).?.data,26303 const error_set_val = try sema.addConstant(error_set_ty, (try mod.intern(.{ .err = .{
26300 );26304 .ty = error_set_ty.ip_index,
26301 return sema.wrapErrorUnionPayload(block, dest_ty, payload, inst_src) catch |err| switch (err) {26305 .name = err_name,
26302 error.NotCoercible => break :eu,26306 } })).toValue());
26303 else => |e| return e,26307 return sema.wrapErrorUnionSet(block, dest_ty, error_set_val, inst_src);
26304 };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 },
26305 },26319 },
26306 else => {},26320 else => unreachable,
26307 },26321 },
26308 else => {},
26309 }26322 }
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);
26315 }26323 }
26316 },26324 },
26317 .ErrorSet => {26325 .ErrorSet => {
...@@ -27029,7 +27037,7 @@ fn coerceInMemoryAllowedErrorSets(...@@ -27029,7 +27037,7 @@ fn coerceInMemoryAllowedErrorSets(
27029 },27037 },
27030 }27038 }
2703127039
27032 if (dst_ies.func == sema.owner_func) {27040 if (dst_ies.func == sema.owner_func_index.unwrap()) {
27033 // We are trying to coerce an error set to the current function's27041 // We are trying to coerce an error set to the current function's
27034 // inferred error set.27042 // inferred error set.
27035 try dst_ies.addErrorSet(src_ty, ip, gpa);27043 try dst_ies.addErrorSet(src_ty, ip, gpa);
...@@ -27323,7 +27331,7 @@ fn coerceVarArgParam(...@@ -27323,7 +27331,7 @@ fn coerceVarArgParam(
27323 ),27331 ),
27324 .Fn => blk: {27332 .Fn => blk: {
27325 const fn_val = try sema.resolveConstValue(block, .unneeded, inst, "");27333 const fn_val = try sema.resolveConstValue(block, .unneeded, inst, "");
27326 const fn_decl = fn_val.pointerDecl().?;27334 const fn_decl = fn_val.pointerDecl(mod).?;
27327 break :blk try sema.analyzeDeclRef(fn_decl);27335 break :blk try sema.analyzeDeclRef(fn_decl);
27328 },27336 },
27329 .Array => return sema.fail(block, inst_src, "arrays must be passed by reference to variadic function", .{}),27337 .Array => return sema.fail(block, inst_src, "arrays must be passed by reference to variadic function", .{}),
...@@ -27441,7 +27449,7 @@ fn storePtr2(...@@ -27441,7 +27449,7 @@ fn storePtr2(
27441 try sema.checkPtrIsNotComptimeMutable(block, ptr_val, ptr_src, operand_src);27449 try sema.checkPtrIsNotComptimeMutable(block, ptr_val, ptr_src, operand_src);
27442 break :rs operand_src;27450 break :rs operand_src;
27443 };27451 };
27444 if (ptr_val.isComptimeMutablePtr()) {27452 if (ptr_val.isComptimeMutablePtr(mod)) {
27445 try sema.storePtrVal(block, src, ptr_val, operand_val, elem_ty);27453 try sema.storePtrVal(block, src, ptr_val, operand_val, elem_ty);
27446 return;27454 return;
27447 } else break :rs ptr_src;27455 } else break :rs ptr_src;
...@@ -27593,7 +27601,7 @@ fn storePtrVal(...@@ -27593,7 +27601,7 @@ fn storePtrVal(
27593}27601}
2759427602
27595const ComptimePtrMutationKit = struct {27603const ComptimePtrMutationKit = struct {
27596 decl_ref_mut: Value.Payload.DeclRefMut.Data,27604 decl_ref_mut: InternPool.Key.Ptr.Addr.MutDecl,
27597 pointee: union(enum) {27605 pointee: union(enum) {
27598 /// The pointer type matches the actual comptime Value so a direct27606 /// The pointer type matches the actual comptime Value so a direct
27599 /// modification is possible.27607 /// modification is possible.
...@@ -27619,12 +27627,12 @@ const ComptimePtrMutationKit = struct {...@@ -27619,12 +27627,12 @@ const ComptimePtrMutationKit = struct {
27619 decl_arena: std.heap.ArenaAllocator = undefined,27627 decl_arena: std.heap.ArenaAllocator = undefined,
2762027628
27621 fn beginArena(self: *ComptimePtrMutationKit, mod: *Module) Allocator {27629 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);
27623 return decl.value_arena.?.acquire(mod.gpa, &self.decl_arena);27631 return decl.value_arena.?.acquire(mod.gpa, &self.decl_arena);
27624 }27632 }
2762527633
27626 fn finishArena(self: *ComptimePtrMutationKit, mod: *Module) void {27634 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);
27628 decl.value_arena.?.release(&self.decl_arena);27636 decl.value_arena.?.release(&self.decl_arena);
27629 self.decl_arena = undefined;27637 self.decl_arena = undefined;
27630 }27638 }
...@@ -27637,6 +27645,7 @@ fn beginComptimePtrMutation(...@@ -27637,6 +27645,7 @@ fn beginComptimePtrMutation(
27637 ptr_val: Value,27645 ptr_val: Value,
27638 ptr_elem_ty: Type,27646 ptr_elem_ty: Type,
27639) CompileError!ComptimePtrMutationKit {27647) CompileError!ComptimePtrMutationKit {
27648 if (true) unreachable;
27640 const mod = sema.mod;27649 const mod = sema.mod;
27641 switch (ptr_val.tag()) {27650 switch (ptr_val.tag()) {
27642 .decl_ref_mut => {27651 .decl_ref_mut => {
...@@ -28169,7 +28178,7 @@ fn beginComptimePtrMutation(...@@ -28169,7 +28178,7 @@ fn beginComptimePtrMutation(
28169 },28178 },
28170 }28179 }
28171 },28180 },
28172 .decl_ref => unreachable, // isComptimeMutablePtr() has been checked already28181 .decl_ref => unreachable, // isComptimeMutablePtr has been checked already
28173 else => unreachable,28182 else => unreachable,
28174 }28183 }
28175}28184}
...@@ -28189,7 +28198,7 @@ fn beginComptimePtrMutationInner(...@@ -28189,7 +28198,7 @@ fn beginComptimePtrMutationInner(
2818928198
28190 const decl = mod.declPtr(decl_ref_mut.decl_index);28199 const decl = mod.declPtr(decl_ref_mut.decl_index);
28191 var decl_arena: std.heap.ArenaAllocator = undefined;28200 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);
28193 defer decl.value_arena.?.release(&decl_arena);28202 defer decl.value_arena.?.release(&decl_arena);
28194 decl_val.* = try decl_val.unintern(allocator, mod);28203 decl_val.* = try decl_val.unintern(allocator, mod);
2819528204
...@@ -28273,44 +28282,83 @@ fn beginComptimePtrLoad(...@@ -28273,44 +28282,83 @@ fn beginComptimePtrLoad(
28273 const mod = sema.mod;28282 const mod = sema.mod;
28274 const target = mod.getTarget();28283 const target = mod.getTarget();
2827528284
28276 var deref: ComptimePtrLoadKit = switch (ptr_val.ip_index) {28285 var deref: ComptimePtrLoadKit = switch (mod.intern_pool.indexToKey(ptr_val.ip_index)) {
28277 .null_value => {28286 .ptr => |ptr| switch (ptr.addr) {
28278 return sema.fail(block, src, "attempt to use null value", .{});28287 .decl, .mut_decl => blk: {
28279 },28288 const decl_index = switch (ptr.addr) {
2828028289 .decl => |decl| decl,
28281 .none => switch (ptr_val.tag()) {28290 .mut_decl => |mut_decl| mut_decl.decl,
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,
28288 else => unreachable,28291 else => unreachable,
28289 };28292 };
28290 const is_mutable = ptr_val.tag() == .decl_ref_mut;
28291 const decl = mod.declPtr(decl_index);28293 const decl = mod.declPtr(decl_index);
28292 const decl_tv = try decl.typedValue();28294 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
28295 const layout_defined = decl.ty.hasWellDefinedLayout(mod);28297 const layout_defined = decl.ty.hasWellDefinedLayout(mod);
28296 break :blk ComptimePtrLoadKit{28298 break :blk ComptimePtrLoadKit{
28297 .parent = if (layout_defined) .{ .tv = decl_tv, .byte_offset = 0 } else null,28299 .parent = if (layout_defined) .{ .tv = decl_tv, .byte_offset = 0 } else null,
28298 .pointee = decl_tv,28300 .pointee = decl_tv,
28299 .is_mutable = is_mutable,28301 .is_mutable = false,
28300 .ty_without_well_defined_layout = if (!layout_defined) decl.ty else null,28302 .ty_without_well_defined_layout = if (!layout_defined) decl.ty else null,
28301 };28303 };
28302 },28304 },
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: {28311 // eu_payload and opt_payload never have a well-defined layout
28305 const elem_ptr = ptr_val.castTag(.elem_ptr).?.data;28312 if (deref.parent != null) {
28306 const elem_ty = elem_ptr.elem_ty;28313 deref.parent = null;
28307 var deref = try sema.beginComptimePtrLoad(block, src, elem_ptr.array_ptr, 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
28309 // This code assumes that elem_ptrs have been "flattened" in order for direct dereference28353 // This code assumes that elem_ptrs have been "flattened" in order for direct dereference
28310 // to succeed, meaning that elem ptrs of the same elem_ty are coalesced. Here we check that28354 // to succeed, meaning that elem ptrs of the same elem_ty are coalesced. Here we check that
28311 // our parent is not an elem_ptr with the same elem_ty, since that would be "unflattened"28355 // 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| {28356 switch (mod.intern_pool.indexToKey(elem_ptr.base)) {
28313 assert(!(parent_elem_ptr.data.elem_ty.eql(elem_ty, mod)));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 => {},
28314 }28362 }
2831528363
28316 if (elem_ptr.index != 0) {28364 if (elem_ptr.index != 0) {
...@@ -28327,7 +28375,7 @@ fn beginComptimePtrLoad(...@@ -28327,7 +28375,7 @@ fn beginComptimePtrLoad(
28327 }28375 }
28328 }28376 }
2832928377
28330 // If we're loading an elem_ptr that was derived from a different type28378 // If we're loading an elem that was derived from a different type
28331 // than the true type of the underlying decl, we cannot deref directly28379 // than the true type of the underlying decl, we cannot deref directly
28332 const ty_matches = if (deref.pointee != null and deref.pointee.?.ty.isArrayOrVector(mod)) x: {28380 const ty_matches = if (deref.pointee != null and deref.pointee.?.ty.isArrayOrVector(mod)) x: {
28333 const deref_elem_ty = deref.pointee.?.ty.childType(mod);28381 const deref_elem_ty = deref.pointee.?.ty.childType(mod);
...@@ -28373,31 +28421,25 @@ fn beginComptimePtrLoad(...@@ -28373,31 +28421,25 @@ fn beginComptimePtrLoad(
28373 };28421 };
28374 break :blk deref;28422 break :blk deref;
28375 },28423 },
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: {28429 if (container_ty.hasWellDefinedLayout(mod)) {
28378 const slice = ptr_val.castTag(.slice).?.data;28430 const struct_obj = mod.typeToStruct(container_ty);
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);
28389 if (struct_obj != null and struct_obj.?.layout == .Packed) {28431 if (struct_obj != null and struct_obj.?.layout == .Packed) {
28390 // packed structs are not byte addressable28432 // packed structs are not byte addressable
28391 deref.parent = null;28433 deref.parent = null;
28392 } else if (deref.parent) |*parent| {28434 } else if (deref.parent) |*parent| {
28393 // Update the byte offset (in-place)28435 // Update the byte offset (in-place)
28394 try sema.resolveTypeLayout(field_ptr.container_ty);28436 try sema.resolveTypeLayout(container_ty);
28395 const field_offset = field_ptr.container_ty.structFieldOffset(field_index, mod);28437 const field_offset = container_ty.structFieldOffset(field_index, mod);
28396 parent.byte_offset = try sema.usizeCast(block, src, parent.byte_offset + field_offset);28438 parent.byte_offset = try sema.usizeCast(block, src, parent.byte_offset + field_offset);
28397 }28439 }
28398 } else {28440 } else {
28399 deref.parent = null;28441 deref.parent = null;
28400 deref.ty_without_well_defined_layout = field_ptr.container_ty;28442 deref.ty_without_well_defined_layout = container_ty;
28401 }28443 }
2840228444
28403 const tv = deref.pointee orelse {28445 const tv = deref.pointee orelse {
...@@ -28405,294 +28447,40 @@ fn beginComptimePtrLoad(...@@ -28405,294 +28447,40 @@ fn beginComptimePtrLoad(
28405 break :blk deref;28447 break :blk deref;
28406 };28448 };
28407 const coerce_in_mem_ok =28449 const coerce_in_mem_ok =
28408 (try sema.coerceInMemoryAllowed(block, field_ptr.container_ty, tv.ty, false, target, src, src)) == .ok or28450 (try sema.coerceInMemoryAllowed(block, 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;28451 (try sema.coerceInMemoryAllowed(block, tv.ty, container_ty, false, target, src, src)) == .ok;
28410 if (!coerce_in_mem_ok) {28452 if (!coerce_in_mem_ok) {
28411 deref.pointee = null;28453 deref.pointee = null;
28412 break :blk deref;28454 break :blk deref;
28413 }28455 }
2841428456
28415 if (field_ptr.container_ty.isSlice(mod)) {28457 if (container_ty.isSlice(mod)) {
28416 const slice_val = tv.val.castTag(.slice).?.data;
28417 deref.pointee = switch (field_index) {28458 deref.pointee = switch (field_index) {
28418 Value.Payload.Slice.ptr_index => TypedValue{28459 Value.slice_ptr_index => TypedValue{
28419 .ty = field_ptr.container_ty.slicePtrFieldType(mod),28460 .ty = container_ty.slicePtrFieldType(mod),
28420 .val = slice_val.ptr,28461 .val = tv.val.slicePtr(mod),
28421 },28462 },
28422 Value.Payload.Slice.len_index => TypedValue{28463 Value.slice_len_index => TypedValue{
28423 .ty = Type.usize,28464 .ty = Type.usize,
28424 .val = slice_val.len,28465 .val = mod.intern_pool.indexToKey(tv.val.ip_index).ptr.len.toValue(),
28425 },28466 },
28426 else => unreachable,28467 else => unreachable,
28427 };28468 };
28428 } else {28469 } else {
28429 const field_ty = field_ptr.container_ty.structFieldType(field_index, mod);28470 const field_ty = container_ty.structFieldType(field_index, mod);
28430 deref.pointee = TypedValue{28471 deref.pointee = TypedValue{
28431 .ty = field_ty,28472 .ty = field_ty,
28432 .val = try tv.val.fieldValue(tv.ty, mod, field_index),28473 .val = try tv.val.fieldValue(mod, field_index),
28433 };28474 };
28434 }28475 }
28435 break :blk deref;28476 break :blk deref;
28436 },28477 },
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,
28498 },28478 },
28499 else => switch (mod.intern_pool.indexToKey(ptr_val.ip_index)) {28479 .opt => |opt| switch (opt.val) {
28500 .int => return error.RuntimeLoad,28480 .none => return sema.fail(block, src, "attempt to use null value", .{}),
28501 .ptr => |ptr| switch (ptr.addr) {28481 else => try sema.beginComptimePtrLoad(block, src, opt.val.toValue(), null),
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,
28695 },28482 },
28483 else => unreachable,
28696 };28484 };
2869728485
28698 if (deref.pointee) |tv| {28486 if (deref.pointee) |tv| {
...@@ -28853,7 +28641,7 @@ fn coerceCompatiblePtrs(...@@ -28853,7 +28641,7 @@ fn coerceCompatiblePtrs(
28853 }28641 }
28854 // The comptime Value representation is compatible with both types.28642 // The comptime Value representation is compatible with both types.
28855 return sema.addConstant(dest_ty, (try mod.intern_pool.getCoerced(28643 return sema.addConstant(dest_ty, (try mod.intern_pool.getCoerced(
28856 mod.gpa,28644 sema.gpa,
28857 try val.intern(inst_ty, mod),28645 try val.intern(inst_ty, mod),
28858 dest_ty.ip_index,28646 dest_ty.ip_index,
28859 )).toValue());28647 )).toValue());
...@@ -29538,7 +29326,7 @@ fn ensureDeclAnalyzed(sema: *Sema, decl_index: Decl.Index) CompileError!void {...@@ -29538,7 +29326,7 @@ fn ensureDeclAnalyzed(sema: *Sema, decl_index: Decl.Index) CompileError!void {
29538 };29326 };
29539}29327}
2954029328
29541fn ensureFuncBodyAnalyzed(sema: *Sema, func: *Module.Fn) CompileError!void {29329fn ensureFuncBodyAnalyzed(sema: *Sema, func: Module.Fn.Index) CompileError!void {
29542 sema.mod.ensureFuncBodyAnalyzed(func) catch |err| {29330 sema.mod.ensureFuncBodyAnalyzed(func) catch |err| {
29543 if (sema.owner_func) |owner_func| {29331 if (sema.owner_func) |owner_func| {
29544 owner_func.state = .dependency_failure;29332 owner_func.state = .dependency_failure;
...@@ -29550,6 +29338,7 @@ fn ensureFuncBodyAnalyzed(sema: *Sema, func: *Module.Fn) CompileError!void {...@@ -29550,6 +29338,7 @@ fn ensureFuncBodyAnalyzed(sema: *Sema, func: *Module.Fn) CompileError!void {
29550}29338}
2955129339
29552fn refValue(sema: *Sema, block: *Block, ty: Type, val: Value) !Value {29340fn refValue(sema: *Sema, block: *Block, ty: Type, val: Value) !Value {
29341 const mod = sema.mod;
29553 var anon_decl = try block.startAnonDecl();29342 var anon_decl = try block.startAnonDecl();
29554 defer anon_decl.deinit();29343 defer anon_decl.deinit();
29555 const decl = try anon_decl.finish(29344 const decl = try anon_decl.finish(
...@@ -29558,15 +29347,23 @@ fn refValue(sema: *Sema, block: *Block, ty: Type, val: Value) !Value {...@@ -29558,15 +29347,23 @@ fn refValue(sema: *Sema, block: *Block, ty: Type, val: Value) !Value {
29558 0, // default alignment29347 0, // default alignment
29559 );29348 );
29560 try sema.maybeQueueFuncBodyAnalysis(decl);29349 try sema.maybeQueueFuncBodyAnalysis(decl);
29561 try sema.mod.declareDeclDependency(sema.owner_decl_index, decl);29350 try mod.declareDeclDependency(sema.owner_decl_index, decl);
29562 return try Value.Tag.decl_ref.create(sema.arena, 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();
29563}29356}
2956429357
29565fn optRefValue(sema: *Sema, block: *Block, ty: Type, opt_val: ?Value) !Value {29358fn optRefValue(sema: *Sema, block: *Block, ty: Type, opt_val: ?Value) !Value {
29359 const mod = sema.mod;
29566 const val = opt_val orelse return Value.null;29360 const val = opt_val orelse return Value.null;
29567 const ptr_val = try sema.refValue(block, ty, val);29361 const ptr_val = try sema.refValue(block, ty, val);
29568 const result = try Value.Tag.opt_payload.create(sema.arena, ptr_val);29362 const result = try mod.intern(.{ .opt = .{
29569 return result;29363 .ty = (try mod.optionalType((try mod.singleConstPtrType(ty)).ip_index)).ip_index,
29364 .val = ptr_val.ip_index,
29365 } });
29366 return result.toValue();
29570}29367}
2957129368
29572fn analyzeDeclRef(sema: *Sema, decl_index: Decl.Index) CompileError!Air.Inst.Ref {29369fn 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...@@ -29587,10 +29384,7 @@ fn analyzeDeclRefInner(sema: *Sema, decl_index: Decl.Index, analyze_fn_body: boo
29587 const ptr_ty = try mod.ptrType(.{29384 const ptr_ty = try mod.ptrType(.{
29588 .elem_type = decl_tv.ty.ip_index,29385 .elem_type = decl_tv.ty.ip_index,
29589 .alignment = InternPool.Alignment.fromByteUnits(decl.@"align"),29386 .alignment = InternPool.Alignment.fromByteUnits(decl.@"align"),
29590 .is_const = if (decl_tv.val.castTag(.variable)) |payload|29387 .is_const = if (decl.getVariable(mod)) |variable| variable.is_const else false,
29591 !payload.data.is_mutable
29592 else
29593 false,
29594 .address_space = decl.@"addrspace",29388 .address_space = decl.@"addrspace",
29595 });29389 });
29596 if (analyze_fn_body) {29390 if (analyze_fn_body) {
...@@ -29608,8 +29402,8 @@ fn maybeQueueFuncBodyAnalysis(sema: *Sema, decl_index: Decl.Index) !void {...@@ -29608,8 +29402,8 @@ fn maybeQueueFuncBodyAnalysis(sema: *Sema, decl_index: Decl.Index) !void {
29608 const tv = try decl.typedValue();29402 const tv = try decl.typedValue();
29609 if (tv.ty.zigTypeTag(mod) != .Fn) return;29403 if (tv.ty.zigTypeTag(mod) != .Fn) return;
29610 if (!try sema.fnHasRuntimeBits(tv.ty)) return;29404 if (!try sema.fnHasRuntimeBits(tv.ty)) return;
29611 const func = tv.val.castTag(.function) orelse return; // undef or extern_fn29405 const func_index = mod.intern_pool.indexToFunc(tv.val.toIntern()).unwrap() orelse return; // undef or extern_fn
29612 try mod.ensureFuncBodyAnalysisQueued(func.data);29406 try mod.ensureFuncBodyAnalysisQueued(func_index);
29613}29407}
2961429408
29615fn analyzeRef(29409fn analyzeRef(
...@@ -29622,14 +29416,12 @@ fn analyzeRef(...@@ -29622,14 +29416,12 @@ fn analyzeRef(
2962229416
29623 if (try sema.resolveMaybeUndefVal(operand)) |val| {29417 if (try sema.resolveMaybeUndefVal(operand)) |val| {
29624 switch (val.ip_index) {29418 switch (val.ip_index) {
29625 .none => switch (val.tag()) {29419 .none => {},
29626 .extern_fn, .function => {29420 else => switch (sema.mod.intern_pool.indexToKey(val.ip_index)) {
29627 const decl_index = val.pointerDecl().?;29421 .extern_func => |extern_func| return sema.analyzeDeclRef(extern_func.decl),
29628 return sema.analyzeDeclRef(decl_index);29422 .func => |func| return sema.analyzeDeclRef(sema.mod.funcPtr(func.index).owner_decl),
29629 },
29630 else => {},29423 else => {},
29631 },29424 },
29632 else => {},
29633 }29425 }
29634 var anon_decl = try block.startAnonDecl();29426 var anon_decl = try block.startAnonDecl();
29635 defer anon_decl.deinit();29427 defer anon_decl.deinit();
...@@ -29854,7 +29646,7 @@ fn analyzeIsNonErrComptimeOnly(...@@ -29854,7 +29646,7 @@ fn analyzeIsNonErrComptimeOnly(
2985429646
29855 if (other_ies.errors.count() != 0) break :blk;29647 if (other_ies.errors.count() != 0) break :blk;
29856 }29648 }
29857 if (ies.func == sema.owner_func) {29649 if (ies.func == sema.owner_func_index.unwrap()) {
29858 // We're checking the inferred errorset of the current function and none of29650 // We're checking the inferred errorset of the current function and none of
29859 // its child inferred error sets contained any errors meaning that any value29651 // its child inferred error sets contained any errors meaning that any value
29860 // so far with this type can't contain errors either.29652 // so far with this type can't contain errors either.
...@@ -29873,7 +29665,7 @@ fn analyzeIsNonErrComptimeOnly(...@@ -29873,7 +29665,7 @@ fn analyzeIsNonErrComptimeOnly(
29873 if (err_union.isUndef(mod)) {29665 if (err_union.isUndef(mod)) {
29874 return sema.addConstUndef(Type.bool);29666 return sema.addConstUndef(Type.bool);
29875 }29667 }
29876 if (err_union.getError() == null) {29668 if (err_union.getError(mod) == null) {
29877 return Air.Inst.Ref.bool_true;29669 return Air.Inst.Ref.bool_true;
29878 } else {29670 } else {
29879 return Air.Inst.Ref.bool_false;29671 return Air.Inst.Ref.bool_false;
...@@ -30137,7 +29929,7 @@ fn analyzeSlice(...@@ -30137,7 +29929,7 @@ fn analyzeSlice(
30137 const end_int = end_val.getUnsignedInt(mod).?;29929 const end_int = end_val.getUnsignedInt(mod).?;
30138 const sentinel_index = try sema.usizeCast(block, end_src, end_int - start_int);29930 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);
30141 const res = try sema.pointerDerefExtra(block, src, elem_ptr, elem_ty, false);29933 const res = try sema.pointerDerefExtra(block, src, elem_ptr, elem_ty, false);
30142 const actual_sentinel = switch (res) {29934 const actual_sentinel = switch (res) {
30143 .runtime_load => break :sentinel_check,29935 .runtime_load => break :sentinel_check,
...@@ -30233,7 +30025,7 @@ fn analyzeSlice(...@@ -30233,7 +30025,7 @@ fn analyzeSlice(
3023330025
30234 if (!new_ptr_val.isUndef(mod)) {30026 if (!new_ptr_val.isUndef(mod)) {
30235 return sema.addConstant(return_ty, (try mod.intern_pool.getCoerced(30027 return sema.addConstant(return_ty, (try mod.intern_pool.getCoerced(
30236 mod.gpa,30028 sema.gpa,
30237 try new_ptr_val.intern(new_ptr_ty, mod),30029 try new_ptr_val.intern(new_ptr_ty, mod),
30238 return_ty.ip_index,30030 return_ty.ip_index,
30239 )).toValue());30031 )).toValue());
...@@ -30753,7 +30545,10 @@ fn wrapOptional(...@@ -30753,7 +30545,10 @@ fn wrapOptional(
30753 inst_src: LazySrcLoc,30545 inst_src: LazySrcLoc,
30754) !Air.Inst.Ref {30546) !Air.Inst.Ref {
30755 if (try sema.resolveMaybeUndefVal(inst)) |val| {30547 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());
30757 }30552 }
3075830553
30759 try sema.requireRuntimeBlock(block, inst_src, null);30554 try sema.requireRuntimeBlock(block, inst_src, null);
...@@ -30771,7 +30566,10 @@ fn wrapErrorUnionPayload(...@@ -30771,7 +30566,10 @@ fn wrapErrorUnionPayload(
30771 const dest_payload_ty = dest_ty.errorUnionPayload(mod);30566 const dest_payload_ty = dest_ty.errorUnionPayload(mod);
30772 const coerced = try sema.coerceExtra(block, dest_payload_ty, inst, inst_src, .{ .report_err = false });30567 const coerced = try sema.coerceExtra(block, dest_payload_ty, inst, inst_src, .{ .report_err = false });
30773 if (try sema.resolveMaybeUndefVal(coerced)) |val| {30568 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());
30775 }30573 }
30776 try sema.requireRuntimeBlock(block, inst_src, null);30574 try sema.requireRuntimeBlock(block, inst_src, null);
30777 try sema.queueFullTypeResolution(dest_payload_ty);30575 try sema.queueFullTypeResolution(dest_payload_ty);
...@@ -30794,27 +30592,20 @@ fn wrapErrorUnionSet(...@@ -30794,27 +30592,20 @@ fn wrapErrorUnionSet(
30794 .anyerror_type => {},30592 .anyerror_type => {},
30795 else => switch (ip.indexToKey(dest_err_set_ty.ip_index)) {30593 else => switch (ip.indexToKey(dest_err_set_ty.ip_index)) {
30796 .error_set_type => |error_set_type| ok: {30594 .error_set_type => |error_set_type| ok: {
30797 const expected_name = val.castTag(.@"error").?.data.name;30595 const expected_name = mod.intern_pool.indexToKey(val.ip_index).err.name;
30798 if (ip.getString(expected_name).unwrap()) |expected_name_interned| {30596 if (error_set_type.nameIndex(ip, expected_name) != null) break :ok;
30799 if (error_set_type.nameIndex(ip, expected_name_interned) != null)
30800 break :ok;
30801 }
30802 return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty);30597 return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty);
30803 },30598 },
30804 .inferred_error_set_type => |ies_index| ok: {30599 .inferred_error_set_type => |ies_index| ok: {
30805 const ies = mod.inferredErrorSetPtr(ies_index);30600 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
30808 // We carefully do this in an order that avoids unnecessarily30603 // We carefully do this in an order that avoids unnecessarily
30809 // resolving the destination error set type.30604 // resolving the destination error set type.
30810 if (ies.is_anyerror) break :ok;30605 if (ies.is_anyerror) break :ok;
3081130606
30812 if (ip.getString(expected_name).unwrap()) |expected_name_interned| {30607 if (ies.errors.contains(expected_name)) break :ok;
30813 if (ies.errors.contains(expected_name_interned)) break :ok;30608 if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, dest_err_set_ty, inst_ty, inst_src, inst_src)) break :ok;
30814 }
30815 if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, dest_err_set_ty, inst_ty, inst_src, inst_src)) {
30816 break :ok;
30817 }
3081830609
30819 return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty);30610 return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty);
30820 },30611 },
...@@ -31462,43 +31253,33 @@ pub fn resolveFnTypes(sema: *Sema, fn_info: InternPool.Key.FuncType) CompileErro...@@ -31462,43 +31253,33 @@ pub fn resolveFnTypes(sema: *Sema, fn_info: InternPool.Key.FuncType) CompileErro
31462/// to a type not having its layout resolved.31253/// to a type not having its layout resolved.
31463fn resolveLazyValue(sema: *Sema, val: Value) CompileError!void {31254fn resolveLazyValue(sema: *Sema, val: Value) CompileError!void {
31464 switch (val.ip_index) {31255 switch (val.ip_index) {
31465 .none => switch (val.tag()) {31256 .none => {},
31466 .lazy_align => {31257 else => switch (sema.mod.intern_pool.indexToKey(val.ip_index)) {
31467 const ty = val.castTag(.lazy_align).?.data;31258 .int => |int| switch (int.storage) {
31468 return sema.resolveTypeLayout(ty);31259 .u64, .i64, .big_int => {},
31469 },31260 .lazy_align, .lazy_size => |lazy_ty| try sema.resolveTypeLayout(lazy_ty.toType()),
31470 .lazy_size => {31261 },
31471 const ty = val.castTag(.lazy_size).?.data;31262 .ptr => |ptr| {
31472 return sema.resolveTypeLayout(ty);31263 switch (ptr.addr) {
31473 },31264 .decl, .mut_decl => {},
31474 .comptime_field_ptr => {31265 .int => |int| try sema.resolveLazyValue(int.toValue()),
31475 const field_ptr = val.castTag(.comptime_field_ptr).?.data;31266 .eu_payload, .opt_payload => |base| try sema.resolveLazyValue(base.toValue()),
31476 return sema.resolveLazyValue(field_ptr.field_val);31267 .comptime_field => |comptime_field| try sema.resolveLazyValue(comptime_field.toValue()),
31477 },31268 .elem, .field => |base_index| try sema.resolveLazyValue(base_index.base.toValue()),
31478 .eu_payload,31269 }
31479 .opt_payload,31270 if (ptr.len != .none) try sema.resolveLazyValue(ptr.len.toValue());
31480 => {31271 },
31481 const sub_val = val.cast(Value.Payload.SubValue).?.data;31272 .aggregate => |aggregate| switch (aggregate.storage) {
31482 return sema.resolveLazyValue(sub_val);31273 .bytes => {},
31483 },31274 .elems => |elems| for (elems) |elem| try sema.resolveLazyValue(elem.toValue()),
31484 .@"union" => {31275 .repeated_elem => |elem| try sema.resolveLazyValue(elem.toValue()),
31485 const union_val = val.castTag(.@"union").?.data;31276 },
31486 return sema.resolveLazyValue(union_val.val);31277 .un => |un| {
31487 },31278 try sema.resolveLazyValue(un.tag.toValue());
31488 .aggregate => {31279 try sema.resolveLazyValue(un.val.toValue());
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);
31498 },31280 },
31499 else => return,31281 else => {},
31500 },31282 },
31501 else => return,
31502 }31283 }
31503}31284}
3150431285
...@@ -31597,7 +31378,7 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {...@@ -31597,7 +31378,7 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {
31597 else blk: {31378 else blk: {
31598 const decl = mod.declPtr(struct_obj.owner_decl);31379 const decl = mod.declPtr(struct_obj.owner_decl);
31599 var decl_arena: std.heap.ArenaAllocator = undefined;31380 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);
31601 defer decl.value_arena.?.release(&decl_arena);31382 defer decl.value_arena.?.release(&decl_arena);
31602 break :blk try decl_arena_allocator.alloc(u32, struct_obj.fields.count());31383 break :blk try decl_arena_allocator.alloc(u32, struct_obj.fields.count());
31603 };31384 };
...@@ -31662,18 +31443,7 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi...@@ -31662,18 +31443,7 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi
31662 var analysis_arena = std.heap.ArenaAllocator.init(gpa);31443 var analysis_arena = std.heap.ArenaAllocator.init(gpa);
31663 defer analysis_arena.deinit();31444 defer analysis_arena.deinit();
3166431445
31665 var sema: Sema = .{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 };
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 };
31677 defer sema.deinit();31447 defer sema.deinit();
3167831448
31679 var wip_captures = try WipCaptureScope.init(gpa, decl_arena_allocator, decl.src_scope);31449 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...@@ -31720,8 +31490,10 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi
31720 .owner_decl = decl,31490 .owner_decl = decl,
31721 .owner_decl_index = decl_index,31491 .owner_decl_index = decl_index,
31722 .func = null,31492 .func = null,
31493 .func_index = .none,
31723 .fn_ret_ty = Type.void,31494 .fn_ret_ty = Type.void,
31724 .owner_func = null,31495 .owner_func = null,
31496 .owner_func_index = .none,
31725 };31497 };
31726 defer sema.deinit();31498 defer sema.deinit();
3172731499
...@@ -31974,16 +31746,23 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {...@@ -31974,16 +31746,23 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
31974 .enum_type => |enum_type| try sema.resolveTypeRequiresComptime(enum_type.tag_ty.toType()),31746 .enum_type => |enum_type| try sema.resolveTypeRequiresComptime(enum_type.tag_ty.toType()),
3197531747
31976 // values, not types31748 // values, not types
31977 .undef => unreachable,31749 .undef,
31978 .un => unreachable,31750 .runtime_value,
31979 .simple_value => unreachable,31751 .simple_value,
31980 .extern_func => unreachable,31752 .variable,
31981 .int => unreachable,31753 .extern_func,
31982 .float => unreachable,31754 .func,
31983 .ptr => unreachable,31755 .int,
31984 .opt => unreachable,31756 .err,
31985 .enum_tag => unreachable,31757 .error_union,
31986 .aggregate => unreachable,31758 .enum_literal,
31759 .enum_tag,
31760 .float,
31761 .ptr,
31762 .opt,
31763 .aggregate,
31764 .un,
31765 => unreachable,
31987 },31766 },
31988 };31767 };
31989}31768}
...@@ -32141,8 +31920,8 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type {...@@ -32141,8 +31920,8 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type {
32141 .manyptr_const_u8_type,31920 .manyptr_const_u8_type,
32142 .manyptr_const_u8_sentinel_0_type,31921 .manyptr_const_u8_sentinel_0_type,
32143 .single_const_pointer_to_comptime_int_type,31922 .single_const_pointer_to_comptime_int_type,
32144 .const_slice_u8_type,31923 .slice_const_u8_type,
32145 .const_slice_u8_sentinel_0_type,31924 .slice_const_u8_sentinel_0_type,
32146 .anyerror_void_error_union_type,31925 .anyerror_void_error_union_type,
32147 .generic_poison_type,31926 .generic_poison_type,
32148 .empty_struct_type,31927 .empty_struct_type,
...@@ -32288,18 +32067,19 @@ fn resolveInferredErrorSet(...@@ -32288,18 +32067,19 @@ fn resolveInferredErrorSet(
3228832067
32289 if (ies.is_resolved) return;32068 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) {
32292 return sema.fail(block, src, "unable to resolve inferred error set", .{});32072 return sema.fail(block, src, "unable to resolve inferred error set", .{});
32293 }32073 }
3229432074
32295 // In order to ensure that all dependencies are properly added to the set, we32075 // In order to ensure that all dependencies are properly added to the set, we
32296 // need to ensure the function body is analyzed of the inferred error set.32076 // need to ensure the function body is analyzed of the inferred error set.
32297 // However, in the case of comptime/inline function calls with inferred error sets,32077 // 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 same32078 // each call gets a new InferredErrorSet object, which contains the same
32299 // `*Module.Fn`. Not only is the function not relevant to the inferred error set32079 // `Module.Fn.Index`. Not only is the function not relevant to the inferred error set
32300 // in this case, it may be a generic function which would cause an assertion failure32080 // in this case, it may be a generic function which would cause an assertion failure
32301 // if we called `ensureFuncBodyAnalyzed` on it here.32081 // 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);
32303 const ies_func_info = mod.typeToFunc(ies_func_owner_decl.ty).?;32083 const ies_func_info = mod.typeToFunc(ies_func_owner_decl.ty).?;
32304 // if ies declared by a inline function with generic return type, the return_type should be generic_poison,32084 // if ies declared by a inline function with generic return type, the return_type should be generic_poison,
32305 // because inline function does not create a new declaration, and the ies has been filled with analyzeCall,32085 // 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...@@ -32414,8 +32194,10 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
32414 .owner_decl = decl,32194 .owner_decl = decl,
32415 .owner_decl_index = decl_index,32195 .owner_decl_index = decl_index,
32416 .func = null,32196 .func = null,
32197 .func_index = .none,
32417 .fn_ret_ty = Type.void,32198 .fn_ret_ty = Type.void,
32418 .owner_func = null,32199 .owner_func = null,
32200 .owner_func_index = .none,
32419 };32201 };
32420 defer sema.deinit();32202 defer sema.deinit();
3242132203
...@@ -32754,8 +32536,10 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -32754,8 +32536,10 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
32754 .owner_decl = decl,32536 .owner_decl = decl,
32755 .owner_decl_index = decl_index,32537 .owner_decl_index = decl_index,
32756 .func = null,32538 .func = null,
32539 .func_index = .none,
32757 .fn_ret_ty = Type.void,32540 .fn_ret_ty = Type.void,
32758 .owner_func = null,32541 .owner_func = null,
32542 .owner_func_index = .none,
32759 };32543 };
32760 defer sema.deinit();32544 defer sema.deinit();
3276132545
...@@ -33111,7 +32895,7 @@ fn generateUnionTagTypeNumbered(...@@ -33111,7 +32895,7 @@ fn generateUnionTagTypeNumbered(
33111 const name = name: {32895 const name = name: {
33112 const fqn = try union_obj.getFullyQualifiedName(mod);32896 const fqn = try union_obj.getFullyQualifiedName(mod);
33113 defer sema.gpa.free(fqn);32897 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});
33115 };32899 };
33116 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, block.namespace, .{32900 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, block.namespace, .{
33117 .ty = Type.type,32901 .ty = Type.type,
...@@ -33160,7 +32944,7 @@ fn generateUnionTagTypeSimple(...@@ -33160,7 +32944,7 @@ fn generateUnionTagTypeSimple(
33160 const name = name: {32944 const name = name: {
33161 const fqn = try union_obj.getFullyQualifiedName(mod);32945 const fqn = try union_obj.getFullyQualifiedName(mod);
33162 defer sema.gpa.free(fqn);32946 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});
33164 };32948 };
33165 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, block.namespace, .{32949 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, block.namespace, .{
33166 .ty = Type.type,32950 .ty = Type.type,
...@@ -33288,19 +33072,19 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -33288,19 +33072,19 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
33288 .inferred_error_set_type,33072 .inferred_error_set_type,
33289 => null,33073 => null,
3329033074
33291 .array_type => |array_type| {33075 inline .array_type, .vector_type => |seq_type| {
33292 if (array_type.len == 0)33076 if (seq_type.len == 0) return (try mod.intern(.{ .aggregate = .{
33293 return Value.initTag(.empty_array);33077 .ty = ty.ip_index,
33294 if ((try sema.typeHasOnePossibleValue(array_type.child.toType())) != null) {33078 .storage = .{ .elems = &.{} },
33295 return Value.initTag(.the_only_possible_value);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();
33296 }33085 }
33297 return null;33086 return null;
33298 },33087 },
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 },
33304 .opt_type => |child| {33088 .opt_type => |child| {
33305 if (child == .noreturn_type) {33089 if (child == .noreturn_type) {
33306 return try mod.nullValue(ty);33090 return try mod.nullValue(ty);
...@@ -33466,16 +33250,23 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -33466,16 +33250,23 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
33466 },33250 },
3346733251
33468 // values, not types33252 // values, not types
33469 .undef => unreachable,33253 .undef,
33470 .un => unreachable,33254 .runtime_value,
33471 .simple_value => unreachable,33255 .simple_value,
33472 .extern_func => unreachable,33256 .variable,
33473 .int => unreachable,33257 .extern_func,
33474 .float => unreachable,33258 .func,
33475 .ptr => unreachable,33259 .int,
33476 .opt => unreachable,33260 .err,
33477 .enum_tag => unreachable,33261 .error_union,
33478 .aggregate => unreachable,33262 .enum_literal,
33263 .enum_tag,
33264 .float,
33265 .ptr,
33266 .opt,
33267 .aggregate,
33268 .un,
33269 => unreachable,
33479 },33270 },
33480 };33271 };
33481}33272}
...@@ -33625,10 +33416,13 @@ fn analyzeComptimeAlloc(...@@ -33625,10 +33416,13 @@ fn analyzeComptimeAlloc(
33625 decl.@"align" = alignment;33416 decl.@"align" = alignment;
3362633417
33627 try sema.mod.declareDeclDependency(sema.owner_decl_index, decl_index);33418 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, .{33419 return sema.addConstant(ptr_type, (try sema.mod.intern(.{ .ptr = .{
33629 .runtime_index = block.runtime_index,33420 .ty = ptr_type.ip_index,
33630 .decl_index = decl_index,33421 .addr = .{ .mut_decl = .{
33631 }));33422 .decl = decl_index,
33423 .runtime_index = block.runtime_index,
33424 } },
33425 } })).toValue());
33632}33426}
3363333427
33634/// The places where a user can specify an address space attribute33428/// The places where a user can specify an address space attribute
...@@ -33969,16 +33763,23 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {...@@ -33969,16 +33763,23 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
33969 .enum_type => |enum_type| try sema.typeRequiresComptime(enum_type.tag_ty.toType()),33763 .enum_type => |enum_type| try sema.typeRequiresComptime(enum_type.tag_ty.toType()),
3397033764
33971 // values, not types33765 // values, not types
33972 .undef => unreachable,33766 .undef,
33973 .un => unreachable,33767 .runtime_value,
33974 .simple_value => unreachable,33768 .simple_value,
33975 .extern_func => unreachable,33769 .variable,
33976 .int => unreachable,33770 .extern_func,
33977 .float => unreachable,33771 .func,
33978 .ptr => unreachable,33772 .int,
33979 .opt => unreachable,33773 .err,
33980 .enum_tag => unreachable,33774 .error_union,
33981 .aggregate => unreachable,33775 .enum_literal,
33776 .enum_tag,
33777 .float,
33778 .ptr,
33779 .opt,
33780 .aggregate,
33781 .un,
33782 => unreachable,
33982 },33783 },
33983 };33784 };
33984}33785}
...@@ -34337,8 +34138,9 @@ fn intFitsInType(...@@ -34337,8 +34138,9 @@ fn intFitsInType(
34337 ty: Type,34138 ty: Type,
34338 vector_index: ?*usize,34139 vector_index: ?*usize,
34339) CompileError!bool {34140) CompileError!bool {
34340 if (ty.ip_index == .comptime_int_type) return true;
34341 const mod = sema.mod;34141 const mod = sema.mod;
34142 if (ty.ip_index == .comptime_int_type) return true;
34143 const info = ty.intInfo(mod);
34342 switch (val.ip_index) {34144 switch (val.ip_index) {
34343 .undef,34145 .undef,
34344 .zero,34146 .zero,
...@@ -34346,40 +34148,8 @@ fn intFitsInType(...@@ -34346,40 +34148,8 @@ fn intFitsInType(
34346 .zero_u8,34148 .zero_u8,
34347 => return true,34149 => return true,
3434834150
34349 .none => switch (val.tag()) {34151 else => switch (mod.intern_pool.indexToKey(val.ip_index)) {
34350 .lazy_align => {34152 .variable, .extern_func, .func, .ptr => {
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);
34383 const target = mod.getTarget();34153 const target = mod.getTarget();
34384 const ptr_bits = target.ptrBitWidth();34154 const ptr_bits = target.ptrBitWidth();
34385 return switch (info.signedness) {34155 return switch (info.signedness) {
...@@ -34387,27 +34157,51 @@ fn intFitsInType(...@@ -34387,27 +34157,51 @@ fn intFitsInType(
34387 .unsigned => info.bits >= ptr_bits,34157 .unsigned => info.bits >= ptr_bits,
34388 };34158 };
34389 },34159 },
3439034160 .int => |int| switch (int.storage) {
34391 .aggregate => {34161 .u64, .i64, .big_int => {
34392 assert(ty.zigTypeTag(mod) == .Vector);34162 var buffer: InternPool.Key.Int.Storage.BigIntSpace = undefined;
34393 for (val.castTag(.aggregate).?.data, 0..) |elem, i| {34163 const big_int = int.storage.toBigInt(&buffer);
34394 if (!(try sema.intFitsInType(elem, ty.scalarType(mod), null))) {34164 return big_int.fitsInTwosComp(info.signedness, info.bits);
34395 if (vector_index) |some| some.* = i;34165 },
34396 return false;34166 .lazy_align => |lazy_ty| {
34397 }34167 const max_needed_bits = @as(u16, 16) + @boolToInt(info.signedness == .signed);
34398 }34168 // If it is u16 or bigger we know the alignment fits without resolving it.
34399 return true;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 },
34400 },34184 },
3440134185 .aggregate => |aggregate| {
34402 else => unreachable,34186 assert(ty.zigTypeTag(mod) == .Vector);
34403 },34187 return switch (aggregate.storage) {
3440434188 .bytes => |bytes| for (bytes, 0..) |byte, i| {
34405 else => switch (mod.intern_pool.indexToKey(val.ip_index)) {34189 if (byte == 0) continue;
34406 .int => |int| {34190 const actual_needed_bits = std.math.log2(byte) + 1 + @boolToInt(info.signedness == .signed);
34407 const info = ty.intInfo(mod);34191 if (info.bits >= actual_needed_bits) continue;
34408 var buffer: InternPool.Key.Int.Storage.BigIntSpace = undefined;34192 if (vector_index) |vi| vi.* = i;
34409 const big_int = int.storage.toBigInt(&buffer);34193 break false;
34410 return big_int.fitsInTwosComp(info.signedness, info.bits);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 };
34411 },34205 },
34412 else => unreachable,34206 else => unreachable,
34413 },34207 },
src/TypedValue.zig+9-236
...@@ -102,248 +102,15 @@ pub fn print(...@@ -102,248 +102,15 @@ pub fn print(
102102
103 return writer.writeAll(" }");103 return writer.writeAll(" }");
104 },104 },
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)}),
202 .bytes => return writer.print("\"{}\"", .{std.zig.fmtEscapes(val.castTag(.bytes).?.data)}),105 .bytes => return writer.print("\"{}\"", .{std.zig.fmtEscapes(val.castTag(.bytes).?.data)}),
203 .str_lit => {106 .str_lit => {
204 const str_lit = val.castTag(.str_lit).?.data;107 const str_lit = val.castTag(.str_lit).?.data;
205 const bytes = mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len];108 const bytes = mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len];
206 return writer.print("\"{}\"", .{std.zig.fmtEscapes(bytes)});109 return writer.print("\"{}\"", .{std.zig.fmtEscapes(bytes)});
207 },110 },
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
343 // TODO these should not appear in this function111 // TODO these should not appear in this function
344 .inferred_alloc => return writer.writeAll("(inferred allocation value)"),112 .inferred_alloc => return writer.writeAll("(inferred allocation value)"),
345 .inferred_alloc_comptime => return writer.writeAll("(inferred comptime allocation value)"),113 .inferred_alloc_comptime => return writer.writeAll("(inferred comptime allocation value)"),
346 .runtime_value => return writer.writeAll("[runtime value]"),
347 },114 },
348 else => {115 else => {
349 const key = mod.intern_pool.indexToKey(val.ip_index);116 const key = mod.intern_pool.indexToKey(val.ip_index);
...@@ -353,6 +120,12 @@ pub fn print(...@@ -353,6 +120,12 @@ pub fn print(
353 switch (key) {120 switch (key) {
354 .int => |int| switch (int.storage) {121 .int => |int| switch (int.storage) {
355 inline .u64, .i64, .big_int => |x| return writer.print("{}", .{x}),122 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 }),
356 },129 },
357 .enum_tag => |enum_tag| {130 .enum_tag => |enum_tag| {
358 if (level == 0) {131 if (level == 0) {
...@@ -407,7 +180,7 @@ fn printAggregate(...@@ -407,7 +180,7 @@ fn printAggregate(
407 }180 }
408 try print(.{181 try print(.{
409 .ty = ty.structFieldType(i, mod),182 .ty = ty.structFieldType(i, mod),
410 .val = try val.fieldValue(ty, mod, i),183 .val = try val.fieldValue(mod, i),
411 }, writer, level - 1, mod);184 }, writer, level - 1, mod);
412 }185 }
413 if (ty.structFieldCount(mod) > max_aggregate_items) {186 if (ty.structFieldCount(mod) > max_aggregate_items) {
...@@ -424,7 +197,7 @@ fn printAggregate(...@@ -424,7 +197,7 @@ fn printAggregate(
424197
425 var i: u32 = 0;198 var i: u32 = 0;
426 while (i < max_len) : (i += 1) {199 while (i < max_len) : (i += 1) {
427 const elem = try val.fieldValue(ty, mod, i);200 const elem = try val.fieldValue(mod, i);
428 if (elem.isUndef(mod)) break :str;201 if (elem.isUndef(mod)) break :str;
429 buf[i] = std.math.cast(u8, elem.toUnsignedInt(mod)) orelse break :str;202 buf[i] = std.math.cast(u8, elem.toUnsignedInt(mod)) orelse break :str;
430 }203 }
...@@ -441,7 +214,7 @@ fn printAggregate(...@@ -441,7 +214,7 @@ fn printAggregate(
441 if (i != 0) try writer.writeAll(", ");214 if (i != 0) try writer.writeAll(", ");
442 try print(.{215 try print(.{
443 .ty = elem_ty,216 .ty = elem_ty,
444 .val = try val.fieldValue(ty, mod, i),217 .val = try val.fieldValue(mod, i),
445 }, writer, level - 1, mod);218 }, writer, level - 1, mod);
446 }219 }
447 if (len > max_aggregate_items) {220 if (len > max_aggregate_items) {
src/Zir.zig+2-2
...@@ -2108,8 +2108,8 @@ pub const Inst = struct {...@@ -2108,8 +2108,8 @@ pub const Inst = struct {
2108 manyptr_const_u8_type = @enumToInt(InternPool.Index.manyptr_const_u8_type),2108 manyptr_const_u8_type = @enumToInt(InternPool.Index.manyptr_const_u8_type),
2109 manyptr_const_u8_sentinel_0_type = @enumToInt(InternPool.Index.manyptr_const_u8_sentinel_0_type),2109 manyptr_const_u8_sentinel_0_type = @enumToInt(InternPool.Index.manyptr_const_u8_sentinel_0_type),
2110 single_const_pointer_to_comptime_int_type = @enumToInt(InternPool.Index.single_const_pointer_to_comptime_int_type),2110 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),2111 slice_const_u8_type = @enumToInt(InternPool.Index.slice_const_u8_type),
2112 const_slice_u8_sentinel_0_type = @enumToInt(InternPool.Index.const_slice_u8_sentinel_0_type),2112 slice_const_u8_sentinel_0_type = @enumToInt(InternPool.Index.slice_const_u8_sentinel_0_type),
2113 anyerror_void_error_union_type = @enumToInt(InternPool.Index.anyerror_void_error_union_type),2113 anyerror_void_error_union_type = @enumToInt(InternPool.Index.anyerror_void_error_union_type),
2114 generic_poison_type = @enumToInt(InternPool.Index.generic_poison_type),2114 generic_poison_type = @enumToInt(InternPool.Index.generic_poison_type),
2115 inferred_alloc_const_type = @enumToInt(InternPool.Index.inferred_alloc_const_type),2115 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();...@@ -328,7 +328,7 @@ const Self = @This();
328pub fn generate(328pub fn generate(
329 bin_file: *link.File,329 bin_file: *link.File,
330 src_loc: Module.SrcLoc,330 src_loc: Module.SrcLoc,
331 module_fn: *Module.Fn,331 module_fn_index: Module.Fn.Index,
332 air: Air,332 air: Air,
333 liveness: Liveness,333 liveness: Liveness,
334 code: *std.ArrayList(u8),334 code: *std.ArrayList(u8),
...@@ -339,6 +339,7 @@ pub fn generate(...@@ -339,6 +339,7 @@ pub fn generate(
339 }339 }
340340
341 const mod = bin_file.options.module.?;341 const mod = bin_file.options.module.?;
342 const module_fn = mod.funcPtr(module_fn_index);
342 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);343 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
343 assert(fn_owner_decl.has_tv);344 assert(fn_owner_decl.has_tv);
344 const fn_type = fn_owner_decl.ty;345 const fn_type = fn_owner_decl.ty;
...@@ -4311,9 +4312,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -4311,9 +4312,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
4311 // Due to incremental compilation, how function calls are generated depends4312 // Due to incremental compilation, how function calls are generated depends
4312 // on linking.4313 // on linking.
4313 if (try self.air.value(callee, mod)) |func_value| {4314 if (try self.air.value(callee, mod)) |func_value| {
4314 if (func_value.castTag(.function)) |func_payload| {4315 if (func_value.getFunction(mod)) |func| {
4315 const func = func_payload.data;
4316
4317 if (self.bin_file.cast(link.File.Elf)) |elf_file| {4316 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
4318 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);4317 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
4319 const atom = elf_file.getAtom(atom_index);4318 const atom = elf_file.getAtom(atom_index);
...@@ -4353,10 +4352,9 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -4353,10 +4352,9 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
4353 .tag = .blr,4352 .tag = .blr,
4354 .data = .{ .reg = .x30 },4353 .data = .{ .reg = .x30 },
4355 });4354 });
4356 } else if (func_value.castTag(.extern_fn)) |func_payload| {4355 } else if (func_value.getExternFunc(mod)) |extern_func| {
4357 const extern_fn = func_payload.data;4356 const decl_name = mem.sliceTo(mod.declPtr(extern_func.decl).name, 0);
4358 const decl_name = mem.sliceTo(mod.declPtr(extern_fn.owner_decl).name, 0);4357 const lib_name = mod.intern_pool.stringToSliceUnwrap(extern_func.lib_name);
4359 const lib_name = mem.sliceTo(extern_fn.lib_name, 0);
4360 if (self.bin_file.cast(link.File.MachO)) |macho_file| {4358 if (self.bin_file.cast(link.File.MachO)) |macho_file| {
4361 const sym_index = try macho_file.getGlobalSymbol(decl_name, lib_name);4359 const sym_index = try macho_file.getGlobalSymbol(decl_name, lib_name);
4362 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);4360 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
...@@ -4627,7 +4625,8 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {...@@ -4627,7 +4625,8 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
46274625
4628fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {4626fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
4629 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;4627 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).?;
4631 // TODO emit debug info for function change4630 // TODO emit debug info for function change
4632 _ = function;4631 _ = function;
4633 return self.finishAir(inst, .dead, .{ .none, .none, .none });4632 return self.finishAir(inst, .dead, .{ .none, .none, .none });
src/arch/arm/CodeGen.zig+6-6
...@@ -334,7 +334,7 @@ const Self = @This();...@@ -334,7 +334,7 @@ const Self = @This();
334pub fn generate(334pub fn generate(
335 bin_file: *link.File,335 bin_file: *link.File,
336 src_loc: Module.SrcLoc,336 src_loc: Module.SrcLoc,
337 module_fn: *Module.Fn,337 module_fn_index: Module.Fn.Index,
338 air: Air,338 air: Air,
339 liveness: Liveness,339 liveness: Liveness,
340 code: *std.ArrayList(u8),340 code: *std.ArrayList(u8),
...@@ -345,6 +345,7 @@ pub fn generate(...@@ -345,6 +345,7 @@ pub fn generate(
345 }345 }
346346
347 const mod = bin_file.options.module.?;347 const mod = bin_file.options.module.?;
348 const module_fn = mod.funcPtr(module_fn_index);
348 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);349 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
349 assert(fn_owner_decl.has_tv);350 assert(fn_owner_decl.has_tv);
350 const fn_type = fn_owner_decl.ty;351 const fn_type = fn_owner_decl.ty;
...@@ -4291,9 +4292,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -4291,9 +4292,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
4291 // Due to incremental compilation, how function calls are generated depends4292 // Due to incremental compilation, how function calls are generated depends
4292 // on linking.4293 // on linking.
4293 if (try self.air.value(callee, mod)) |func_value| {4294 if (try self.air.value(callee, mod)) |func_value| {
4294 if (func_value.castTag(.function)) |func_payload| {4295 if (func_value.getFunction(mod)) |func| {
4295 const func = func_payload.data;
4296
4297 if (self.bin_file.cast(link.File.Elf)) |elf_file| {4296 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
4298 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);4297 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
4299 const atom = elf_file.getAtom(atom_index);4298 const atom = elf_file.getAtom(atom_index);
...@@ -4308,7 +4307,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -4308,7 +4307,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
4308 @tagName(self.target.cpu.arch),4307 @tagName(self.target.cpu.arch),
4309 });4308 });
4310 }4309 }
4311 } else if (func_value.castTag(.extern_fn)) |_| {4310 } else if (func_value.getExternFunc(mod)) |_| {
4312 return self.fail("TODO implement calling extern functions", .{});4311 return self.fail("TODO implement calling extern functions", .{});
4313 } else {4312 } else {
4314 return self.fail("TODO implement calling bitcasted functions", .{});4313 return self.fail("TODO implement calling bitcasted functions", .{});
...@@ -4573,7 +4572,8 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {...@@ -4573,7 +4572,8 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
45734572
4574fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {4573fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
4575 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;4574 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).?;
4577 // TODO emit debug info for function change4577 // TODO emit debug info for function change
4578 _ = function;4578 _ = function;
4579 return self.finishAir(inst, .dead, .{ .none, .none, .none });4579 return self.finishAir(inst, .dead, .{ .none, .none, .none });
src/arch/riscv64/CodeGen.zig+6-5
...@@ -217,7 +217,7 @@ const Self = @This();...@@ -217,7 +217,7 @@ const Self = @This();
217pub fn generate(217pub fn generate(
218 bin_file: *link.File,218 bin_file: *link.File,
219 src_loc: Module.SrcLoc,219 src_loc: Module.SrcLoc,
220 module_fn: *Module.Fn,220 module_fn_index: Module.Fn.Index,
221 air: Air,221 air: Air,
222 liveness: Liveness,222 liveness: Liveness,
223 code: *std.ArrayList(u8),223 code: *std.ArrayList(u8),
...@@ -228,6 +228,7 @@ pub fn generate(...@@ -228,6 +228,7 @@ pub fn generate(
228 }228 }
229229
230 const mod = bin_file.options.module.?;230 const mod = bin_file.options.module.?;
231 const module_fn = mod.funcPtr(module_fn_index);
231 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);232 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
232 assert(fn_owner_decl.has_tv);233 assert(fn_owner_decl.has_tv);
233 const fn_type = fn_owner_decl.ty;234 const fn_type = fn_owner_decl.ty;
...@@ -1745,8 +1746,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -1745,8 +1746,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
1745 }1746 }
17461747
1747 if (try self.air.value(callee, mod)) |func_value| {1748 if (try self.air.value(callee, mod)) |func_value| {
1748 if (func_value.castTag(.function)) |func_payload| {1749 if (mod.funcPtrUnwrap(mod.intern_pool.indexToFunc(func_value.ip_index))) |func| {
1749 const func = func_payload.data;
1750 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);1750 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
1751 const atom = elf_file.getAtom(atom_index);1751 const atom = elf_file.getAtom(atom_index);
1752 _ = try atom.getOrCreateOffsetTableEntry(elf_file);1752 _ = try atom.getOrCreateOffsetTableEntry(elf_file);
...@@ -1760,7 +1760,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -1760,7 +1760,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
1760 .imm12 = 0,1760 .imm12 = 0,
1761 } },1761 } },
1762 });1762 });
1763 } else if (func_value.castTag(.extern_fn)) |_| {1763 } else if (mod.intern_pool.indexToKey(func_value.ip_index) == .extern_func) {
1764 return self.fail("TODO implement calling extern functions", .{});1764 return self.fail("TODO implement calling extern functions", .{});
1765 } else {1765 } else {
1766 return self.fail("TODO implement calling bitcasted functions", .{});1766 return self.fail("TODO implement calling bitcasted functions", .{});
...@@ -1879,7 +1879,8 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {...@@ -1879,7 +1879,8 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
18791879
1880fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {1880fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
1881 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;1881 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).?;
1883 // TODO emit debug info for function change1884 // TODO emit debug info for function change
1884 _ = function;1885 _ = function;
1885 return self.finishAir(inst, .dead, .{ .none, .none, .none });1886 return self.finishAir(inst, .dead, .{ .none, .none, .none });
src/arch/sparc64/CodeGen.zig+6-5
...@@ -260,7 +260,7 @@ const BigTomb = struct {...@@ -260,7 +260,7 @@ const BigTomb = struct {
260pub fn generate(260pub fn generate(
261 bin_file: *link.File,261 bin_file: *link.File,
262 src_loc: Module.SrcLoc,262 src_loc: Module.SrcLoc,
263 module_fn: *Module.Fn,263 module_fn_index: Module.Fn.Index,
264 air: Air,264 air: Air,
265 liveness: Liveness,265 liveness: Liveness,
266 code: *std.ArrayList(u8),266 code: *std.ArrayList(u8),
...@@ -271,6 +271,7 @@ pub fn generate(...@@ -271,6 +271,7 @@ pub fn generate(
271 }271 }
272272
273 const mod = bin_file.options.module.?;273 const mod = bin_file.options.module.?;
274 const module_fn = mod.funcPtr(module_fn_index);
274 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);275 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
275 assert(fn_owner_decl.has_tv);276 assert(fn_owner_decl.has_tv);
276 const fn_type = fn_owner_decl.ty;277 const fn_type = fn_owner_decl.ty;
...@@ -1346,8 +1347,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -1346,8 +1347,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
1346 // on linking.1347 // on linking.
1347 if (try self.air.value(callee, mod)) |func_value| {1348 if (try self.air.value(callee, mod)) |func_value| {
1348 if (self.bin_file.tag == link.File.Elf.base_tag) {1349 if (self.bin_file.tag == link.File.Elf.base_tag) {
1349 if (func_value.castTag(.function)) |func_payload| {1350 if (mod.funcPtrUnwrap(mod.intern_pool.indexToFunc(func_value.ip_index))) |func| {
1350 const func = func_payload.data;
1351 const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: {1351 const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: {
1352 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);1352 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
1353 const atom = elf_file.getAtom(atom_index);1353 const atom = elf_file.getAtom(atom_index);
...@@ -1374,7 +1374,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -1374,7 +1374,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
1374 .tag = .nop,1374 .tag = .nop,
1375 .data = .{ .nop = {} },1375 .data = .{ .nop = {} },
1376 });1376 });
1377 } else if (func_value.castTag(.extern_fn)) |_| {1377 } else if (mod.intern_pool.indexToKey(func_value.ip_index) == .extern_func) {
1378 return self.fail("TODO implement calling extern functions", .{});1378 return self.fail("TODO implement calling extern functions", .{});
1379 } else {1379 } else {
1380 return self.fail("TODO implement calling bitcasted functions", .{});1380 return self.fail("TODO implement calling bitcasted functions", .{});
...@@ -1663,7 +1663,8 @@ fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void {...@@ -1663,7 +1663,8 @@ fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void {
16631663
1664fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {1664fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
1665 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;1665 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).?;
1667 // TODO emit debug info for function change1668 // TODO emit debug info for function change
1668 _ = function;1669 _ = function;
1669 return self.finishAir(inst, .dead, .{ .none, .none, .none });1670 return self.finishAir(inst, .dead, .{ .none, .none, .none });
src/arch/wasm/CodeGen.zig+219-132
...@@ -1203,20 +1203,22 @@ fn genFunctype(...@@ -1203,20 +1203,22 @@ fn genFunctype(
1203pub fn generate(1203pub fn generate(
1204 bin_file: *link.File,1204 bin_file: *link.File,
1205 src_loc: Module.SrcLoc,1205 src_loc: Module.SrcLoc,
1206 func: *Module.Fn,1206 func_index: Module.Fn.Index,
1207 air: Air,1207 air: Air,
1208 liveness: Liveness,1208 liveness: Liveness,
1209 code: *std.ArrayList(u8),1209 code: *std.ArrayList(u8),
1210 debug_output: codegen.DebugInfoOutput,1210 debug_output: codegen.DebugInfoOutput,
1211) codegen.CodeGenError!codegen.Result {1211) codegen.CodeGenError!codegen.Result {
1212 _ = src_loc;1212 _ = src_loc;
1213 const mod = bin_file.options.module.?;
1214 const func = mod.funcPtr(func_index);
1213 var code_gen: CodeGen = .{1215 var code_gen: CodeGen = .{
1214 .gpa = bin_file.allocator,1216 .gpa = bin_file.allocator,
1215 .air = air,1217 .air = air,
1216 .liveness = liveness,1218 .liveness = liveness,
1217 .code = code,1219 .code = code,
1218 .decl_index = func.owner_decl,1220 .decl_index = func.owner_decl,
1219 .decl = bin_file.options.module.?.declPtr(func.owner_decl),1221 .decl = mod.declPtr(func.owner_decl),
1220 .err_msg = undefined,1222 .err_msg = undefined,
1221 .locals = .{},1223 .locals = .{},
1222 .target = bin_file.options.target,1224 .target = bin_file.options.target,
...@@ -2196,27 +2198,33 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif...@@ -2196,27 +2198,33 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
2196 const callee: ?Decl.Index = blk: {2198 const callee: ?Decl.Index = blk: {
2197 const func_val = (try func.air.value(pl_op.operand, mod)) orelse break :blk null;2199 const func_val = (try func.air.value(pl_op.operand, mod)) orelse break :blk null;
21982200
2199 if (func_val.castTag(.function)) |function| {2201 if (func_val.getFunction(mod)) |function| {
2200 _ = try func.bin_file.getOrCreateAtomForDecl(function.data.owner_decl);2202 _ = try func.bin_file.getOrCreateAtomForDecl(function.owner_decl);
2201 break :blk function.data.owner_decl;2203 break :blk function.owner_decl;
2202 } else if (func_val.castTag(.extern_fn)) |extern_fn| {2204 } else if (func_val.getExternFunc(mod)) |extern_func| {
2203 const ext_decl = mod.declPtr(extern_fn.data.owner_decl);2205 const ext_decl = mod.declPtr(extern_func.decl);
2204 const ext_info = mod.typeToFunc(ext_decl.ty).?;2206 const ext_info = mod.typeToFunc(ext_decl.ty).?;
2205 var func_type = try genFunctype(func.gpa, ext_info.cc, ext_info.param_types, ext_info.return_type.toType(), mod);2207 var func_type = try genFunctype(func.gpa, ext_info.cc, ext_info.param_types, ext_info.return_type.toType(), mod);
2206 defer func_type.deinit(func.gpa);2208 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);
2208 const atom = func.bin_file.getAtomPtr(atom_index);2210 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);
2210 try func.bin_file.addOrUpdateImport(2212 try func.bin_file.addOrUpdateImport(
2211 mem.sliceTo(ext_decl.name, 0),2213 mem.sliceTo(ext_decl.name, 0),
2212 atom.getSymbolIndex().?,2214 atom.getSymbolIndex().?,
2213 ext_decl.getExternFn().?.lib_name,2215 mod.intern_pool.stringToSliceUnwrap(ext_decl.getExternFunc(mod).?.lib_name),
2214 type_index,2216 type_index,
2215 );2217 );
2216 break :blk extern_fn.data.owner_decl;2218 break :blk extern_func.decl;
2217 } else if (func_val.castTag(.decl_ref)) |decl_ref| {2219 } else switch (mod.intern_pool.indexToKey(func_val.ip_index)) {
2218 _ = try func.bin_file.getOrCreateAtomForDecl(decl_ref.data);2220 .ptr => |ptr| switch (ptr.addr) {
2219 break :blk decl_ref.data;2221 .decl => |decl| {
2222 _ = try func.bin_file.getOrCreateAtomForDecl(decl);
2223 break :blk decl;
2224 },
2225 else => {},
2226 },
2227 else => {},
2220 }2228 }
2221 return func.fail("Expected a function, but instead found type '{}'", .{func_val.tag()});2229 return func.fail("Expected a function, but instead found type '{}'", .{func_val.tag()});
2222 };2230 };
...@@ -2932,29 +2940,41 @@ fn wrapOperand(func: *CodeGen, operand: WValue, ty: Type) InnerError!WValue {...@@ -2932,29 +2940,41 @@ fn wrapOperand(func: *CodeGen, operand: WValue, ty: Type) InnerError!WValue {
2932 return WValue{ .stack = {} };2940 return WValue{ .stack = {} };
2933}2941}
29342942
2935fn lowerParentPtr(func: *CodeGen, ptr_val: Value, offset: u32) InnerError!WValue {2943fn lowerParentPtr(func: *CodeGen, ptr_val: Value) InnerError!WValue {
2936 const mod = func.bin_file.base.options.module.?;2944 const mod = func.bin_file.base.options.module.?;
2937 switch (ptr_val.tag()) {2945 const ptr = mod.intern_pool.indexToKey(ptr_val.ip_index).ptr;
2938 .decl_ref_mut => {2946 switch (ptr.addr) {
2939 const decl_index = ptr_val.castTag(.decl_ref_mut).?.data.decl_index;2947 .decl => |decl_index| {
2940 return func.lowerParentPtrDecl(ptr_val, decl_index, offset);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);
2941 },2953 },
2942 .decl_ref => {2954 .int, .eu_payload => |tag| return func.fail("TODO: Implement lowerParentPtr for {}", .{tag}),
2943 const decl_index = ptr_val.castTag(.decl_ref).?.data;2955 .opt_payload => |base_ptr| {
2944 return func.lowerParentPtrDecl(ptr_val, decl_index, offset);2956 return func.lowerParentPtr(base_ptr.toValue());
2945 },2957 },
2946 .variable => {2958 .comptime_field => unreachable,
2947 const decl_index = ptr_val.castTag(.variable).?.data.owner_decl;2959 .elem => |elem| {
2948 return func.lowerParentPtrDecl(ptr_val, decl_index, offset);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 } };
2949 },2969 },
2950 .field_ptr => {2970 .field => |field| {
2951 const field_ptr = ptr_val.castTag(.field_ptr).?.data;2971 const parent_ty = mod.intern_pool.typeOf(field.base).toType().childType(mod);
2952 const parent_ty = field_ptr.container_ty;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)) {
2955 .Struct => switch (parent_ty.containerLayout(mod)) {2975 .Struct => switch (parent_ty.containerLayout(mod)) {
2956 .Packed => parent_ty.packedStructFieldByteOffset(field_ptr.field_index, mod),2976 .Packed => parent_ty.packedStructFieldByteOffset(field.index, mod),
2957 else => parent_ty.structFieldOffset(field_ptr.field_index, mod),2977 else => parent_ty.structFieldOffset(field.index, mod),
2958 },2978 },
2959 .Union => switch (parent_ty.containerLayout(mod)) {2979 .Union => switch (parent_ty.containerLayout(mod)) {
2960 .Packed => 0,2980 .Packed => 0,
...@@ -2964,12 +2984,12 @@ fn lowerParentPtr(func: *CodeGen, ptr_val: Value, offset: u32) InnerError!WValue...@@ -2964,12 +2984,12 @@ fn lowerParentPtr(func: *CodeGen, ptr_val: Value, offset: u32) InnerError!WValue
2964 if (layout.payload_align > layout.tag_align) break :blk 0;2984 if (layout.payload_align > layout.tag_align) break :blk 0;
29652985
2966 // tag is stored first so calculate offset from where payload starts2986 // 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));2987 const offset = @intCast(u32, std.mem.alignForwardGeneric(u64, layout.tag_size, layout.tag_align));
2968 break :blk field_offset;2988 break :blk offset;
2969 },2989 },
2970 },2990 },
2971 .Pointer => switch (parent_ty.ptrSize(mod)) {2991 .Pointer => switch (parent_ty.ptrSize(mod)) {
2972 .Slice => switch (field_ptr.field_index) {2992 .Slice => switch (field.index) {
2973 0 => 0,2993 0 => 0,
2974 1 => func.ptrSize(),2994 1 => func.ptrSize(),
2975 else => unreachable,2995 else => unreachable,
...@@ -2978,19 +2998,23 @@ fn lowerParentPtr(func: *CodeGen, ptr_val: Value, offset: u32) InnerError!WValue...@@ -2978,19 +2998,23 @@ fn lowerParentPtr(func: *CodeGen, ptr_val: Value, offset: u32) InnerError!WValue
2978 },2998 },
2979 else => unreachable,2999 else => unreachable,
2980 };3000 };
2981 return func.lowerParentPtr(field_ptr.container_ptr, offset + @intCast(u32, field_offset));3001
2982 },3002 return switch (parent_ptr) {
2983 .elem_ptr => {3003 .memory => |ptr_| WValue{
2984 const elem_ptr = ptr_val.castTag(.elem_ptr).?.data;3004 .memory_offset = .{
2985 const index = elem_ptr.index;3005 .pointer = ptr_,
2986 const elem_offset = index * elem_ptr.elem_ty.abiSize(mod);3006 .offset = @intCast(u32, offset),
2987 return func.lowerParentPtr(elem_ptr.array_ptr, offset + @intCast(u32, elem_offset));3007 },
2988 },3008 },
2989 .opt_payload_ptr => {3009 .memory_offset => |mem_off| WValue{
2990 const payload_ptr = ptr_val.castTag(.opt_payload_ptr).?.data;3010 .memory_offset = .{
2991 return func.lowerParentPtr(payload_ptr.container_ptr, offset);3011 .pointer = mem_off.pointer,
3012 .offset = @intCast(u32, offset) + mem_off.offset,
3013 },
3014 },
3015 else => unreachable,
3016 };
2992 },3017 },
2993 else => |tag| return func.fail("TODO: Implement lowerParentPtr for tag: {}", .{tag}),
2994 }3018 }
2995}3019}
29963020
...@@ -3045,21 +3069,97 @@ fn toTwosComplement(value: anytype, bits: u7) std.meta.Int(.unsigned, @typeInfo(...@@ -3045,21 +3069,97 @@ fn toTwosComplement(value: anytype, bits: u7) std.meta.Int(.unsigned, @typeInfo(
3045fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {3069fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {
3046 const mod = func.bin_file.base.options.module.?;3070 const mod = func.bin_file.base.options.module.?;
3047 var val = arg_val;3071 var val = arg_val;
3048 if (val.castTag(.runtime_value)) |rt| {3072 switch (mod.intern_pool.indexToKey(val.ip_index)) {
3049 val = rt.data;3073 .runtime_value => |rt| val = rt.val.toValue(),
3074 else => {},
3050 }3075 }
3051 if (val.isUndefDeep(mod)) return func.emitUndefined(ty);3076 if (val.isUndefDeep(mod)) return func.emitUndefined(ty);
3052 if (val.castTag(.decl_ref)) |decl_ref| {3077
3053 const decl_index = decl_ref.data;3078 if (val.ip_index == .none) switch (ty.zigTypeTag(mod)) {
3054 return func.lowerDeclRefValue(.{ .ty = ty, .val = val }, decl_index, 0);3079 .Array => |zig_type| return func.fail("Wasm TODO: LowerConstant for zigTypeTag {}", .{zig_type}),
3055 }3080 .Struct => {
3056 if (val.castTag(.decl_ref_mut)) |decl_ref_mut| {3081 const struct_obj = mod.typeToStruct(ty).?;
3057 const decl_index = decl_ref_mut.data.decl_index;3082 assert(struct_obj.layout == .Packed);
3058 return func.lowerDeclRefValue(.{ .ty = ty, .val = val }, decl_index, 0);3083 var buf: [8]u8 = .{0} ** 8; // zero the buffer so we do not read 0xaa as integer
3059 }3084 val.writeToPackedMemory(ty, func.bin_file.base.options.module.?, &buf, 0) catch unreachable;
3060 switch (ty.zigTypeTag(mod)) {3085 const int_val = try mod.intValue(
3061 .Void => return WValue{ .none = {} },3086 struct_obj.backing_int_ty,
3062 .Int => {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 => {
3063 const int_info = ty.intInfo(mod);3163 const int_info = ty.intInfo(mod);
3064 switch (int_info.signedness) {3164 switch (int_info.signedness) {
3065 .signed => switch (int_info.bits) {3165 .signed => switch (int_info.bits) {
...@@ -3080,86 +3180,71 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {...@@ -3080,86 +3180,71 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {
3080 },3180 },
3081 }3181 }
3082 },3182 },
3083 .Bool => return WValue{ .imm32 = @intCast(u32, val.toUnsignedInt(mod)) },3183 .err => |err| {
3084 .Float => switch (ty.floatBits(func.target)) {3184 const name = mod.intern_pool.stringToSlice(err.name);
3085 16 => return WValue{ .imm32 = @bitCast(u16, val.toFloat(f16, mod)) },3185 const kv = try mod.getErrorValue(name);
3086 32 => return WValue{ .float32 = val.toFloat(f32, mod) },3186 return WValue{ .imm32 = kv.value };
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 },
3112 },3187 },
3113 .ErrorUnion => {3188 .error_union => {
3114 const error_type = ty.errorUnionSet(mod);3189 const error_type = ty.errorUnionSet(mod);
3115 const payload_type = ty.errorUnionPayload(mod);3190 const payload_type = ty.errorUnionPayload(mod);
3116 if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) {3191 if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) {
3117 // We use the error type directly as the type.3192 // We use the error type directly as the type.
3118 const is_pl = val.errorUnionIsPayload();3193 const is_pl = val.errorUnionIsPayload(mod);
3119 const err_val = if (!is_pl) val else try mod.intValue(error_type, 0);3194 const err_val = if (!is_pl) val else try mod.intValue(error_type, 0);
3120 return func.lowerConstant(err_val, error_type);3195 return func.lowerConstant(err_val, error_type);
3121 }3196 }
3122 return func.fail("Wasm TODO: lowerConstant error union with non-zero-bit payload type", .{});3197 return func.fail("Wasm TODO: lowerConstant error union with non-zero-bit payload type", .{});
3123 },3198 },
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)) {
3125 const pl_ty = ty.optionalChild(mod);3217 const pl_ty = ty.optionalChild(mod);
3126 if (val.castTag(.opt_payload)) |payload| {3218 if (val.optionalValue(mod)) |payload| {
3127 return func.lowerConstant(payload.data, pl_ty);3219 return func.lowerConstant(payload, pl_ty);
3128 } else if (val.isNull(mod)) {
3129 return WValue{ .imm32 = 0 };
3130 } else {3220 } else {
3131 return func.lowerConstant(val, pl_ty);3221 return WValue{ .imm32 = 0 };
3132 }3222 }
3133 } else {3223 } else {
3134 const is_pl = val.tag() == .opt_payload;3224 return WValue{ .imm32 = @boolToInt(!val.isNull(mod)) };
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);
3147 },3225 },
3148 .Vector => {3226 .aggregate => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
3149 assert(determineSimdStoreStrategy(ty, mod) == .direct);3227 .array_type => return func.fail("Wasm TODO: LowerConstant for {}", .{ty.fmt(mod)}),
3150 var buf: [16]u8 = undefined;3228 .vector_type => {
3151 val.writeToMemory(ty, func.bin_file.base.options.module.?, &buf) catch unreachable;3229 assert(determineSimdStoreStrategy(ty, mod) == .direct);
3152 return func.storeSimdImmd(buf);3230 var buf: [16]u8 = undefined;
3153 },3231 val.writeToMemory(ty, mod, &buf) catch unreachable;
3154 .Union => {3232 return func.storeSimdImmd(buf);
3155 // in this case we have a packed union which will not be passed by reference.3233 },
3156 const union_ty = mod.typeToUnion(ty).?;3234 .struct_type, .anon_struct_type => {
3157 const union_obj = val.castTag(.@"union").?.data;3235 const struct_obj = mod.typeToStruct(ty).?;
3158 const field_index = ty.unionTagFieldIndex(union_obj.tag, func.bin_file.base.options.module.?).?;3236 assert(struct_obj.layout == .Packed);
3159 const field_ty = union_ty.fields.values()[field_index].ty;3237 var buf: [8]u8 = .{0} ** 8; // zero the buffer so we do not read 0xaa as integer
3160 return func.lowerConstant(union_obj.val, field_ty);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,
3161 },3246 },
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)}),
3163 }3248 }
3164}3249}
31653250
...@@ -3221,31 +3306,33 @@ fn valueAsI32(func: *const CodeGen, val: Value, ty: Type) i32 {...@@ -3221,31 +3306,33 @@ fn valueAsI32(func: *const CodeGen, val: Value, ty: Type) i32 {
3221 .bool_true => return 1,3306 .bool_true => return 1,
3222 .bool_false => return 0,3307 .bool_false => return 0,
3223 else => return switch (mod.intern_pool.indexToKey(val.ip_index)) {3308 else => return switch (mod.intern_pool.indexToKey(val.ip_index)) {
3224 .enum_tag => |enum_tag| intIndexAsI32(&mod.intern_pool, enum_tag.int),3309 .enum_tag => |enum_tag| intIndexAsI32(&mod.intern_pool, enum_tag.int, mod),
3225 .int => |int| intStorageAsI32(int.storage),3310 .int => |int| intStorageAsI32(int.storage, mod),
3226 .ptr => |ptr| intIndexAsI32(&mod.intern_pool, ptr.addr.int),3311 .ptr => |ptr| intIndexAsI32(&mod.intern_pool, ptr.addr.int, mod),
3227 else => unreachable,3312 else => unreachable,
3228 },3313 },
3229 }3314 }
32303315
3231 switch (ty.zigTypeTag(mod)) {3316 switch (ty.zigTypeTag(mod)) {
3232 .ErrorSet => {3317 .ErrorSet => {
3233 const kv = func.bin_file.base.options.module.?.getErrorValue(val.getError().?) catch unreachable; // passed invalid `Value` to function3318 const kv = func.bin_file.base.options.module.?.getErrorValue(val.getError(mod).?) catch unreachable; // passed invalid `Value` to function
3234 return @bitCast(i32, kv.value);3319 return @bitCast(i32, kv.value);
3235 },3320 },
3236 else => unreachable, // Programmer called this function for an illegal type3321 else => unreachable, // Programmer called this function for an illegal type
3237 }3322 }
3238}3323}
32393324
3240fn intIndexAsI32(ip: *const InternPool, int: InternPool.Index) i32 {3325fn intIndexAsI32(ip: *const InternPool, int: InternPool.Index, mod: *Module) i32 {
3241 return intStorageAsI32(ip.indexToKey(int).int.storage);3326 return intStorageAsI32(ip.indexToKey(int).int.storage, mod);
3242}3327}
32433328
3244fn intStorageAsI32(storage: InternPool.Key.Int.Storage) i32 {3329fn intStorageAsI32(storage: InternPool.Key.Int.Storage, mod: *Module) i32 {
3245 return switch (storage) {3330 return switch (storage) {
3246 .i64 => |x| @intCast(i32, x),3331 .i64 => |x| @intCast(i32, x),
3247 .u64 => |x| @bitCast(i32, @intCast(u32, x)),3332 .u64 => |x| @bitCast(i32, @intCast(u32, x)),
3248 .big_int => unreachable,3333 .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))),
3249 };3336 };
3250}3337}
32513338
...@@ -5514,7 +5601,7 @@ fn airErrorName(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5514,7 +5601,7 @@ fn airErrorName(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5514 // As the names are global and the slice elements are constant, we do not have5601 // As the names are global and the slice elements are constant, we do not have
5515 // to make a copy of the ptr+value but can point towards them directly.5602 // to make a copy of the ptr+value but can point towards them directly.
5516 const error_table_symbol = try func.bin_file.getErrorTableSymbol();5603 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;
5518 const mod = func.bin_file.base.options.module.?;5605 const mod = func.bin_file.base.options.module.?;
5519 const abi_size = name_ty.abiSize(mod);5606 const abi_size = name_ty.abiSize(mod);
55205607
...@@ -6935,7 +7022,7 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 {...@@ -6935,7 +7022,7 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 {
6935 // finish function body7022 // finish function body
6936 try writer.writeByte(std.wasm.opcode(.end));7023 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;
6939 const func_type = try genFunctype(arena, .Unspecified, &.{int_tag_ty.ip_index}, slice_ty, mod);7026 const func_type = try genFunctype(arena, .Unspecified, &.{int_tag_ty.ip_index}, slice_ty, mod);
6940 return func.bin_file.createFunction(func_name, func_type, &body_list, &relocs);7027 return func.bin_file.createFunction(func_name, func_type, &body_list, &relocs);
6941}7028}
src/arch/x86_64/CodeGen.zig+29-36
...@@ -632,7 +632,7 @@ const Self = @This();...@@ -632,7 +632,7 @@ const Self = @This();
632pub fn generate(632pub fn generate(
633 bin_file: *link.File,633 bin_file: *link.File,
634 src_loc: Module.SrcLoc,634 src_loc: Module.SrcLoc,
635 module_fn: *Module.Fn,635 module_fn_index: Module.Fn.Index,
636 air: Air,636 air: Air,
637 liveness: Liveness,637 liveness: Liveness,
638 code: *std.ArrayList(u8),638 code: *std.ArrayList(u8),
...@@ -643,6 +643,7 @@ pub fn generate(...@@ -643,6 +643,7 @@ pub fn generate(
643 }643 }
644644
645 const mod = bin_file.options.module.?;645 const mod = bin_file.options.module.?;
646 const module_fn = mod.funcPtr(module_fn_index);
646 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);647 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
647 assert(fn_owner_decl.has_tv);648 assert(fn_owner_decl.has_tv);
648 const fn_type = fn_owner_decl.ty;649 const fn_type = fn_owner_decl.ty;
...@@ -687,7 +688,7 @@ pub fn generate(...@@ -687,7 +688,7 @@ pub fn generate(
687 @enumToInt(FrameIndex.stack_frame),688 @enumToInt(FrameIndex.stack_frame),
688 FrameAlloc.init(.{689 FrameAlloc.init(.{
689 .size = 0,690 .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|
691 set_align_stack.alignment692 set_align_stack.alignment
692 else693 else
693 1,694 1,
...@@ -2760,19 +2761,18 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {...@@ -2760,19 +2761,18 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
2760 const elem_ty = src_ty.childType(mod);2761 const elem_ty = src_ty.childType(mod);
2761 const mask_val = try mod.intValue(elem_ty, @as(u64, math.maxInt(u64)) >> @intCast(u6, 64 - dst_info.bits));2762 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 const splat_ty = try mod.vectorType(.{
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(.{
2770 .len = @intCast(u32, @divExact(@as(u64, if (src_abi_size > 16) 256 else 128), src_info.bits)),2765 .len = @intCast(u32, @divExact(@as(u64, if (src_abi_size > 16) 256 else 128), src_info.bits)),
2771 .child = elem_ty.ip_index,2766 .child = elem_ty.ip_index,
2772 });2767 });
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() });
2776 const splat_addr_mcv: MCValue = switch (splat_mcv) {2776 const splat_addr_mcv: MCValue = switch (splat_mcv) {
2777 .memory, .indirect, .load_frame => splat_mcv.address(),2777 .memory, .indirect, .load_frame => splat_mcv.address(),
2778 else => .{ .register = try self.copyToTmpRegister(Type.usize, splat_mcv.address()) },2778 else => .{ .register = try self.copyToTmpRegister(Type.usize, splat_mcv.address()) },
...@@ -2784,14 +2784,14 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {...@@ -2784,14 +2784,14 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
2784 .{ .vp_, .@"and" },2784 .{ .vp_, .@"and" },
2785 dst_reg,2785 dst_reg,
2786 dst_reg,2786 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)),
2788 );2788 );
2789 try self.asmRegisterRegisterRegister(mir_tag, dst_reg, dst_reg, dst_reg);2789 try self.asmRegisterRegisterRegister(mir_tag, dst_reg, dst_reg, dst_reg);
2790 } else {2790 } else {
2791 try self.asmRegisterMemory(2791 try self.asmRegisterMemory(
2792 .{ .p_, .@"and" },2792 .{ .p_, .@"and" },
2793 dst_reg,2793 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)),
2795 );2795 );
2796 try self.asmRegisterRegister(mir_tag, dst_reg, dst_reg);2796 try self.asmRegisterRegister(mir_tag, dst_reg, dst_reg);
2797 }2797 }
...@@ -4893,23 +4893,14 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void {...@@ -4893,23 +4893,14 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void {
4893 const dst_lock = self.register_manager.lockReg(dst_reg);4893 const dst_lock = self.register_manager.lockReg(dst_reg);
4894 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);4894 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
4905 const vec_ty = try mod.vectorType(.{4896 const vec_ty = try mod.vectorType(.{
4906 .len = @divExact(abi_size * 8, scalar_bits),4897 .len = @divExact(abi_size * 8, scalar_bits),
4907 .child = (try mod.intType(.signed, scalar_bits)).ip_index,4898 .child = (try mod.intType(.signed, scalar_bits)).ip_index,
4908 });4899 });
49094900
4910 const sign_val = switch (tag) {4901 const sign_val = switch (tag) {
4911 .neg => try vec_ty.minInt(stack.get(), mod),4902 .neg => try vec_ty.minInt(mod),
4912 .fabs => try vec_ty.maxInt(stack.get(), mod, vec_ty),4903 .fabs => try vec_ty.maxInt(mod, vec_ty),
4913 else => unreachable,4904 else => unreachable,
4914 };4905 };
49154906
...@@ -8106,13 +8097,15 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -8106,13 +8097,15 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
8106 // Due to incremental compilation, how function calls are generated depends8097 // Due to incremental compilation, how function calls are generated depends
8107 // on linking.8098 // on linking.
8108 if (try self.air.value(callee, mod)) |func_value| {8099 if (try self.air.value(callee, mod)) |func_value| {
8109 if (if (func_value.castTag(.function)) |func_payload|8100 const func_key = mod.intern_pool.indexToKey(func_value.ip_index);
8110 func_payload.data.owner_decl8101 if (switch (func_key) {
8111 else if (func_value.castTag(.decl_ref)) |decl_ref_payload|8102 .func => |func| mod.funcPtr(func.index).owner_decl,
8112 decl_ref_payload.data8103 .ptr => |ptr| switch (ptr.addr) {
8113 else8104 .decl => |decl| decl,
8114 null) |owner_decl|8105 else => null,
8115 {8106 },
8107 else => null,
8108 }) |owner_decl| {
8116 if (self.bin_file.cast(link.File.Elf)) |elf_file| {8109 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
8117 const atom_index = try elf_file.getOrCreateAtomForDecl(owner_decl);8110 const atom_index = try elf_file.getOrCreateAtomForDecl(owner_decl);
8118 const atom = elf_file.getAtom(atom_index);8111 const atom = elf_file.getAtom(atom_index);
...@@ -8145,10 +8138,9 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -8145,10 +8138,9 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
8145 .disp = @intCast(i32, fn_got_addr),8138 .disp = @intCast(i32, fn_got_addr),
8146 }));8139 }));
8147 } else unreachable;8140 } else unreachable;
8148 } else if (func_value.castTag(.extern_fn)) |func_payload| {8141 } else if (func_value.getExternFunc(mod)) |extern_func| {
8149 const extern_fn = func_payload.data;8142 const decl_name = mem.sliceTo(mod.declPtr(extern_func.decl).name, 0);
8150 const decl_name = mem.sliceTo(mod.declPtr(extern_fn.owner_decl).name, 0);8143 const lib_name = mod.intern_pool.stringToSliceUnwrap(extern_func.lib_name);
8151 const lib_name = mem.sliceTo(extern_fn.lib_name, 0);
8152 if (self.bin_file.cast(link.File.Coff)) |coff_file| {8144 if (self.bin_file.cast(link.File.Coff)) |coff_file| {
8153 const atom_index = try self.owner.getSymbolIndex(self);8145 const atom_index = try self.owner.getSymbolIndex(self);
8154 const sym_index = try coff_file.getGlobalSymbol(decl_name, lib_name);8146 const sym_index = try coff_file.getGlobalSymbol(decl_name, lib_name);
...@@ -8554,7 +8546,8 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {...@@ -8554,7 +8546,8 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
85548546
8555fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {8547fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
8556 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;8548 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).?;
8558 // TODO emit debug info for function change8551 // TODO emit debug info for function change
8559 _ = function;8552 _ = function;
8560 return self.finishAir(inst, .unreach, .{ .none, .none, .none });8553 return self.finishAir(inst, .unreach, .{ .none, .none, .none });
src/codegen.zig+430-605
...@@ -14,6 +14,7 @@ const Air = @import("Air.zig");...@@ -14,6 +14,7 @@ const Air = @import("Air.zig");
14const Allocator = mem.Allocator;14const Allocator = mem.Allocator;
15const Compilation = @import("Compilation.zig");15const Compilation = @import("Compilation.zig");
16const ErrorMsg = Module.ErrorMsg;16const ErrorMsg = Module.ErrorMsg;
17const InternPool = @import("InternPool.zig");
17const Liveness = @import("Liveness.zig");18const Liveness = @import("Liveness.zig");
18const Module = @import("Module.zig");19const Module = @import("Module.zig");
19const Target = std.Target;20const Target = std.Target;
...@@ -66,7 +67,7 @@ pub const DebugInfoOutput = union(enum) {...@@ -66,7 +67,7 @@ pub const DebugInfoOutput = union(enum) {
66pub fn generateFunction(67pub fn generateFunction(
67 bin_file: *link.File,68 bin_file: *link.File,
68 src_loc: Module.SrcLoc,69 src_loc: Module.SrcLoc,
69 func: *Module.Fn,70 func_index: Module.Fn.Index,
70 air: Air,71 air: Air,
71 liveness: Liveness,72 liveness: Liveness,
72 code: *std.ArrayList(u8),73 code: *std.ArrayList(u8),
...@@ -75,17 +76,17 @@ pub fn generateFunction(...@@ -75,17 +76,17 @@ pub fn generateFunction(
75 switch (bin_file.options.target.cpu.arch) {76 switch (bin_file.options.target.cpu.arch) {
76 .arm,77 .arm,
77 .armeb,78 .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),
79 .aarch64,80 .aarch64,
80 .aarch64_be,81 .aarch64_be,
81 .aarch64_32,82 .aarch64_32,
82 => return @import("arch/aarch64/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),
83 .riscv64 => return @import("arch/riscv64/CodeGen.zig").generate(bin_file, src_loc, func, 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),
84 .sparc64 => return @import("arch/sparc64/CodeGen.zig").generate(bin_file, src_loc, func, 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),
85 .x86_64 => return @import("arch/x86_64/CodeGen.zig").generate(bin_file, src_loc, func, 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),
86 .wasm32,87 .wasm32,
87 .wasm64,88 .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),
89 else => unreachable,90 else => unreachable,
90 }91 }
91}92}
...@@ -182,12 +183,13 @@ pub fn generateSymbol(...@@ -182,12 +183,13 @@ pub fn generateSymbol(
182 const tracy = trace(@src());183 const tracy = trace(@src());
183 defer tracy.end();184 defer tracy.end();
184185
186 const mod = bin_file.options.module.?;
185 var typed_value = arg_tv;187 var typed_value = arg_tv;
186 if (arg_tv.val.castTag(.runtime_value)) |rt| {188 switch (mod.intern_pool.indexToKey(typed_value.val.ip_index)) {
187 typed_value.val = rt.data;189 .runtime_value => |rt| typed_value.val = rt.val.toValue(),
190 else => {},
188 }191 }
189192
190 const mod = bin_file.options.module.?;
191 const target = mod.getTarget();193 const target = mod.getTarget();
192 const endian = target.cpu.arch.endian();194 const endian = target.cpu.arch.endian();
193195
...@@ -199,35 +201,10 @@ pub fn generateSymbol(...@@ -199,35 +201,10 @@ pub fn generateSymbol(
199 if (typed_value.val.isUndefDeep(mod)) {201 if (typed_value.val.isUndefDeep(mod)) {
200 const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow;202 const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow;
201 try code.appendNTimes(0xaa, abi_size);203 try code.appendNTimes(0xaa, abi_size);
202 return Result.ok;204 return .ok;
203 }205 }
204206
205 switch (typed_value.ty.zigTypeTag(mod)) {207 if (typed_value.val.ip_index == .none) 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 },
231 .Array => switch (typed_value.val.tag()) {208 .Array => switch (typed_value.val.tag()) {
232 .bytes => {209 .bytes => {
233 const bytes = typed_value.val.castTag(.bytes).?.data;210 const bytes = typed_value.val.castTag(.bytes).?.data;
...@@ -248,62 +225,6 @@ pub fn generateSymbol(...@@ -248,62 +225,6 @@ pub fn generateSymbol(
248 }225 }
249 return Result.ok;226 return Result.ok;
250 },227 },
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 },
307 else => return Result{228 else => return Result{
308 .fail = try ErrorMsg.create(229 .fail = try ErrorMsg.create(
309 bin_file.allocator,230 bin_file.allocator,
...@@ -313,195 +234,6 @@ pub fn generateSymbol(...@@ -313,195 +234,6 @@ pub fn generateSymbol(
313 ),234 ),
314 },235 },
315 },236 },
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 },
505 .Struct => {237 .Struct => {
506 if (typed_value.ty.containerLayout(mod) == .Packed) {238 if (typed_value.ty.containerLayout(mod) == .Packed) {
507 const struct_obj = mod.typeToStruct(typed_value.ty).?;239 const struct_obj = mod.typeToStruct(typed_value.ty).?;
...@@ -562,370 +294,497 @@ pub fn generateSymbol(...@@ -562,370 +294,497 @@ pub fn generateSymbol(
562294
563 return Result.ok;295 return Result.ok;
564 },296 },
565 .Union => {297 .Vector => switch (typed_value.val.tag()) {
566 const union_obj = typed_value.val.castTag(.@"union").?.data;298 .bytes => {
567 const layout = typed_value.ty.unionGetLayout(mod);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) {351 switch (mod.intern_pool.indexToKey(typed_value.val.ip_index)) {
570 return generateSymbol(bin_file, src_loc, .{352 .int_type,
571 .ty = typed_value.ty.unionTagType(mod).?,353 .ptr_type,
572 .val = union_obj.tag,354 .array_type,
573 }, code, debug_output, reloc_info);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;
574 }412 }
575413
576 // Check if we should store the tag first.414 const payload_align = payload_ty.abiAlignment(mod);
577 if (layout.tag_align >= layout.payload_align) {415 const error_align = Type.anyerror.abiAlignment(mod);
578 switch (try generateSymbol(bin_file, src_loc, .{416 const abi_align = typed_value.ty.abiAlignment(mod);
579 .ty = typed_value.ty.unionTagType(mod).?,417
580 .val = union_obj.tag,418 // error value first when its type is larger than the error union's payload
581 }, code, debug_output, reloc_info)) {419 if (error_align > payload_align) {
582 .ok => {},420 try code.writer().writeInt(u16, err_val, endian);
583 .fail => |em| return Result{ .fail = em },
584 }
585 }421 }
586422
587 const union_ty = mod.typeToUnion(typed_value.ty).?;423 // emit payload part of the error union
588 const field_index = typed_value.ty.unionTagFieldIndex(union_obj.tag, mod).?;424 {
589 assert(union_ty.haveFieldTypes());425 const begin = code.items.len;
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 {
594 switch (try generateSymbol(bin_file, src_loc, .{426 switch (try generateSymbol(bin_file, src_loc, .{
595 .ty = field_ty,427 .ty = payload_ty,
596 .val = union_obj.val,428 .val = switch (error_union.val) {
429 .err_name => try mod.intern(.{ .undef = payload_ty.ip_index }),
430 .payload => |payload| payload,
431 }.toValue(),
597 }, code, debug_output, reloc_info)) {432 }, code, debug_output, reloc_info)) {
598 .ok => {},433 .ok => {},
599 .fail => |em| return Result{ .fail = em },434 .fail => |em| return .{ .fail = em },
600 }435 }
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;
603 if (padding > 0) {440 if (padding > 0) {
604 try code.writer().writeByteNTimes(0, padding);441 try code.writer().writeByteNTimes(0, padding);
605 }442 }
606 }443 }
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
609 switch (try generateSymbol(bin_file, src_loc, .{490 switch (try generateSymbol(bin_file, src_loc, .{
610 .ty = union_ty.tag_ty,491 .ty = Type.usize,
611 .val = union_obj.tag,492 .val = ptr.len.toValue(),
612 }, code, debug_output, reloc_info)) {493 }, code, debug_output, reloc_info)) {
613 .ok => {},494 .ok => {},
614 .fail => |em| return Result{ .fail = em },495 .fail => |em| return Result{ .fail = em },
615 }496 }
616 }497 }
617
618 if (layout.padding > 0) {
619 try code.writer().writeByteNTimes(0, layout.padding);
620 }
621
622 return Result.ok;
623 },498 },
624 .Optional => {499 .opt => {
625 const payload_type = typed_value.ty.optionalChild(mod);500 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);
627 const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow;502 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
634 if (typed_value.ty.optionalReprIsPayload(mod)) {504 if (typed_value.ty.optionalReprIsPayload(mod)) {
635 if (typed_value.val.castTag(.opt_payload)) |payload| {505 if (payload_val) |value| {
636 switch (try generateSymbol(bin_file, src_loc, .{506 switch (try generateSymbol(bin_file, src_loc, .{
637 .ty = payload_type,507 .ty = payload_type,
638 .val = payload.data,508 .val = value,
639 }, code, debug_output, reloc_info)) {509 }, code, debug_output, reloc_info)) {
640 .ok => {},510 .ok => {},
641 .fail => |em| return Result{ .fail = em },511 .fail => |em| return Result{ .fail = em },
642 }512 }
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();
644 switch (try generateSymbol(bin_file, src_loc, .{520 switch (try generateSymbol(bin_file, src_loc, .{
645 .ty = payload_type,521 .ty = payload_type,
646 .val = typed_value.val,522 .val = value,
647 }, code, debug_output, reloc_info)) {523 }, code, debug_output, reloc_info)) {
648 .ok => {},524 .ok => {},
649 .fail => |em| return Result{ .fail = em },525 .fail => |em| return Result{ .fail = em },
650 }526 }
651 } else {
652 try code.writer().writeByteNTimes(0, abi_size);
653 }527 }
654528 try code.writer().writeByte(@boolToInt(payload_val != null));
655 return Result.ok;529 try code.writer().writeByteNTimes(0, padding);
656 }530 }
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;552 if (array_type.sentinel != .none) {
659 const value = if (typed_value.val.castTag(.opt_payload)) |payload| payload.data else Value.undef;553 switch (try generateSymbol(bin_file, src_loc, .{
660 switch (try generateSymbol(bin_file, src_loc, .{554 .ty = array_type.child.toType(),
661 .ty = payload_type,555 .val = array_type.sentinel.toValue(),
662 .val = value,556 }, code, debug_output, reloc_info)) {
663 }, code, debug_output, reloc_info)) {557 .ok => {},
664 .ok => {},558 .fail => |em| return .{ .fail = em },
665 .fail => |em| return Result{ .fail = em },559 }
666 }560 }
667 try code.writer().writeByte(@boolToInt(is_pl));561 },
668 try code.writer().writeByteNTimes(0, padding);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,
671 },645 },
672 .ErrorUnion => {646 .un => |un| {
673 const error_ty = typed_value.ty.errorUnionSet(mod);647 const layout = typed_value.ty.unionGetLayout(mod);
674 const payload_ty = typed_value.ty.errorUnionPayload(mod);
675 const is_payload = typed_value.val.errorUnionIsPayload();
676648
677 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {649 if (layout.payload_size == 0) {
678 const err_val = if (is_payload) try mod.intValue(error_ty, 0) else typed_value.val;
679 return generateSymbol(bin_file, src_loc, .{650 return generateSymbol(bin_file, src_loc, .{
680 .ty = error_ty,651 .ty = typed_value.ty.unionTagType(mod).?,
681 .val = err_val,652 .val = un.tag.toValue(),
682 }, code, debug_output, reloc_info);653 }, code, debug_output, reloc_info);
683 }654 }
684655
685 const payload_align = payload_ty.abiAlignment(mod);656 // Check if we should store the tag first.
686 const error_align = Type.anyerror.abiAlignment(mod);657 if (layout.tag_align >= layout.payload_align) {
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) {
691 switch (try generateSymbol(bin_file, src_loc, .{658 switch (try generateSymbol(bin_file, src_loc, .{
692 .ty = error_ty,659 .ty = typed_value.ty.unionTagType(mod).?,
693 .val = if (is_payload) try mod.intValue(error_ty, 0) else typed_value.val,660 .val = un.tag.toValue(),
694 }, code, debug_output, reloc_info)) {661 }, code, debug_output, reloc_info)) {
695 .ok => {},662 .ok => {},
696 .fail => |em| return Result{ .fail = em },663 .fail => |em| return Result{ .fail = em },
697 }664 }
698 }665 }
699666
700 // emit payload part of the error union667 const union_ty = mod.typeToUnion(typed_value.ty).?;
701 {668 const field_index = typed_value.ty.unionTagFieldIndex(un.tag.toValue(), mod).?;
702 const begin = code.items.len;669 assert(union_ty.haveFieldTypes());
703 const payload_val = if (typed_value.val.castTag(.eu_payload)) |val| val.data else Value.undef;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 {
704 switch (try generateSymbol(bin_file, src_loc, .{674 switch (try generateSymbol(bin_file, src_loc, .{
705 .ty = payload_ty,675 .ty = field_ty,
706 .val = payload_val,676 .val = un.val.toValue(),
707 }, code, debug_output, reloc_info)) {677 }, code, debug_output, reloc_info)) {
708 .ok => {},678 .ok => {},
709 .fail => |em| return Result{ .fail = em },679 .fail => |em| return Result{ .fail = em },
710 }680 }
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;
715 if (padding > 0) {683 if (padding > 0) {
716 try code.writer().writeByteNTimes(0, padding);684 try code.writer().writeByteNTimes(0, padding);
717 }685 }
718 }686 }
719687
720 // Payload size is larger than error set, so emit our error set last688 if (layout.tag_size > 0) {
721 if (error_align <= payload_align) {
722 const begin = code.items.len;
723 switch (try generateSymbol(bin_file, src_loc, .{689 switch (try generateSymbol(bin_file, src_loc, .{
724 .ty = error_ty,690 .ty = union_ty.tag_ty,
725 .val = if (is_payload) try mod.intValue(error_ty, 0) else typed_value.val,691 .val = un.tag.toValue(),
726 }, code, debug_output, reloc_info)) {692 }, code, debug_output, reloc_info)) {
727 .ok => {},693 .ok => {},
728 .fail => |em| return Result{ .fail = em },694 .fail => |em| return Result{ .fail = em },
729 }695 }
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 },
751 }696 }
752 return Result.ok;
753 },697 },
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 ) },
826 }698 }
699 return .ok;
827}700}
828701
829fn lowerParentPtr(702fn lowerParentPtr(
830 bin_file: *link.File,703 bin_file: *link.File,
831 src_loc: Module.SrcLoc,704 src_loc: Module.SrcLoc,
832 typed_value: TypedValue,705 parent_ptr: InternPool.Index,
833 parent_ptr: Value,
834 code: *std.ArrayList(u8),706 code: *std.ArrayList(u8),
835 debug_output: DebugInfoOutput,707 debug_output: DebugInfoOutput,
836 reloc_info: RelocInfo,708 reloc_info: RelocInfo,
837) CodeGenError!Result {709) CodeGenError!Result {
838 const mod = bin_file.options.module.?;710 const mod = bin_file.options.module.?;
839 switch (parent_ptr.tag()) {711 const ptr = mod.intern_pool.indexToKey(parent_ptr).ptr;
840 .field_ptr => {712 assert(ptr.len == .none);
841 const field_ptr = parent_ptr.castTag(.field_ptr).?.data;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);
842 return lowerParentPtr(760 return lowerParentPtr(
843 bin_file,761 bin_file,
844 src_loc,762 src_loc,
845 typed_value,763 field.base,
846 field_ptr.container_ptr,
847 code,764 code,
848 debug_output,765 debug_output,
849 reloc_info.offset(@intCast(u32, switch (field_ptr.container_ty.zigTypeTag(mod)) {766 reloc_info.offset(switch (mod.intern_pool.indexToKey(base_type)) {
850 .Pointer => offset: {767 .ptr_type => |ptr_type| switch (ptr_type.size) {
851 assert(field_ptr.container_ty.isSlice(mod));768 .One, .Many, .C => unreachable,
852 break :offset switch (field_ptr.field_index) {769 .Slice => switch (field.index) {
853 0 => 0,770 0 => 0,
854 1 => field_ptr.container_ty.slicePtrFieldType(mod).abiSize(mod),771 1 => @divExact(mod.getTarget().ptrBitWidth(), 8),
855 else => unreachable,772 else => unreachable,
856 };773 },
857 },774 },
858 .Struct, .Union => field_ptr.container_ty.structFieldOffset(775 .struct_type,
859 field_ptr.field_index,776 .anon_struct_type,
777 .union_type,
778 => @intCast(u32, base_type.toType().childType(mod).structFieldOffset(
779 @intCast(u32, field.index),
860 mod,780 mod,
861 ),781 )),
862 else => return Result{ .fail = try ErrorMsg.create(782 else => unreachable,
863 bin_file.allocator,783 }),
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))),
906 );784 );
907 },785 },
908 .variable, .decl_ref, .decl_ref_mut => |tag| return lowerDeclRef(786 .comptime_field => unreachable,
909 bin_file,787 };
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 }
929}788}
930789
931const RelocInfo = struct {790const RelocInfo = struct {
...@@ -940,36 +799,15 @@ const RelocInfo = struct {...@@ -940,36 +799,15 @@ const RelocInfo = struct {
940fn lowerDeclRef(799fn lowerDeclRef(
941 bin_file: *link.File,800 bin_file: *link.File,
942 src_loc: Module.SrcLoc,801 src_loc: Module.SrcLoc,
943 typed_value: TypedValue,
944 decl_index: Module.Decl.Index,802 decl_index: Module.Decl.Index,
945 code: *std.ArrayList(u8),803 code: *std.ArrayList(u8),
946 debug_output: DebugInfoOutput,804 debug_output: DebugInfoOutput,
947 reloc_info: RelocInfo,805 reloc_info: RelocInfo,
948) CodeGenError!Result {806) CodeGenError!Result {
807 _ = src_loc;
808 _ = debug_output;
949 const target = bin_file.options.target;809 const target = bin_file.options.target;
950 const mod = bin_file.options.module.?;810 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
974 const ptr_width = target.ptrBitWidth();812 const ptr_width = target.ptrBitWidth();
975 const decl = mod.declPtr(decl_index);813 const decl = mod.declPtr(decl_index);
...@@ -1154,12 +992,13 @@ pub fn genTypedValue(...@@ -1154,12 +992,13 @@ pub fn genTypedValue(
1154 arg_tv: TypedValue,992 arg_tv: TypedValue,
1155 owner_decl_index: Module.Decl.Index,993 owner_decl_index: Module.Decl.Index,
1156) CodeGenError!GenResult {994) CodeGenError!GenResult {
995 const mod = bin_file.options.module.?;
1157 var typed_value = arg_tv;996 var typed_value = arg_tv;
1158 if (typed_value.val.castTag(.runtime_value)) |rt| {997 switch (mod.intern_pool.indexToKey(typed_value.val.ip_index)) {
1159 typed_value.val = rt.data;998 .runtime_value => |rt| typed_value.val = rt.val.toValue(),
999 else => {},
1160 }1000 }
11611001
1162 const mod = bin_file.options.module.?;
1163 log.debug("genTypedValue: ty = {}, val = {}", .{1002 log.debug("genTypedValue: ty = {}, val = {}", .{
1164 typed_value.ty.fmt(mod),1003 typed_value.ty.fmt(mod),
1165 typed_value.val.fmtValue(typed_value.ty, mod),1004 typed_value.val.fmtValue(typed_value.ty, mod),
...@@ -1171,17 +1010,14 @@ pub fn genTypedValue(...@@ -1171,17 +1010,14 @@ pub fn genTypedValue(
1171 const target = bin_file.options.target;1010 const target = bin_file.options.target;
1172 const ptr_bits = target.ptrBitWidth();1011 const ptr_bits = target.ptrBitWidth();
11731012
1174 if (!typed_value.ty.isSlice(mod)) {1013 if (!typed_value.ty.isSlice(mod)) switch (mod.intern_pool.indexToKey(typed_value.val.ip_index)) {
1175 if (typed_value.val.castTag(.variable)) |payload| {1014 .ptr => |ptr| switch (ptr.addr) {
1176 return genDeclRef(bin_file, src_loc, typed_value, payload.data.owner_decl);1015 .decl => |decl| return genDeclRef(bin_file, src_loc, typed_value, decl),
1177 }1016 .mut_decl => |mut_decl| return genDeclRef(bin_file, src_loc, typed_value, mut_decl.decl),
1178 if (typed_value.val.castTag(.decl_ref)) |payload| {1017 else => {},
1179 return genDeclRef(bin_file, src_loc, typed_value, payload.data);1018 },
1180 }1019 else => {},
1181 if (typed_value.val.castTag(.decl_ref_mut)) |payload| {1020 };
1182 return genDeclRef(bin_file, src_loc, typed_value, payload.data.decl_index);
1183 }
1184 }
11851021
1186 switch (typed_value.ty.zigTypeTag(mod)) {1022 switch (typed_value.ty.zigTypeTag(mod)) {
1187 .Void => return GenResult.mcv(.none),1023 .Void => return GenResult.mcv(.none),
...@@ -1215,11 +1051,9 @@ pub fn genTypedValue(...@@ -1215,11 +1051,9 @@ pub fn genTypedValue(
1215 },1051 },
1216 .Optional => {1052 .Optional => {
1217 if (typed_value.ty.isPtrLikeOptional(mod)) {1053 if (typed_value.ty.isPtrLikeOptional(mod)) {
1218 if (typed_value.val.ip_index == .null_value) return GenResult.mcv(.{ .immediate = 0 });
1219
1220 return genTypedValue(bin_file, src_loc, .{1054 return genTypedValue(bin_file, src_loc, .{
1221 .ty = typed_value.ty.optionalChild(mod),1055 .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 }),
1223 }, owner_decl_index);1057 }, owner_decl_index);
1224 } else if (typed_value.ty.abiSize(mod) == 1) {1058 } else if (typed_value.ty.abiSize(mod) == 1) {
1225 return GenResult.mcv(.{ .immediate = @boolToInt(!typed_value.val.isNull(mod)) });1059 return GenResult.mcv(.{ .immediate = @boolToInt(!typed_value.val.isNull(mod)) });
...@@ -1234,24 +1068,15 @@ pub fn genTypedValue(...@@ -1234,24 +1068,15 @@ pub fn genTypedValue(
1234 }, owner_decl_index);1068 }, owner_decl_index);
1235 },1069 },
1236 .ErrorSet => {1070 .ErrorSet => {
1237 switch (typed_value.val.tag()) {1071 const err_name = mod.intern_pool.stringToSlice(mod.intern_pool.indexToKey(typed_value.val.ip_index).err.name);
1238 .@"error" => {1072 const global_error_set = mod.global_error_set;
1239 const err_name = typed_value.val.castTag(.@"error").?.data.name;1073 const error_index = global_error_set.get(err_name).?;
1240 const module = bin_file.options.module.?;1074 return GenResult.mcv(.{ .immediate = error_index });
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 }
1250 },1075 },
1251 .ErrorUnion => {1076 .ErrorUnion => {
1252 const error_type = typed_value.ty.errorUnionSet(mod);1077 const error_type = typed_value.ty.errorUnionSet(mod);
1253 const payload_type = typed_value.ty.errorUnionPayload(mod);1078 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
1256 if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) {1081 if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) {
1257 // We use the error type directly as the type.1082 // 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) {...@@ -257,7 +257,7 @@ pub fn fmtIdent(ident: []const u8) std.fmt.Formatter(formatIdent) {
257 return .{ .data = ident };257 return .{ .data = ident };
258}258}
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`.
261/// It is not available when generating .h file.261/// It is not available when generating .h file.
262pub const Function = struct {262pub const Function = struct {
263 air: Air,263 air: Air,
...@@ -268,7 +268,7 @@ pub const Function = struct {...@@ -268,7 +268,7 @@ pub const Function = struct {
268 next_block_index: usize = 0,268 next_block_index: usize = 0,
269 object: Object,269 object: Object,
270 lazy_fns: LazyFnMap,270 lazy_fns: LazyFnMap,
271 func: *Module.Fn,271 func_index: Module.Fn.Index,
272 /// All the locals, to be emitted at the top of the function.272 /// All the locals, to be emitted at the top of the function.
273 locals: std.ArrayListUnmanaged(Local) = .{},273 locals: std.ArrayListUnmanaged(Local) = .{},
274 /// Which locals are available for reuse, based on Type.274 /// Which locals are available for reuse, based on Type.
...@@ -549,33 +549,12 @@ pub const DeclGen = struct {...@@ -549,33 +549,12 @@ pub const DeclGen = struct {
549 }549 }
550550
551 // Chase function values in order to be able to reference the original function.551 // Chase function values in order to be able to reference the original function.
552 inline for (.{ .function, .extern_fn }) |tag|552 if (decl.getFunction(mod)) |func| if (func.owner_decl != decl_index)
553 if (decl.val.castTag(tag)) |func|553 return dg.renderDeclValue(writer, ty, val, func.owner_decl, location);
554 if (func.data.owner_decl != decl_index)554 if (decl.getExternFunc(mod)) |extern_func| if (extern_func.decl != decl_index)
555 return dg.renderDeclValue(writer, ty, val, func.data.owner_decl, location);555 return dg.renderDeclValue(writer, ty, val, extern_func.decl, location);
556556
557 if (decl.val.castTag(.variable)) |var_payload|557 if (decl.getVariable(mod)) |variable| try dg.renderFwdDecl(decl_index, variable);
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 }
579558
580 // We shouldn't cast C function pointers as this is UB (when you call559 // We shouldn't cast C function pointers as this is UB (when you call
581 // them). The analysis until now should ensure that the C function560 // them). The analysis until now should ensure that the C function
...@@ -594,125 +573,77 @@ pub const DeclGen = struct {...@@ -594,125 +573,77 @@ pub const DeclGen = struct {
594573
595 /// Renders a "parent" pointer by recursing to the root decl/variable574 /// Renders a "parent" pointer by recursing to the root decl/variable
596 /// that its contents are defined with respect to.575 /// that its contents are defined with respect to.
597 ///
598 /// Used for .elem_ptr, .field_ptr, .opt_payload_ptr, .eu_payload_ptr
599 fn renderParentPtr(576 fn renderParentPtr(
600 dg: *DeclGen,577 dg: *DeclGen,
601 writer: anytype,578 writer: anytype,
602 ptr_val: Value,579 ptr_val: InternPool.Index,
603 ptr_ty: Type,
604 location: ValueRenderLocation,580 location: ValueRenderLocation,
605 ) error{ OutOfMemory, AnalysisFail }!void {581 ) error{ OutOfMemory, AnalysisFail }!void {
606 const mod = dg.module;582 const mod = dg.module;
607583 const ptr_ty = mod.intern_pool.typeOf(ptr_val).toType();
608 if (!ptr_ty.isSlice(mod)) {584 const ptr = mod.intern_pool.indexToKey(ptr_val).ptr;
609 try writer.writeByte('(');585 switch (ptr.addr) {
610 try dg.renderType(writer, ptr_ty);586 .decl, .mut_decl => try dg.renderDeclValue(
611 try writer.writeByte(')');587 writer,
612 }588 ptr_ty,
613 if (ptr_val.ip_index != .none) switch (mod.intern_pool.indexToKey(ptr_val.ip_index)) {589 ptr_val.toValue(),
614 .int => try writer.print("{x}", .{try dg.fmtIntLiteral(Type.usize, ptr_val, .Other)}),590 switch (ptr.addr) {
615 else => unreachable,591 .decl => |decl| decl,
616 };592 .mut_decl => |mut_decl| mut_decl.decl,
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,
623 else => unreachable,593 else => unreachable,
624 };594 },
625 try dg.renderDeclValue(writer, ptr_ty, ptr_val, decl_index, location);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");
626 },607 },
627 .field_ptr => {608 .elem => |elem| {
628 const field_ptr = ptr_val.castTag(.field_ptr).?.data;609 try writer.writeAll("&(");
629610 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);
630 // Ensure complete type definition is visible before accessing fields.615 // Ensure complete type definition is visible before accessing fields.
631 _ = try dg.typeToIndex(field_ptr.container_ty, .complete);616 _ = try dg.typeToIndex(base_ty, .complete);
632617 switch (fieldLocation(base_ty, ptr_ty, @intCast(u32, field.index), mod)) {
633 const container_ptr_ty = try mod.adjustPtrTypeChild(ptr_ty, field_ptr.container_ty);618 .begin => try dg.renderParentPtr(writer, field.base, location),
634619 .field => |name| {
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| {
648 try writer.writeAll("&(");620 try writer.writeAll("&(");
649 try dg.renderParentPtr(621 try dg.renderParentPtr(writer, field.base, location);
650 writer,
651 field_ptr.container_ptr,
652 container_ptr_ty,
653 location,
654 );
655 try writer.writeAll(")->");622 try writer.writeAll(")->");
656 try dg.writeCValue(writer, field);623 try dg.writeCValue(writer, name);
657 },624 },
658 .byte_offset => |byte_offset| {625 .byte_offset => |byte_offset| {
659 const u8_ptr_ty = try mod.adjustPtrTypeChild(ptr_ty, Type.u8);626 const u8_ptr_ty = try mod.adjustPtrTypeChild(ptr_ty, Type.u8);
660
661 const byte_offset_val = try mod.intValue(Type.usize, byte_offset);627 const byte_offset_val = try mod.intValue(Type.usize, byte_offset);
662628
663 try writer.writeAll("((");629 try writer.writeAll("((");
664 try dg.renderType(writer, u8_ptr_ty);630 try dg.renderType(writer, u8_ptr_ty);
665 try writer.writeByte(')');631 try writer.writeByte(')');
666 try dg.renderParentPtr(632 try dg.renderParentPtr(writer, field.base, location);
667 writer,
668 field_ptr.container_ptr,
669 container_ptr_ty,
670 location,
671 );
672 try writer.print(" + {})", .{633 try writer.print(" + {})", .{
673 try dg.fmtIntLiteral(Type.usize, byte_offset_val, .Other),634 try dg.fmtIntLiteral(Type.usize, byte_offset_val, .Other),
674 });635 });
675 },636 },
676 .end => {637 .end => {
677 try writer.writeAll("((");638 try writer.writeAll("((");
678 try dg.renderParentPtr(639 try dg.renderParentPtr(writer, field.base, location);
679 writer,
680 field_ptr.container_ptr,
681 container_ptr_ty,
682 location,
683 );
684 try writer.print(") + {})", .{640 try writer.print(") + {})", .{
685 try dg.fmtIntLiteral(Type.usize, try mod.intValue(Type.usize, 1), .Other),641 try dg.fmtIntLiteral(Type.usize, try mod.intValue(Type.usize, 1), .Other),
686 });642 });
687 },643 },
688 }644 }
689 },645 },
690 .elem_ptr => {646 .comptime_field => unreachable,
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,
716 }647 }
717 }648 }
718649
...@@ -723,11 +654,12 @@ pub const DeclGen = struct {...@@ -723,11 +654,12 @@ pub const DeclGen = struct {
723 arg_val: Value,654 arg_val: Value,
724 location: ValueRenderLocation,655 location: ValueRenderLocation,
725 ) error{ OutOfMemory, AnalysisFail }!void {656 ) error{ OutOfMemory, AnalysisFail }!void {
657 const mod = dg.module;
726 var val = arg_val;658 var val = arg_val;
727 if (val.castTag(.runtime_value)) |rt| {659 switch (mod.intern_pool.indexToKey(val.ip_index)) {
728 val = rt.data;660 .runtime_value => |rt| val = rt.val.toValue(),
661 else => {},
729 }662 }
730 const mod = dg.module;
731 const target = mod.getTarget();663 const target = mod.getTarget();
732 const initializer_type: ValueRenderLocation = switch (location) {664 const initializer_type: ValueRenderLocation = switch (location) {
733 .StaticInitializer => .StaticInitializer,665 .StaticInitializer => .StaticInitializer,
...@@ -928,175 +860,8 @@ pub const DeclGen = struct {...@@ -928,175 +860,8 @@ pub const DeclGen = struct {
928 }860 }
929 unreachable;861 unreachable;
930 }862 }
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) {864 if (val.ip_index == .none) switch (ty.zigTypeTag(mod)) {
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 },
1100 .Array, .Vector => {865 .Array, .Vector => {
1101 if (location == .FunctionArgument) {866 if (location == .FunctionArgument) {
1102 try writer.writeByte('(');867 try writer.writeByte('(');
...@@ -1129,17 +894,6 @@ pub const DeclGen = struct {...@@ -1129,17 +894,6 @@ pub const DeclGen = struct {
1129 return;894 return;
1130 },895 },
1131 .none => switch (val.tag()) {896 .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 },
1143 .bytes, .str_lit => |t| {897 .bytes, .str_lit => |t| {
1144 const bytes = switch (t) {898 const bytes = switch (t) {
1145 .bytes => val.castTag(.bytes).?.data,899 .bytes => val.castTag(.bytes).?.data,
...@@ -1210,91 +964,6 @@ pub const DeclGen = struct {...@@ -1210,91 +964,6 @@ pub const DeclGen = struct {
1210 try writer.writeByte('}');964 try writer.writeByte('}');
1211 }965 }
1212 },966 },
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 },
1298 .Struct => switch (ty.containerLayout(mod)) {967 .Struct => switch (ty.containerLayout(mod)) {
1299 .Auto, .Extern => {968 .Auto, .Extern => {
1300 const field_vals = val.castTag(.aggregate).?.data;969 const field_vals = val.castTag(.aggregate).?.data;
...@@ -1408,7 +1077,448 @@ pub const DeclGen = struct {...@@ -1408,7 +1077,448 @@ pub const DeclGen = struct {
1408 }1077 }
1409 },1078 },
1410 },1079 },
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 => {
1412 const union_obj = val.castTag(.@"union").?.data;1522 const union_obj = val.castTag(.@"union").?.data;
14131523
1414 if (!location.isInitializer()) {1524 if (!location.isInitializer()) {
...@@ -1461,22 +1571,6 @@ pub const DeclGen = struct {...@@ -1461,22 +1571,6 @@ pub const DeclGen = struct {
1461 if (ty.unionTagTypeSafety(mod)) |_| try writer.writeByte('}');1571 if (ty.unionTagTypeSafety(mod)) |_| try writer.writeByte('}');
1462 try writer.writeByte('}');1572 try writer.writeByte('}');
1463 },1573 },
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 }),
1480 }1574 }
1481 }1575 }
14821576
...@@ -1504,8 +1598,7 @@ pub const DeclGen = struct {...@@ -1504,8 +1598,7 @@ pub const DeclGen = struct {
1504 else => unreachable,1598 else => unreachable,
1505 }1599 }
1506 }1600 }
1507 if (fn_decl.val.castTag(.function)) |func_payload|1601 if (fn_decl.getFunction(mod)) |func| if (func.is_cold) try w.writeAll("zig_cold ");
1508 if (func_payload.data.is_cold) try w.writeAll("zig_cold ");
1509 if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn ");1602 if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn ");
15101603
1511 const trailing = try renderTypePrefix(1604 const trailing = try renderTypePrefix(
...@@ -1747,18 +1840,12 @@ pub const DeclGen = struct {...@@ -1747,18 +1840,12 @@ pub const DeclGen = struct {
17471840
1748 fn declIsGlobal(dg: *DeclGen, tv: TypedValue) bool {1841 fn declIsGlobal(dg: *DeclGen, tv: TypedValue) bool {
1749 const mod = dg.module;1842 const mod = dg.module;
1750 switch (tv.val.tag()) {1843 return switch (mod.intern_pool.indexToKey(tv.val.ip_index)) {
1751 .extern_fn => return true,1844 .variable => |variable| mod.decl_exports.contains(variable.decl),
1752 .function => {1845 .extern_func => true,
1753 const func = tv.val.castTag(.function).?.data;1846 .func => |func| mod.decl_exports.contains(mod.funcPtr(func.index).owner_decl),
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 },
1760 else => unreachable,1847 else => unreachable,
1761 }1848 };
1762 }1849 }
17631850
1764 fn writeCValue(dg: *DeclGen, w: anytype, c_value: CValue) !void {1851 fn writeCValue(dg: *DeclGen, w: anytype, c_value: CValue) !void {
...@@ -1833,7 +1920,7 @@ pub const DeclGen = struct {...@@ -1833,7 +1920,7 @@ pub const DeclGen = struct {
1833 try dg.writeCValue(writer, member);1920 try dg.writeCValue(writer, member);
1834 }1921 }
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 {
1837 const decl = dg.module.declPtr(decl_index);1924 const decl = dg.module.declPtr(decl_index);
1838 const fwd_decl_writer = dg.fwd_decl.writer();1925 const fwd_decl_writer = dg.fwd_decl.writer();
1839 const is_global = dg.declIsGlobal(.{ .ty = decl.ty, .val = decl.val }) or variable.is_extern;1926 const is_global = dg.declIsGlobal(.{ .ty = decl.ty, .val = decl.val }) or variable.is_extern;
...@@ -1844,7 +1931,7 @@ pub const DeclGen = struct {...@@ -1844,7 +1931,7 @@ pub const DeclGen = struct {
1844 fwd_decl_writer,1931 fwd_decl_writer,
1845 decl.ty,1932 decl.ty,
1846 .{ .decl = decl_index },1933 .{ .decl = decl_index },
1847 CQualifiers.init(.{ .@"const" = !variable.is_mutable }),1934 CQualifiers.init(.{ .@"const" = variable.is_const }),
1848 decl.@"align",1935 decl.@"align",
1849 .complete,1936 .complete,
1850 );1937 );
...@@ -1858,7 +1945,7 @@ pub const DeclGen = struct {...@@ -1858,7 +1945,7 @@ pub const DeclGen = struct {
18581945
1859 if (mod.decl_exports.get(decl_index)) |exports| {1946 if (mod.decl_exports.get(decl_index)) |exports| {
1860 try writer.writeAll(exports.items[export_index].options.name);1947 try writer.writeAll(exports.items[export_index].options.name);
1861 } else if (decl.isExtern()) {1948 } else if (decl.isExtern(mod)) {
1862 try writer.writeAll(mem.span(decl.name));1949 try writer.writeAll(mem.span(decl.name));
1863 } else {1950 } else {
1864 // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case),1951 // 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 {...@@ -2416,8 +2503,11 @@ pub fn genErrDecls(o: *Object) !void {
2416 var max_name_len: usize = 0;2503 var max_name_len: usize = 0;
2417 for (mod.error_name_list.items, 0..) |name, value| {2504 for (mod.error_name_list.items, 0..) |name, value| {
2418 max_name_len = std.math.max(name.len, max_name_len);2505 max_name_len = std.math.max(name.len, max_name_len);
2419 var err_pl = Value.Payload.Error{ .data = .{ .name = name } };2506 const err_val = try mod.intern(.{ .err = .{
2420 try o.dg.renderValue(writer, Type.anyerror, Value.initPayload(&err_pl.base), .Other);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);
2421 try writer.print(" = {d}u,\n", .{value});2511 try writer.print(" = {d}u,\n", .{value});
2422 }2512 }
2423 o.indent_writer.popIndent();2513 o.indent_writer.popIndent();
...@@ -2451,7 +2541,7 @@ pub fn genErrDecls(o: *Object) !void {...@@ -2451,7 +2541,7 @@ pub fn genErrDecls(o: *Object) !void {
24512541
2452 const name_array_ty = try mod.arrayType(.{2542 const name_array_ty = try mod.arrayType(.{
2453 .len = mod.error_name_list.items.len,2543 .len = mod.error_name_list.items.len,
2454 .child = .const_slice_u8_sentinel_0_type,2544 .child = .slice_const_u8_sentinel_0_type,
2455 .sentinel = .zero_u8,2545 .sentinel = .zero_u8,
2456 });2546 });
24572547
...@@ -2497,7 +2587,7 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void {...@@ -2497,7 +2587,7 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void {
2497 .tag_name => {2587 .tag_name => {
2498 const enum_ty = val.data.tag_name;2588 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
2502 try w.writeAll("static ");2592 try w.writeAll("static ");
2503 try o.dg.renderType(w, name_slice_ty);2593 try o.dg.renderType(w, name_slice_ty);
...@@ -2668,14 +2758,13 @@ pub fn genDecl(o: *Object) !void {...@@ -2668,14 +2758,13 @@ pub fn genDecl(o: *Object) !void {
2668 const tv: TypedValue = .{ .ty = decl.ty, .val = decl.val };2758 const tv: TypedValue = .{ .ty = decl.ty, .val = decl.val };
26692759
2670 if (!tv.ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return;2760 if (!tv.ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return;
2671 if (tv.val.tag() == .extern_fn) {2761 if (decl.getExternFunc(mod)) |_| {
2672 const fwd_decl_writer = o.dg.fwd_decl.writer();2762 const fwd_decl_writer = o.dg.fwd_decl.writer();
2673 try fwd_decl_writer.writeAll("zig_extern ");2763 try fwd_decl_writer.writeAll("zig_extern ");
2674 try o.dg.renderFunctionSignature(fwd_decl_writer, decl_c_value.decl, .forward, .{ .export_index = 0 });2764 try o.dg.renderFunctionSignature(fwd_decl_writer, decl_c_value.decl, .forward, .{ .export_index = 0 });
2675 try fwd_decl_writer.writeAll(";\n");2765 try fwd_decl_writer.writeAll(";\n");
2676 try genExports(o);2766 try genExports(o);
2677 } else if (tv.val.castTag(.variable)) |var_payload| {2767 } else if (decl.getVariable(mod)) |variable| {
2678 const variable: *Module.Var = var_payload.data;
2679 try o.dg.renderFwdDecl(decl_c_value.decl, variable);2768 try o.dg.renderFwdDecl(decl_c_value.decl, variable);
2680 try genExports(o);2769 try genExports(o);
26812770
...@@ -2690,7 +2779,7 @@ pub fn genDecl(o: *Object) !void {...@@ -2690,7 +2779,7 @@ pub fn genDecl(o: *Object) !void {
2690 try o.dg.renderTypeAndName(w, tv.ty, decl_c_value, .{}, decl.@"align", .complete);2779 try o.dg.renderTypeAndName(w, tv.ty, decl_c_value, .{}, decl.@"align", .complete);
2691 if (decl.@"linksection" != null) try w.writeAll(", read, write)");2780 if (decl.@"linksection" != null) try w.writeAll(", read, write)");
2692 try w.writeAll(" = ");2781 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);
2694 try w.writeByte(';');2783 try w.writeByte(';');
2695 try o.indent_writer.insertNewline();2784 try o.indent_writer.insertNewline();
2696 } else {2785 } else {
...@@ -4157,10 +4246,13 @@ fn airCall(...@@ -4157,10 +4246,13 @@ fn airCall(
4157 known: {4246 known: {
4158 const fn_decl = fn_decl: {4247 const fn_decl = fn_decl: {
4159 const callee_val = (try f.air.value(pl_op.operand, mod)) orelse break :known;4248 const callee_val = (try f.air.value(pl_op.operand, mod)) orelse break :known;
4160 break :fn_decl switch (callee_val.tag()) {4249 break :fn_decl switch (mod.intern_pool.indexToKey(callee_val.ip_index)) {
4161 .extern_fn => callee_val.castTag(.extern_fn).?.data.owner_decl,4250 .extern_func => |extern_func| extern_func.decl,
4162 .function => callee_val.castTag(.function).?.data.owner_decl,4251 .func => |func| mod.funcPtr(func.index).owner_decl,
4163 .decl_ref => callee_val.castTag(.decl_ref).?.data,4252 .ptr => |ptr| switch (ptr.addr) {
4253 .decl => |decl| decl,
4254 else => break :known,
4255 },
4164 else => break :known,4256 else => break :known,
4165 };4257 };
4166 };4258 };
...@@ -4231,9 +4323,9 @@ fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4231,9 +4323,9 @@ fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue {
42314323
4232fn airDbgInline(f: *Function, inst: Air.Inst.Index) !CValue {4324fn airDbgInline(f: *Function, inst: Air.Inst.Index) !CValue {
4233 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;4325 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;
4236 const mod = f.object.dg.module;4326 const mod = f.object.dg.module;
4327 const writer = f.object.writer();
4328 const function = f.air.values[ty_pl.payload].getFunction(mod).?;
4237 try writer.print("/* dbg func:{s} */\n", .{mod.declPtr(function.owner_decl).name});4329 try writer.print("/* dbg func:{s} */\n", .{mod.declPtr(function.owner_decl).name});
4238 return .none;4330 return .none;
4239}4331}
...@@ -6634,9 +6726,6 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6634,9 +6726,6 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
6634 try f.writeCValue(writer, accum, .Other);6726 try f.writeCValue(writer, accum, .Other);
6635 try writer.writeAll(" = ");6727 try writer.writeAll(" = ");
66366728
6637 var arena = std.heap.ArenaAllocator.init(f.object.dg.gpa);
6638 defer arena.deinit();
6639
6640 try f.object.dg.renderValue(writer, scalar_ty, switch (reduce.operation) {6729 try f.object.dg.renderValue(writer, scalar_ty, switch (reduce.operation) {
6641 .Or, .Xor, .Add => try mod.intValue(scalar_ty, 0),6730 .Or, .Xor, .Add => try mod.intValue(scalar_ty, 0),
6642 .And => switch (scalar_ty.zigTypeTag(mod)) {6731 .And => switch (scalar_ty.zigTypeTag(mod)) {
...@@ -6654,7 +6743,7 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6654,7 +6743,7 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
6654 },6743 },
6655 .Max => switch (scalar_ty.zigTypeTag(mod)) {6744 .Max => switch (scalar_ty.zigTypeTag(mod)) {
6656 .Bool => try mod.intValue(scalar_ty, 0),6745 .Bool => try mod.intValue(scalar_ty, 0),
6657 .Int => try scalar_ty.minInt(arena.allocator(), mod),6746 .Int => try scalar_ty.minInt(mod),
6658 .Float => try mod.floatValue(scalar_ty, std.math.nan_f128),6747 .Float => try mod.floatValue(scalar_ty, std.math.nan_f128),
6659 else => unreachable,6748 else => unreachable,
6660 },6749 },
src/codegen/llvm.zig+732-876
...@@ -582,7 +582,7 @@ pub const Object = struct {...@@ -582,7 +582,7 @@ pub const Object = struct {
582 llvm_usize_ty,582 llvm_usize_ty,
583 };583 };
584 const llvm_slice_ty = self.context.structType(&type_fields, type_fields.len, .False);584 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;
586 const slice_alignment = slice_ty.abiAlignment(mod);586 const slice_alignment = slice_ty.abiAlignment(mod);
587587
588 const error_name_list = mod.error_name_list.items;588 const error_name_list = mod.error_name_list.items;
...@@ -866,10 +866,11 @@ pub const Object = struct {...@@ -866,10 +866,11 @@ pub const Object = struct {
866 pub fn updateFunc(866 pub fn updateFunc(
867 o: *Object,867 o: *Object,
868 mod: *Module,868 mod: *Module,
869 func: *Module.Fn,869 func_index: Module.Fn.Index,
870 air: Air,870 air: Air,
871 liveness: Liveness,871 liveness: Liveness,
872 ) !void {872 ) !void {
873 const func = mod.funcPtr(func_index);
873 const decl_index = func.owner_decl;874 const decl_index = func.owner_decl;
874 const decl = mod.declPtr(decl_index);875 const decl = mod.declPtr(decl_index);
875 const target = mod.getTarget();876 const target = mod.getTarget();
...@@ -886,7 +887,7 @@ pub const Object = struct {...@@ -886,7 +887,7 @@ pub const Object = struct {
886887
887 const llvm_func = try dg.resolveLlvmFunction(decl_index);888 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| {
890 dg.addFnAttrInt(llvm_func, "alignstack", align_info.alignment);891 dg.addFnAttrInt(llvm_func, "alignstack", align_info.alignment);
891 dg.addFnAttr(llvm_func, "noinline");892 dg.addFnAttr(llvm_func, "noinline");
892 } else {893 } else {
...@@ -1164,7 +1165,7 @@ pub const Object = struct {...@@ -1164,7 +1165,7 @@ pub const Object = struct {
1164 di_file = try dg.object.getDIFile(gpa, mod.namespacePtr(decl.src_namespace).file_scope);1165 di_file = try dg.object.getDIFile(gpa, mod.namespacePtr(decl.src_namespace).file_scope);
11651166
1166 const line_number = decl.src_line + 1;1167 const line_number = decl.src_line + 1;
1167 const is_internal_linkage = decl.val.tag() != .extern_fn and1168 const is_internal_linkage = decl.getExternFunc(mod) == null and
1168 !mod.decl_exports.contains(decl_index);1169 !mod.decl_exports.contains(decl_index);
1169 const noret_bit: c_uint = if (fn_info.return_type == .noreturn_type)1170 const noret_bit: c_uint = if (fn_info.return_type == .noreturn_type)
1170 llvm.DIFlags.NoReturn1171 llvm.DIFlags.NoReturn
...@@ -1269,18 +1270,20 @@ pub const Object = struct {...@@ -1269,18 +1270,20 @@ pub const Object = struct {
1269 // because we call `updateDeclExports` at the end of `updateFunc` and `updateDecl`.1270 // because we call `updateDeclExports` at the end of `updateFunc` and `updateDecl`.
1270 const llvm_global = self.decl_map.get(decl_index) orelse return;1271 const llvm_global = self.decl_map.get(decl_index) orelse return;
1271 const decl = mod.declPtr(decl_index);1272 const decl = mod.declPtr(decl_index);
1272 if (decl.isExtern()) {1273 if (decl.isExtern(mod)) {
1273 const is_wasm_fn = mod.getTarget().isWasm() and try decl.isFunction(mod);1274 var free_decl_name = false;
1274 const mangle_name = is_wasm_fn and1275 const decl_name = decl_name: {
1275 decl.getExternFn().?.lib_name != null and1276 if (mod.getTarget().isWasm() and try decl.isFunction(mod)) {
1276 !std.mem.eql(u8, std.mem.sliceTo(decl.getExternFn().?.lib_name.?, 0), "c");1277 if (mod.intern_pool.stringToSliceUnwrap(decl.getExternFunc(mod).?.lib_name)) |lib_name| {
1277 const decl_name = if (mangle_name) name: {1278 if (!std.mem.eql(u8, lib_name, "c")) {
1278 const tmp = try std.fmt.allocPrintZ(gpa, "{s}|{s}", .{1279 free_decl_name = true;
1279 decl.name, decl.getExternFn().?.lib_name.?,1280 break :decl_name try std.fmt.allocPrintZ(gpa, "{s}|{s}", .{ decl.name, lib_name });
1280 });1281 }
1281 break :name tmp.ptr;1282 }
1282 } else decl.name;1283 }
1283 defer if (mangle_name) gpa.free(std.mem.sliceTo(decl_name, 0));1284 break :decl_name std.mem.span(decl.name);
1285 };
1286 defer if (free_decl_name) gpa.free(decl_name);
12841287
1285 llvm_global.setValueName(decl_name);1288 llvm_global.setValueName(decl_name);
1286 if (self.getLlvmGlobal(decl_name)) |other_global| {1289 if (self.getLlvmGlobal(decl_name)) |other_global| {
...@@ -1303,13 +1306,13 @@ pub const Object = struct {...@@ -1303,13 +1306,13 @@ pub const Object = struct {
1303 di_global.replaceLinkageName(linkage_name);1306 di_global.replaceLinkageName(linkage_name);
1304 }1307 }
1305 }1308 }
1306 if (decl.val.castTag(.variable)) |variable| {1309 if (decl.getVariable(mod)) |variable| {
1307 if (variable.data.is_threadlocal) {1310 if (variable.is_threadlocal) {
1308 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);1311 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);
1309 } else {1312 } else {
1310 llvm_global.setThreadLocalMode(.NotThreadLocal);1313 llvm_global.setThreadLocalMode(.NotThreadLocal);
1311 }1314 }
1312 if (variable.data.is_weak_linkage) {1315 if (variable.is_weak_linkage) {
1313 llvm_global.setLinkage(.ExternalWeak);1316 llvm_global.setLinkage(.ExternalWeak);
1314 }1317 }
1315 }1318 }
...@@ -1345,8 +1348,8 @@ pub const Object = struct {...@@ -1345,8 +1348,8 @@ pub const Object = struct {
1345 defer gpa.free(section_z);1348 defer gpa.free(section_z);
1346 llvm_global.setSection(section_z);1349 llvm_global.setSection(section_z);
1347 }1350 }
1348 if (decl.val.castTag(.variable)) |variable| {1351 if (decl.getVariable(mod)) |variable| {
1349 if (variable.data.is_threadlocal) {1352 if (variable.is_threadlocal) {
1350 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);1353 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);
1351 }1354 }
1352 }1355 }
...@@ -1379,9 +1382,9 @@ pub const Object = struct {...@@ -1379,9 +1382,9 @@ pub const Object = struct {
1379 llvm_global.setLinkage(.Internal);1382 llvm_global.setLinkage(.Internal);
1380 if (mod.wantDllExports()) llvm_global.setDLLStorageClass(.Default);1383 if (mod.wantDllExports()) llvm_global.setDLLStorageClass(.Default);
1381 llvm_global.setUnnamedAddr(.True);1384 llvm_global.setUnnamedAddr(.True);
1382 if (decl.val.castTag(.variable)) |variable| {1385 if (decl.getVariable(mod)) |variable| {
1383 const single_threaded = mod.comp.bin_file.options.single_threaded;1386 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) {
1385 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);1388 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);
1386 } else {1389 } else {
1387 llvm_global.setThreadLocalMode(.NotThreadLocal);1390 llvm_global.setThreadLocalMode(.NotThreadLocal);
...@@ -1510,12 +1513,11 @@ pub const Object = struct {...@@ -1510,12 +1513,11 @@ pub const Object = struct {
1510 for (enum_type.names, 0..) |field_name_ip, i| {1513 for (enum_type.names, 0..) |field_name_ip, i| {
1511 const field_name_z = ip.stringToSlice(field_name_ip);1514 const field_name_z = ip.stringToSlice(field_name_ip);
15121515
1513 var bigint_space: InternPool.Key.Int.Storage.BigIntSpace = undefined;1516 var bigint_space: Value.BigIntSpace = undefined;
1514 const storage = if (enum_type.values.len != 0)1517 const bigint = if (enum_type.values.len != 0)
1515 ip.indexToKey(enum_type.values[i]).int.storage1518 enum_type.values[i].toValue().toBigInt(&bigint_space, mod)
1516 else1519 else
1517 InternPool.Key.Int.Storage{ .u64 = i };1520 std.math.big.int.Mutable.init(&bigint_space.limbs, i).toConst();
1518 const bigint = storage.toBigInt(&bigint_space);
15191521
1520 if (bigint.limbs.len == 1) {1522 if (bigint.limbs.len == 1) {
1521 enumerators[i] = dib.createEnumerator(field_name_z, bigint.limbs[0], int_info.signedness == .unsigned);1523 enumerators[i] = dib.createEnumerator(field_name_z, bigint.limbs[0], int_info.signedness == .unsigned);
...@@ -2442,6 +2444,7 @@ pub const DeclGen = struct {...@@ -2442,6 +2444,7 @@ pub const DeclGen = struct {
2442 }2444 }
24432445
2444 fn genDecl(dg: *DeclGen) !void {2446 fn genDecl(dg: *DeclGen) !void {
2447 const mod = dg.module;
2445 const decl = dg.decl;2448 const decl = dg.decl;
2446 const decl_index = dg.decl_index;2449 const decl_index = dg.decl_index;
2447 assert(decl.has_tv);2450 assert(decl.has_tv);
...@@ -2449,19 +2452,16 @@ pub const DeclGen = struct {...@@ -2449,19 +2452,16 @@ pub const DeclGen = struct {
2449 log.debug("gen: {s} type: {}, value: {}", .{2452 log.debug("gen: {s} type: {}, value: {}", .{
2450 decl.name, decl.ty.fmtDebug(), decl.val.fmtDebug(),2453 decl.name, decl.ty.fmtDebug(), decl.val.fmtDebug(),
2451 });2454 });
2452 assert(decl.val.ip_index != .none or decl.val.tag() != .function);2455 if (decl.getExternFunc(mod)) |extern_func| {
2453 if (decl.val.castTag(.extern_fn)) |extern_fn| {2456 _ = try dg.resolveLlvmFunction(extern_func.decl);
2454 _ = try dg.resolveLlvmFunction(extern_fn.data.owner_decl);
2455 } else {2457 } else {
2456 const mod = dg.module;
2457 const target = mod.getTarget();2458 const target = mod.getTarget();
2458 var global = try dg.resolveGlobalDecl(decl_index);2459 var global = try dg.resolveGlobalDecl(decl_index);
2459 global.setAlignment(decl.getAlignment(mod));2460 global.setAlignment(decl.getAlignment(mod));
2460 if (decl.@"linksection") |section| global.setSection(section);2461 if (decl.@"linksection") |section| global.setSection(section);
2461 assert(decl.has_tv);2462 assert(decl.has_tv);
2462 const init_val = if (decl.val.castTag(.variable)) |payload| init_val: {2463 const init_val = if (decl.getVariable(mod)) |variable| init_val: {
2463 const variable = payload.data;2464 break :init_val variable.init.toValue();
2464 break :init_val variable.init;
2465 } else init_val: {2465 } else init_val: {
2466 global.setGlobalConstant(.True);2466 global.setGlobalConstant(.True);
2467 break :init_val decl.val;2467 break :init_val decl.val;
...@@ -2519,7 +2519,7 @@ pub const DeclGen = struct {...@@ -2519,7 +2519,7 @@ pub const DeclGen = struct {
2519 );2519 );
25202520
2521 try dg.object.di_map.put(dg.gpa, dg.decl, di_global.getVariable().toNode());2521 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);
2523 }2523 }
2524 }2524 }
2525 }2525 }
...@@ -2548,17 +2548,16 @@ pub const DeclGen = struct {...@@ -2548,17 +2548,16 @@ pub const DeclGen = struct {
2548 const llvm_fn = dg.llvmModule().addFunctionInAddressSpace(fqn, fn_type, llvm_addrspace);2548 const llvm_fn = dg.llvmModule().addFunctionInAddressSpace(fqn, fn_type, llvm_addrspace);
2549 gop.value_ptr.* = llvm_fn;2549 gop.value_ptr.* = llvm_fn;
25502550
2551 const is_extern = decl.isExtern();2551 const is_extern = decl.isExtern(mod);
2552 if (!is_extern) {2552 if (!is_extern) {
2553 llvm_fn.setLinkage(.Internal);2553 llvm_fn.setLinkage(.Internal);
2554 llvm_fn.setUnnamedAddr(.True);2554 llvm_fn.setUnnamedAddr(.True);
2555 } else {2555 } else {
2556 if (target.isWasm()) {2556 if (target.isWasm()) {
2557 dg.addFnAttrString(llvm_fn, "wasm-import-name", std.mem.sliceTo(decl.name, 0));2557 dg.addFnAttrString(llvm_fn, "wasm-import-name", std.mem.sliceTo(decl.name, 0));
2558 if (decl.getExternFn().?.lib_name) |lib_name| {2558 if (mod.intern_pool.stringToSliceUnwrap(decl.getExternFunc(mod).?.lib_name)) |lib_name| {
2559 const module_name = std.mem.sliceTo(lib_name, 0);2559 if (!std.mem.eql(u8, lib_name, "c")) {
2560 if (!std.mem.eql(u8, module_name, "c")) {2560 dg.addFnAttrString(llvm_fn, "wasm-import-module", lib_name);
2561 dg.addFnAttrString(llvm_fn, "wasm-import-module", module_name);
2562 }2561 }
2563 }2562 }
2564 }2563 }
...@@ -2695,11 +2694,12 @@ pub const DeclGen = struct {...@@ -2695,11 +2694,12 @@ pub const DeclGen = struct {
2695 if (gop.found_existing) return gop.value_ptr.*;2694 if (gop.found_existing) return gop.value_ptr.*;
2696 errdefer assert(dg.object.decl_map.remove(decl_index));2695 errdefer assert(dg.object.decl_map.remove(decl_index));
26972696
2698 const decl = dg.module.declPtr(decl_index);2697 const mod = dg.module;
2699 const fqn = try decl.getFullyQualifiedName(dg.module);2698 const decl = mod.declPtr(decl_index);
2699 const fqn = try decl.getFullyQualifiedName(mod);
2700 defer dg.gpa.free(fqn);2700 defer dg.gpa.free(fqn);
27012701
2702 const target = dg.module.getTarget();2702 const target = mod.getTarget();
27032703
2704 const llvm_type = try dg.lowerType(decl.ty);2704 const llvm_type = try dg.lowerType(decl.ty);
2705 const llvm_actual_addrspace = toLlvmGlobalAddressSpace(decl.@"addrspace", target);2705 const llvm_actual_addrspace = toLlvmGlobalAddressSpace(decl.@"addrspace", target);
...@@ -2712,18 +2712,18 @@ pub const DeclGen = struct {...@@ -2712,18 +2712,18 @@ pub const DeclGen = struct {
2712 gop.value_ptr.* = llvm_global;2712 gop.value_ptr.* = llvm_global;
27132713
2714 // This is needed for declarations created by `@extern`.2714 // This is needed for declarations created by `@extern`.
2715 if (decl.isExtern()) {2715 if (decl.isExtern(mod)) {
2716 llvm_global.setValueName(decl.name);2716 llvm_global.setValueName(decl.name);
2717 llvm_global.setUnnamedAddr(.False);2717 llvm_global.setUnnamedAddr(.False);
2718 llvm_global.setLinkage(.External);2718 llvm_global.setLinkage(.External);
2719 if (decl.val.castTag(.variable)) |variable| {2719 if (decl.getVariable(mod)) |variable| {
2720 const single_threaded = dg.module.comp.bin_file.options.single_threaded;2720 const single_threaded = mod.comp.bin_file.options.single_threaded;
2721 if (variable.data.is_threadlocal and !single_threaded) {2721 if (variable.is_threadlocal and !single_threaded) {
2722 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);2722 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);
2723 } else {2723 } else {
2724 llvm_global.setThreadLocalMode(.NotThreadLocal);2724 llvm_global.setThreadLocalMode(.NotThreadLocal);
2725 }2725 }
2726 if (variable.data.is_weak_linkage) llvm_global.setLinkage(.ExternalWeak);2726 if (variable.is_weak_linkage) llvm_global.setLinkage(.ExternalWeak);
2727 }2727 }
2728 } else {2728 } else {
2729 llvm_global.setLinkage(.Internal);2729 llvm_global.setLinkage(.Internal);
...@@ -3199,468 +3199,344 @@ pub const DeclGen = struct {...@@ -3199,468 +3199,344 @@ pub const DeclGen = struct {
3199 const mod = dg.module;3199 const mod = dg.module;
3200 const target = mod.getTarget();3200 const target = mod.getTarget();
3201 var tv = arg_tv;3201 var tv = arg_tv;
3202 if (tv.val.castTag(.runtime_value)) |rt| {3202 switch (mod.intern_pool.indexToKey(tv.val.ip_index)) {
3203 tv.val = rt.data;3203 .runtime_value => |rt| tv.val = rt.val.toValue(),
3204 else => {},
3204 }3205 }
3205 if (tv.val.isUndef(mod)) {3206 if (tv.val.isUndefDeep(mod)) {
3206 const llvm_type = try dg.lowerType(tv.ty);3207 const llvm_type = try dg.lowerType(tv.ty);
3207 return llvm_type.getUndef();3208 return llvm_type.getUndef();
3208 }3209 }
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;3211 if (tv.val.ip_index == .none) switch (tv.ty.zigTypeTag(mod)) {
3237 const bigint = int_val.toBigInt(&bigint_space, mod);3212 .Array => switch (tv.val.tag()) {
32383213 .bytes => {
3239 const int_info = tv.ty.intInfo(mod);3214 const bytes = tv.val.castTag(.bytes).?.data;
3240 const llvm_type = dg.context.intType(int_info.bits);3215 return dg.context.constString(
32413216 bytes.ptr,
3242 const unsigned_val = v: {3217 @intCast(c_uint, tv.ty.arrayLenIncludingSentinel(mod)),
3243 if (bigint.limbs.len == 1) {3218 .True, // Don't null terminate. Bytes has the sentinel, if any.
3244 break :v llvm_type.constInt(bigint.limbs[0], .False);3219 );
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,
3403 },3220 },
3404 },3221 .str_lit => {
3405 .Array => switch (tv.val.ip_index) {3222 const str_lit = tv.val.castTag(.str_lit).?.data;
3406 .none => switch (tv.val.tag()) {3223 const bytes = dg.module.string_literal_bytes.items[str_lit.index..][0..str_lit.len];
3407 .bytes => {3224 if (tv.ty.sentinel(mod)) |sent_val| {
3408 const bytes = tv.val.castTag(.bytes).?.data;3225 const byte = @intCast(u8, sent_val.toUnsignedInt(mod));
3409 return dg.context.constString(3226 if (byte == 0 and bytes.len > 0) {
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 {
3438 return dg.context.constString(3227 return dg.context.constString(
3439 bytes.ptr,3228 bytes.ptr,
3440 @intCast(c_uint, bytes.len),3229 @intCast(c_uint, bytes.len),
3441 .True, // Don't null terminate. `bytes` has the sentinel, if any.3230 .False, // Yes, null terminate.
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),
3468 );3231 );
3469 }3232 }
3470 },3233 var array = std.ArrayList(u8).init(dg.gpa);
3471 .repeated => {3234 defer array.deinit();
3472 const val = tv.val.castTag(.repeated).?.data;3235 try array.ensureUnusedCapacity(bytes.len + 1);
3473 const elem_ty = tv.ty.childType(mod);3236 array.appendSliceAssumeCapacity(bytes);
3474 const sentinel = tv.ty.sentinel(mod);3237 array.appendAssumeCapacity(byte);
3475 const len = @intCast(usize, tv.ty.arrayLen(mod));3238 return dg.context.constString(
3476 const len_including_sent = len + @boolToInt(sentinel != null);3239 array.items.ptr,
3477 const gpa = dg.gpa;3240 @intCast(c_uint, array.items.len),
3478 const llvm_elems = try gpa.alloc(*llvm.Value, len_including_sent);3241 .True, // Don't null terminate.
3479 defer gpa.free(llvm_elems);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;
3481 var need_unnamed = false;3267 var need_unnamed = false;
3482 if (len != 0) {3268
3483 for (llvm_elems[0..len]) |*elem| {3269 for (tuple.types, tuple.values, 0..) |field_ty, field_val, i| {
3484 elem.* = try dg.lowerValue(.{ .ty = elem_ty, .val = val });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());
3485 }3284 }
3486 need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[0]);
3487 }
34883285
3489 if (sentinel) |sent| {3286 const field_llvm_val = try dg.lowerValue(.{
3490 llvm_elems[len] = try dg.lowerValue(.{ .ty = elem_ty, .val = sent });3287 .ty = field_ty.toType(),
3491 need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[len]);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 }
3492 }3305 }
34933306
3494 if (need_unnamed) {3307 if (need_unnamed) {
3495 return dg.context.constStruct(3308 return dg.context.constStruct(
3496 llvm_elems.ptr,3309 llvm_fields.items.ptr,
3497 @intCast(c_uint, llvm_elems.len),3310 @intCast(c_uint, llvm_fields.items.len),
3498 .True,3311 .False,
3499 );3312 );
3500 } else {3313 } else {
3501 const llvm_elem_ty = try dg.lowerType(elem_ty);3314 return llvm_struct_ty.constNamedStruct(
3502 return llvm_elem_ty.constArray(3315 llvm_fields.items.ptr,
3503 llvm_elems.ptr,3316 @intCast(c_uint, llvm_fields.items.len),
3504 @intCast(c_uint, llvm_elems.len),
3505 );3317 );
3506 }3318 }
3507 },3319 },
3508 .empty_array_sentinel => {3320 .struct_type => |struct_type| struct_type,
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 },
3521 else => unreachable,3321 else => unreachable,
3522 },3322 };
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);
35573323
3558 var need_unnamed = false;3324 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
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 }
35653325
3566 if (sentinel) |sent| {3326 if (struct_obj.layout == .Packed) {
3567 llvm_elems[len] = try dg.lowerValue(.{ .ty = elem_ty, .val = sent });3327 assert(struct_obj.haveLayout());
3568 need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[len]);3328 const big_bits = struct_obj.backing_int_ty.bitSize(mod);
3569 }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) {3337 const non_int_val = try dg.lowerValue(.{
3572 return dg.context.constStruct(3338 .ty = field.ty,
3573 llvm_elems.ptr,3339 .val = try tv.val.fieldValue(mod, i),
3574 @intCast(c_uint, llvm_elems.len),3340 });
3575 .True,3341 const ty_bit_size = @intCast(u16, field.ty.bitSize(mod));
3576 );3342 const small_int_ty = dg.context.intType(ty_bit_size);
3577 } else {3343 const small_int_val = if (field.ty.isPtrAtRuntime(mod))
3578 const llvm_elem_ty = try dg.lowerType(elem_ty);3344 non_int_val.constPtrToInt(small_int_ty)
3579 return llvm_elem_ty.constArray(3345 else
3580 llvm_elems.ptr,3346 non_int_val.constBitCast(small_int_ty);
3581 @intCast(c_uint, llvm_elems.len),3347 const shift_rhs = int_llvm_ty.constInt(running_bits, .False);
3582 );3348 // If the field is as large as the entire packed struct, this
3583 }3349 // zext would go from, e.g. i16 to i16. This is legal with
3584 },3350 // constZExtOrBitCast but not legal with constZExt.
3585 },3351 const extended_int_val = small_int_val.constZExtOrBitCast(int_llvm_ty);
3586 else => unreachable,3352 const shifted = extended_int_val.constShl(shift_rhs);
3587 },3353 running_int = running_int.constOr(shifted);
3588 },3354 running_bits += ty_bit_size;
3589 .Optional => {3355 }
3590 comptime assert(optional_layout_version == 3);3356 return running_int;
3591 const payload_ty = tv.ty.optionalChild(mod);3357 }
35923358
3593 const llvm_i8 = dg.context.intType(8);3359 const llvm_field_count = llvm_struct_ty.countStructElementTypes();
3594 const is_pl = !tv.val.isNull(mod);3360 var llvm_fields = try std.ArrayListUnmanaged(*llvm.Value).initCapacity(gpa, llvm_field_count);
3595 const non_null_bit = if (is_pl) llvm_i8.constInt(1, .False) else llvm_i8.constNull();3361 defer llvm_fields.deinit(gpa);
3596 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {3362
3597 return non_null_bit;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 }
3598 }3403 }
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();3405 if (need_unnamed) {
3619 var fields_buf: [3]*llvm.Value = undefined;3406 return dg.context.constStruct(
3620 fields_buf[0] = try dg.lowerValue(.{3407 llvm_fields.items.ptr,
3621 .ty = payload_ty,3408 @intCast(c_uint, llvm_fields.items.len),
3622 .val = if (tv.val.castTag(.opt_payload)) |pl| pl.data else Value.undef,3409 .False,
3623 });3410 );
3624 fields_buf[1] = non_null_bit;3411 } else {
3625 if (llvm_field_count > 2) {3412 return llvm_struct_ty.constNamedStruct(
3626 assert(llvm_field_count == 3);3413 llvm_fields.items.ptr,
3627 fields_buf[2] = llvm_ty.structGetTypeAtIndex(2).getUndef();3414 @intCast(c_uint, llvm_fields.items.len),
3415 );
3628 }3416 }
3629 return dg.context.constStruct(&fields_buf, llvm_field_count, .False);
3630 },3417 },
3631 .Fn => {3418 .Vector => switch (tv.val.tag()) {
3632 const fn_decl_index = switch (tv.val.tag()) {3419 .bytes => {
3633 .extern_fn => tv.val.castTag(.extern_fn).?.data.owner_decl,3420 // Note, sentinel is not stored even if the type has a sentinel.
3634 .function => tv.val.castTag(.function).?.data.owner_decl,3421 const bytes = tv.val.castTag(.bytes).?.data;
3635 else => unreachable,3422 const vector_len = @intCast(usize, tv.ty.arrayLen(mod));
3636 };3423 assert(vector_len == bytes.len or vector_len + 1 == bytes.len);
3637 const fn_decl = dg.module.declPtr(fn_decl_index);3424
3638 dg.module.markDeclAlive(fn_decl);3425 const elem_ty = tv.ty.childType(mod);
3639 return dg.resolveLlvmFunction(fn_decl_index);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,
3640 },3461 },
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| {
3642 const llvm_ty = try dg.lowerType(Type.anyerror);3532 const llvm_ty = try dg.lowerType(Type.anyerror);
3643 switch (tv.val.ip_index) {3533 const name = mod.intern_pool.stringToSlice(err.name);
3644 .none => switch (tv.val.tag()) {3534 const kv = try mod.getErrorValue(name);
3645 .@"error" => {3535 return llvm_ty.constInt(kv.value, .False);
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 }
3660 },3536 },
3661 .ErrorUnion => {3537 .error_union => |error_union| {
3662 const payload_type = tv.ty.errorUnionPayload(mod);3538 const payload_type = tv.ty.errorUnionPayload(mod);
3663 const is_pl = tv.val.errorUnionIsPayload();3539 const is_pl = tv.val.errorUnionIsPayload(mod);
36643540
3665 if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) {3541 if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) {
3666 // We use the error type directly as the type.3542 // We use the error type directly as the type.
...@@ -3676,7 +3552,10 @@ pub const DeclGen = struct {...@@ -3676,7 +3552,10 @@ pub const DeclGen = struct {
3676 });3552 });
3677 const llvm_payload_value = try dg.lowerValue(.{3553 const llvm_payload_value = try dg.lowerValue(.{
3678 .ty = payload_type,3554 .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(),
3680 });3559 });
3681 var fields_buf: [3]*llvm.Value = undefined;3560 var fields_buf: [3]*llvm.Value = undefined;
36823561
...@@ -3697,172 +3576,396 @@ pub const DeclGen = struct {...@@ -3697,172 +3576,396 @@ pub const DeclGen = struct {
3697 return dg.context.constStruct(&fields_buf, llvm_field_count, .False);3576 return dg.context.constStruct(&fields_buf, llvm_field_count, .False);
3698 }3577 }
3699 },3578 },
3700 .Struct => {3579 .enum_tag => {
3701 const llvm_struct_ty = try dg.lowerType(tv.ty);3580 const int_val = try tv.enumToInt(mod);
3702 const gpa = dg.gpa;
37033581
3704 const struct_type = switch (mod.intern_pool.indexToKey(tv.ty.ip_index)) {3582 var bigint_space: Value.BigIntSpace = undefined;
3705 .anon_struct_type => |tuple| {3583 const bigint = int_val.toBigInt(&bigint_space, mod);
3706 var llvm_fields: std.ArrayListUnmanaged(*llvm.Value) = .{};
3707 defer llvm_fields.deinit(gpa);
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);3588 const unsigned_val = v: {
3712 var offset: u64 = 0;3589 if (bigint.limbs.len == 1) {
3713 var big_align: u32 = 0;3590 break :v llvm_type.constInt(bigint.limbs[0], .False);
3714 var need_unnamed = 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| {3683 const llvm_i8 = dg.context.intType(8);
3717 if (field_val != .none) continue;3684 const non_null_bit = switch (opt.val) {
3718 if (!field_ty.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;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);3698 const llvm_field_count = llvm_ty.countStructElementTypes();
3721 big_align = @max(big_align, field_align);3699 var fields_buf: [3]*llvm.Value = undefined;
3722 const prev_offset = offset;3700 fields_buf[0] = try dg.lowerValue(.{
3723 offset = std.mem.alignForwardGeneric(u64, offset, field_align);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;3754 var need_unnamed = false;
3726 if (padding_len > 0) {3755 if (len != 0) {
3727 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));3756 for (llvm_elems[0..len]) |*elem| {
3728 // TODO make this and all other padding elsewhere in debug3757 elem.* = try dg.lowerValue(.{ .ty = elem_ty, .val = val.toValue() });
3729 // builds be 0xaa not undef.
3730 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());
3731 }3758 }
3759 need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[0]);
3760 }
37323761
3733 const field_llvm_val = try dg.lowerValue(.{3762 if (sentinel) |sent| {
3734 .ty = field_ty.toType(),3763 llvm_elems[len] = try dg.lowerValue(.{ .ty = elem_ty, .val = sent });
3735 .val = try tv.val.fieldValue(field_ty.toType(), mod, i),3764 need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[len]);
3736 });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);3810 try llvm_fields.ensureUnusedCapacity(gpa, tuple.types.len);
3743 }3811
3744 {3812 comptime assert(struct_layout_version == 2);
3745 const prev_offset = offset;3813 var offset: u64 = 0;
3746 offset = std.mem.alignForwardGeneric(u64, offset, big_align);3814 var big_align: u32 = 0;
3747 const padding_len = offset - prev_offset;3815 var need_unnamed = false;
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 }
37533816
3754 if (need_unnamed) {3817 for (tuple.types, tuple.values, 0..) |field_ty, field_val, i| {
3755 return dg.context.constStruct(3818 if (field_val != .none) continue;
3756 llvm_fields.items.ptr,3819 if (!field_ty.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
3757 @intCast(c_uint, llvm_fields.items.len),3820
3758 .False,3821 const field_align = field_ty.toType().abiAlignment(mod);
3759 );3822 big_align = @max(big_align, field_align);
3760 } else {3823 const prev_offset = offset;
3761 return llvm_struct_ty.constNamedStruct(3824 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
3762 llvm_fields.items.ptr,3825
3763 @intCast(c_uint, llvm_fields.items.len),3826 const padding_len = offset - prev_offset;
3764 );3827 if (padding_len > 0) {
3765 }3828 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
3766 },3829 // TODO make this and all other padding elsewhere in debug
3767 .struct_type => |struct_type| struct_type,3830 // builds be 0xaa not undef.
3768 else => unreachable,3831 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());
3769 };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) {3839 need_unnamed = need_unnamed or dg.isUnnamedType(field_ty.toType(), field_llvm_val);
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;
37833840
3784 const non_int_val = try dg.lowerValue(.{3841 llvm_fields.appendAssumeCapacity(field_llvm_val);
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 }
38053842
3806 const llvm_field_count = llvm_struct_ty.countStructElementTypes();3843 offset += field_ty.toType().abiSize(mod);
3807 var llvm_fields = try std.ArrayListUnmanaged(*llvm.Value).initCapacity(gpa, llvm_field_count);3844 }
3808 defer llvm_fields.deinit(gpa);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);3855 if (need_unnamed) {
3811 var offset: u64 = 0;3856 return dg.context.constStruct(
3812 var big_align: u32 = 0;3857 llvm_fields.items.ptr,
3813 var need_unnamed = false;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);3872 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
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);
38223873
3823 const padding_len = offset - prev_offset;3874 if (struct_obj.layout == .Packed) {
3824 if (padding_len > 0) {3875 assert(struct_obj.haveLayout());
3825 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));3876 const big_bits = struct_obj.backing_int_ty.bitSize(mod);
3826 // TODO make this and all other padding elsewhere in debug3877 const int_llvm_ty = dg.context.intType(@intCast(c_uint, big_bits));
3827 // builds be 0xaa not undef.3878 const fields = struct_obj.fields.values();
3828 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());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;
3829 }3905 }
38303906
3831 const field_llvm_val = try dg.lowerValue(.{3907 const llvm_field_count = llvm_struct_ty.countStructElementTypes();
3832 .ty = field.ty,3908 var llvm_fields = try std.ArrayListUnmanaged(*llvm.Value).initCapacity(gpa, llvm_field_count);
3833 .val = try tv.val.fieldValue(field.ty, mod, field_and_index.index),3909 defer llvm_fields.deinit(gpa);
3834 });
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);3937 need_unnamed = need_unnamed or dg.isUnnamedType(field.ty, field_llvm_val);
3841 }3938
3842 {3939 llvm_fields.appendAssumeCapacity(field_llvm_val);
3843 const prev_offset = offset;3940
3844 offset = std.mem.alignForwardGeneric(u64, offset, big_align);3941 offset += field.ty.abiSize(mod);
3845 const padding_len = offset - prev_offset;3942 }
3846 if (padding_len > 0) {3943 {
3847 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));3944 const prev_offset = offset;
3848 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());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 }
3849 }3951 }
3850 }
38513952
3852 if (need_unnamed) {3953 if (need_unnamed) {
3853 return dg.context.constStruct(3954 return dg.context.constStruct(
3854 llvm_fields.items.ptr,3955 llvm_fields.items.ptr,
3855 @intCast(c_uint, llvm_fields.items.len),3956 @intCast(c_uint, llvm_fields.items.len),
3856 .False,3957 .False,
3857 );3958 );
3858 } else {3959 } else {
3859 return llvm_struct_ty.constNamedStruct(3960 return llvm_struct_ty.constNamedStruct(
3860 llvm_fields.items.ptr,3961 llvm_fields.items.ptr,
3861 @intCast(c_uint, llvm_fields.items.len),3962 @intCast(c_uint, llvm_fields.items.len),
3862 );3963 );
3863 }3964 }
3965 },
3966 else => unreachable,
3864 },3967 },
3865 .Union => {3968 .un => {
3866 const llvm_union_ty = try dg.lowerType(tv.ty);3969 const llvm_union_ty = try dg.lowerType(tv.ty);
3867 const tag_and_val: Value.Payload.Union.Data = switch (tv.val.ip_index) {3970 const tag_and_val: Value.Payload.Union.Data = switch (tv.val.ip_index) {
3868 .none => tv.val.castTag(.@"union").?.data,3971 .none => tv.val.castTag(.@"union").?.data,
...@@ -3950,96 +4053,6 @@ pub const DeclGen = struct {...@@ -3950,96 +4053,6 @@ pub const DeclGen = struct {
3950 return llvm_union_ty.constNamedStruct(&fields, fields_len);4053 return llvm_union_ty.constNamedStruct(&fields, fields_len);
3951 }4054 }
3952 },4055 },
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()}),
4043 }4056 }
4044 }4057 }
40454058
...@@ -4094,10 +4107,9 @@ pub const DeclGen = struct {...@@ -4094,10 +4107,9 @@ pub const DeclGen = struct {
4094 fn lowerParentPtr(dg: *DeclGen, ptr_val: Value, byte_aligned: bool) Error!*llvm.Value {4107 fn lowerParentPtr(dg: *DeclGen, ptr_val: Value, byte_aligned: bool) Error!*llvm.Value {
4095 const mod = dg.module;4108 const mod = dg.module;
4096 const target = mod.getTarget();4109 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)) {
4098 .int => |int| dg.lowerIntAsPtr(int),4111 .int => |int| dg.lowerIntAsPtr(int),
4099 .ptr => |ptr| switch (ptr.addr) {4112 .ptr => |ptr| switch (ptr.addr) {
4100 .@"var" => |@"var"| dg.lowerParentPtrDecl(ptr_val, @"var".owner_decl),
4101 .decl => |decl| dg.lowerParentPtrDecl(ptr_val, decl),4113 .decl => |decl| dg.lowerParentPtrDecl(ptr_val, decl),
4102 .mut_decl => |mut_decl| dg.lowerParentPtrDecl(ptr_val, mut_decl.decl),4114 .mut_decl => |mut_decl| dg.lowerParentPtrDecl(ptr_val, mut_decl.decl),
4103 .int => |int| dg.lowerIntAsPtr(mod.intern_pool.indexToKey(int).int),4115 .int => |int| dg.lowerIntAsPtr(mod.intern_pool.indexToKey(int).int),
...@@ -4150,7 +4162,7 @@ pub const DeclGen = struct {...@@ -4150,7 +4162,7 @@ pub const DeclGen = struct {
4150 const indices: [1]*llvm.Value = .{4162 const indices: [1]*llvm.Value = .{
4151 llvm_usize.constInt(elem_ptr.index, .False),4163 llvm_usize.constInt(elem_ptr.index, .False),
4152 };4164 };
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));
4154 return elem_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);4166 return elem_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
4155 },4167 },
4156 .field => |field_ptr| {4168 .field => |field_ptr| {
...@@ -4185,7 +4197,7 @@ pub const DeclGen = struct {...@@ -4185,7 +4197,7 @@ pub const DeclGen = struct {
4185 .Struct => {4197 .Struct => {
4186 if (parent_ty.containerLayout(mod) == .Packed) {4198 if (parent_ty.containerLayout(mod) == .Packed) {
4187 if (!byte_aligned) return parent_llvm_ptr;4199 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());
4189 const base_addr = parent_llvm_ptr.constPtrToInt(llvm_usize);4201 const base_addr = parent_llvm_ptr.constPtrToInt(llvm_usize);
4190 // count bits of fields before this one4202 // count bits of fields before this one
4191 const prev_bits = b: {4203 const prev_bits = b: {
...@@ -4230,148 +4242,6 @@ pub const DeclGen = struct {...@@ -4230,148 +4242,6 @@ pub const DeclGen = struct {
4230 },4242 },
4231 else => unreachable,4243 else => unreachable,
4232 };4244 };
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 }
4375 }4245 }
43764246
4377 fn lowerDeclRefValue(4247 fn lowerDeclRefValue(
...@@ -4380,20 +4250,6 @@ pub const DeclGen = struct {...@@ -4380,20 +4250,6 @@ pub const DeclGen = struct {
4380 decl_index: Module.Decl.Index,4250 decl_index: Module.Decl.Index,
4381 ) Error!*llvm.Value {4251 ) Error!*llvm.Value {
4382 const mod = self.module;4252 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
4398 // In the case of something like:4254 // In the case of something like:
4399 // fn foo() void {}4255 // fn foo() void {}
...@@ -4401,13 +4257,13 @@ pub const DeclGen = struct {...@@ -4401,13 +4257,13 @@ pub const DeclGen = struct {
4401 // ... &bar;4257 // ... &bar;
4402 // `bar` is just an alias and we actually want to lower a reference to `foo`.4258 // `bar` is just an alias and we actually want to lower a reference to `foo`.
4403 const decl = mod.declPtr(decl_index);4259 const decl = mod.declPtr(decl_index);
4404 if (decl.val.castTag(.function)) |func| {4260 if (decl.getFunction(mod)) |func| {
4405 if (func.data.owner_decl != decl_index) {4261 if (func.owner_decl != decl_index) {
4406 return self.lowerDeclRefValue(tv, func.data.owner_decl);4262 return self.lowerDeclRefValue(tv, func.owner_decl);
4407 }4263 }
4408 } else if (decl.val.castTag(.extern_fn)) |func| {4264 } else if (decl.getExternFunc(mod)) |func| {
4409 if (func.data.owner_decl != decl_index) {4265 if (func.decl != decl_index) {
4410 return self.lowerDeclRefValue(tv, func.data.owner_decl);4266 return self.lowerDeclRefValue(tv, func.decl);
4411 }4267 }
4412 }4268 }
44134269
...@@ -6333,11 +6189,11 @@ pub const FuncGen = struct {...@@ -6333,11 +6189,11 @@ pub const FuncGen = struct {
6333 }6189 }
63346190
6335 fn airDbgInlineBegin(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {6191 fn airDbgInlineBegin(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6336 const mod = self.dg.module;
6337 const dib = self.dg.object.di_builder orelse return null;6192 const dib = self.dg.object.di_builder orelse return null;
6338 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;6193 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).?;
6341 const decl_index = func.owner_decl;6197 const decl_index = func.owner_decl;
6342 const decl = mod.declPtr(decl_index);6198 const decl = mod.declPtr(decl_index);
6343 const di_file = try self.dg.object.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope);6199 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 {...@@ -6395,8 +6251,8 @@ pub const FuncGen = struct {
6395 if (self.dg.object.di_builder == null) return null;6251 if (self.dg.object.di_builder == null) return null;
6396 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;6252 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
63976253
6398 const func = self.air.values[ty_pl.payload].castTag(.function).?.data;
6399 const mod = self.dg.module;6254 const mod = self.dg.module;
6255 const func = self.air.values[ty_pl.payload].getFunction(mod).?;
6400 const decl = mod.declPtr(func.owner_decl);6256 const decl = mod.declPtr(func.owner_decl);
6401 const di_file = try self.dg.object.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope);6257 const di_file = try self.dg.object.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope);
6402 self.di_file = di_file;6258 self.di_file = di_file;
...@@ -8349,7 +8205,7 @@ pub const FuncGen = struct {...@@ -8349,7 +8205,7 @@ pub const FuncGen = struct {
8349 }8205 }
83508206
8351 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;8207 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).?;
8353 const lbrace_line = mod.declPtr(func.owner_decl).src_line + func.lbrace_line + 1;8209 const lbrace_line = mod.declPtr(func.owner_decl).src_line + func.lbrace_line + 1;
8354 const lbrace_col = func.lbrace_column + 1;8210 const lbrace_col = func.lbrace_column + 1;
8355 const di_local_var = dib.createParameterVariable(8211 const di_local_var = dib.createParameterVariable(
...@@ -9147,7 +9003,7 @@ pub const FuncGen = struct {...@@ -9147,7 +9003,7 @@ pub const FuncGen = struct {
9147 defer self.gpa.free(fqn);9003 defer self.gpa.free(fqn);
9148 const llvm_fn_name = try std.fmt.allocPrintZ(arena, "__zig_tag_name_{s}", .{fqn});9004 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;
9151 const llvm_ret_ty = try self.dg.lowerType(slice_ty);9007 const llvm_ret_ty = try self.dg.lowerType(slice_ty);
9152 const usize_llvm_ty = try self.dg.lowerType(Type.usize);9008 const usize_llvm_ty = try self.dg.lowerType(Type.usize);
9153 const slice_alignment = slice_ty.abiAlignment(mod);9009 const slice_alignment = slice_ty.abiAlignment(mod);
...@@ -9861,7 +9717,7 @@ pub const FuncGen = struct {...@@ -9861,7 +9717,7 @@ pub const FuncGen = struct {
9861 }9717 }
98629718
9863 const mod = self.dg.module;9719 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;
9865 const slice_alignment = slice_ty.abiAlignment(mod);9721 const slice_alignment = slice_ty.abiAlignment(mod);
9866 const llvm_slice_ptr_ty = self.context.pointerType(0); // TODO: Address space9722 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 {...@@ -236,9 +236,9 @@ pub const DeclGen = struct {
236 if (try self.air.value(inst, mod)) |val| {236 if (try self.air.value(inst, mod)) |val| {
237 const ty = self.typeOf(inst);237 const ty = self.typeOf(inst);
238 if (ty.zigTypeTag(mod) == .Fn) {238 if (ty.zigTypeTag(mod) == .Fn) {
239 const fn_decl_index = switch (val.tag()) {239 const fn_decl_index = switch (mod.intern_pool.indexToKey(val.ip_index)) {
240 .extern_fn => val.castTag(.extern_fn).?.data.owner_decl,240 .extern_func => |extern_func| extern_func.decl,
241 .function => val.castTag(.function).?.data.owner_decl,241 .func => |func| mod.funcPtr(func.index).owner_decl,
242 else => unreachable,242 else => unreachable,
243 };243 };
244 const spv_decl_index = try self.resolveDecl(fn_decl_index);244 const spv_decl_index = try self.resolveDecl(fn_decl_index);
...@@ -261,7 +261,7 @@ pub const DeclGen = struct {...@@ -261,7 +261,7 @@ pub const DeclGen = struct {
261 const entry = try self.decl_link.getOrPut(decl_index);261 const entry = try self.decl_link.getOrPut(decl_index);
262 if (!entry.found_existing) {262 if (!entry.found_existing) {
263 // TODO: Extern fn?263 // TODO: Extern fn?
264 const kind: SpvModule.DeclKind = if (decl.val.tag() == .function)264 const kind: SpvModule.DeclKind = if (decl.getFunctionIndex(self.module) != .none)
265 .func265 .func
266 else266 else
267 .global;267 .global;
...@@ -573,6 +573,7 @@ pub const DeclGen = struct {...@@ -573,6 +573,7 @@ pub const DeclGen = struct {
573573
574 fn addDeclRef(self: *@This(), ty: Type, decl_index: Decl.Index) !void {574 fn addDeclRef(self: *@This(), ty: Type, decl_index: Decl.Index) !void {
575 const dg = self.dg;575 const dg = self.dg;
576 const mod = dg.module;
576577
577 const ty_ref = try self.dg.resolveType(ty, .indirect);578 const ty_ref = try self.dg.resolveType(ty, .indirect);
578 const ty_id = dg.typeId(ty_ref);579 const ty_id = dg.typeId(ty_ref);
...@@ -580,8 +581,8 @@ pub const DeclGen = struct {...@@ -580,8 +581,8 @@ pub const DeclGen = struct {
580 const decl = dg.module.declPtr(decl_index);581 const decl = dg.module.declPtr(decl_index);
581 const spv_decl_index = try dg.resolveDecl(decl_index);582 const spv_decl_index = try dg.resolveDecl(decl_index);
582583
583 switch (decl.val.tag()) {584 switch (mod.intern_pool.indexToKey(decl.val.ip_index)) {
584 .function => {585 .func => {
585 // TODO: Properly lower function pointers. For now we are going to hack around it and586 // TODO: Properly lower function pointers. For now we are going to hack around it and
586 // just generate an empty pointer. Function pointers are represented by usize for now,587 // just generate an empty pointer. Function pointers are represented by usize for now,
587 // though.588 // though.
...@@ -589,7 +590,7 @@ pub const DeclGen = struct {...@@ -589,7 +590,7 @@ pub const DeclGen = struct {
589 // TODO: Add dependency590 // TODO: Add dependency
590 return;591 return;
591 },592 },
592 .extern_fn => unreachable, // TODO593 .extern_func => unreachable, // TODO
593 else => {594 else => {
594 const result_id = dg.spv.allocId();595 const result_id = dg.spv.allocId();
595 log.debug("addDeclRef: id = {}, index = {}, name = {s}", .{ result_id.id, @enumToInt(spv_decl_index), decl.name });596 log.debug("addDeclRef: id = {}, index = {}, name = {s}", .{ result_id.id, @enumToInt(spv_decl_index), decl.name });
...@@ -610,39 +611,23 @@ pub const DeclGen = struct {...@@ -610,39 +611,23 @@ pub const DeclGen = struct {
610 }611 }
611 }612 }
612613
613 fn lower(self: *@This(), ty: Type, val: Value) !void {614 fn lower(self: *@This(), ty: Type, arg_val: Value) !void {
614 const dg = self.dg;615 const dg = self.dg;
615 const mod = dg.module;616 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)) {
618 const size = ty.abiSize(mod);625 const size = ty.abiSize(mod);
619 return try self.addUndef(size);626 return try self.addUndef(size);
620 }627 }
621628
622 switch (ty.zigTypeTag(mod)) {629 if (val.ip_index == .none) 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)),
626 .Array => switch (val.tag()) {630 .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 },
646 .str_lit => {631 .str_lit => {
647 const str_lit = val.castTag(.str_lit).?.data;632 const str_lit = val.castTag(.str_lit).?.data;
648 const bytes = dg.module.string_literal_bytes.items[str_lit.index..][0..str_lit.len];633 const bytes = dg.module.string_literal_bytes.items[str_lit.index..][0..str_lit.len];
...@@ -657,29 +642,6 @@ pub const DeclGen = struct {...@@ -657,29 +642,6 @@ pub const DeclGen = struct {
657 },642 },
658 else => |tag| return dg.todo("indirect array constant with tag {s}", .{@tagName(tag)}),643 else => |tag| return dg.todo("indirect array constant with tag {s}", .{@tagName(tag)}),
659 },644 },
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 },
683 .Struct => {645 .Struct => {
684 if (ty.isSimpleTupleOrAnonStruct(mod)) {646 if (ty.isSimpleTupleOrAnonStruct(mod)) {
685 unreachable; // TODO647 unreachable; // TODO
...@@ -705,20 +667,134 @@ pub const DeclGen = struct {...@@ -705,20 +667,134 @@ pub const DeclGen = struct {
705 }667 }
706 }668 }
707 },669 },
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 => {
709 const payload_ty = ty.optionalChild(mod);787 const payload_ty = ty.optionalChild(mod);
710 const has_payload = !val.isNull(mod);788 const payload_val = val.optionalValue(mod);
711 const abi_size = ty.abiSize(mod);789 const abi_size = ty.abiSize(mod);
712790
713 if (!payload_ty.hasRuntimeBits(mod)) {791 if (!payload_ty.hasRuntimeBits(mod)) {
714 try self.addConstBool(has_payload);792 try self.addConstBool(payload_val != null);
715 return;793 return;
716 } else if (ty.optionalReprIsPayload(mod)) {794 } else if (ty.optionalReprIsPayload(mod)) {
717 // Optional representation is a nullable pointer or slice.795 // Optional representation is a nullable pointer or slice.
718 if (val.castTag(.opt_payload)) |payload| {796 if (payload_val) |pl_val| {
719 try self.lower(payload_ty, payload.data);797 try self.lower(payload_ty, pl_val);
720 } else if (has_payload) {
721 try self.lower(payload_ty, val);
722 } else {798 } else {
723 const ptr_ty_ref = try dg.resolveType(ty, .indirect);799 const ptr_ty_ref = try dg.resolveType(ty, .indirect);
724 try self.addNullPtr(ptr_ty_ref);800 try self.addNullPtr(ptr_ty_ref);
...@@ -734,27 +810,63 @@ pub const DeclGen = struct {...@@ -734,27 +810,63 @@ pub const DeclGen = struct {
734 const payload_size = payload_ty.abiSize(mod);810 const payload_size = payload_ty.abiSize(mod);
735 const padding = abi_size - payload_size - 1;811 const padding = abi_size - payload_size - 1;
736812
737 if (val.castTag(.opt_payload)) |payload| {813 if (payload_val) |pl_val| {
738 try self.lower(payload_ty, payload.data);814 try self.lower(payload_ty, pl_val);
739 } else {815 } else {
740 try self.addUndef(payload_size);816 try self.addUndef(payload_size);
741 }817 }
742 try self.addConstBool(has_payload);818 try self.addConstBool(payload_val != null);
743 try self.addUndef(padding);819 try self.addUndef(padding);
744 },820 },
745 .Enum => {821 .aggregate => |aggregate| switch (mod.intern_pool.indexToKey(ty.ip_index)) {
746 const int_val = try val.enumToInt(ty, mod);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,
751 },864 },
752 .Union => {865 .un => |un| {
753 const tag_and_val = val.castTag(.@"union").?.data;
754 const layout = ty.unionGetLayout(mod);866 const layout = ty.unionGetLayout(mod);
755867
756 if (layout.payload_size == 0) {868 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());
758 }870 }
759871
760 const union_ty = mod.typeToUnion(ty).?;872 const union_ty = mod.typeToUnion(ty).?;
...@@ -762,18 +874,18 @@ pub const DeclGen = struct {...@@ -762,18 +874,18 @@ pub const DeclGen = struct {
762 return dg.todo("packed union constants", .{});874 return dg.todo("packed union constants", .{});
763 }875 }
764876
765 const active_field = ty.unionTagFieldIndex(tag_and_val.tag, dg.module).?;877 const active_field = ty.unionTagFieldIndex(un.tag.toValue(), dg.module).?;
766 const active_field_ty = union_ty.fields.values()[active_field].ty;878 const active_field_ty = union_ty.fields.values()[active_field].ty;
767879
768 const has_tag = layout.tag_size != 0;880 const has_tag = layout.tag_size != 0;
769 const tag_first = layout.tag_align >= layout.payload_align;881 const tag_first = layout.tag_align >= layout.payload_align;
770882
771 if (has_tag and tag_first) {883 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());
773 }885 }
774886
775 const active_field_size = if (active_field_ty.hasRuntimeBitsIgnoreComptime(mod)) blk: {887 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());
777 break :blk active_field_ty.abiSize(mod);889 break :blk active_field_ty.abiSize(mod);
778 } else 0;890 } else 0;
779891
...@@ -781,53 +893,11 @@ pub const DeclGen = struct {...@@ -781,53 +893,11 @@ pub const DeclGen = struct {
781 try self.addUndef(payload_padding_len);893 try self.addUndef(payload_padding_len);
782894
783 if (has_tag and !tag_first) {895 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());
785 }897 }
786898
787 try self.addUndef(layout.padding);899 try self.addUndef(layout.padding);
788 },900 },
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)}),
831 }901 }
832 }902 }
833 };903 };
...@@ -1542,7 +1612,7 @@ pub const DeclGen = struct {...@@ -1542,7 +1612,7 @@ pub const DeclGen = struct {
1542 const decl_id = self.spv.declPtr(spv_decl_index).result_id;1612 const decl_id = self.spv.declPtr(spv_decl_index).result_id;
1543 log.debug("genDecl: id = {}, index = {}, name = {s}", .{ decl_id.id, @enumToInt(spv_decl_index), decl.name });1613 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)) |_| {
1546 assert(decl.ty.zigTypeTag(mod) == .Fn);1616 assert(decl.ty.zigTypeTag(mod) == .Fn);
1547 const prototype_id = try self.resolveTypeId(decl.ty);1617 const prototype_id = try self.resolveTypeId(decl.ty);
1548 try self.func.prologue.emit(self.spv.gpa, .OpFunction, .{1618 try self.func.prologue.emit(self.spv.gpa, .OpFunction, .{
...@@ -1595,8 +1665,8 @@ pub const DeclGen = struct {...@@ -1595,8 +1665,8 @@ pub const DeclGen = struct {
1595 try self.generateTestEntryPoint(fqn, spv_decl_index);1665 try self.generateTestEntryPoint(fqn, spv_decl_index);
1596 }1666 }
1597 } else {1667 } else {
1598 const init_val = if (decl.val.castTag(.variable)) |payload|1668 const init_val = if (decl.getVariable(mod)) |payload|
1599 payload.data.init1669 payload.init.toValue()
1600 else1670 else
1601 decl.val;1671 decl.val;
16021672
src/link.zig+10-9
...@@ -564,7 +564,8 @@ pub const File = struct {...@@ -564,7 +564,8 @@ pub const File = struct {
564 }564 }
565565
566 /// May be called before or after updateDeclExports for any given Decl.566 /// 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);
568 const owner_decl = module.declPtr(func.owner_decl);569 const owner_decl = module.declPtr(func.owner_decl);
569 log.debug("updateFunc {*} ({s}), type={}", .{570 log.debug("updateFunc {*} ({s}), type={}", .{
570 owner_decl, owner_decl.name, owner_decl.ty.fmt(module),571 owner_decl, owner_decl.name, owner_decl.ty.fmt(module),
...@@ -575,14 +576,14 @@ pub const File = struct {...@@ -575,14 +576,14 @@ pub const File = struct {
575 }576 }
576 switch (base.tag) {577 switch (base.tag) {
577 // zig fmt: off578 // zig fmt: off
578 .coff => return @fieldParentPtr(Coff, "base", base).updateFunc(module, func, air, liveness),579 .coff => return @fieldParentPtr(Coff, "base", base).updateFunc(module, func_index, air, liveness),
579 .elf => return @fieldParentPtr(Elf, "base", base).updateFunc(module, func, air, liveness),580 .elf => return @fieldParentPtr(Elf, "base", base).updateFunc(module, func_index, air, liveness),
580 .macho => return @fieldParentPtr(MachO, "base", base).updateFunc(module, func, air, liveness),581 .macho => return @fieldParentPtr(MachO, "base", base).updateFunc(module, func_index, air, liveness),
581 .c => return @fieldParentPtr(C, "base", base).updateFunc(module, func, air, liveness),582 .c => return @fieldParentPtr(C, "base", base).updateFunc(module, func_index, air, liveness),
582 .wasm => return @fieldParentPtr(Wasm, "base", base).updateFunc(module, func, air, liveness),583 .wasm => return @fieldParentPtr(Wasm, "base", base).updateFunc(module, func_index, air, liveness),
583 .spirv => return @fieldParentPtr(SpirV, "base", base).updateFunc(module, func, air, liveness),584 .spirv => return @fieldParentPtr(SpirV, "base", base).updateFunc(module, func_index, air, liveness),
584 .plan9 => return @fieldParentPtr(Plan9, "base", base).updateFunc(module, func, air, liveness),585 .plan9 => return @fieldParentPtr(Plan9, "base", base).updateFunc(module, func_index, air, liveness),
585 .nvptx => return @fieldParentPtr(NvPtx, "base", base).updateFunc(module, func, air, liveness),586 .nvptx => return @fieldParentPtr(NvPtx, "base", base).updateFunc(module, func_index, air, liveness),
586 // zig fmt: on587 // zig fmt: on
587 }588 }
588 }589 }
src/link/C.zig+6-4
...@@ -87,12 +87,13 @@ pub fn freeDecl(self: *C, decl_index: Module.Decl.Index) void {...@@ -87,12 +87,13 @@ pub fn freeDecl(self: *C, decl_index: Module.Decl.Index) void {
87 }87 }
88}88}
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 {
91 const tracy = trace(@src());91 const tracy = trace(@src());
92 defer tracy.end();92 defer tracy.end();
9393
94 const gpa = self.base.allocator;94 const gpa = self.base.allocator;
9595
96 const func = module.funcPtr(func_index);
96 const decl_index = func.owner_decl;97 const decl_index = func.owner_decl;
97 const gop = try self.decl_table.getOrPut(gpa, decl_index);98 const gop = try self.decl_table.getOrPut(gpa, decl_index);
98 if (!gop.found_existing) {99 if (!gop.found_existing) {
...@@ -111,7 +112,7 @@ pub fn updateFunc(self: *C, module: *Module, func: *Module.Fn, air: Air, livenes...@@ -111,7 +112,7 @@ pub fn updateFunc(self: *C, module: *Module, func: *Module.Fn, air: Air, livenes
111 .value_map = codegen.CValueMap.init(gpa),112 .value_map = codegen.CValueMap.init(gpa),
112 .air = air,113 .air = air,
113 .liveness = liveness,114 .liveness = liveness,
114 .func = func,115 .func_index = func_index,
115 .object = .{116 .object = .{
116 .dg = .{117 .dg = .{
117 .gpa = gpa,118 .gpa = gpa,
...@@ -555,7 +556,8 @@ fn flushDecl(...@@ -555,7 +556,8 @@ fn flushDecl(
555 export_names: std.StringHashMapUnmanaged(void),556 export_names: std.StringHashMapUnmanaged(void),
556) FlushDeclError!void {557) FlushDeclError!void {
557 const gpa = self.base.allocator;558 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);
559 // Before flushing any particular Decl we must ensure its561 // Before flushing any particular Decl we must ensure its
560 // dependencies are already flushed, so that the order in the .c562 // dependencies are already flushed, so that the order in the .c
561 // file comes out correctly.563 // file comes out correctly.
...@@ -569,7 +571,7 @@ fn flushDecl(...@@ -569,7 +571,7 @@ fn flushDecl(
569571
570 try self.flushLazyFns(f, decl_block.lazy_fns);572 try self.flushLazyFns(f, decl_block.lazy_fns);
571 try f.all_buffers.ensureUnusedCapacity(gpa, 1);573 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))))
573 f.appendBufAssumeCapacity(decl_block.fwd_decl.items);575 f.appendBufAssumeCapacity(decl_block.fwd_decl.items);
574}576}
575577
src/link/Coff.zig+9-9
...@@ -1032,18 +1032,19 @@ fn freeAtom(self: *Coff, atom_index: Atom.Index) void {...@@ -1032,18 +1032,19 @@ fn freeAtom(self: *Coff, atom_index: Atom.Index) void {
1032 self.getAtomPtr(atom_index).sym_index = 0;1032 self.getAtomPtr(atom_index).sym_index = 0;
1033}1033}
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 {
1036 if (build_options.skip_non_native and builtin.object_format != .coff) {1036 if (build_options.skip_non_native and builtin.object_format != .coff) {
1037 @panic("Attempted to compile for object format that was disabled by build configuration");1037 @panic("Attempted to compile for object format that was disabled by build configuration");
1038 }1038 }
1039 if (build_options.have_llvm) {1039 if (build_options.have_llvm) {
1040 if (self.llvm_object) |llvm_object| {1040 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);
1042 }1042 }
1043 }1043 }
1044 const tracy = trace(@src());1044 const tracy = trace(@src());
1045 defer tracy.end();1045 defer tracy.end();
10461046
1047 const func = mod.funcPtr(func_index);
1047 const decl_index = func.owner_decl;1048 const decl_index = func.owner_decl;
1048 const decl = mod.declPtr(decl_index);1049 const decl = mod.declPtr(decl_index);
10491050
...@@ -1057,7 +1058,7 @@ pub fn updateFunc(self: *Coff, mod: *Module, func: *Module.Fn, air: Air, livenes...@@ -1057,7 +1058,7 @@ pub fn updateFunc(self: *Coff, mod: *Module, func: *Module.Fn, air: Air, livenes
1057 const res = try codegen.generateFunction(1058 const res = try codegen.generateFunction(
1058 &self.base,1059 &self.base,
1059 decl.srcLoc(mod),1060 decl.srcLoc(mod),
1060 func,1061 func_index,
1061 air,1062 air,
1062 liveness,1063 liveness,
1063 &code_buffer,1064 &code_buffer,
...@@ -1155,11 +1156,10 @@ pub fn updateDecl(...@@ -1155,11 +1156,10 @@ pub fn updateDecl(
11551156
1156 const decl = mod.declPtr(decl_index);1157 const decl = mod.declPtr(decl_index);
11571158
1158 if (decl.val.tag() == .extern_fn) {1159 if (decl.getExternFunc(mod)) |_| {
1159 return; // TODO Should we do more when front-end analyzed extern decl?1160 return; // TODO Should we do more when front-end analyzed extern decl?
1160 }1161 }
1161 if (decl.val.castTag(.variable)) |payload| {1162 if (decl.getVariable(mod)) |variable| {
1162 const variable = payload.data;
1163 if (variable.is_extern) {1163 if (variable.is_extern) {
1164 return; // TODO Should we do more when front-end analyzed extern decl?1164 return; // TODO Should we do more when front-end analyzed extern decl?
1165 }1165 }
...@@ -1172,7 +1172,7 @@ pub fn updateDecl(...@@ -1172,7 +1172,7 @@ pub fn updateDecl(
1172 var code_buffer = std.ArrayList(u8).init(self.base.allocator);1172 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
1173 defer code_buffer.deinit();1173 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;
1176 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), .{1176 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), .{
1177 .ty = decl.ty,1177 .ty = decl.ty,
1178 .val = decl_val,1178 .val = decl_val,
...@@ -1313,7 +1313,7 @@ fn getDeclOutputSection(self: *Coff, decl_index: Module.Decl.Index) u16 {...@@ -1313,7 +1313,7 @@ fn getDeclOutputSection(self: *Coff, decl_index: Module.Decl.Index) u16 {
1313 // TODO: what if this is a function pointer?1313 // TODO: what if this is a function pointer?
1314 .Fn => break :blk self.text_section_index.?,1314 .Fn => break :blk self.text_section_index.?,
1315 else => {1315 else => {
1316 if (val.castTag(.variable)) |_| {1316 if (decl.getVariable(mod)) |_| {
1317 break :blk self.data_section_index.?;1317 break :blk self.data_section_index.?;
1318 }1318 }
1319 break :blk self.rdata_section_index.?;1319 break :blk self.rdata_section_index.?;
...@@ -1425,7 +1425,7 @@ pub fn updateDeclExports(...@@ -1425,7 +1425,7 @@ pub fn updateDeclExports(
1425 // detect the default subsystem.1425 // detect the default subsystem.
1426 for (exports) |exp| {1426 for (exports) |exp| {
1427 const exported_decl = mod.declPtr(exp.exported_decl);1427 const exported_decl = mod.declPtr(exp.exported_decl);
1428 if (exported_decl.getFunction() == null) continue;1428 if (exported_decl.getFunctionIndex(mod) == .none) continue;
1429 const winapi_cc = switch (self.base.options.target.cpu.arch) {1429 const winapi_cc = switch (self.base.options.target.cpu.arch) {
1430 .x86 => std.builtin.CallingConvention.Stdcall,1430 .x86 => std.builtin.CallingConvention.Stdcall,
1431 else => std.builtin.CallingConvention.C,1431 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)...@@ -971,7 +971,7 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index)
971 // For functions we need to add a prologue to the debug line program.971 // For functions we need to add a prologue to the debug line program.
972 try dbg_line_buffer.ensureTotalCapacity(26);972 try dbg_line_buffer.ensureTotalCapacity(26);
973973
974 const func = decl.val.castTag(.function).?.data;974 const func = decl.getFunction(mod).?;
975 log.debug("decl.src_line={d}, func.lbrace_line={d}, func.rbrace_line={d}", .{975 log.debug("decl.src_line={d}, func.lbrace_line={d}, func.rbrace_line={d}", .{
976 decl.src_line,976 decl.src_line,
977 func.lbrace_line,977 func.lbrace_line,
...@@ -1514,7 +1514,7 @@ fn writeDeclDebugInfo(self: *Dwarf, atom_index: Atom.Index, dbg_info_buf: []cons...@@ -1514,7 +1514,7 @@ fn writeDeclDebugInfo(self: *Dwarf, atom_index: Atom.Index, dbg_info_buf: []cons
1514 }1514 }
1515}1515}
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 {
1518 const tracy = trace(@src());1518 const tracy = trace(@src());
1519 defer tracy.end();1519 defer tracy.end();
15201520
...@@ -1522,8 +1522,8 @@ pub fn updateDeclLineNumber(self: *Dwarf, module: *Module, decl_index: Module.De...@@ -1522,8 +1522,8 @@ pub fn updateDeclLineNumber(self: *Dwarf, module: *Module, decl_index: Module.De
1522 const atom = self.getAtom(.src_fn, atom_index);1522 const atom = self.getAtom(.src_fn, atom_index);
1523 if (atom.len == 0) return;1523 if (atom.len == 0) return;
15241524
1525 const decl = module.declPtr(decl_index);1525 const decl = mod.declPtr(decl_index);
1526 const func = decl.val.castTag(.function).?.data;1526 const func = decl.getFunction(mod).?;
1527 log.debug("decl.src_line={d}, func.lbrace_line={d}, func.rbrace_line={d}", .{1527 log.debug("decl.src_line={d}, func.lbrace_line={d}, func.rbrace_line={d}", .{
1528 decl.src_line,1528 decl.src_line,
1529 func.lbrace_line,1529 func.lbrace_line,
src/link/Elf.zig+9-9
...@@ -2465,7 +2465,7 @@ fn getDeclShdrIndex(self: *Elf, decl_index: Module.Decl.Index) u16 {...@@ -2465,7 +2465,7 @@ fn getDeclShdrIndex(self: *Elf, decl_index: Module.Decl.Index) u16 {
2465 // TODO: what if this is a function pointer?2465 // TODO: what if this is a function pointer?
2466 .Fn => break :blk self.text_section_index.?,2466 .Fn => break :blk self.text_section_index.?,
2467 else => {2467 else => {
2468 if (val.castTag(.variable)) |_| {2468 if (decl.getVariable(mod)) |_| {
2469 break :blk self.data_section_index.?;2469 break :blk self.data_section_index.?;
2470 }2470 }
2471 break :blk self.rodata_section_index.?;2471 break :blk self.rodata_section_index.?;
...@@ -2574,17 +2574,18 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s...@@ -2574,17 +2574,18 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s
2574 return local_sym;2574 return local_sym;
2575}2575}
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 {
2578 if (build_options.skip_non_native and builtin.object_format != .elf) {2578 if (build_options.skip_non_native and builtin.object_format != .elf) {
2579 @panic("Attempted to compile for object format that was disabled by build configuration");2579 @panic("Attempted to compile for object format that was disabled by build configuration");
2580 }2580 }
2581 if (build_options.have_llvm) {2581 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);
2583 }2583 }
25842584
2585 const tracy = trace(@src());2585 const tracy = trace(@src());
2586 defer tracy.end();2586 defer tracy.end();
25872587
2588 const func = mod.funcPtr(func_index);
2588 const decl_index = func.owner_decl;2589 const decl_index = func.owner_decl;
2589 const decl = mod.declPtr(decl_index);2590 const decl = mod.declPtr(decl_index);
25902591
...@@ -2599,11 +2600,11 @@ pub fn updateFunc(self: *Elf, mod: *Module, func: *Module.Fn, air: Air, liveness...@@ -2599,11 +2600,11 @@ pub fn updateFunc(self: *Elf, mod: *Module, func: *Module.Fn, air: Air, liveness
2599 defer if (decl_state) |*ds| ds.deinit();2600 defer if (decl_state) |*ds| ds.deinit();
26002601
2601 const res = if (decl_state) |*ds|2602 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, .{
2603 .dwarf = ds,2604 .dwarf = ds,
2604 })2605 })
2605 else2606 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
2608 const code = switch (res) {2609 const code = switch (res) {
2609 .ok => code_buffer.items,2610 .ok => code_buffer.items,
...@@ -2646,11 +2647,10 @@ pub fn updateDecl(...@@ -2646,11 +2647,10 @@ pub fn updateDecl(
26462647
2647 const decl = mod.declPtr(decl_index);2648 const decl = mod.declPtr(decl_index);
26482649
2649 if (decl.val.tag() == .extern_fn) {2650 if (decl.getExternFunc(mod)) |_| {
2650 return; // TODO Should we do more when front-end analyzed extern decl?2651 return; // TODO Should we do more when front-end analyzed extern decl?
2651 }2652 }
2652 if (decl.val.castTag(.variable)) |payload| {2653 if (decl.getVariable(mod)) |variable| {
2653 const variable = payload.data;
2654 if (variable.is_extern) {2654 if (variable.is_extern) {
2655 return; // TODO Should we do more when front-end analyzed extern decl?2655 return; // TODO Should we do more when front-end analyzed extern decl?
2656 }2656 }
...@@ -2667,7 +2667,7 @@ pub fn updateDecl(...@@ -2667,7 +2667,7 @@ pub fn updateDecl(
2667 defer if (decl_state) |*ds| ds.deinit();2667 defer if (decl_state) |*ds| ds.deinit();
26682668
2669 // TODO implement .debug_info for global variables2669 // 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;
2671 const res = if (decl_state) |*ds|2671 const res = if (decl_state) |*ds|
2672 try codegen.generateSymbol(&self.base, decl.srcLoc(mod), .{2672 try codegen.generateSymbol(&self.base, decl.srcLoc(mod), .{
2673 .ty = decl.ty,2673 .ty = decl.ty,
src/link/MachO.zig+14-14
...@@ -1847,16 +1847,17 @@ fn addStubEntry(self: *MachO, target: SymbolWithLoc) !void {...@@ -1847,16 +1847,17 @@ fn addStubEntry(self: *MachO, target: SymbolWithLoc) !void {
1847 self.markRelocsDirtyByTarget(target);1847 self.markRelocsDirtyByTarget(target);
1848}1848}
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 {
1851 if (build_options.skip_non_native and builtin.object_format != .macho) {1851 if (build_options.skip_non_native and builtin.object_format != .macho) {
1852 @panic("Attempted to compile for object format that was disabled by build configuration");1852 @panic("Attempted to compile for object format that was disabled by build configuration");
1853 }1853 }
1854 if (build_options.have_llvm) {1854 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);
1856 }1856 }
1857 const tracy = trace(@src());1857 const tracy = trace(@src());
1858 defer tracy.end();1858 defer tracy.end();
18591859
1860 const func = mod.funcPtr(func_index);
1860 const decl_index = func.owner_decl;1861 const decl_index = func.owner_decl;
1861 const decl = mod.declPtr(decl_index);1862 const decl = mod.declPtr(decl_index);
18621863
...@@ -1874,11 +1875,11 @@ pub fn updateFunc(self: *MachO, mod: *Module, func: *Module.Fn, air: Air, livene...@@ -1874,11 +1875,11 @@ pub fn updateFunc(self: *MachO, mod: *Module, func: *Module.Fn, air: Air, livene
1874 defer if (decl_state) |*ds| ds.deinit();1875 defer if (decl_state) |*ds| ds.deinit();
18751876
1876 const res = if (decl_state) |*ds|1877 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, .{
1878 .dwarf = ds,1879 .dwarf = ds,
1879 })1880 })
1880 else1881 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
1883 var code = switch (res) {1884 var code = switch (res) {
1884 .ok => code_buffer.items,1885 .ok => code_buffer.items,
...@@ -1983,18 +1984,17 @@ pub fn updateDecl(self: *MachO, mod: *Module, decl_index: Module.Decl.Index) !vo...@@ -1983,18 +1984,17 @@ pub fn updateDecl(self: *MachO, mod: *Module, decl_index: Module.Decl.Index) !vo
19831984
1984 const decl = mod.declPtr(decl_index);1985 const decl = mod.declPtr(decl_index);
19851986
1986 if (decl.val.tag() == .extern_fn) {1987 if (decl.getExternFunc(mod)) |_| {
1987 return; // TODO Should we do more when front-end analyzed extern decl?1988 return; // TODO Should we do more when front-end analyzed extern decl?
1988 }1989 }
1989 if (decl.val.castTag(.variable)) |payload| {1990 if (decl.getVariable(mod)) |variable| {
1990 const variable = payload.data;
1991 if (variable.is_extern) {1991 if (variable.is_extern) {
1992 return; // TODO Should we do more when front-end analyzed extern decl?1992 return; // TODO Should we do more when front-end analyzed extern decl?
1993 }1993 }
1994 }1994 }
19951995
1996 const is_threadlocal = if (decl.val.castTag(.variable)) |payload|1996 const is_threadlocal = if (decl.getVariable(mod)) |variable|
1997 payload.data.is_threadlocal and !self.base.options.single_threaded1997 variable.is_threadlocal and !self.base.options.single_threaded
1998 else1998 else
1999 false;1999 false;
2000 if (is_threadlocal) return self.updateThreadlocalVariable(mod, decl_index);2000 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...@@ -2012,7 +2012,7 @@ pub fn updateDecl(self: *MachO, mod: *Module, decl_index: Module.Decl.Index) !vo
2012 null;2012 null;
2013 defer if (decl_state) |*ds| ds.deinit();2013 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;
2016 const res = if (decl_state) |*ds|2016 const res = if (decl_state) |*ds|
2017 try codegen.generateSymbol(&self.base, decl.srcLoc(mod), .{2017 try codegen.generateSymbol(&self.base, decl.srcLoc(mod), .{
2018 .ty = decl.ty,2018 .ty = decl.ty,
...@@ -2177,7 +2177,7 @@ fn updateThreadlocalVariable(self: *MachO, module: *Module, decl_index: Module.D...@@ -2177,7 +2177,7 @@ fn updateThreadlocalVariable(self: *MachO, module: *Module, decl_index: Module.D
21772177
2178 const decl = module.declPtr(decl_index);2178 const decl = module.declPtr(decl_index);
2179 const decl_metadata = self.decls.get(decl_index).?;2179 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();
2181 const res = if (decl_state) |*ds|2181 const res = if (decl_state) |*ds|
2182 try codegen.generateSymbol(&self.base, decl.srcLoc(mod), .{2182 try codegen.generateSymbol(&self.base, decl.srcLoc(mod), .{
2183 .ty = decl.ty,2183 .ty = decl.ty,
...@@ -2278,8 +2278,8 @@ fn getDeclOutputSection(self: *MachO, decl_index: Module.Decl.Index) u8 {...@@ -2278,8 +2278,8 @@ fn getDeclOutputSection(self: *MachO, decl_index: Module.Decl.Index) u8 {
2278 }2278 }
2279 }2279 }
22802280
2281 if (val.castTag(.variable)) |variable| {2281 if (decl.getVariable(mod)) |variable| {
2282 if (variable.data.is_threadlocal and !single_threaded) {2282 if (variable.is_threadlocal and !single_threaded) {
2283 break :blk self.thread_data_section_index.?;2283 break :blk self.thread_data_section_index.?;
2284 }2284 }
2285 break :blk self.data_section_index.?;2285 break :blk self.data_section_index.?;
...@@ -2289,7 +2289,7 @@ fn getDeclOutputSection(self: *MachO, decl_index: Module.Decl.Index) u8 {...@@ -2289,7 +2289,7 @@ fn getDeclOutputSection(self: *MachO, decl_index: Module.Decl.Index) u8 {
2289 // TODO: what if this is a function pointer?2289 // TODO: what if this is a function pointer?
2290 .Fn => break :blk self.text_section_index.?,2290 .Fn => break :blk self.text_section_index.?,
2291 else => {2291 else => {
2292 if (val.castTag(.variable)) |_| {2292 if (decl.getVariable(mod)) |_| {
2293 break :blk self.data_section_index.?;2293 break :blk self.data_section_index.?;
2294 }2294 }
2295 break :blk self.data_const_section_index.?;2295 break :blk self.data_const_section_index.?;
src/link/NvPtx.zig+2-2
...@@ -68,9 +68,9 @@ pub fn deinit(self: *NvPtx) void {...@@ -68,9 +68,9 @@ pub fn deinit(self: *NvPtx) void {
68 self.base.allocator.free(self.ptx_file_name);68 self.base.allocator.free(self.ptx_file_name);
69}69}
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 {
72 if (!build_options.have_llvm) return;72 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);
74}74}
7575
76pub fn updateDecl(self: *NvPtx, module: *Module, decl_index: Module.Decl.Index) !void {76pub 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...@@ -276,11 +276,12 @@ fn addPathComponents(self: *Plan9, path: []const u8, a: *std.ArrayList(u8)) !voi
276 }276 }
277}277}
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 {
280 if (build_options.skip_non_native and builtin.object_format != .plan9) {280 if (build_options.skip_non_native and builtin.object_format != .plan9) {
281 @panic("Attempted to compile for object format that was disabled by build configuration");281 @panic("Attempted to compile for object format that was disabled by build configuration");
282 }282 }
283283
284 const func = mod.funcPtr(func_index);
284 const decl_index = func.owner_decl;285 const decl_index = func.owner_decl;
285 const decl = mod.declPtr(decl_index);286 const decl = mod.declPtr(decl_index);
286 self.freeUnnamedConsts(decl_index);287 self.freeUnnamedConsts(decl_index);
...@@ -299,7 +300,7 @@ pub fn updateFunc(self: *Plan9, mod: *Module, func: *Module.Fn, air: Air, livene...@@ -299,7 +300,7 @@ pub fn updateFunc(self: *Plan9, mod: *Module, func: *Module.Fn, air: Air, livene
299 const res = try codegen.generateFunction(300 const res = try codegen.generateFunction(
300 &self.base,301 &self.base,
301 decl.srcLoc(mod),302 decl.srcLoc(mod),
302 func,303 func_index,
303 air,304 air,
304 liveness,305 liveness,
305 &code_buffer,306 &code_buffer,
...@@ -391,11 +392,10 @@ pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: Module.Decl.I...@@ -391,11 +392,10 @@ pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: Module.Decl.I
391pub fn updateDecl(self: *Plan9, mod: *Module, decl_index: Module.Decl.Index) !void {392pub fn updateDecl(self: *Plan9, mod: *Module, decl_index: Module.Decl.Index) !void {
392 const decl = mod.declPtr(decl_index);393 const decl = mod.declPtr(decl_index);
393394
394 if (decl.val.tag() == .extern_fn) {395 if (decl.getExternFunc(mod)) |_| {
395 return; // TODO Should we do more when front-end analyzed extern decl?396 return; // TODO Should we do more when front-end analyzed extern decl?
396 }397 }
397 if (decl.val.castTag(.variable)) |payload| {398 if (decl.getVariable(mod)) |variable| {
398 const variable = payload.data;
399 if (variable.is_extern) {399 if (variable.is_extern) {
400 return; // TODO Should we do more when front-end analyzed extern decl?400 return; // TODO Should we do more when front-end analyzed extern decl?
401 }401 }
...@@ -407,7 +407,7 @@ pub fn updateDecl(self: *Plan9, mod: *Module, decl_index: Module.Decl.Index) !vo...@@ -407,7 +407,7 @@ pub fn updateDecl(self: *Plan9, mod: *Module, decl_index: Module.Decl.Index) !vo
407407
408 var code_buffer = std.ArrayList(u8).init(self.base.allocator);408 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
409 defer code_buffer.deinit();409 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;
411 // TODO we need the symbol index for symbol in the table of locals for the containing atom411 // TODO we need the symbol index for symbol in the table of locals for the containing atom
412 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), .{412 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), .{
413 .ty = decl.ty,413 .ty = decl.ty,
...@@ -771,7 +771,7 @@ pub fn freeDecl(self: *Plan9, decl_index: Module.Decl.Index) void {...@@ -771,7 +771,7 @@ pub fn freeDecl(self: *Plan9, decl_index: Module.Decl.Index) void {
771 // in the deleteUnusedDecl function.771 // in the deleteUnusedDecl function.
772 const mod = self.base.options.module.?;772 const mod = self.base.options.module.?;
773 const decl = mod.declPtr(decl_index);773 const decl = mod.declPtr(decl_index);
774 const is_fn = (decl.val.tag() == .function);774 const is_fn = decl.getFunctionIndex(mod) != .none;
775 if (is_fn) {775 if (is_fn) {
776 var symidx_and_submap = self.fn_decl_table.get(decl.getFileScope(mod)).?;776 var symidx_and_submap = self.fn_decl_table.get(decl.getFileScope(mod)).?;
777 var submap = symidx_and_submap.functions;777 var submap = symidx_and_submap.functions;
src/link/SpirV.zig+4-2
...@@ -103,11 +103,13 @@ pub fn deinit(self: *SpirV) void {...@@ -103,11 +103,13 @@ pub fn deinit(self: *SpirV) void {
103 self.decl_link.deinit();103 self.decl_link.deinit();
104}104}
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 {
107 if (build_options.skip_non_native) {107 if (build_options.skip_non_native) {
108 @panic("Attempted to compile for architecture that was disabled by build configuration");108 @panic("Attempted to compile for architecture that was disabled by build configuration");
109 }109 }
110110
111 const func = module.funcPtr(func_index);
112
111 var decl_gen = codegen.DeclGen.init(self.base.allocator, module, &self.spv, &self.decl_link);113 var decl_gen = codegen.DeclGen.init(self.base.allocator, module, &self.spv, &self.decl_link);
112 defer decl_gen.deinit();114 defer decl_gen.deinit();
113115
...@@ -136,7 +138,7 @@ pub fn updateDeclExports(...@@ -136,7 +138,7 @@ pub fn updateDeclExports(
136 exports: []const *Module.Export,138 exports: []const *Module.Export,
137) !void {139) !void {
138 const decl = mod.declPtr(decl_index);140 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) {
140 // TODO: Unify with resolveDecl in spirv.zig.142 // TODO: Unify with resolveDecl in spirv.zig.
141 const entry = try self.decl_link.getOrPut(decl_index);143 const entry = try self.decl_link.getOrPut(decl_index);
142 if (!entry.found_existing) {144 if (!entry.found_existing) {
src/link/Wasm.zig+21-19
...@@ -1324,17 +1324,18 @@ pub fn allocateSymbol(wasm: *Wasm) !u32 {...@@ -1324,17 +1324,18 @@ pub fn allocateSymbol(wasm: *Wasm) !u32 {
1324 return index;1324 return index;
1325}1325}
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 {
1328 if (build_options.skip_non_native and builtin.object_format != .wasm) {1328 if (build_options.skip_non_native and builtin.object_format != .wasm) {
1329 @panic("Attempted to compile for object format that was disabled by build configuration");1329 @panic("Attempted to compile for object format that was disabled by build configuration");
1330 }1330 }
1331 if (build_options.have_llvm) {1331 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);
1333 }1333 }
13341334
1335 const tracy = trace(@src());1335 const tracy = trace(@src());
1336 defer tracy.end();1336 defer tracy.end();
13371337
1338 const func = mod.funcPtr(func_index);
1338 const decl_index = func.owner_decl;1339 const decl_index = func.owner_decl;
1339 const decl = mod.declPtr(decl_index);1340 const decl = mod.declPtr(decl_index);
1340 const atom_index = try wasm.getOrCreateAtomForDecl(decl_index);1341 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...@@ -1358,7 +1359,7 @@ pub fn updateFunc(wasm: *Wasm, mod: *Module, func: *Module.Fn, air: Air, livenes
1358 const result = try codegen.generateFunction(1359 const result = try codegen.generateFunction(
1359 &wasm.base,1360 &wasm.base,
1360 decl.srcLoc(mod),1361 decl.srcLoc(mod),
1361 func,1362 func_index,
1362 air,1363 air,
1363 liveness,1364 liveness,
1364 &code_writer,1365 &code_writer,
...@@ -1403,9 +1404,9 @@ pub fn updateDecl(wasm: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !voi...@@ -1403,9 +1404,9 @@ pub fn updateDecl(wasm: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !voi
1403 defer tracy.end();1404 defer tracy.end();
14041405
1405 const decl = mod.declPtr(decl_index);1406 const decl = mod.declPtr(decl_index);
1406 if (decl.val.castTag(.function)) |_| {1407 if (decl.getFunction(mod)) |_| {
1407 return;1408 return;
1408 } else if (decl.val.castTag(.extern_fn)) |_| {1409 } else if (decl.getExternFunc(mod)) |_| {
1409 return;1410 return;
1410 }1411 }
14111412
...@@ -1413,12 +1414,13 @@ pub fn updateDecl(wasm: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !voi...@@ -1413,12 +1414,13 @@ pub fn updateDecl(wasm: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !voi
1413 const atom = wasm.getAtomPtr(atom_index);1414 const atom = wasm.getAtomPtr(atom_index);
1414 atom.clear();1415 atom.clear();
14151416
1416 if (decl.isExtern()) {1417 if (decl.isExtern(mod)) {
1417 const variable = decl.getVariable().?;1418 const variable = decl.getVariable(mod).?;
1418 const name = mem.sliceTo(decl.name, 0);1419 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);
1420 }1422 }
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
1423 var code_writer = std.ArrayList(u8).init(wasm.base.allocator);1425 var code_writer = std.ArrayList(u8).init(wasm.base.allocator);
1424 defer code_writer.deinit();1426 defer code_writer.deinit();
...@@ -1791,7 +1793,7 @@ pub fn freeDecl(wasm: *Wasm, decl_index: Module.Decl.Index) void {...@@ -1791,7 +1793,7 @@ pub fn freeDecl(wasm: *Wasm, decl_index: Module.Decl.Index) void {
1791 assert(wasm.symbol_atom.remove(local_atom.symbolLoc()));1793 assert(wasm.symbol_atom.remove(local_atom.symbolLoc()));
1792 }1794 }
17931795
1794 if (decl.isExtern()) {1796 if (decl.isExtern(mod)) {
1795 _ = wasm.imports.remove(atom.symbolLoc());1797 _ = wasm.imports.remove(atom.symbolLoc());
1796 }1798 }
1797 _ = wasm.resolved_symbols.swapRemove(atom.symbolLoc());1799 _ = wasm.resolved_symbols.swapRemove(atom.symbolLoc());
...@@ -1852,7 +1854,7 @@ pub fn addOrUpdateImport(...@@ -1852,7 +1854,7 @@ pub fn addOrUpdateImport(
1852 /// Symbol index that is external1854 /// Symbol index that is external
1853 symbol_index: u32,1855 symbol_index: u32,
1854 /// Optional library name (i.e. `extern "c" fn foo() void`1856 /// Optional library name (i.e. `extern "c" fn foo() void`
1855 lib_name: ?[*:0]const u8,1857 lib_name: ?[:0]const u8,
1856 /// The index of the type that represents the function signature1858 /// The index of the type that represents the function signature
1857 /// when the extern is a function. When this is null, a data-symbol1859 /// when the extern is a function. When this is null, a data-symbol
1858 /// is asserted instead.1860 /// is asserted instead.
...@@ -1863,7 +1865,7 @@ pub fn addOrUpdateImport(...@@ -1863,7 +1865,7 @@ pub fn addOrUpdateImport(
1863 // Also mangle the name when the lib name is set and not equal to "C" so imports with the same1865 // Also mangle the name when the lib name is set and not equal to "C" so imports with the same
1864 // name but different module can be resolved correctly.1866 // name but different module can be resolved correctly.
1865 const mangle_name = lib_name != null and1867 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");
1867 const full_name = if (mangle_name) full_name: {1869 const full_name = if (mangle_name) full_name: {
1868 break :full_name try std.fmt.allocPrint(wasm.base.allocator, "{s}|{s}", .{ name, lib_name.? });1870 break :full_name try std.fmt.allocPrint(wasm.base.allocator, "{s}|{s}", .{ name, lib_name.? });
1869 } else name;1871 } else name;
...@@ -1889,7 +1891,7 @@ pub fn addOrUpdateImport(...@@ -1889,7 +1891,7 @@ pub fn addOrUpdateImport(
1889 if (type_index) |ty_index| {1891 if (type_index) |ty_index| {
1890 const gop = try wasm.imports.getOrPut(wasm.base.allocator, .{ .index = symbol_index, .file = null });1892 const gop = try wasm.imports.getOrPut(wasm.base.allocator, .{ .index = symbol_index, .file = null });
1891 const module_name = if (lib_name) |l_name| blk: {1893 const module_name = if (lib_name) |l_name| blk: {
1892 break :blk mem.sliceTo(l_name, 0);1894 break :blk l_name;
1893 } else wasm.host_name;1895 } else wasm.host_name;
1894 if (!gop.found_existing) {1896 if (!gop.found_existing) {
1895 gop.value_ptr.* = .{1897 gop.value_ptr.* = .{
...@@ -2931,7 +2933,7 @@ pub fn getErrorTableSymbol(wasm: *Wasm) !u32 {...@@ -2931,7 +2933,7 @@ pub fn getErrorTableSymbol(wasm: *Wasm) !u32 {
29312933
2932 const atom_index = try wasm.createAtom();2934 const atom_index = try wasm.createAtom();
2933 const atom = wasm.getAtomPtr(atom_index);2935 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;
2935 const mod = wasm.base.options.module.?;2937 const mod = wasm.base.options.module.?;
2936 atom.alignment = slice_ty.abiAlignment(mod);2938 atom.alignment = slice_ty.abiAlignment(mod);
2937 const sym_index = atom.sym_index;2939 const sym_index = atom.sym_index;
...@@ -2988,7 +2990,7 @@ fn populateErrorNameTable(wasm: *Wasm) !void {...@@ -2988,7 +2990,7 @@ fn populateErrorNameTable(wasm: *Wasm) !void {
2988 for (mod.error_name_list.items) |error_name| {2990 for (mod.error_name_list.items) |error_name| {
2989 const len = @intCast(u32, error_name.len + 1); // names are 0-termianted2991 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;
2992 const offset = @intCast(u32, atom.code.items.len);2994 const offset = @intCast(u32, atom.code.items.len);
2993 // first we create the data for the slice of the name2995 // first we create the data for the slice of the name
2994 try atom.code.appendNTimes(wasm.base.allocator, 0, 4); // ptr to name, will be relocated2996 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...@@ -3366,15 +3368,15 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
3366 var decl_it = wasm.decls.iterator();3368 var decl_it = wasm.decls.iterator();
3367 while (decl_it.next()) |entry| {3369 while (decl_it.next()) |entry| {
3368 const decl = mod.declPtr(entry.key_ptr.*);3370 const decl = mod.declPtr(entry.key_ptr.*);
3369 if (decl.isExtern()) continue;3371 if (decl.isExtern(mod)) continue;
3370 const atom_index = entry.value_ptr.*;3372 const atom_index = entry.value_ptr.*;
3371 const atom = wasm.getAtomPtr(atom_index);3373 const atom = wasm.getAtomPtr(atom_index);
3372 if (decl.ty.zigTypeTag(mod) == .Fn) {3374 if (decl.ty.zigTypeTag(mod) == .Fn) {
3373 try wasm.parseAtom(atom_index, .function);3375 try wasm.parseAtom(atom_index, .function);
3374 } else if (decl.getVariable()) |variable| {3376 } else if (decl.getVariable(mod)) |variable| {
3375 if (!variable.is_mutable) {3377 if (variable.is_const) {
3376 try wasm.parseAtom(atom_index, .{ .data = .read_only });3378 try wasm.parseAtom(atom_index, .{ .data = .read_only });
3377 } else if (variable.init.isUndefDeep(mod)) {3379 } else if (variable.init.toValue().isUndefDeep(mod)) {
3378 // for safe build modes, we store the atom in the data segment,3380 // for safe build modes, we store the atom in the data segment,
3379 // whereas for unsafe build modes we store it in bss.3381 // whereas for unsafe build modes we store it in bss.
3380 const is_initialized = wasm.base.options.optimize_mode == .Debug or3382 const is_initialized = wasm.base.options.optimize_mode == .Debug or
src/print_air.zig+2-2
...@@ -699,8 +699,8 @@ const Writer = struct {...@@ -699,8 +699,8 @@ const Writer = struct {
699699
700 fn writeDbgInline(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {700 fn writeDbgInline(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
701 const ty_pl = w.air.instructions.items(.data)[inst].ty_pl;701 const ty_pl = w.air.instructions.items(.data)[inst].ty_pl;
702 const function = w.air.values[ty_pl.payload].castTag(.function).?.data;702 const func_index = w.module.intern_pool.indexToFunc(w.air.values[ty_pl.payload].ip_index);
703 const owner_decl = w.module.declPtr(function.owner_decl);703 const owner_decl = w.module.declPtr(w.module.funcPtrUnwrap(func_index).?.owner_decl);
704 try s.print("{s}", .{owner_decl.name});704 try s.print("{s}", .{owner_decl.name});
705 }705 }
706706
src/type.zig+290-173
...@@ -93,16 +93,23 @@ pub const Type = struct {...@@ -93,16 +93,23 @@ pub const Type = struct {
93 },93 },
9494
95 // values, not types95 // values, not types
96 .undef => unreachable,96 .undef,
97 .un => unreachable,97 .runtime_value,
98 .extern_func => unreachable,98 .simple_value,
99 .int => unreachable,99 .variable,
100 .float => unreachable,100 .extern_func,
101 .ptr => unreachable,101 .func,
102 .opt => unreachable,102 .int,
103 .enum_tag => unreachable,103 .err,
104 .simple_value => unreachable,104 .error_union,
105 .aggregate => unreachable,105 .enum_literal,
106 .enum_tag,
107 .float,
108 .ptr,
109 .opt,
110 .aggregate,
111 .un,
112 => unreachable,
106 };113 };
107 }114 }
108115
...@@ -358,7 +365,7 @@ pub const Type = struct {...@@ -358,7 +365,7 @@ pub const Type = struct {
358 const func = ies.func;365 const func = ies.func;
359366
360 try writer.writeAll("@typeInfo(@typeInfo(@TypeOf(");367 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);
362 try owner_decl.renderFullyQualifiedName(mod, writer);369 try owner_decl.renderFullyQualifiedName(mod, writer);
363 try writer.writeAll(")).Fn.return_type.?).ErrorUnion.error_set");370 try writer.writeAll(")).Fn.return_type.?).ErrorUnion.error_set");
364 },371 },
...@@ -467,16 +474,23 @@ pub const Type = struct {...@@ -467,16 +474,23 @@ pub const Type = struct {
467 },474 },
468475
469 // values, not types476 // values, not types
470 .undef => unreachable,477 .undef,
471 .un => unreachable,478 .runtime_value,
472 .simple_value => unreachable,479 .simple_value,
473 .extern_func => unreachable,480 .variable,
474 .int => unreachable,481 .extern_func,
475 .float => unreachable,482 .func,
476 .ptr => unreachable,483 .int,
477 .opt => unreachable,484 .err,
478 .enum_tag => unreachable,485 .error_union,
479 .aggregate => unreachable,486 .enum_literal,
487 .enum_tag,
488 .float,
489 .ptr,
490 .opt,
491 .aggregate,
492 .un,
493 => unreachable,
480 }494 }
481 }495 }
482496
...@@ -675,16 +689,23 @@ pub const Type = struct {...@@ -675,16 +689,23 @@ pub const Type = struct {
675 .enum_type => |enum_type| enum_type.tag_ty.toType().hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat),689 .enum_type => |enum_type| enum_type.tag_ty.toType().hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat),
676690
677 // values, not types691 // values, not types
678 .undef => unreachable,692 .undef,
679 .un => unreachable,693 .runtime_value,
680 .simple_value => unreachable,694 .simple_value,
681 .extern_func => unreachable,695 .variable,
682 .int => unreachable,696 .extern_func,
683 .float => unreachable,697 .func,
684 .ptr => unreachable,698 .int,
685 .opt => unreachable,699 .err,
686 .enum_tag => unreachable,700 .error_union,
687 .aggregate => unreachable,701 .enum_literal,
702 .enum_tag,
703 .float,
704 .ptr,
705 .opt,
706 .aggregate,
707 .un,
708 => unreachable,
688 },709 },
689 };710 };
690 }711 }
...@@ -777,16 +798,23 @@ pub const Type = struct {...@@ -777,16 +798,23 @@ pub const Type = struct {
777 },798 },
778799
779 // values, not types800 // values, not types
780 .undef => unreachable,801 .undef,
781 .un => unreachable,802 .runtime_value,
782 .simple_value => unreachable,803 .simple_value,
783 .extern_func => unreachable,804 .variable,
784 .int => unreachable,805 .extern_func,
785 .float => unreachable,806 .func,
786 .ptr => unreachable,807 .int,
787 .opt => unreachable,808 .err,
788 .enum_tag => unreachable,809 .error_union,
789 .aggregate => unreachable,810 .enum_literal,
811 .enum_tag,
812 .float,
813 .ptr,
814 .opt,
815 .aggregate,
816 .un,
817 => unreachable,
790 };818 };
791 }819 }
792820
...@@ -866,8 +894,8 @@ pub const Type = struct {...@@ -866,8 +894,8 @@ pub const Type = struct {
866894
867 /// May capture a reference to `ty`.895 /// May capture a reference to `ty`.
868 /// Returned value has type `comptime_int`.896 /// Returned value has type `comptime_int`.
869 pub fn lazyAbiAlignment(ty: Type, mod: *Module, arena: Allocator) !Value {897 pub fn lazyAbiAlignment(ty: Type, mod: *Module) !Value {
870 switch (try ty.abiAlignmentAdvanced(mod, .{ .lazy = arena })) {898 switch (try ty.abiAlignmentAdvanced(mod, .lazy)) {
871 .val => |val| return val,899 .val => |val| return val,
872 .scalar => |x| return mod.intValue(Type.comptime_int, x),900 .scalar => |x| return mod.intValue(Type.comptime_int, x),
873 }901 }
...@@ -880,7 +908,7 @@ pub const Type = struct {...@@ -880,7 +908,7 @@ pub const Type = struct {
880908
881 pub const AbiAlignmentAdvancedStrat = union(enum) {909 pub const AbiAlignmentAdvancedStrat = union(enum) {
882 eager,910 eager,
883 lazy: Allocator,911 lazy,
884 sema: *Sema,912 sema: *Sema,
885 };913 };
886914
...@@ -1019,16 +1047,18 @@ pub const Type = struct {...@@ -1019,16 +1047,18 @@ pub const Type = struct {
1019 if (!struct_obj.haveFieldTypes()) switch (strat) {1047 if (!struct_obj.haveFieldTypes()) switch (strat) {
1020 .eager => unreachable, // struct layout not resolved1048 .eager => unreachable, // struct layout not resolved
1021 .sema => unreachable, // handled above1049 .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() },
1023 };1054 };
1024 if (struct_obj.layout == .Packed) {1055 if (struct_obj.layout == .Packed) {
1025 switch (strat) {1056 switch (strat) {
1026 .sema => |sema| try sema.resolveTypeLayout(ty),1057 .sema => |sema| try sema.resolveTypeLayout(ty),
1027 .lazy => |arena| {1058 .lazy => if (!struct_obj.haveLayout()) return .{ .val = (try mod.intern(.{ .int = .{
1028 if (!struct_obj.haveLayout()) {1059 .ty = .comptime_int_type,
1029 return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) };1060 .storage = .{ .lazy_align = ty.ip_index },
1030 }1061 } })).toValue() },
1031 },
1032 .eager => {},1062 .eager => {},
1033 }1063 }
1034 assert(struct_obj.haveLayout());1064 assert(struct_obj.haveLayout());
...@@ -1039,7 +1069,10 @@ pub const Type = struct {...@@ -1039,7 +1069,10 @@ pub const Type = struct {
1039 var big_align: u32 = 0;1069 var big_align: u32 = 0;
1040 for (fields.values()) |field| {1070 for (fields.values()) |field| {
1041 if (!(field.ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {1071 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() },
1043 else => |e| return e,1076 else => |e| return e,
1044 })) continue;1077 })) continue;
10451078
...@@ -1050,7 +1083,10 @@ pub const Type = struct {...@@ -1050,7 +1083,10 @@ pub const Type = struct {
1050 .val => switch (strat) {1083 .val => switch (strat) {
1051 .eager => unreachable, // struct layout not resolved1084 .eager => unreachable, // struct layout not resolved
1052 .sema => unreachable, // handled above1085 .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() },
1054 },1090 },
1055 };1091 };
1056 big_align = @max(big_align, field_align);1092 big_align = @max(big_align, field_align);
...@@ -1077,7 +1113,10 @@ pub const Type = struct {...@@ -1077,7 +1113,10 @@ pub const Type = struct {
1077 .val => switch (strat) {1113 .val => switch (strat) {
1078 .eager => unreachable, // field type alignment not resolved1114 .eager => unreachable, // field type alignment not resolved
1079 .sema => unreachable, // passed to abiAlignmentAdvanced above1115 .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() },
1081 },1120 },
1082 }1121 }
1083 }1122 }
...@@ -1092,16 +1131,23 @@ pub const Type = struct {...@@ -1092,16 +1131,23 @@ pub const Type = struct {
1092 .enum_type => |enum_type| return AbiAlignmentAdvanced{ .scalar = enum_type.tag_ty.toType().abiAlignment(mod) },1131 .enum_type => |enum_type| return AbiAlignmentAdvanced{ .scalar = enum_type.tag_ty.toType().abiAlignment(mod) },
10931132
1094 // values, not types1133 // values, not types
1095 .undef => unreachable,1134 .undef,
1096 .un => unreachable,1135 .runtime_value,
1097 .simple_value => unreachable,1136 .simple_value,
1098 .extern_func => unreachable,1137 .variable,
1099 .int => unreachable,1138 .extern_func,
1100 .float => unreachable,1139 .func,
1101 .ptr => unreachable,1140 .int,
1102 .opt => unreachable,1141 .err,
1103 .enum_tag => unreachable,1142 .error_union,
1104 .aggregate => unreachable,1143 .enum_literal,
1144 .enum_tag,
1145 .float,
1146 .ptr,
1147 .opt,
1148 .aggregate,
1149 .un,
1150 => unreachable,
1105 },1151 },
1106 }1152 }
1107 }1153 }
...@@ -1118,7 +1164,10 @@ pub const Type = struct {...@@ -1118,7 +1164,10 @@ pub const Type = struct {
1118 switch (strat) {1164 switch (strat) {
1119 .eager, .sema => {1165 .eager, .sema => {
1120 if (!(payload_ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {1166 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() },
1122 else => |e| return e,1171 else => |e| return e,
1123 })) {1172 })) {
1124 return AbiAlignmentAdvanced{ .scalar = code_align };1173 return AbiAlignmentAdvanced{ .scalar = code_align };
...@@ -1128,7 +1177,7 @@ pub const Type = struct {...@@ -1128,7 +1177,7 @@ pub const Type = struct {
1128 (try payload_ty.abiAlignmentAdvanced(mod, strat)).scalar,1177 (try payload_ty.abiAlignmentAdvanced(mod, strat)).scalar,
1129 ) };1178 ) };
1130 },1179 },
1131 .lazy => |arena| {1180 .lazy => {
1132 switch (try payload_ty.abiAlignmentAdvanced(mod, strat)) {1181 switch (try payload_ty.abiAlignmentAdvanced(mod, strat)) {
1133 .scalar => |payload_align| {1182 .scalar => |payload_align| {
1134 return AbiAlignmentAdvanced{1183 return AbiAlignmentAdvanced{
...@@ -1137,7 +1186,10 @@ pub const Type = struct {...@@ -1137,7 +1186,10 @@ pub const Type = struct {
1137 },1186 },
1138 .val => {},1187 .val => {},
1139 }1188 }
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() };
1141 },1193 },
1142 }1194 }
1143 }1195 }
...@@ -1160,16 +1212,22 @@ pub const Type = struct {...@@ -1160,16 +1212,22 @@ pub const Type = struct {
1160 switch (strat) {1212 switch (strat) {
1161 .eager, .sema => {1213 .eager, .sema => {
1162 if (!(child_type.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {1214 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() },
1164 else => |e| return e,1219 else => |e| return e,
1165 })) {1220 })) {
1166 return AbiAlignmentAdvanced{ .scalar = 1 };1221 return AbiAlignmentAdvanced{ .scalar = 1 };
1167 }1222 }
1168 return child_type.abiAlignmentAdvanced(mod, strat);1223 return child_type.abiAlignmentAdvanced(mod, strat);
1169 },1224 },
1170 .lazy => |arena| switch (try child_type.abiAlignmentAdvanced(mod, strat)) {1225 .lazy => switch (try child_type.abiAlignmentAdvanced(mod, strat)) {
1171 .scalar => |x| return AbiAlignmentAdvanced{ .scalar = @max(x, 1) },1226 .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() },
1173 },1231 },
1174 }1232 }
1175 }1233 }
...@@ -1198,7 +1256,10 @@ pub const Type = struct {...@@ -1198,7 +1256,10 @@ pub const Type = struct {
1198 if (!union_obj.haveFieldTypes()) switch (strat) {1256 if (!union_obj.haveFieldTypes()) switch (strat) {
1199 .eager => unreachable, // union layout not resolved1257 .eager => unreachable, // union layout not resolved
1200 .sema => unreachable, // handled above1258 .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() },
1202 };1263 };
1203 if (union_obj.fields.count() == 0) {1264 if (union_obj.fields.count() == 0) {
1204 if (have_tag) {1265 if (have_tag) {
...@@ -1212,7 +1273,10 @@ pub const Type = struct {...@@ -1212,7 +1273,10 @@ pub const Type = struct {
1212 if (have_tag) max_align = union_obj.tag_ty.abiAlignment(mod);1273 if (have_tag) max_align = union_obj.tag_ty.abiAlignment(mod);
1213 for (union_obj.fields.values()) |field| {1274 for (union_obj.fields.values()) |field| {
1214 if (!(field.ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {1275 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() },
1216 else => |e| return e,1280 else => |e| return e,
1217 })) continue;1281 })) continue;
12181282
...@@ -1223,7 +1287,10 @@ pub const Type = struct {...@@ -1223,7 +1287,10 @@ pub const Type = struct {
1223 .val => switch (strat) {1287 .val => switch (strat) {
1224 .eager => unreachable, // struct layout not resolved1288 .eager => unreachable, // struct layout not resolved
1225 .sema => unreachable, // handled above1289 .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() },
1227 },1294 },
1228 };1295 };
1229 max_align = @max(max_align, field_align);1296 max_align = @max(max_align, field_align);
...@@ -1232,8 +1299,8 @@ pub const Type = struct {...@@ -1232,8 +1299,8 @@ pub const Type = struct {
1232 }1299 }
12331300
1234 /// May capture a reference to `ty`.1301 /// May capture a reference to `ty`.
1235 pub fn lazyAbiSize(ty: Type, mod: *Module, arena: Allocator) !Value {1302 pub fn lazyAbiSize(ty: Type, mod: *Module) !Value {
1236 switch (try ty.abiSizeAdvanced(mod, .{ .lazy = arena })) {1303 switch (try ty.abiSizeAdvanced(mod, .lazy)) {
1237 .val => |val| return val,1304 .val => |val| return val,
1238 .scalar => |x| return mod.intValue(Type.comptime_int, x),1305 .scalar => |x| return mod.intValue(Type.comptime_int, x),
1239 }1306 }
...@@ -1283,7 +1350,10 @@ pub const Type = struct {...@@ -1283,7 +1350,10 @@ pub const Type = struct {
1283 .scalar => |elem_size| return .{ .scalar = len * elem_size },1350 .scalar => |elem_size| return .{ .scalar = len * elem_size },
1284 .val => switch (strat) {1351 .val => switch (strat) {
1285 .sema, .eager => unreachable,1352 .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() },
1287 },1357 },
1288 }1358 }
1289 },1359 },
...@@ -1291,9 +1361,10 @@ pub const Type = struct {...@@ -1291,9 +1361,10 @@ pub const Type = struct {
1291 const opt_sema = switch (strat) {1361 const opt_sema = switch (strat) {
1292 .sema => |sema| sema,1362 .sema => |sema| sema,
1293 .eager => null,1363 .eager => null,
1294 .lazy => |arena| return AbiSizeAdvanced{1364 .lazy => return .{ .val = (try mod.intern(.{ .int = .{
1295 .val = try Value.Tag.lazy_size.create(arena, ty),1365 .ty = .comptime_int_type,
1296 },1366 .storage = .{ .lazy_size = ty.ip_index },
1367 } })).toValue() },
1297 };1368 };
1298 const elem_bits_u64 = try vector_type.child.toType().bitSizeAdvanced(mod, opt_sema);1369 const elem_bits_u64 = try vector_type.child.toType().bitSizeAdvanced(mod, opt_sema);
1299 const elem_bits = @intCast(u32, elem_bits_u64);1370 const elem_bits = @intCast(u32, elem_bits_u64);
...@@ -1301,9 +1372,10 @@ pub const Type = struct {...@@ -1301,9 +1372,10 @@ pub const Type = struct {
1301 const total_bytes = (total_bits + 7) / 8;1372 const total_bytes = (total_bits + 7) / 8;
1302 const alignment = switch (try ty.abiAlignmentAdvanced(mod, strat)) {1373 const alignment = switch (try ty.abiAlignmentAdvanced(mod, strat)) {
1303 .scalar => |x| x,1374 .scalar => |x| x,
1304 .val => return AbiSizeAdvanced{1375 .val => return .{ .val = (try mod.intern(.{ .int = .{
1305 .val = try Value.Tag.lazy_size.create(strat.lazy, ty),1376 .ty = .comptime_int_type,
1306 },1377 .storage = .{ .lazy_size = ty.ip_index },
1378 } })).toValue() },
1307 };1379 };
1308 const result = std.mem.alignForwardGeneric(u32, total_bytes, alignment);1380 const result = std.mem.alignForwardGeneric(u32, total_bytes, alignment);
1309 return AbiSizeAdvanced{ .scalar = result };1381 return AbiSizeAdvanced{ .scalar = result };
...@@ -1320,7 +1392,10 @@ pub const Type = struct {...@@ -1320,7 +1392,10 @@ pub const Type = struct {
1320 // in abiAlignmentAdvanced.1392 // in abiAlignmentAdvanced.
1321 const code_size = abiSize(Type.anyerror, mod);1393 const code_size = abiSize(Type.anyerror, mod);
1322 if (!(payload_ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {1394 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() },
1324 else => |e| return e,1399 else => |e| return e,
1325 })) {1400 })) {
1326 // Same as anyerror.1401 // Same as anyerror.
...@@ -1333,7 +1408,10 @@ pub const Type = struct {...@@ -1333,7 +1408,10 @@ pub const Type = struct {
1333 .val => switch (strat) {1408 .val => switch (strat) {
1334 .sema => unreachable,1409 .sema => unreachable,
1335 .eager => unreachable,1410 .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() },
1337 },1415 },
1338 };1416 };
13391417
...@@ -1420,11 +1498,10 @@ pub const Type = struct {...@@ -1420,11 +1498,10 @@ pub const Type = struct {
14201498
1421 switch (strat) {1499 switch (strat) {
1422 .sema => |sema| try sema.resolveTypeLayout(ty),1500 .sema => |sema| try sema.resolveTypeLayout(ty),
1423 .lazy => |arena| {1501 .lazy => if (!struct_obj.haveLayout()) return .{ .val = (try mod.intern(.{ .int = .{
1424 if (!struct_obj.haveLayout()) {1502 .ty = .comptime_int_type,
1425 return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) };1503 .storage = .{ .lazy_size = ty.ip_index },
1426 }1504 } })).toValue() },
1427 },
1428 .eager => {},1505 .eager => {},
1429 }1506 }
1430 assert(struct_obj.haveLayout());1507 assert(struct_obj.haveLayout());
...@@ -1433,12 +1510,13 @@ pub const Type = struct {...@@ -1433,12 +1510,13 @@ pub const Type = struct {
1433 else => {1510 else => {
1434 switch (strat) {1511 switch (strat) {
1435 .sema => |sema| try sema.resolveTypeLayout(ty),1512 .sema => |sema| try sema.resolveTypeLayout(ty),
1436 .lazy => |arena| {1513 .lazy => {
1437 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse1514 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse
1438 return AbiSizeAdvanced{ .scalar = 0 };1515 return AbiSizeAdvanced{ .scalar = 0 };
1439 if (!struct_obj.haveLayout()) {1516 if (!struct_obj.haveLayout()) return .{ .val = (try mod.intern(.{ .int = .{
1440 return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) };1517 .ty = .comptime_int_type,
1441 }1518 .storage = .{ .lazy_size = ty.ip_index },
1519 } })).toValue() };
1442 },1520 },
1443 .eager => {},1521 .eager => {},
1444 }1522 }
...@@ -1469,16 +1547,23 @@ pub const Type = struct {...@@ -1469,16 +1547,23 @@ pub const Type = struct {
1469 .enum_type => |enum_type| return AbiSizeAdvanced{ .scalar = enum_type.tag_ty.toType().abiSize(mod) },1547 .enum_type => |enum_type| return AbiSizeAdvanced{ .scalar = enum_type.tag_ty.toType().abiSize(mod) },
14701548
1471 // values, not types1549 // values, not types
1472 .undef => unreachable,1550 .undef,
1473 .un => unreachable,1551 .runtime_value,
1474 .simple_value => unreachable,1552 .simple_value,
1475 .extern_func => unreachable,1553 .variable,
1476 .int => unreachable,1554 .extern_func,
1477 .float => unreachable,1555 .func,
1478 .ptr => unreachable,1556 .int,
1479 .opt => unreachable,1557 .err,
1480 .enum_tag => unreachable,1558 .error_union,
1481 .aggregate => unreachable,1559 .enum_literal,
1560 .enum_tag,
1561 .float,
1562 .ptr,
1563 .opt,
1564 .aggregate,
1565 .un,
1566 => unreachable,
1482 },1567 },
1483 }1568 }
1484 }1569 }
...@@ -1492,11 +1577,10 @@ pub const Type = struct {...@@ -1492,11 +1577,10 @@ pub const Type = struct {
1492 ) Module.CompileError!AbiSizeAdvanced {1577 ) Module.CompileError!AbiSizeAdvanced {
1493 switch (strat) {1578 switch (strat) {
1494 .sema => |sema| try sema.resolveTypeLayout(ty),1579 .sema => |sema| try sema.resolveTypeLayout(ty),
1495 .lazy => |arena| {1580 .lazy => if (!union_obj.haveLayout()) return .{ .val = (try mod.intern(.{ .int = .{
1496 if (!union_obj.haveLayout()) {1581 .ty = .comptime_int_type,
1497 return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) };1582 .storage = .{ .lazy_size = ty.ip_index },
1498 }1583 } })).toValue() },
1499 },
1500 .eager => {},1584 .eager => {},
1501 }1585 }
1502 return AbiSizeAdvanced{ .scalar = union_obj.abiSize(mod, have_tag) };1586 return AbiSizeAdvanced{ .scalar = union_obj.abiSize(mod, have_tag) };
...@@ -1514,7 +1598,10 @@ pub const Type = struct {...@@ -1514,7 +1598,10 @@ pub const Type = struct {
1514 }1598 }
15151599
1516 if (!(child_ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {1600 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() },
1518 else => |e| return e,1605 else => |e| return e,
1519 })) return AbiSizeAdvanced{ .scalar = 1 };1606 })) return AbiSizeAdvanced{ .scalar = 1 };
15201607
...@@ -1527,7 +1614,10 @@ pub const Type = struct {...@@ -1527,7 +1614,10 @@ pub const Type = struct {
1527 .val => switch (strat) {1614 .val => switch (strat) {
1528 .sema => unreachable,1615 .sema => unreachable,
1529 .eager => unreachable,1616 .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() },
1531 },1621 },
1532 };1622 };
15331623
...@@ -1690,16 +1780,23 @@ pub const Type = struct {...@@ -1690,16 +1780,23 @@ pub const Type = struct {
1690 .enum_type => |enum_type| return bitSizeAdvanced(enum_type.tag_ty.toType(), mod, opt_sema),1780 .enum_type => |enum_type| return bitSizeAdvanced(enum_type.tag_ty.toType(), mod, opt_sema),
16911781
1692 // values, not types1782 // values, not types
1693 .undef => unreachable,1783 .undef,
1694 .un => unreachable,1784 .runtime_value,
1695 .simple_value => unreachable,1785 .simple_value,
1696 .extern_func => unreachable,1786 .variable,
1697 .int => unreachable,1787 .extern_func,
1698 .float => unreachable,1788 .func,
1699 .ptr => unreachable,1789 .int,
1700 .opt => unreachable,1790 .err,
1701 .enum_tag => unreachable,1791 .error_union,
1702 .aggregate => unreachable,1792 .enum_literal,
1793 .enum_tag,
1794 .float,
1795 .ptr,
1796 .opt,
1797 .aggregate,
1798 .un,
1799 => unreachable,
1703 }1800 }
1704 }1801 }
17051802
...@@ -2270,16 +2367,23 @@ pub const Type = struct {...@@ -2270,16 +2367,23 @@ pub const Type = struct {
2270 .opaque_type => unreachable,2367 .opaque_type => unreachable,
22712368
2272 // values, not types2369 // values, not types
2273 .undef => unreachable,2370 .undef,
2274 .un => unreachable,2371 .runtime_value,
2275 .simple_value => unreachable,2372 .simple_value,
2276 .extern_func => unreachable,2373 .variable,
2277 .int => unreachable,2374 .extern_func,
2278 .float => unreachable,2375 .func,
2279 .ptr => unreachable,2376 .int,
2280 .opt => unreachable,2377 .err,
2281 .enum_tag => unreachable,2378 .error_union,
2282 .aggregate => unreachable,2379 .enum_literal,
2380 .enum_tag,
2381 .float,
2382 .ptr,
2383 .opt,
2384 .aggregate,
2385 .un,
2386 => unreachable,
2283 },2387 },
2284 };2388 };
2285 }2389 }
...@@ -2443,16 +2547,17 @@ pub const Type = struct {...@@ -2443,16 +2547,17 @@ pub const Type = struct {
2443 .inferred_error_set_type,2547 .inferred_error_set_type,
2444 => return null,2548 => return null,
24452549
2446 .array_type => |array_type| {2550 inline .array_type, .vector_type => |seq_type| {
2447 if (array_type.len == 0)2551 if (seq_type.len == 0) return (try mod.intern(.{ .aggregate = .{
2448 return Value.initTag(.empty_array);2552 .ty = ty.ip_index,
2449 if ((try array_type.child.toType().onePossibleValue(mod)) != null)2553 .storage = .{ .elems = &.{} },
2450 return Value.initTag(.the_only_possible_value);2554 } })).toValue();
2451 return null;2555 if (try seq_type.child.toType().onePossibleValue(mod)) |opv| {
2452 },2556 return (try mod.intern(.{ .aggregate = .{
2453 .vector_type => |vector_type| {2557 .ty = ty.ip_index,
2454 if (vector_type.len == 0) return Value.initTag(.empty_array);2558 .storage = .{ .repeated_elem = opv.ip_index },
2455 if (try vector_type.child.toType().onePossibleValue(mod)) |v| return v;2559 } })).toValue();
2560 }
2456 return null;2561 return null;
2457 },2562 },
2458 .opt_type => |child| {2563 .opt_type => |child| {
...@@ -2595,16 +2700,23 @@ pub const Type = struct {...@@ -2595,16 +2700,23 @@ pub const Type = struct {
2595 },2700 },
25962701
2597 // values, not types2702 // values, not types
2598 .undef => unreachable,2703 .undef,
2599 .un => unreachable,2704 .runtime_value,
2600 .simple_value => unreachable,2705 .simple_value,
2601 .extern_func => unreachable,2706 .variable,
2602 .int => unreachable,2707 .extern_func,
2603 .float => unreachable,2708 .func,
2604 .ptr => unreachable,2709 .int,
2605 .opt => unreachable,2710 .err,
2606 .enum_tag => unreachable,2711 .error_union,
2607 .aggregate => unreachable,2712 .enum_literal,
2713 .enum_tag,
2714 .float,
2715 .ptr,
2716 .opt,
2717 .aggregate,
2718 .un,
2719 => unreachable,
2608 },2720 },
2609 };2721 };
2610 }2722 }
...@@ -2733,16 +2845,23 @@ pub const Type = struct {...@@ -2733,16 +2845,23 @@ pub const Type = struct {
2733 .enum_type => |enum_type| enum_type.tag_ty.toType().comptimeOnly(mod),2845 .enum_type => |enum_type| enum_type.tag_ty.toType().comptimeOnly(mod),
27342846
2735 // values, not types2847 // values, not types
2736 .undef => unreachable,2848 .undef,
2737 .un => unreachable,2849 .runtime_value,
2738 .simple_value => unreachable,2850 .simple_value,
2739 .extern_func => unreachable,2851 .variable,
2740 .int => unreachable,2852 .extern_func,
2741 .float => unreachable,2853 .func,
2742 .ptr => unreachable,2854 .int,
2743 .opt => unreachable,2855 .err,
2744 .enum_tag => unreachable,2856 .error_union,
2745 .aggregate => unreachable,2857 .enum_literal,
2858 .enum_tag,
2859 .float,
2860 .ptr,
2861 .opt,
2862 .aggregate,
2863 .un,
2864 => unreachable,
2746 },2865 },
2747 };2866 };
2748 }2867 }
...@@ -2802,13 +2921,12 @@ pub const Type = struct {...@@ -2802,13 +2921,12 @@ pub const Type = struct {
2802 }2921 }
28032922
2804 // Works for vectors and vectors of integers.2923 // 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 {
2806 const scalar = try minIntScalar(ty.scalarType(mod), mod);2925 const scalar = try minIntScalar(ty.scalarType(mod), mod);
2807 if (ty.zigTypeTag(mod) == .Vector and scalar.tag() != .the_only_possible_value) {2926 return if (ty.zigTypeTag(mod) == .Vector) (try mod.intern(.{ .aggregate = .{
2808 return Value.Tag.repeated.create(arena, scalar);2927 .ty = ty.ip_index,
2809 } else {2928 .storage = .{ .repeated_elem = scalar.ip_index },
2810 return scalar;2929 } })).toValue() else scalar;
2811 }
2812 }2930 }
28132931
2814 /// Asserts that the type is an integer.2932 /// Asserts that the type is an integer.
...@@ -2832,13 +2950,12 @@ pub const Type = struct {...@@ -2832,13 +2950,12 @@ pub const Type = struct {
28322950
2833 // Works for vectors and vectors of integers.2951 // Works for vectors and vectors of integers.
2834 /// The returned Value will have type dest_ty.2952 /// 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 {
2836 const scalar = try maxIntScalar(ty.scalarType(mod), mod, dest_ty);2954 const scalar = try maxIntScalar(ty.scalarType(mod), mod, dest_ty);
2837 if (ty.zigTypeTag(mod) == .Vector and scalar.tag() != .the_only_possible_value) {2955 return if (ty.zigTypeTag(mod) == .Vector) (try mod.intern(.{ .aggregate = .{
2838 return Value.Tag.repeated.create(arena, scalar);2956 .ty = ty.ip_index,
2839 } else {2957 .storage = .{ .repeated_elem = scalar.ip_index },
2840 return scalar;2958 } })).toValue() else scalar;
2841 }
2842 }2959 }
28432960
2844 /// The returned Value will have type dest_ty.2961 /// The returned Value will have type dest_ty.
...@@ -3386,12 +3503,12 @@ pub const Type = struct {...@@ -3386,12 +3503,12 @@ pub const Type = struct {
3386 pub const @"c_ulonglong": Type = .{ .ip_index = .c_ulonglong_type };3503 pub const @"c_ulonglong": Type = .{ .ip_index = .c_ulonglong_type };
3387 pub const @"c_longdouble": Type = .{ .ip_index = .c_longdouble_type };3504 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 };
3390 pub const manyptr_u8: Type = .{ .ip_index = .manyptr_u8_type };3507 pub const manyptr_u8: Type = .{ .ip_index = .manyptr_u8_type };
3391 pub const single_const_pointer_to_comptime_int: Type = .{3508 pub const single_const_pointer_to_comptime_int: Type = .{
3392 .ip_index = .single_const_pointer_to_comptime_int_type,3509 .ip_index = .single_const_pointer_to_comptime_int_type,
3393 };3510 };
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 };
3395 pub const empty_struct_literal: Type = .{ .ip_index = .empty_struct_type };3512 pub const empty_struct_literal: Type = .{ .ip_index = .empty_struct_type };
33963513
3397 pub const generic_poison: Type = .{ .ip_index = .generic_poison_type };3514 pub const generic_poison: Type = .{ .ip_index = .generic_poison_type };
src/value.zig+422-1353
...@@ -33,64 +33,12 @@ pub const Value = struct {...@@ -33,64 +33,12 @@ pub const Value = struct {
33 // Keep in sync with tools/stage2_pretty_printers_common.py33 // Keep in sync with tools/stage2_pretty_printers_common.py
34 pub const Tag = enum(usize) {34 pub const Tag = enum(usize) {
35 // The first section of this enum are tags that require no payload.35 // 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.
40 // After this, the tag requires a payload.36 // 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,
63 /// A slice of u8 whose memory is managed externally.38 /// A slice of u8 whose memory is managed externally.
64 bytes,39 bytes,
65 /// Similar to bytes however it stores an index relative to `Module.string_literal_bytes`.40 /// Similar to bytes however it stores an index relative to `Module.string_literal_bytes`.
66 str_lit,41 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,
94 /// An instance of a struct, array, or vector.42 /// An instance of a struct, array, or vector.
95 /// Each element/field stored as a `Value`.43 /// Each element/field stored as a `Value`.
96 /// In the case of sentinel-terminated arrays, the sentinel value *is* stored,44 /// In the case of sentinel-terminated arrays, the sentinel value *is* stored,
...@@ -104,57 +52,19 @@ pub const Value = struct {...@@ -104,57 +52,19 @@ pub const Value = struct {
104 /// Used to coordinate alloc_inferred, store_to_inferred_ptr, and resolve_inferred_alloc52 /// Used to coordinate alloc_inferred, store_to_inferred_ptr, and resolve_inferred_alloc
105 /// instructions for comptime code.53 /// instructions for comptime code.
106 inferred_alloc_comptime,54 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;56 pub const no_payload_count = 0;
113 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
11457
115 pub fn Type(comptime t: Tag) type {58 pub fn Type(comptime t: Tag) type {
116 return switch (t) {59 return switch (t) {
117 .the_only_possible_value,60 .bytes => Payload.Bytes,
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,
13961
140 .str_lit => Payload.StrLit,62 .str_lit => Payload.StrLit,
141 .slice => Payload.Slice,63
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,
153 .inferred_alloc => Payload.InferredAlloc,64 .inferred_alloc => Payload.InferredAlloc,
154 .inferred_alloc_comptime => Payload.InferredAllocComptime,65 .inferred_alloc_comptime => Payload.InferredAllocComptime,
155 .aggregate => Payload.Aggregate,66 .aggregate => Payload.Aggregate,
156 .@"union" => Payload.Union,67 .@"union" => Payload.Union,
157 .comptime_field_ptr => Payload.ComptimeFieldPtr,
158 };68 };
159 }69 }
16070
...@@ -249,91 +159,6 @@ pub const Value = struct {...@@ -249,91 +159,6 @@ pub const Value = struct {
249 .legacy = .{ .tag_if_small_enough = self.legacy.tag_if_small_enough },159 .legacy = .{ .tag_if_small_enough = self.legacy.tag_if_small_enough },
250 };160 };
251 } else switch (self.legacy.ptr_otherwise.tag) {161 } 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 },
337 .bytes => {162 .bytes => {
338 const bytes = self.castTag(.bytes).?.data;163 const bytes = self.castTag(.bytes).?.data;
339 const new_payload = try arena.create(Payload.Bytes);164 const new_payload = try arena.create(Payload.Bytes);
...@@ -347,52 +172,6 @@ pub const Value = struct {...@@ -347,52 +172,6 @@ pub const Value = struct {
347 };172 };
348 },173 },
349 .str_lit => return self.copyPayloadShallow(arena, Payload.StrLit),174 .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
396 .aggregate => {175 .aggregate => {
397 const payload = self.castTag(.aggregate).?;176 const payload = self.castTag(.aggregate).?;
398 const new_payload = try arena.create(Payload.Aggregate);177 const new_payload = try arena.create(Payload.Aggregate);
...@@ -453,7 +232,7 @@ pub const Value = struct {...@@ -453,7 +232,7 @@ pub const Value = struct {
453 pub fn dump(232 pub fn dump(
454 start_val: Value,233 start_val: Value,
455 comptime fmt: []const u8,234 comptime fmt: []const u8,
456 options: std.fmt.FormatOptions,235 _: std.fmt.FormatOptions,
457 out_stream: anytype,236 out_stream: anytype,
458 ) !void {237 ) !void {
459 comptime assert(fmt.len == 0);238 comptime assert(fmt.len == 0);
...@@ -469,44 +248,6 @@ pub const Value = struct {...@@ -469,44 +248,6 @@ pub const Value = struct {
469 .@"union" => {248 .@"union" => {
470 return out_stream.writeAll("(union value)");249 return out_stream.writeAll("(union value)");
471 },250 },
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)}),
510 .bytes => return out_stream.print("\"{}\"", .{std.zig.fmtEscapes(val.castTag(.bytes).?.data)}),251 .bytes => return out_stream.print("\"{}\"", .{std.zig.fmtEscapes(val.castTag(.bytes).?.data)}),
511 .str_lit => {252 .str_lit => {
512 const str_lit = val.castTag(.str_lit).?.data;253 const str_lit = val.castTag(.str_lit).?.data;
...@@ -514,31 +255,8 @@ pub const Value = struct {...@@ -514,31 +255,8 @@ pub const Value = struct {
514 str_lit.index, str_lit.len,255 str_lit.index, str_lit.len,
515 });256 });
516 },257 },
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 },
532 .inferred_alloc => return out_stream.writeAll("(inferred allocation value)"),258 .inferred_alloc => return out_stream.writeAll("(inferred allocation value)"),
533 .inferred_alloc_comptime => return out_stream.writeAll("(inferred comptime allocation value)"),259 .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 },
542 };260 };
543 }261 }
544262
...@@ -569,30 +287,23 @@ pub const Value = struct {...@@ -569,30 +287,23 @@ pub const Value = struct {
569 const bytes = mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len];287 const bytes = mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len];
570 return allocator.dupe(u8, bytes);288 return allocator.dupe(u8, bytes);
571 },289 },
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 },
590 else => return arrayToAllocatedBytes(val, ty.arrayLen(mod), allocator, mod),290 else => return arrayToAllocatedBytes(val, ty.arrayLen(mod), allocator, mod),
591 },291 },
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)),
593 .ptr => |ptr| switch (ptr.len) {294 .ptr => |ptr| switch (ptr.len) {
594 .none => unreachable,295 .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 },
596 },307 },
597 else => unreachable,308 else => unreachable,
598 },309 },
...@@ -611,29 +322,6 @@ pub const Value = struct {...@@ -611,29 +322,6 @@ pub const Value = struct {
611 pub fn intern(val: Value, ty: Type, mod: *Module) Allocator.Error!InternPool.Index {322 pub fn intern(val: Value, ty: Type, mod: *Module) Allocator.Error!InternPool.Index {
612 if (val.ip_index != .none) return mod.intern_pool.getCoerced(mod.gpa, val.ip_index, ty.ip_index);323 if (val.ip_index != .none) return mod.intern_pool.getCoerced(mod.gpa, val.ip_index, ty.ip_index);
613 switch (val.tag()) {324 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 } }),
637 .aggregate => {325 .aggregate => {
638 const old_elems = val.castTag(.aggregate).?.data;326 const old_elems = val.castTag(.aggregate).?.data;
639 const new_elems = try mod.gpa.alloc(InternPool.Index, old_elems.len);327 const new_elems = try mod.gpa.alloc(InternPool.Index, old_elems.len);
...@@ -651,13 +339,6 @@ pub const Value = struct {...@@ -651,13 +339,6 @@ pub const Value = struct {
651 .storage = .{ .elems = new_elems },339 .storage = .{ .elems = new_elems },
652 } });340 } });
653 },341 },
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 } }),
661 .@"union" => {342 .@"union" => {
662 const pl = val.castTag(.@"union").?.data;343 const pl = val.castTag(.@"union").?.data;
663 return mod.intern(.{ .un = .{344 return mod.intern(.{ .un = .{
...@@ -679,7 +360,6 @@ pub const Value = struct {...@@ -679,7 +360,6 @@ pub const Value = struct {
679 for (new_elems, old_elems) |*new_elem, old_elem| new_elem.* = old_elem.toValue();360 for (new_elems, old_elems) |*new_elem, old_elem| new_elem.* = old_elem.toValue();
680 return Tag.aggregate.create(arena, new_elems);361 return Tag.aggregate.create(arena, new_elems);
681 },362 },
682 .repeated_elem => |elem| return Tag.repeated.create(arena, elem.toValue()),
683 },363 },
684 else => return val,364 else => return val,
685 }365 }
...@@ -698,31 +378,21 @@ pub const Value = struct {...@@ -698,31 +378,21 @@ pub const Value = struct {
698 pub fn enumToInt(val: Value, ty: Type, mod: *Module) Allocator.Error!Value {378 pub fn enumToInt(val: Value, ty: Type, mod: *Module) Allocator.Error!Value {
699 const ip = &mod.intern_pool;379 const ip = &mod.intern_pool;
700 switch (val.ip_index) {380 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 },
723 else => return switch (ip.indexToKey(ip.typeOf(val.ip_index))) {381 else => return switch (ip.indexToKey(ip.typeOf(val.ip_index))) {
724 // Assume it is already an integer and return it directly.382 // Assume it is already an integer and return it directly.
725 .simple_type, .int_type => val,383 .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 },
726 .enum_type => |enum_type| (try ip.getCoerced(396 .enum_type => |enum_type| (try ip.getCoerced(
727 mod.gpa,397 mod.gpa,
728 val.ip_index,398 val.ip_index,
...@@ -733,18 +403,12 @@ pub const Value = struct {...@@ -733,18 +403,12 @@ pub const Value = struct {
733 }403 }
734 }404 }
735405
736 pub fn tagName(val: Value, ty: Type, mod: *Module) []const u8 {406 pub fn tagName(val: Value, 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
743 const ip = &mod.intern_pool;407 const ip = &mod.intern_pool;
744
745 const enum_tag = switch (ip.indexToKey(val.ip_index)) {408 const enum_tag = switch (ip.indexToKey(val.ip_index)) {
746 .un => |un| ip.indexToKey(un.tag).enum_tag,409 .un => |un| ip.indexToKey(un.tag).enum_tag,
747 .enum_tag => |x| x,410 .enum_tag => |x| x,
411 .enum_literal => |name| return ip.stringToSlice(name),
748 else => unreachable,412 else => unreachable,
749 };413 };
750 const enum_type = ip.indexToKey(enum_tag.ty).enum_type;414 const enum_type = ip.indexToKey(enum_tag.ty).enum_type;
...@@ -773,49 +437,61 @@ pub const Value = struct {...@@ -773,49 +437,61 @@ pub const Value = struct {
773 .bool_true => BigIntMutable.init(&space.limbs, 1).toConst(),437 .bool_true => BigIntMutable.init(&space.limbs, 1).toConst(),
774 .undef => unreachable,438 .undef => unreachable,
775 .null_value => BigIntMutable.init(&space.limbs, 0).toConst(),439 .null_value => BigIntMutable.init(&space.limbs, 0).toConst(),
776 .none => switch (val.tag()) {440 else => switch (mod.intern_pool.indexToKey(val.ip_index)) {
777 .the_only_possible_value, // i0, u0441 .runtime_value => |runtime_value| runtime_value.val.toValue().toBigIntAdvanced(space, mod, opt_sema),
778 => BigIntMutable.init(&space.limbs, 0).toConst(),442 .int => |int| switch (int.storage) {
779443 .u64, .i64, .big_int => int.storage.toBigInt(space),
780 .runtime_value => {444 .lazy_align, .lazy_size => |ty| {
781 const sub_val = val.castTag(.runtime_value).?.data;445 if (opt_sema) |sema| try sema.resolveTypeLayout(ty.toType());
782 return sub_val.toBigIntAdvanced(space, mod, opt_sema);446 const x = switch (int.storage) {
783 },447 else => unreachable,
784 .lazy_align => {448 .lazy_align => ty.toType().abiAlignment(mod),
785 const ty = val.castTag(.lazy_align).?.data;449 .lazy_size => ty.toType().abiSize(mod),
786 if (opt_sema) |sema| {450 };
787 try sema.resolveTypeLayout(ty);451 return BigIntMutable.init(&space.limbs, x).toConst();
788 }452 },
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();
799 },453 },
800454 .enum_tag => |enum_tag| enum_tag.int.toValue().toBigIntAdvanced(space, mod, opt_sema),
801 .elem_ptr => {455 .ptr => |ptr| switch (ptr.len) {
802 const elem_ptr = val.castTag(.elem_ptr).?.data;456 .none => switch (ptr.addr) {
803 const array_addr = (try elem_ptr.array_ptr.getUnsignedIntAdvanced(mod, opt_sema)).?;457 .int => |int| int.toValue().toBigIntAdvanced(space, mod, opt_sema),
804 const elem_size = elem_ptr.elem_ty.abiSize(mod);458 .elem => |elem| {
805 const new_addr = array_addr + elem_size * elem_ptr.index;459 const base_addr = (try elem.base.toValue().getUnsignedIntAdvanced(mod, opt_sema)).?;
806 return BigIntMutable.init(&space.limbs, new_addr).toConst();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,
807 },467 },
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),
814 else => unreachable,468 else => unreachable,
815 },469 },
816 };470 };
817 }471 }
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
819 /// If the value fits in a u64, return it, otherwise null.495 /// If the value fits in a u64, return it, otherwise null.
820 /// Asserts not undefined.496 /// Asserts not undefined.
821 pub fn getUnsignedInt(val: Value, mod: *Module) ?u64 {497 pub fn getUnsignedInt(val: Value, mod: *Module) ?u64 {
...@@ -825,42 +501,27 @@ pub const Value = struct {...@@ -825,42 +501,27 @@ pub const Value = struct {
825 /// If the value fits in a u64, return it, otherwise null.501 /// If the value fits in a u64, return it, otherwise null.
826 /// Asserts not undefined.502 /// Asserts not undefined.
827 pub fn getUnsignedIntAdvanced(val: Value, mod: *Module, opt_sema: ?*Sema) !?u64 {503 pub fn getUnsignedIntAdvanced(val: Value, mod: *Module, opt_sema: ?*Sema) !?u64 {
828 switch (val.ip_index) {504 return switch (val.ip_index) {
829 .bool_false => return 0,505 .bool_false => 0,
830 .bool_true => return 1,506 .bool_true => 1,
831 .undef => unreachable,507 .undef => unreachable,
832 .none => switch (val.tag()) {508 else => switch (mod.intern_pool.indexToKey(val.ip_index)) {
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)) {
856 .int => |int| switch (int.storage) {509 .int => |int| switch (int.storage) {
857 .big_int => |big_int| big_int.to(u64) catch null,510 .big_int => |big_int| big_int.to(u64) catch null,
858 .u64 => |x| x,511 .u64 => |x| x,
859 .i64 => |x| std.math.cast(u64, x),512 .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),
860 },521 },
861 else => null,522 else => null,
862 },523 },
863 }524 };
864 }525 }
865526
866 /// Asserts the value is an integer and it fits in a u64527 /// Asserts the value is an integer and it fits in a u64
...@@ -870,58 +531,40 @@ pub const Value = struct {...@@ -870,58 +531,40 @@ pub const Value = struct {
870531
871 /// Asserts the value is an integer and it fits in a i64532 /// Asserts the value is an integer and it fits in a i64
872 pub fn toSignedInt(val: Value, mod: *Module) i64 {533 pub fn toSignedInt(val: Value, mod: *Module) i64 {
873 switch (val.ip_index) {534 return switch (val.ip_index) {
874 .bool_false => return 0,535 .bool_false => 0,
875 .bool_true => return 1,536 .bool_true => 1,
876 .undef => unreachable,537 .undef => unreachable,
877 .none => switch (val.tag()) {538 else => switch (mod.intern_pool.indexToKey(val.ip_index)) {
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)) {
893 .int => |int| switch (int.storage) {539 .int => |int| switch (int.storage) {
894 .big_int => |big_int| big_int.to(i64) catch unreachable,540 .big_int => |big_int| big_int.to(i64) catch unreachable,
895 .i64 => |x| x,541 .i64 => |x| x,
896 .u64 => |x| @intCast(i64, x),542 .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)),
897 },545 },
898 else => unreachable,546 else => unreachable,
899 },547 },
900 }548 };
901 }549 }
902550
903 pub fn toBool(val: Value, mod: *const Module) bool {551 pub fn toBool(val: Value, _: *const Module) bool {
904 return switch (val.ip_index) {552 return switch (val.ip_index) {
905 .bool_true => true,553 .bool_true => true,
906 .bool_false => false,554 .bool_false => false,
907 .none => unreachable,555 else => 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 },
915 };556 };
916 }557 }
917558
918 fn isDeclRef(val: Value) bool {559 fn isDeclRef(val: Value, mod: *Module) bool {
919 var check = val;560 var check = val;
920 while (true) switch (check.tag()) {561 while (true) switch (mod.intern_pool.indexToKey(check.ip_index)) {
921 .variable, .decl_ref, .decl_ref_mut, .comptime_field_ptr => return true,562 .ptr => |ptr| switch (ptr.addr) {
922 .field_ptr => check = check.castTag(.field_ptr).?.data.container_ptr,563 .decl, .mut_decl, .comptime_field => return true,
923 .elem_ptr => check = check.castTag(.elem_ptr).?.data.array_ptr,564 .eu_payload, .opt_payload => |index| check = index.toValue(),
924 .eu_payload_ptr, .opt_payload_ptr => check = check.cast(Value.Payload.PayloadPtr).?.data.container_ptr,565 .elem, .field => |base_index| check = base_index.base.toValue(),
566 else => return false,
567 },
925 else => return false,568 else => return false,
926 };569 };
927 }570 }
...@@ -953,24 +596,9 @@ pub const Value = struct {...@@ -953,24 +596,9 @@ pub const Value = struct {
953 const bits = int_info.bits;596 const bits = int_info.bits;
954 const byte_count = (bits + 7) / 8;597 const byte_count = (bits + 7) / 8;
955598
956 const int_val = try val.enumToInt(ty, mod);599 var bigint_buffer: BigIntSpace = undefined;
957600 const bigint = val.toBigInt(&bigint_buffer, mod);
958 if (byte_count <= @sizeOf(u64)) {601 bigint.writeTwosComplement(buffer[0..byte_count], endian);
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 }
974 },602 },
975 .Float => switch (ty.floatBits(target)) {603 .Float => switch (ty.floatBits(target)) {
976 16 => std.mem.writeInt(u16, buffer[0..2], @bitCast(u16, val.toFloat(f16, mod)), endian),604 16 => std.mem.writeInt(u16, buffer[0..2], @bitCast(u16, val.toFloat(f16, mod)), endian),
...@@ -1016,7 +644,12 @@ pub const Value = struct {...@@ -1016,7 +644,12 @@ pub const Value = struct {
1016 .ErrorSet => {644 .ErrorSet => {
1017 // TODO revisit this when we have the concept of the error tag type645 // TODO revisit this when we have the concept of the error tag type
1018 const Int = u16;646 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)).?;
1020 std.mem.writeInt(Int, buffer[0..@sizeOf(Int)], @intCast(Int, int), endian);653 std.mem.writeInt(Int, buffer[0..@sizeOf(Int)], @intCast(Int, int), endian);
1021 },654 },
1022 .Union => switch (ty.containerLayout(mod)) {655 .Union => switch (ty.containerLayout(mod)) {
...@@ -1029,7 +662,7 @@ pub const Value = struct {...@@ -1029,7 +662,7 @@ pub const Value = struct {
1029 },662 },
1030 .Pointer => {663 .Pointer => {
1031 if (ty.isSlice(mod)) return error.IllDefinedMemoryLayout;664 if (ty.isSlice(mod)) return error.IllDefinedMemoryLayout;
1032 if (val.isDeclRef()) return error.ReinterpretDeclRef;665 if (val.isDeclRef(mod)) return error.ReinterpretDeclRef;
1033 return val.writeToMemory(Type.usize, mod, buffer);666 return val.writeToMemory(Type.usize, mod, buffer);
1034 },667 },
1035 .Optional => {668 .Optional => {
...@@ -1141,14 +774,14 @@ pub const Value = struct {...@@ -1141,14 +774,14 @@ pub const Value = struct {
1141 .Packed => {774 .Packed => {
1142 const field_index = ty.unionTagFieldIndex(val.unionTag(mod), mod);775 const field_index = ty.unionTagFieldIndex(val.unionTag(mod), mod);
1143 const field_type = ty.unionFields(mod).values()[field_index.?].ty;776 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
1146 return field_val.writeToPackedMemory(field_type, mod, buffer, bit_offset);779 return field_val.writeToPackedMemory(field_type, mod, buffer, bit_offset);
1147 },780 },
1148 },781 },
1149 .Pointer => {782 .Pointer => {
1150 assert(!ty.isSlice(mod)); // No well defined layout.783 assert(!ty.isSlice(mod)); // No well defined layout.
1151 if (val.isDeclRef()) return error.ReinterpretDeclRef;784 if (val.isDeclRef(mod)) return error.ReinterpretDeclRef;
1152 return val.writeToPackedMemory(Type.usize, mod, buffer, bit_offset);785 return val.writeToPackedMemory(Type.usize, mod, buffer, bit_offset);
1153 },786 },
1154 .Optional => {787 .Optional => {
...@@ -1262,13 +895,11 @@ pub const Value = struct {...@@ -1262,13 +895,11 @@ pub const Value = struct {
1262 // TODO revisit this when we have the concept of the error tag type895 // TODO revisit this when we have the concept of the error tag type
1263 const Int = u16;896 const Int = u16;
1264 const int = std.mem.readInt(Int, buffer[0..@sizeOf(Int)], endian);897 const int = std.mem.readInt(Int, buffer[0..@sizeOf(Int)], endian);
1265898 const name = mod.error_name_list.items[@intCast(usize, int)];
1266 const payload = try arena.create(Value.Payload.Error);899 return (try mod.intern(.{ .err = .{
1267 payload.* = .{900 .ty = ty.ip_index,
1268 .base = .{ .tag = .@"error" },901 .name = mod.intern_pool.getString(name).unwrap().?,
1269 .data = .{ .name = mod.error_name_list.items[@intCast(usize, int)] },902 } })).toValue();
1270 };
1271 return Value.initPayload(&payload.base);
1272 },903 },
1273 .Pointer => {904 .Pointer => {
1274 assert(!ty.isSlice(mod)); // No well defined layout.905 assert(!ty.isSlice(mod)); // No well defined layout.
...@@ -1383,7 +1014,7 @@ pub const Value = struct {...@@ -1383,7 +1014,7 @@ pub const Value = struct {
1383 }1014 }
13841015
1385 /// Asserts that the value is a float or an integer.1016 /// 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 {
1387 return switch (mod.intern_pool.indexToKey(val.ip_index)) {1018 return switch (mod.intern_pool.indexToKey(val.ip_index)) {
1388 .int => |int| switch (int.storage) {1019 .int => |int| switch (int.storage) {
1389 .big_int => |big_int| @floatCast(T, bigIntToFloat(big_int.limbs, big_int.positive)),1020 .big_int => |big_int| @floatCast(T, bigIntToFloat(big_int.limbs, big_int.positive)),
...@@ -1393,6 +1024,8 @@ pub const Value = struct {...@@ -1393,6 +1024,8 @@ pub const Value = struct {
1393 }1024 }
1394 return @intToFloat(T, x);1025 return @intToFloat(T, x);
1395 },1026 },
1027 .lazy_align => |ty| @intToFloat(T, ty.toType().abiAlignment(mod)),
1028 .lazy_size => |ty| @intToFloat(T, ty.toType().abiSize(mod)),
1396 },1029 },
1397 .float => |float| switch (float.storage) {1030 .float => |float| switch (float.storage) {
1398 inline else => |x| @floatCast(T, x),1031 inline else => |x| @floatCast(T, x),
...@@ -1421,89 +1054,24 @@ pub const Value = struct {...@@ -1421,89 +1054,24 @@ pub const Value = struct {
1421 }1054 }
14221055
1423 pub fn clz(val: Value, ty: Type, mod: *Module) u64 {1056 pub fn clz(val: Value, ty: Type, mod: *Module) u64 {
1424 const ty_bits = ty.intInfo(mod).bits;1057 var bigint_buf: BigIntSpace = undefined;
1425 return switch (val.ip_index) {1058 const bigint = val.toBigInt(&bigint_buf, mod);
1426 .bool_false => ty_bits,1059 return bigint.clz(ty.intInfo(mod).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 };
1451 }1060 }
14521061
1453 pub fn ctz(val: Value, ty: Type, mod: *Module) u64 {1062 pub fn ctz(val: Value, _: Type, mod: *Module) u64 {
1454 const ty_bits = ty.intInfo(mod).bits;1063 var bigint_buf: BigIntSpace = undefined;
1455 return switch (val.ip_index) {1064 const bigint = val.toBigInt(&bigint_buf, mod);
1456 .bool_false => ty_bits,1065 return bigint.ctz();
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 };
1484 }1066 }
14851067
1486 pub fn popCount(val: Value, ty: Type, mod: *Module) u64 {1068 pub fn popCount(val: Value, ty: Type, mod: *Module) u64 {
1487 assert(!val.isUndef(mod));1069 var bigint_buf: BigIntSpace = undefined;
1488 switch (val.ip_index) {1070 const bigint = val.toBigInt(&bigint_buf, mod);
1489 .bool_false => return 0,1071 return @intCast(u64, bigint.popCount(ty.intInfo(mod).bits));
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 }
1502 }1072 }
15031073
1504 pub fn bitReverse(val: Value, ty: Type, mod: *Module, arena: Allocator) !Value {1074 pub fn bitReverse(val: Value, ty: Type, mod: *Module, arena: Allocator) !Value {
1505 assert(!val.isUndef(mod));
1506
1507 const info = ty.intInfo(mod);1075 const info = ty.intInfo(mod);
15081076
1509 var buffer: Value.BigIntSpace = undefined;1077 var buffer: Value.BigIntSpace = undefined;
...@@ -1520,8 +1088,6 @@ pub const Value = struct {...@@ -1520,8 +1088,6 @@ pub const Value = struct {
1520 }1088 }
15211089
1522 pub fn byteSwap(val: Value, ty: Type, mod: *Module, arena: Allocator) !Value {1090 pub fn byteSwap(val: Value, ty: Type, mod: *Module, arena: Allocator) !Value {
1523 assert(!val.isUndef(mod));
1524
1525 const info = ty.intInfo(mod);1091 const info = ty.intInfo(mod);
15261092
1527 // Bit count must be evenly divisible by 81093 // Bit count must be evenly divisible by 8
...@@ -1543,41 +1109,9 @@ pub const Value = struct {...@@ -1543,41 +1109,9 @@ pub const Value = struct {
1543 /// Asserts the value is an integer and not undefined.1109 /// Asserts the value is an integer and not undefined.
1544 /// Returns the number of bits the value requires to represent stored in twos complement form.1110 /// Returns the number of bits the value requires to represent stored in twos complement form.
1545 pub fn intBitCountTwosComp(self: Value, mod: *Module) usize {1111 pub fn intBitCountTwosComp(self: Value, mod: *Module) usize {
1546 const target = mod.getTarget();1112 var buffer: BigIntSpace = undefined;
1547 return switch (self.ip_index) {1113 const big_int = self.toBigInt(&buffer, mod);
1548 .bool_false => 0,1114 return big_int.bitCountTwosComp();
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 };
1581 }1115 }
15821116
1583 /// Converts an integer or a float to a float. May result in a loss of information.1117 /// Converts an integer or a float to a float. May result in a loss of information.
...@@ -1616,84 +1150,39 @@ pub const Value = struct {...@@ -1616,84 +1150,39 @@ pub const Value = struct {
1616 mod: *Module,1150 mod: *Module,
1617 opt_sema: ?*Sema,1151 opt_sema: ?*Sema,
1618 ) Module.CompileError!std.math.Order {1152 ) Module.CompileError!std.math.Order {
1619 switch (lhs.ip_index) {1153 return switch (lhs.ip_index) {
1620 .bool_false => return .eq,1154 .bool_false => .eq,
1621 .bool_true => return .gt,1155 .bool_true => .gt,
1622 .none => return switch (lhs.tag()) {1156 else => switch (mod.intern_pool.indexToKey(lhs.ip_index)) {
1623 .the_only_possible_value => .eq,1157 .ptr => |ptr| switch (ptr.addr) {
16241158 .decl, .mut_decl, .comptime_field => .gt,
1625 .decl_ref,1159 .int => |int| int.toValue().orderAgainstZeroAdvanced(mod, opt_sema),
1626 .decl_ref_mut,1160 .elem => |elem| switch (try elem.base.toValue().orderAgainstZeroAdvanced(mod, opt_sema)) {
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)) {
1668 .lt => unreachable,1161 .lt => unreachable,
1669 .gt => return .gt,1162 .gt => .gt,
1670 .eq => {1163 .eq => if (elem.index == 0) .eq else .gt,
1671 if (elem_ptr.index == 0) {1164 },
1672 return .eq;1165 else => unreachable,
1673 } else {
1674 return .gt;
1675 }
1676 },
1677 }
1678 },1166 },
1679
1680 else => unreachable,
1681 },
1682 else => return switch (mod.intern_pool.indexToKey(lhs.ip_index)) {
1683 .int => |int| switch (int.storage) {1167 .int => |int| switch (int.storage) {
1684 .big_int => |big_int| big_int.orderAgainstScalar(0),1168 .big_int => |big_int| big_int.orderAgainstScalar(0),
1685 inline .u64, .i64 => |x| std.math.order(x, 0),1169 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,
1686 },1178 },
1687 .enum_tag => |enum_tag| switch (mod.intern_pool.indexToKey(enum_tag.int).int.storage) {1179 .enum_tag => |enum_tag| enum_tag.int.toValue().orderAgainstZeroAdvanced(mod, opt_sema),
1688 .big_int => |big_int| big_int.orderAgainstScalar(0),
1689 inline .u64, .i64 => |x| std.math.order(x, 0),
1690 },
1691 .float => |float| switch (float.storage) {1180 .float => |float| switch (float.storage) {
1692 inline else => |x| std.math.order(x, 0),1181 inline else => |x| std.math.order(x, 0),
1693 },1182 },
1694 else => unreachable,1183 else => unreachable,
1695 },1184 },
1696 }1185 };
1697 }1186 }
16981187
1699 /// Asserts the value is comparable.1188 /// Asserts the value is comparable.
...@@ -1760,8 +1249,8 @@ pub const Value = struct {...@@ -1760,8 +1249,8 @@ pub const Value = struct {
1760 mod: *Module,1249 mod: *Module,
1761 opt_sema: ?*Sema,1250 opt_sema: ?*Sema,
1762 ) !bool {1251 ) !bool {
1763 if (lhs.pointerDecl()) |lhs_decl| {1252 if (lhs.pointerDecl(mod)) |lhs_decl| {
1764 if (rhs.pointerDecl()) |rhs_decl| {1253 if (rhs.pointerDecl(mod)) |rhs_decl| {
1765 switch (op) {1254 switch (op) {
1766 .eq => return lhs_decl == rhs_decl,1255 .eq => return lhs_decl == rhs_decl,
1767 .neq => return lhs_decl != rhs_decl,1256 .neq => return lhs_decl != rhs_decl,
...@@ -1774,7 +1263,7 @@ pub const Value = struct {...@@ -1774,7 +1263,7 @@ pub const Value = struct {
1774 else => {},1263 else => {},
1775 }1264 }
1776 }1265 }
1777 } else if (rhs.pointerDecl()) |_| {1266 } else if (rhs.pointerDecl(mod)) |_| {
1778 switch (op) {1267 switch (op) {
1779 .eq => return false,1268 .eq => return false,
1780 .neq => return true,1269 .neq => return true,
...@@ -1849,7 +1338,6 @@ pub const Value = struct {...@@ -1849,7 +1338,6 @@ pub const Value = struct {
18491338
1850 switch (lhs.ip_index) {1339 switch (lhs.ip_index) {
1851 .none => switch (lhs.tag()) {1340 .none => switch (lhs.tag()) {
1852 .repeated => return lhs.castTag(.repeated).?.data.compareAllWithZeroAdvancedExtra(op, mod, opt_sema),
1853 .aggregate => {1341 .aggregate => {
1854 for (lhs.castTag(.aggregate).?.data) |elem_val| {1342 for (lhs.castTag(.aggregate).?.data) |elem_val| {
1855 if (!(try elem_val.compareAllWithZeroAdvancedExtra(op, mod, opt_sema))) return false;1343 if (!(try elem_val.compareAllWithZeroAdvancedExtra(op, mod, opt_sema))) return false;
...@@ -1877,6 +1365,15 @@ pub const Value = struct {...@@ -1877,6 +1365,15 @@ pub const Value = struct {
1877 .float => |float| switch (float.storage) {1365 .float => |float| switch (float.storage) {
1878 inline else => |x| if (std.math.isNan(x)) return op == .neq,1366 inline else => |x| if (std.math.isNan(x)) return op == .neq,
1879 },1367 },
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 },
1880 else => {},1377 else => {},
1881 },1378 },
1882 }1379 }
...@@ -1910,69 +1407,6 @@ pub const Value = struct {...@@ -1910,69 +1407,6 @@ pub const Value = struct {
1910 const a_tag = a.tag();1407 const a_tag = a.tag();
1911 const b_tag = b.tag();1408 const b_tag = b.tag();
1912 if (a_tag == b_tag) switch (a_tag) {1409 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 },
1976 .aggregate => {1410 .aggregate => {
1977 const a_field_vals = a.castTag(.aggregate).?.data;1411 const a_field_vals = a.castTag(.aggregate).?.data;
1978 const b_field_vals = b.castTag(.aggregate).?.data;1412 const b_field_vals = b.castTag(.aggregate).?.data;
...@@ -2035,17 +1469,15 @@ pub const Value = struct {...@@ -2035,17 +1469,15 @@ pub const Value = struct {
2035 return eqlAdvanced(a_union.val, active_field_ty, b_union.val, active_field_ty, mod, opt_sema);1469 return eqlAdvanced(a_union.val, active_field_ty, b_union.val, active_field_ty, mod, opt_sema);
2036 },1470 },
2037 else => {},1471 else => {},
2038 } else if (b_tag == .@"error") {1472 };
2039 return false;
2040 }
20411473
2042 if (a.pointerDecl()) |a_decl| {1474 if (a.pointerDecl(mod)) |a_decl| {
2043 if (b.pointerDecl()) |b_decl| {1475 if (b.pointerDecl(mod)) |b_decl| {
2044 return a_decl == b_decl;1476 return a_decl == b_decl;
2045 } else {1477 } else {
2046 return false;1478 return false;
2047 }1479 }
2048 } else if (b.pointerDecl()) |_| {1480 } else if (b.pointerDecl(mod)) |_| {
2049 return false;1481 return false;
2050 }1482 }
20511483
...@@ -2130,25 +1562,11 @@ pub const Value = struct {...@@ -2130,25 +1562,11 @@ pub const Value = struct {
2130 if (a_nan) return true;1562 if (a_nan) return true;
2131 return a_float == b_float;1563 return a_float == b_float;
2132 },1564 },
2133 .Optional => if (b_tag == .opt_payload) {1565 .Optional,
2134 var sub_pl: Payload.SubValue = .{1566 .ErrorUnion,
2135 .base = .{ .tag = b.tag() },1567 => unreachable, // handled by InternPool
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 },
2149 else => {},1568 else => {},
2150 }1569 }
2151 if (a_tag == .@"error") return false;
2152 return (try orderAdvanced(a, b, mod, opt_sema)).compare(.eq);1570 return (try orderAdvanced(a, b, mod, opt_sema)).compare(.eq);
2153 }1571 }
21541572
...@@ -2166,7 +1584,7 @@ pub const Value = struct {...@@ -2166,7 +1584,7 @@ pub const Value = struct {
2166 std.hash.autoHash(hasher, zig_ty_tag);1584 std.hash.autoHash(hasher, zig_ty_tag);
2167 if (val.isUndef(mod)) return;1585 if (val.isUndef(mod)) return;
2168 // The value is runtime-known and shouldn't affect the hash.1586 // The value is runtime-known and shouldn't affect the hash.
2169 if (val.isRuntimeValue()) return;1587 if (val.isRuntimeValue(mod)) return;
21701588
2171 switch (zig_ty_tag) {1589 switch (zig_ty_tag) {
2172 .Opaque => unreachable, // Cannot hash opaque types1590 .Opaque => unreachable, // Cannot hash opaque types
...@@ -2177,38 +1595,20 @@ pub const Value = struct {...@@ -2177,38 +1595,20 @@ pub const Value = struct {
2177 .Null,1595 .Null,
2178 => {},1596 => {},
21791597
2180 .Type => unreachable, // handled via ip_index check above1598 .Type,
2181 .Float => {1599 .Float,
2182 // For hash/eql purposes, we treat floats as their IEEE integer representation.1600 .ComptimeFloat,
2183 switch (ty.floatBits(mod.getTarget())) {1601 .Bool,
2184 16 => std.hash.autoHash(hasher, @bitCast(u16, val.toFloat(f16, mod))),1602 .Int,
2185 32 => std.hash.autoHash(hasher, @bitCast(u32, val.toFloat(f32, mod))),1603 .ComptimeInt,
2186 64 => std.hash.autoHash(hasher, @bitCast(u64, val.toFloat(f64, mod))),1604 .Pointer,
2187 80 => std.hash.autoHash(hasher, @bitCast(u80, val.toFloat(f80, mod))),1605 .Optional,
2188 128 => std.hash.autoHash(hasher, @bitCast(u128, val.toFloat(f128, mod))),1606 .ErrorUnion,
2189 else => unreachable,1607 .ErrorSet,
2190 }1608 .Enum,
2191 },1609 .EnumLiteral,
2192 .ComptimeFloat => {1610 .Fn,
2193 const float = val.toFloat(f128, mod);1611 => unreachable, // handled via ip_index check above
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 },
2212 .Array, .Vector => {1612 .Array, .Vector => {
2213 const len = ty.arrayLen(mod);1613 const len = ty.arrayLen(mod);
2214 const elem_ty = ty.childType(mod);1614 const elem_ty = ty.childType(mod);
...@@ -2233,42 +1633,6 @@ pub const Value = struct {...@@ -2233,42 +1633,6 @@ pub const Value = struct {
2233 else => unreachable,1633 else => unreachable,
2234 }1634 }
2235 },1635 },
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 },
2272 .Union => {1636 .Union => {
2273 const union_obj = val.cast(Payload.Union).?.data;1637 const union_obj = val.cast(Payload.Union).?.data;
2274 if (ty.unionTagType(mod)) |tag_ty| {1638 if (ty.unionTagType(mod)) |tag_ty| {
...@@ -2277,27 +1641,12 @@ pub const Value = struct {...@@ -2277,27 +1641,12 @@ pub const Value = struct {
2277 const active_field_ty = ty.unionFieldType(union_obj.tag, mod);1641 const active_field_ty = ty.unionFieldType(union_obj.tag, mod);
2278 union_obj.val.hash(active_field_ty, hasher, mod);1642 union_obj.val.hash(active_field_ty, hasher, mod);
2279 },1643 },
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 },
2291 .Frame => {1644 .Frame => {
2292 @panic("TODO implement hashing frame values");1645 @panic("TODO implement hashing frame values");
2293 },1646 },
2294 .AnyFrame => {1647 .AnyFrame => {
2295 @panic("TODO implement hashing anyframe values");1648 @panic("TODO implement hashing anyframe values");
2296 },1649 },
2297 .EnumLiteral => {
2298 const bytes = val.castTag(.enum_literal).?.data;
2299 hasher.update(bytes);
2300 },
2301 }1650 }
2302 }1651 }
23031652
...@@ -2308,7 +1657,7 @@ pub const Value = struct {...@@ -2308,7 +1657,7 @@ pub const Value = struct {
2308 pub fn hashUncoerced(val: Value, ty: Type, hasher: *std.hash.Wyhash, mod: *Module) void {1657 pub fn hashUncoerced(val: Value, ty: Type, hasher: *std.hash.Wyhash, mod: *Module) void {
2309 if (val.isUndef(mod)) return;1658 if (val.isUndef(mod)) return;
2310 // The value is runtime-known and shouldn't affect the hash.1659 // The value is runtime-known and shouldn't affect the hash.
2311 if (val.isRuntimeValue()) return;1660 if (val.isRuntimeValue(mod)) return;
23121661
2313 if (val.ip_index != .none) {1662 if (val.ip_index != .none) {
2314 // The InternPool data structure hashes based on Key to make interned objects1663 // The InternPool data structure hashes based on Key to make interned objects
...@@ -2326,16 +1675,20 @@ pub const Value = struct {...@@ -2326,16 +1675,20 @@ pub const Value = struct {
2326 .Null,1675 .Null,
2327 .Struct, // It sure would be nice to do something clever with structs.1676 .Struct, // It sure would be nice to do something clever with structs.
2328 => |zig_type_tag| std.hash.autoHash(hasher, zig_type_tag),1677 => |zig_type_tag| std.hash.autoHash(hasher, zig_type_tag),
2329 .Type => unreachable, // handled above with the ip_index check1678 .Type,
2330 .Float, .ComptimeFloat => std.hash.autoHash(hasher, @bitCast(u128, val.toFloat(f128, mod))),1679 .Float,
2331 .Bool, .Int, .ComptimeInt, .Pointer, .Fn => switch (val.tag()) {1680 .ComptimeFloat,
2332 .slice => {1681 .Bool,
2333 const slice = val.castTag(.slice).?.data;1682 .Int,
2334 const ptr_ty = ty.slicePtrFieldType(mod);1683 .ComptimeInt,
2335 slice.ptr.hashUncoerced(ptr_ty, hasher, mod);1684 .Pointer,
2336 },1685 .Fn,
2337 else => val.hashPtr(hasher, mod),1686 .Optional,
2338 },1687 .ErrorSet,
1688 .ErrorUnion,
1689 .Enum,
1690 .EnumLiteral,
1691 => unreachable, // handled above with the ip_index check
2339 .Array, .Vector => {1692 .Array, .Vector => {
2340 const len = ty.arrayLen(mod);1693 const len = ty.arrayLen(mod);
2341 const elem_ty = ty.childType(mod);1694 const elem_ty = ty.childType(mod);
...@@ -2348,21 +1701,16 @@ pub const Value = struct {...@@ -2348,21 +1701,16 @@ pub const Value = struct {
2348 elem_val.hashUncoerced(elem_ty, hasher, mod);1701 elem_val.hashUncoerced(elem_ty, hasher, mod);
2349 }1702 }
2350 },1703 },
2351 .Optional => if (val.castTag(.opt_payload)) |payload| {1704 .Union => {
2352 const child_ty = ty.optionalChild(mod);1705 hasher.update(val.tagName(mod));
2353 payload.data.hashUncoerced(child_ty, hasher, mod);1706 switch (mod.intern_pool.indexToKey(val.ip_index)) {
2354 } else std.hash.autoHash(hasher, std.builtin.TypeId.Null),1707 .un => |un| {
2355 .ErrorSet, .ErrorUnion => if (val.getError()) |err| hasher.update(err) else {1708 const active_field_ty = ty.unionFieldType(un.tag.toValue(), mod);
2356 const pl_ty = ty.errorUnionPayload(mod);1709 un.val.toValue().hashUncoerced(active_field_ty, hasher, mod);
2357 val.castTag(.eu_payload).?.data.hashUncoerced(pl_ty, hasher, mod);1710 },
2358 },1711 else => std.hash.autoHash(hasher, std.builtin.TypeId.Void),
2359 .Enum, .EnumLiteral, .Union => {1712 }
2360 hasher.update(val.tagName(ty, mod));1713 },
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 },
2366 .Frame => @panic("TODO implement hashing frame values"),1714 .Frame => @panic("TODO implement hashing frame values"),
2367 .AnyFrame => @panic("TODO implement hashing anyframe values"),1715 .AnyFrame => @panic("TODO implement hashing anyframe values"),
2368 }1716 }
...@@ -2397,57 +1745,53 @@ pub const Value = struct {...@@ -2397,57 +1745,53 @@ pub const Value = struct {
2397 }1745 }
2398 };1746 };
23991747
2400 pub fn isComptimeMutablePtr(val: Value) bool {1748 pub fn isComptimeMutablePtr(val: Value, mod: *Module) bool {
2401 return switch (val.ip_index) {1749 return switch (mod.intern_pool.indexToKey(val.ip_index)) {
2402 .none => switch (val.tag()) {1750 .ptr => |ptr| switch (ptr.addr) {
2403 .decl_ref_mut, .comptime_field_ptr => true,1751 .mut_decl, .comptime_field => true,
2404 .elem_ptr => isComptimeMutablePtr(val.castTag(.elem_ptr).?.data.array_ptr),1752 .eu_payload, .opt_payload => |base_ptr| base_ptr.toValue().isComptimeMutablePtr(mod),
2405 .field_ptr => isComptimeMutablePtr(val.castTag(.field_ptr).?.data.container_ptr),1753 .elem, .field => |base_index| base_index.base.toValue().isComptimeMutablePtr(mod),
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
2410 else => false,1754 else => false,
2411 },1755 },
2412 else => false,1756 else => false,
2413 };1757 };
2414 }1758 }
24151759
2416 pub fn canMutateComptimeVarState(val: Value) bool {1760 pub fn canMutateComptimeVarState(val: Value, mod: *Module) bool {
2417 if (val.isComptimeMutablePtr()) return true;1761 return val.isComptimeMutablePtr(mod) or switch (val.ip_index) {
2418 return switch (val.ip_index) {1762 else => switch (mod.intern_pool.indexToKey(val.ip_index)) {
2419 .none => switch (val.tag()) {1763 .error_union => |error_union| switch (error_union.val) {
2420 .repeated => return val.castTag(.repeated).?.data.canMutateComptimeVarState(),1764 .err_name => false,
2421 .eu_payload => return val.castTag(.eu_payload).?.data.canMutateComptimeVarState(),1765 .payload => |payload| payload.toValue().canMutateComptimeVarState(mod),
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;
2431 },1766 },
2432 .@"union" => return val.cast(Payload.Union).?.data.val.canMutateComptimeVarState(),1767 .ptr => |ptr| switch (ptr.addr) {
2433 .slice => return val.castTag(.slice).?.data.ptr.canMutateComptimeVarState(),1768 .eu_payload, .opt_payload => |base| base.toValue().canMutateComptimeVarState(mod),
2434 else => return false,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,
2435 },1780 },
2436 else => return false,
2437 };1781 };
2438 }1782 }
24391783
2440 /// Gets the decl referenced by this pointer. If the pointer does not point1784 /// Gets the decl referenced by this pointer. If the pointer does not point
2441 /// to a decl, or if it points to some part of a decl (like field_ptr or element_ptr),1785 /// to a decl, or if it points to some part of a decl (like field_ptr or element_ptr),
2442 /// this function returns null.1786 /// this function returns null.
2443 pub fn pointerDecl(val: Value) ?Module.Decl.Index {1787 pub fn pointerDecl(val: Value, mod: *Module) ?Module.Decl.Index {
2444 return switch (val.ip_index) {1788 return switch (mod.intern_pool.indexToKey(val.ip_index)) {
2445 .none => switch (val.tag()) {1789 .variable => |variable| variable.decl,
2446 .decl_ref_mut => val.castTag(.decl_ref_mut).?.data.decl_index,1790 .extern_func => |extern_func| extern_func.decl,
2447 .extern_fn => val.castTag(.extern_fn).?.data.owner_decl,1791 .func => |func| mod.funcPtr(func.index).owner_decl,
2448 .function => val.castTag(.function).?.data.owner_decl,1792 .ptr => |ptr| switch (ptr.addr) {
2449 .variable => val.castTag(.variable).?.data.owner_decl,1793 .decl => |decl| decl,
2450 .decl_ref => val.cast(Payload.Decl).?.data,1794 .mut_decl => |mut_decl| mut_decl.decl,
2451 else => null,1795 else => null,
2452 },1796 },
2453 else => null,1797 else => null,
...@@ -2463,95 +1807,15 @@ pub const Value = struct {...@@ -2463,95 +1807,15 @@ pub const Value = struct {
2463 }1807 }
2464 }1808 }
24651809
2466 fn hashPtr(ptr_val: Value, hasher: *std.hash.Wyhash, mod: *Module) void {1810 pub const slice_ptr_index = 0;
2467 switch (ptr_val.tag()) {1811 pub const slice_len_index = 1;
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 }
25121812
2513 pub fn slicePtr(val: Value, mod: *Module) Value {1813 pub fn slicePtr(val: Value, mod: *Module) Value {
2514 if (val.ip_index != .none) return mod.intern_pool.slicePtr(val.ip_index).toValue();1814 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 };
2521 }1815 }
25221816
2523 pub fn sliceLen(val: Value, mod: *Module) u64 {1817 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);1818 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 };
2555 }1819 }
25561820
2557 /// Asserts the value is a single-item pointer to an array, or an array,1821 /// Asserts the value is a single-item pointer to an array, or an array,
...@@ -2560,14 +1824,6 @@ pub const Value = struct {...@@ -2560,14 +1824,6 @@ pub const Value = struct {
2560 switch (val.ip_index) {1824 switch (val.ip_index) {
2561 .undef => return Value.undef,1825 .undef => return Value.undef,
2562 .none => switch (val.tag()) {1826 .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
2571 .bytes => {1827 .bytes => {
2572 const byte = val.castTag(.bytes).?.data[index];1828 const byte = val.castTag(.bytes).?.data[index];
2573 return mod.intValue(Type.u8, byte);1829 return mod.intValue(Type.u8, byte);
...@@ -2579,128 +1835,101 @@ pub const Value = struct {...@@ -2579,128 +1835,101 @@ pub const Value = struct {
2579 return mod.intValue(Type.u8, byte);1835 return mod.intValue(Type.u8, byte);
2580 },1836 },
25811837
2582 // No matter the index; all the elements are the same!
2583 .repeated => return val.castTag(.repeated).?.data,
2584
2585 .aggregate => return val.castTag(.aggregate).?.data[index],1838 .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
2615 else => unreachable,1840 else => unreachable,
2616 },1841 },
2617 else => return switch (mod.intern_pool.indexToKey(val.ip_index)) {1842 else => return switch (mod.intern_pool.indexToKey(val.ip_index)) {
2618 .ptr => |ptr| switch (ptr.addr) {1843 .ptr => |ptr| switch (ptr.addr) {
2619 .@"var" => unreachable,
2620 .decl => |decl| mod.declPtr(decl).val.elemValue(mod, index),1844 .decl => |decl| mod.declPtr(decl).val.elemValue(mod, index),
2621 .mut_decl => |mut_decl| mod.declPtr(mut_decl.decl).val.elemValue(mod, index),1845 .mut_decl => |mut_decl| mod.declPtr(mut_decl.decl).val.elemValue(mod, index),
2622 .int, .eu_payload, .opt_payload => unreachable,1846 .int, .eu_payload, .opt_payload => unreachable,
2623 .comptime_field => |field_val| field_val.toValue().elemValue(mod, index),1847 .comptime_field => |field_val| field_val.toValue().elemValue(mod, index),
2624 .elem => |elem| elem.base.toValue().elemValue(mod, index + elem.index),1848 .elem => |elem| elem.base.toValue().elemValue(mod, index + elem.index),
2625 .field => unreachable,1849 .field => |field| if (field.base.toValue().pointerDecl(mod)) |decl_index| {
2626 },1850 const base_decl = mod.declPtr(decl_index);
2627 .aggregate => |aggregate| switch (aggregate.storage) {1851 const field_val = try base_decl.val.fieldValue(mod, field.index);
2628 .elems => |elems| elems[index].toValue(),1852 return field_val.elemValue(mod, index);
2629 .repeated_elem => |elem| elem.toValue(),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();
2630 },1867 },
2631 else => unreachable,1868 else => unreachable,
2632 },1869 },
2633 }1870 }
2634 }1871 }
26351872
2636 pub fn isLazyAlign(val: Value) bool {1873 pub fn isLazyAlign(val: Value, mod: *Module) bool {
2637 return val.ip_index == .none and val.tag() == .lazy_align;1874 return switch (mod.intern_pool.indexToKey(val.ip_index)) {
2638 }1875 .int => |int| int.storage == .lazy_align,
26391876 else => false,
2640 pub fn isLazySize(val: Value) bool {1877 };
2641 return val.ip_index == .none and val.tag() == .lazy_size;
2642 }1878 }
26431879
2644 pub fn isRuntimeValue(val: Value) bool {1880 pub fn isLazySize(val: Value, mod: *Module) bool {
2645 return val.ip_index == .none and val.tag() == .runtime_value;1881 return switch (mod.intern_pool.indexToKey(val.ip_index)) {
1882 .int => |int| int.storage == .lazy_size,
1883 else => false,
1884 };
2646 }1885 }
26471886
2648 pub fn tagIsVariable(val: Value) bool {1887 pub fn isRuntimeValue(val: Value, mod: *Module) bool {
2649 return val.ip_index == .none and val.tag() == .variable;1888 return mod.intern_pool.indexToKey(val.ip_index) == .runtime_value;
2650 }1889 }
26511890
2652 /// Returns true if a Value is backed by a variable1891 /// Returns true if a Value is backed by a variable
2653 pub fn isVariable(val: Value, mod: *Module) bool {1892 pub fn isVariable(val: Value, mod: *Module) bool {
2654 return switch (val.ip_index) {1893 return switch (mod.intern_pool.indexToKey(val.ip_index)) {
2655 .none => switch (val.tag()) {1894 .variable => true,
2656 .slice => val.castTag(.slice).?.data.ptr.isVariable(mod),1895 .ptr => |ptr| switch (ptr.addr) {
2657 .comptime_field_ptr => val.castTag(.comptime_field_ptr).?.data.field_val.isVariable(mod),1896 .decl => |decl_index| {
2658 .elem_ptr => val.castTag(.elem_ptr).?.data.array_ptr.isVariable(mod),1897 const decl = mod.declPtr(decl_index);
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);
2664 assert(decl.has_tv);1898 assert(decl.has_tv);
2665 return decl.val.isVariable(mod);1899 return decl.val.isVariable(mod);
2666 },1900 },
2667 .decl_ref_mut => {1901 .mut_decl => |mut_decl| {
2668 const decl = mod.declPtr(val.castTag(.decl_ref_mut).?.data.decl_index);1902 const decl = mod.declPtr(mut_decl.decl);
2669 assert(decl.has_tv);1903 assert(decl.has_tv);
2670 return decl.val.isVariable(mod);1904 return decl.val.isVariable(mod);
2671 },1905 },
26721906 .int => false,
2673 .variable => true,1907 .eu_payload, .opt_payload => |base_ptr| base_ptr.toValue().isVariable(mod),
2674 else => false,1908 .comptime_field => |comptime_field| comptime_field.toValue().isVariable(mod),
1909 .elem, .field => |base_index| base_index.base.toValue().isVariable(mod),
2675 },1910 },
2676 else => false,1911 else => false,
2677 };1912 };
2678 }1913 }
26791914
2680 pub fn isPtrToThreadLocal(val: Value, mod: *Module) bool {1915 pub fn isPtrToThreadLocal(val: Value, mod: *Module) bool {
2681 return switch (val.ip_index) {1916 return switch (mod.intern_pool.indexToKey(val.ip_index)) {
2682 .none => switch (val.tag()) {1917 .variable => |variable| variable.is_threadlocal,
2683 .variable => false,1918 .ptr => |ptr| switch (ptr.addr) {
2684 else => val.isPtrToThreadLocalInner(mod),1919 .decl => |decl_index| {
2685 },1920 const decl = mod.declPtr(decl_index);
2686 else => val.isPtrToThreadLocalInner(mod),1921 assert(decl.has_tv);
2687 };1922 return decl.val.isPtrToThreadLocal(mod);
2688 }1923 },
26891924 .mut_decl => |mut_decl| {
2690 fn isPtrToThreadLocalInner(val: Value, mod: *Module) bool {1925 const decl = mod.declPtr(mut_decl.decl);
2691 return switch (val.ip_index) {1926 assert(decl.has_tv);
2692 .none => switch (val.tag()) {1927 return decl.val.isPtrToThreadLocal(mod);
2693 .slice => val.castTag(.slice).?.data.ptr.isPtrToThreadLocalInner(mod),1928 },
2694 .comptime_field_ptr => val.castTag(.comptime_field_ptr).?.data.field_val.isPtrToThreadLocalInner(mod),1929 .int => false,
2695 .elem_ptr => val.castTag(.elem_ptr).?.data.array_ptr.isPtrToThreadLocalInner(mod),1930 .eu_payload, .opt_payload => |base_ptr| base_ptr.toValue().isPtrToThreadLocal(mod),
2696 .field_ptr => val.castTag(.field_ptr).?.data.container_ptr.isPtrToThreadLocalInner(mod),1931 .comptime_field => |comptime_field| comptime_field.toValue().isPtrToThreadLocal(mod),
2697 .eu_payload_ptr => val.castTag(.eu_payload_ptr).?.data.container_ptr.isPtrToThreadLocalInner(mod),1932 .elem, .field => |base_index| base_index.base.toValue().isPtrToThreadLocal(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,
2704 },1933 },
2705 else => false,1934 else => false,
2706 };1935 };
...@@ -2714,39 +1943,42 @@ pub const Value = struct {...@@ -2714,39 +1943,42 @@ pub const Value = struct {
2714 start: usize,1943 start: usize,
2715 end: usize,1944 end: usize,
2716 ) error{OutOfMemory}!Value {1945 ) error{OutOfMemory}!Value {
2717 return switch (val.tag()) {1946 return switch (val.ip_index) {
2718 .empty_array_sentinel => if (start == 0 and end == 1) val else Value.initTag(.empty_array),1947 .none => switch (val.tag()) {
2719 .bytes => Tag.bytes.create(arena, val.castTag(.bytes).?.data[start..end]),1948 .bytes => Tag.bytes.create(arena, val.castTag(.bytes).?.data[start..end]),
2720 .str_lit => {1949 .str_lit => {
2721 const str_lit = val.castTag(.str_lit).?.data;1950 const str_lit = val.castTag(.str_lit).?.data;
2722 return Tag.str_lit.create(arena, .{1951 return Tag.str_lit.create(arena, .{
2723 .index = @intCast(u32, str_lit.index + start),1952 .index = @intCast(u32, str_lit.index + start),
2724 .len = @intCast(u32, end - start),1953 .len = @intCast(u32, end - start),
2725 });1954 });
1955 },
1956 else => unreachable,
2726 },1957 },
2727 .aggregate => Tag.aggregate.create(arena, val.castTag(.aggregate).?.data[start..end]),1958 else => switch (mod.intern_pool.indexToKey(val.ip_index)) {
2728 .slice => sliceArray(val.castTag(.slice).?.data.ptr, mod, arena, start, end),1959 .ptr => |ptr| switch (ptr.addr) {
27291960 .decl => |decl| try mod.declPtr(decl).val.sliceArray(mod, arena, start, end),
2730 .decl_ref => sliceArray(mod.declPtr(val.castTag(.decl_ref).?.data).val, mod, arena, start, end),1961 .mut_decl => |mut_decl| try mod.declPtr(mut_decl.decl).val.sliceArray(mod, arena, start, end),
2731 .decl_ref_mut => sliceArray(mod.declPtr(val.castTag(.decl_ref_mut).?.data.decl_index).val, mod, arena, start, end),1962 .comptime_field => |comptime_field| try comptime_field.toValue().sliceArray(mod, arena, start, end),
2732 .comptime_field_ptr => sliceArray(val.castTag(.comptime_field_ptr).?.data.field_val, mod, arena, start, end),1963 .elem => |elem| try elem.base.toValue().sliceArray(mod, arena, start + elem.index, end + elem.index),
2733 .elem_ptr => blk: {1964 else => unreachable,
2734 const elem_ptr = val.castTag(.elem_ptr).?.data;1965 },
2735 break :blk sliceArray(elem_ptr.array_ptr, mod, arena, start + elem_ptr.index, end + elem_ptr.index);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,
2736 },1975 },
2737
2738 .repeated,
2739 .the_only_possible_value,
2740 => val,
2741
2742 else => unreachable,
2743 };1976 };
2744 }1977 }
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 {
2747 switch (val.ip_index) {1980 switch (val.ip_index) {
2748 .undef => return Value.undef,1981 .undef => return Value.undef,
2749
2750 .none => switch (val.tag()) {1982 .none => switch (val.tag()) {
2751 .aggregate => {1983 .aggregate => {
2752 const field_values = val.castTag(.aggregate).?.data;1984 const field_values = val.castTag(.aggregate).?.data;
...@@ -2757,13 +1989,14 @@ pub const Value = struct {...@@ -2757,13 +1989,14 @@ pub const Value = struct {
2757 // TODO assert the tag is correct1989 // TODO assert the tag is correct
2758 return payload.val;1990 return payload.val;
2759 },1991 },
2760
2761 .the_only_possible_value => return (try ty.onePossibleValue(mod)).?,
2762
2763 else => unreachable,1992 else => unreachable,
2764 },1993 },
2765 else => return switch (mod.intern_pool.indexToKey(val.ip_index)) {1994 else => return switch (mod.intern_pool.indexToKey(val.ip_index)) {
2766 .aggregate => |aggregate| switch (aggregate.storage) {1995 .aggregate => |aggregate| switch (aggregate.storage) {
1996 .bytes => |bytes| try mod.intern(.{ .int = .{
1997 .ty = .u8_type,
1998 .storage = .{ .u64 = bytes[index] },
1999 } }),
2767 .elems => |elems| elems[index],2000 .elems => |elems| elems[index],
2768 .repeated_elem => |elem| elem,2001 .repeated_elem => |elem| elem,
2769 }.toValue(),2002 }.toValue(),
...@@ -2785,40 +2018,37 @@ pub const Value = struct {...@@ -2785,40 +2018,37 @@ pub const Value = struct {
2785 pub fn elemPtr(2018 pub fn elemPtr(
2786 val: Value,2019 val: Value,
2787 ty: Type,2020 ty: Type,
2788 arena: Allocator,
2789 index: usize,2021 index: usize,
2790 mod: *Module,2022 mod: *Module,
2791 ) Allocator.Error!Value {2023 ) Allocator.Error!Value {
2792 const elem_ty = ty.elemType2(mod);2024 const elem_ty = ty.elemType2(mod);
2793 const ptr_val = switch (val.ip_index) {2025 const ptr_val = switch (mod.intern_pool.indexToKey(val.ip_index)) {
2794 .none => switch (val.tag()) {2026 .ptr => |ptr| ptr: {
2795 .slice => val.castTag(.slice).?.data.ptr,2027 switch (ptr.addr) {
2796 else => val,2028 .elem => |elem| if (mod.intern_pool.typeOf(elem.base).toType().elemType2(mod).eql(elem_ty, mod))
2797 },2029 return (try mod.intern(.{ .ptr = .{
2798 else => switch (mod.intern_pool.indexToKey(val.ip_index)) {2030 .ty = ty.ip_index,
2799 .ptr => |ptr| switch (ptr.len) {2031 .addr = .{ .elem = .{
2032 .base = elem.base,
2033 .index = elem.index + index,
2034 } },
2035 } })).toValue(),
2036 else => {},
2037 }
2038 break :ptr switch (ptr.len) {
2800 .none => val,2039 .none => val,
2801 else => val.slicePtr(mod),2040 else => val.slicePtr(mod),
2802 },2041 };
2803 else => val,
2804 },2042 },
2043 else => val,
2805 };2044 };
28062045 return (try mod.intern(.{ .ptr = .{
2807 if (ptr_val.ip_index == .none and ptr_val.tag() == .elem_ptr) {2046 .ty = ty.ip_index,
2808 const elem_ptr = ptr_val.castTag(.elem_ptr).?.data;2047 .addr = .{ .elem = .{
2809 if (elem_ptr.elem_ty.eql(elem_ty, mod)) {2048 .base = ptr_val.ip_index,
2810 return Tag.elem_ptr.create(arena, .{2049 .index = index,
2811 .array_ptr = elem_ptr.array_ptr,2050 } },
2812 .elem_ty = elem_ptr.elem_ty,2051 } })).toValue();
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 });
2822 }2052 }
28232053
2824 pub fn isUndef(val: Value, mod: *Module) bool {2054 pub fn isUndef(val: Value, mod: *Module) bool {
...@@ -2840,69 +2070,44 @@ pub const Value = struct {...@@ -2840,69 +2070,44 @@ pub const Value = struct {
2840 /// Returns true if any value contained in `self` is undefined.2070 /// Returns true if any value contained in `self` is undefined.
2841 pub fn anyUndef(val: Value, mod: *Module) !bool {2071 pub fn anyUndef(val: Value, mod: *Module) !bool {
2842 if (val.ip_index == .none) return false;2072 if (val.ip_index == .none) return false;
2843 switch (val.ip_index) {2073 return switch (val.ip_index) {
2844 .undef => return true,2074 .undef => true,
2845 .none => switch (val.tag()) {2075 .none => switch (val.tag()) {
2846 .slice => {2076 .aggregate => for (val.castTag(.aggregate).?.data) |field| {
2847 const payload = val.castTag(.slice).?;2077 if (try field.anyUndef(mod)) break true;
2848 const len = payload.data.len.toUnsignedInt(mod);2078 } else false,
28492079 else => false,
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 => {},
2863 },2080 },
2864 else => switch (mod.intern_pool.indexToKey(val.ip_index)) {2081 else => switch (mod.intern_pool.indexToKey(val.ip_index)) {
2865 .undef => return true,2082 .undef => true,
2866 .simple_value => |v| if (v == .undefined) return true,2083 .simple_value => |v| v == .undefined,
2867 .aggregate => |aggregate| switch (aggregate.storage) {2084 .ptr => |ptr| switch (ptr.len) {
2868 .elems => |elems| for (elems) |elem| {2085 .none => false,
2869 if (try anyUndef(elem.toValue(), mod)) return true;2086 else => for (0..@intCast(usize, ptr.len.toValue().toUnsignedInt(mod))) |index| {
2870 },2087 if (try (try val.elemValue(mod, index)).anyUndef(mod)) break true;
2871 .repeated_elem => |elem| if (try anyUndef(elem.toValue(), mod)) return true,2088 } else false,
2872 },2089 },
2873 else => {},2090 .aggregate => |aggregate| for (aggregate.storage.values()) |elem| {
2091 if (try anyUndef(elem.toValue(), mod)) break true;
2092 } else false,
2093 else => false,
2874 },2094 },
2875 }2095 };
2876
2877 return false;
2878 }2096 }
28792097
2880 /// Asserts the value is not undefined and not unreachable.2098 /// Asserts the value is not undefined and not unreachable.
2881 /// Integer value 0 is considered null because of C pointers.2099 /// 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 {
2883 return switch (val.ip_index) {2101 return switch (val.ip_index) {
2884 .undef => unreachable,2102 .undef => unreachable,
2885 .unreachable_value => unreachable,2103 .unreachable_value => unreachable,
28862104
2887 .null_value => true,2105 .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 },
2902 else => return switch (mod.intern_pool.indexToKey(val.ip_index)) {2107 else => return switch (mod.intern_pool.indexToKey(val.ip_index)) {
2903 .int => |int| switch (int.storage) {2108 .int => {
2904 .big_int => |big_int| big_int.eqZero(),2109 var buf: BigIntSpace = undefined;
2905 inline .u64, .i64 => |x| x == 0,2110 return val.toBigInt(&buf, mod).eqZero();
2906 },2111 },
2907 .opt => |opt| opt.val == .none,2112 .opt => |opt| opt.val == .none,
2908 else => false,2113 else => false,
...@@ -2914,53 +2119,28 @@ pub const Value = struct {...@@ -2914,53 +2119,28 @@ pub const Value = struct {
2914 /// unreachable. For error unions, prefer `errorUnionIsPayload` to find out whether2119 /// unreachable. For error unions, prefer `errorUnionIsPayload` to find out whether
2915 /// something is an error or not because it works without having to figure out the2120 /// something is an error or not because it works without having to figure out the
2916 /// string.2121 /// string.
2917 pub fn getError(self: Value) ?[]const u8 {2122 pub fn getError(self: Value, mod: *const Module) ?[]const u8 {
2918 return switch (self.ip_index) {2123 return mod.intern_pool.stringToSliceUnwrap(switch (mod.intern_pool.indexToKey(self.ip_index)) {
2919 .undef => unreachable,2124 .err => |err| err.name.toOptional(),
2920 .unreachable_value => unreachable,2125 .error_union => |error_union| switch (error_union.val) {
2921 .none => switch (self.tag()) {2126 .err_name => |err_name| err_name.toOptional(),
2922 .@"error" => self.castTag(.@"error").?.data.name,2127 .payload => .none,
2923 .eu_payload => null,
2924
2925 .inferred_alloc => unreachable,
2926 .inferred_alloc_comptime => unreachable,
2927 else => unreachable,
2928 },2128 },
2929 else => unreachable,2129 else => unreachable,
2930 };2130 });
2931 }2131 }
29322132
2933 /// Assumes the type is an error union. Returns true if and only if the value is2133 /// Assumes the type is an error union. Returns true if and only if the value is
2934 /// the error union payload, not an error.2134 /// the error union payload, not an error.
2935 pub fn errorUnionIsPayload(val: Value) bool {2135 pub fn errorUnionIsPayload(val: Value, mod: *const Module) bool {
2936 return switch (val.ip_index) {2136 return mod.intern_pool.indexToKey(val.ip_index).error_union.val == .payload;
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 };
2947 }2137 }
29482138
2949 /// Value of the optional, null if optional has no payload.2139 /// Value of the optional, null if optional has no payload.
2950 pub fn optionalValue(val: Value, mod: *const Module) ?Value {2140 pub fn optionalValue(val: Value, mod: *const Module) ?Value {
2951 return switch (val.ip_index) {2141 return switch (mod.intern_pool.indexToKey(val.ip_index).opt.val) {
2952 .none => if (val.isNull(mod)) null2142 .none => null,
2953 // Valid for optional representation to be the direct value2143 else => |index| index.toValue(),
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 },
2964 };2144 };
2965 }2145 }
29662146
...@@ -3001,28 +2181,8 @@ pub const Value = struct {...@@ -3001,28 +2181,8 @@ pub const Value = struct {
3001 }2181 }
30022182
3003 pub fn intToFloatScalar(val: Value, float_ty: Type, mod: *Module, opt_sema: ?*Sema) !Value {2183 pub fn intToFloatScalar(val: Value, float_ty: Type, mod: *Module, opt_sema: ?*Sema) !Value {
3004 switch (val.ip_index) {2184 return switch (val.ip_index) {
3005 .undef => return val,2185 .undef => 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 },
3026 else => return switch (mod.intern_pool.indexToKey(val.ip_index)) {2186 else => return switch (mod.intern_pool.indexToKey(val.ip_index)) {
3027 .int => |int| switch (int.storage) {2187 .int => |int| switch (int.storage) {
3028 .big_int => |big_int| {2188 .big_int => |big_int| {
...@@ -3030,10 +2190,20 @@ pub const Value = struct {...@@ -3030,10 +2190,20 @@ pub const Value = struct {
3030 return mod.floatValue(float_ty, float);2190 return mod.floatValue(float_ty, float);
3031 },2191 },
3032 inline .u64, .i64 => |x| intToFloatInner(x, float_ty, mod),2192 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 },
3033 },2203 },
3034 else => unreachable,2204 else => unreachable,
3035 },2205 },
3036 }2206 };
3037 }2207 }
30382208
3039 fn intToFloatInner(x: anytype, dest_ty: Type, mod: *Module) !Value {2209 fn intToFloatInner(x: anytype, dest_ty: Type, mod: *Module) !Value {
...@@ -4768,81 +3938,6 @@ pub const Value = struct {...@@ -4768,81 +3938,6 @@ pub const Value = struct {
4768 pub const Payload = struct {3938 pub const Payload = struct {
4769 tag: Tag,3939 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
4846 pub const Bytes = struct {3941 pub const Bytes = struct {
4847 base: Payload,3942 base: Payload,
4848 /// Includes the sentinel, if any.3943 /// Includes the sentinel, if any.
...@@ -4861,32 +3956,6 @@ pub const Value = struct {...@@ -4861,32 +3956,6 @@ pub const Value = struct {
4861 data: []Value,3956 data: []Value,
4862 };3957 };
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
4890 pub const InferredAlloc = struct {3959 pub const InferredAlloc = struct {
4891 pub const base_tag = Tag.inferred_alloc;3960 pub const base_tag = Tag.inferred_alloc;
48923961
tools/lldb_pretty_printers.py+3-3
...@@ -533,8 +533,8 @@ type_tag_handlers = {...@@ -533,8 +533,8 @@ type_tag_handlers = {
533 'empty_struct_literal': lambda payload: '@TypeOf(.{})',533 'empty_struct_literal': lambda payload: '@TypeOf(.{})',
534534
535 'anyerror_void_error_union': lambda payload: 'anyerror!void',535 'anyerror_void_error_union': lambda payload: 'anyerror!void',
536 'const_slice_u8': lambda payload: '[]const u8',536 'slice_const_u8': lambda payload: '[]const u8',
537 'const_slice_u8_sentinel_0': lambda payload: '[:0]const u8',537 'slice_const_u8_sentinel_0': lambda payload: '[:0]const u8',
538 'fn_noreturn_no_args': lambda payload: 'fn() noreturn',538 'fn_noreturn_no_args': lambda payload: 'fn() noreturn',
539 'fn_void_no_args': lambda payload: 'fn() void',539 'fn_void_no_args': lambda payload: 'fn() void',
540 'fn_naked_noreturn_no_args': lambda payload: 'fn() callconv(.Naked) noreturn',540 'fn_naked_noreturn_no_args': lambda payload: 'fn() callconv(.Naked) noreturn',
...@@ -560,7 +560,7 @@ type_tag_handlers = {...@@ -560,7 +560,7 @@ type_tag_handlers = {
560 'many_mut_pointer': lambda payload: '[*]%s' % type_Type_SummaryProvider(payload),560 'many_mut_pointer': lambda payload: '[*]%s' % type_Type_SummaryProvider(payload),
561 'c_const_pointer': lambda payload: '[*c]const %s' % type_Type_SummaryProvider(payload),561 'c_const_pointer': lambda payload: '[*c]const %s' % type_Type_SummaryProvider(payload),
562 'c_mut_pointer': lambda payload: '[*c]%s' % type_Type_SummaryProvider(payload),562 '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),
564 'mut_slice': lambda payload: '[]%s' % type_Type_SummaryProvider(payload),564 'mut_slice': lambda payload: '[]%s' % type_Type_SummaryProvider(payload),
565 'int_signed': lambda payload: 'i%d' % payload.unsigned,565 'int_signed': lambda payload: 'i%d' % payload.unsigned,
566 'int_unsigned': lambda payload: 'u%d' % payload.unsigned,566 'int_unsigned': lambda payload: 'u%d' % payload.unsigned,
tools/stage2_gdb_pretty_printers.py+1-1
...@@ -18,7 +18,7 @@ class TypePrinter:...@@ -18,7 +18,7 @@ class TypePrinter:
18 'many_mut_pointer': 'Type.Payload.ElemType',18 'many_mut_pointer': 'Type.Payload.ElemType',
19 'c_const_pointer': 'Type.Payload.ElemType',19 'c_const_pointer': 'Type.Payload.ElemType',
20 'c_mut_pointer': 'Type.Payload.ElemType',20 'c_mut_pointer': 'Type.Payload.ElemType',
21 'const_slice': 'Type.Payload.ElemType',21 'slice_const': 'Type.Payload.ElemType',
22 'mut_slice': 'Type.Payload.ElemType',22 'mut_slice': 'Type.Payload.ElemType',
23 'optional': 'Type.Payload.ElemType',23 'optional': 'Type.Payload.ElemType',
24 'optional_single_mut_pointer': 'Type.Payload.ElemType',24 'optional_single_mut_pointer': 'Type.Payload.ElemType',