| author | |
| committer | |
| log | 6e0de1d11694a58745da76d601ebab7562feed09 |
| tree | cd6cf352788d8f47bad97a95e4390dd3f6a309c5 |
| parent | 5555bdca047f8dbf8d7adfa8f248f5ce9b692b9e |
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 | } |
| 461 | 461 | ||
| 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 | } |
| 951 | 973 | ||
| 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 { |
| 1382 | 1382 | ||
| 1383 | .bool_to_int => return Type.u1, | 1383 | .bool_to_int => return Type.u1, |
| 1384 | 1384 | ||
| 1385 | .tag_name, .error_name => return Type.const_slice_u8_sentinel_0, | 1385 | .tag_name, .error_name => return Type.slice_const_u8_sentinel_0, |
| 1386 | 1386 | ||
| 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), |
| 8272 | 8272 | ||
| 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 by | 3208 | // Tests are always emitted in test binaries. The decl_refs are created by |
| 3209 | // Module.populateTestFunctions, but this will not queue body analysis, so do | 3209 | // 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. |
| 35 | unions_free_list: std.ArrayListUnmanaged(Module.Union.Index) = .{}, | 35 | unions_free_list: std.ArrayListUnmanaged(Module.Union.Index) = .{}, |
| 36 | 36 | ||
| 37 | /// Fn objects are stored in this data structure because: | ||
| 38 | /// * They need to be mutated after creation. | ||
| 39 | allocated_funcs: std.SegmentedList(Module.Fn, 0) = .{}, | ||
| 40 | /// When a Fn object is freed from `allocated_funcs`, it is pushed into this stack. | ||
| 41 | funcs_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; |
| 66 | 72 | ||
| 67 | const InternPool = @This(); | 73 | const InternPool = @This(); |
| 68 | const Module = @import("Module.zig"); | 74 | const Module = @import("Module.zig"); |
| 75 | const Sema = @import("Sema.zig"); | ||
| 69 | 76 | ||
| 70 | const KeyAdapter = struct { | 77 | const KeyAdapter = struct { |
| 71 | intern_pool: *const InternPool, | 78 | intern_pool: *const InternPool, |
| 72 | 79 | ||
| 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 | } |
| 77 | 84 | ||
| 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 | }; |
| 83 | 89 | ||
| ... | @@ -111,10 +117,19 @@ pub const RuntimeIndex = enum(u32) { | ... | @@ -111,10 +117,19 @@ pub const RuntimeIndex = enum(u32) { |
| 111 | } | 117 | } |
| 112 | }; | 118 | }; |
| 113 | 119 | ||
| 120 | /// An index into `string_bytes`. | ||
| 121 | pub const String = enum(u32) { | ||
| 122 | _, | ||
| 123 | }; | ||
| 124 | |||
| 114 | /// An index into `string_bytes`. | 125 | /// An index into `string_bytes`. |
| 115 | pub const NullTerminatedString = enum(u32) { | 126 | pub const NullTerminatedString = enum(u32) { |
| 116 | _, | 127 | _, |
| 117 | 128 | ||
| 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 represented | 195 | /// 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 | }; |
| 266 | 278 | ||
| 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 range | 383 | .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 | }; |
| 443 | 456 | ||
| 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, | ||
| 452 | 493 | ||
| 453 | /// Big enough to fit any non-BigInt value | 494 | /// 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 | }; |
| 469 | 510 | ||
| 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, |
| 498 | 552 | ||
| 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, |
| 519 | 562 | ||
| 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, |
| 547 | 594 | ||
| 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 | }; |
| 553 | 609 | ||
| 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 | } |
| 557 | 613 | ||
| 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 | } |
| 563 | 619 | ||
| 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), |
| 587 | 645 | ||
| 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), |
| 590 | 649 | ||
| 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 => { |
| 595 | 658 | 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 | }, |
| 600 | 674 | ||
| 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) { |
| 629 | 702 | ||
| 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 | }, |
| 641 | 748 | ||
| ... | @@ -663,7 +770,7 @@ pub const Key = union(enum) { | ... | @@ -663,7 +770,7 @@ pub const Key = union(enum) { |
| 663 | } | 770 | } |
| 664 | } | 771 | } |
| 665 | 772 | ||
| 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 | }, |
| 736 | 855 | ||
| 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; |
| 743 | 875 | ||
| 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; |
| 819 | 961 | ||
| 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 | } | ||
| 822 | 985 | ||
| 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, |
| 878 | 1051 | ||
| 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, |
| 888 | 1066 | ||
| 1067 | .enum_literal => .enum_literal_type, | ||
| 1068 | |||
| 889 | .undef => |x| x, | 1069 | .undef => |x| x, |
| 890 | 1070 | ||
| 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 | }, |
| 1129 | 1309 | ||
| 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 | } }, |
| 1320 | 1509 | ||
| 1321 | // const_slice_u8_type | 1510 | // 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 | } }, |
| 1327 | 1516 | ||
| 1328 | // const_slice_u8_sentinel_0_type | 1517 | // 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 use | 1712 | /// 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 have | 1837 | /// 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 | }; |
| 1672 | 1888 | ||
| 1889 | pub 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 len | 1897 | /// 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 | }; |
| 1845 | 2068 | ||
| 2069 | pub 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 order | 2075 | /// 0. field name: NullTerminatedString for each fields_len; declaration order |
| 1848 | /// 1. tag value: Index for each fields_len; declaration order | 2076 | /// 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 | }; |
| 1890 | 2118 | ||
| 1891 | pub const PtrVar = struct { | 2119 | pub 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, |
| 1900 | 2127 | ||
| 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 | }; |
| 1908 | 2137 | ||
| ... | @@ -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 | }; |
| 1919 | 2148 | ||
| 1920 | pub const PtrInt = struct { | 2149 | pub 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 | }; |
| 1951 | 2180 | ||
| 2181 | pub 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. |
| 1953 | pub const Float64 = struct { | 2187 | pub 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); |
| 2065 | 2299 | ||
| 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); |
| 2068 | 2305 | ||
| ... | @@ -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) }, |
| 2236 | 2473 | ||
| 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 | }, | ||
| 2680 | 2965 | ||
| 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 | }, |
| 2811 | 3096 | ||
| 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 | }), | ||
| 2813 | 3126 | ||
| 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 | }, |
| 2922 | 3231 | ||
| 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 | }, |
| 3082 | 3415 | ||
| 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 | }, |
| 3132 | 3492 | ||
| 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 | } |
| 3153 | 3516 | ||
| 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 | } |
| 3174 | 3543 | ||
| 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 | } |
| 3198 | 3581 | ||
| 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 | } |
| 3425 | 3840 | ||
| 3426 | pub fn getAssumeExists(ip: *const InternPool, key: Key) Index { | 3841 | pub 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 | } |
| 3431 | 3846 | ||
| 3847 | pub fn getAssumeExists(ip: *const InternPool, key: Key) Index { | ||
| 3848 | return ip.getIfExists(key).?; | ||
| 3849 | } | ||
| 3850 | |||
| 3432 | fn addStringsToMap( | 3851 | fn 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. |
| 3701 | pub fn slicePtrType(ip: InternPool, i: Index) Index { | 4124 | pub 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 | } |
| 3835 | 4260 | ||
| ... | @@ -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 | } |
| 3864 | 4289 | ||
| 4290 | pub 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 | |||
| 3865 | pub fn indexToInferredErrorSetType(ip: InternPool, val: Index) Module.Fn.InferredErrorSet.OptionalIndex { | 4298 | pub 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 | } |
| 3893 | 4326 | ||
| 4327 | /// The is only legal because the initializer is not part of the hash. | ||
| 4328 | pub 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 | |||
| 3894 | pub fn dump(ip: InternPool) void { | 4336 | pub 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)); | ||
| 3906 | 4350 | ||
| 3907 | // TODO: map overhead size is not taken into account | 4351 | // 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; |
| 3910 | 4354 | ||
| 3911 | std.debug.print( | 4355 | std.debug.print( |
| 3912 | \\InternPool size: {d} bytes | 4356 | \\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} bytes | 4359 | \\ {d} limbs: {d} bytes |
| 3916 | \\ {d} structs: {d} bytes | 4360 | \\ {d} structs: {d} bytes |
| 3917 | \\ {d} unions: {d} bytes | 4361 | \\ {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 | }); |
| 3932 | 4379 | ||
| 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 | }, |
| 3983 | 4430 | ||
| 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), |
| 4015 | 4468 | ||
| 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 | } |
| 4073 | 4533 | ||
| 4534 | pub fn funcPtr(ip: *InternPool, index: Module.Fn.Index) *Module.Fn { | ||
| 4535 | return ip.allocated_funcs.at(@enumToInt(index)); | ||
| 4536 | } | ||
| 4537 | |||
| 4538 | pub fn funcPtrConst(ip: InternPool, index: Module.Fn.Index) *const Module.Fn { | ||
| 4539 | return ip.allocated_funcs.at(@enumToInt(index)); | ||
| 4540 | } | ||
| 4541 | |||
| 4074 | pub fn inferredErrorSetPtr(ip: *InternPool, index: Module.Fn.InferredErrorSet.Index) *Module.Fn.InferredErrorSet { | 4542 | pub 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 | } |
| 4119 | 4587 | ||
| 4588 | pub 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 | |||
| 4599 | pub 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 | |||
| 4120 | pub fn createInferredErrorSet( | 4607 | pub 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. | ||
| 4639 | pub 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 | } |
| 4181 | 4684 | ||
| 4685 | pub fn stringToSliceUnwrap(ip: InternPool, s: OptionalNullTerminatedString) ?[:0]const u8 { | ||
| 4686 | return ip.stringToSlice(s.unwrap() orelse return null); | ||
| 4687 | } | ||
| 4688 | |||
| 4182 | pub fn typeOf(ip: InternPool, index: Index) Index { | 4689 | pub 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 | } |
| 4201 | 4708 | ||
| 4202 | pub fn isNoReturn(ip: InternPool, ty: InternPool.Index) bool { | 4709 | pub 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 here | 109 | /// Contains the values from `@setAlignStack`. A sparse table is used here |
| 110 | /// instead of a field of `Fn` because usage of `@setAlignStack` is rare, while | 110 | /// instead of a field of `Fn` because usage of `@setAlignStack` is rare, while |
| 111 | /// functions are many. | 111 | /// functions are many. |
| 112 | align_stack_fns: std.AutoHashMapUnmanaged(*const Fn, SetAlignStack) = .{}, | 112 | align_stack_fns: std.AutoHashMapUnmanaged(Fn.Index, SetAlignStack) = .{}, |
| 113 | 113 | ||
| 114 | /// We optimize memory usage for a compilation with no compile errors by storing the | 114 | /// 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 | }; |
| 243 | 243 | ||
| 244 | const MonomorphedFuncsSet = std.HashMapUnmanaged( | 244 | const 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 | ); |
| 250 | 250 | ||
| 251 | const MonomorphedFuncsContext = struct { | 251 | const 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 | } |
| 256 | 258 | ||
| 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 | }; |
| 263 | 264 | ||
| ... | @@ -272,7 +273,7 @@ pub const MemoizedCall = struct { | ... | @@ -272,7 +273,7 @@ pub const MemoizedCall = struct { |
| 272 | module: *Module, | 273 | module: *Module, |
| 273 | 274 | ||
| 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 | }; |
| 278 | 279 | ||
| ... | @@ -652,21 +653,12 @@ pub const Decl = struct { | ... | @@ -652,21 +653,12 @@ pub const Decl = struct { |
| 652 | 653 | ||
| 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 { |
| 835 | 827 | ||
| 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 | } |
| 841 | 833 | ||
| 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 { |
| 847 | 839 | ||
| 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 { |
| 855 | 847 | ||
| 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 | } |
| 863 | 857 | ||
| 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 | } |
| 871 | 863 | ||
| 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 | } |
| 879 | 869 | ||
| 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 | } |
| 897 | 887 | ||
| 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 | } |
| 902 | 892 | ||
| 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 | } |
| 929 | 919 | ||
| 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, |
| 1496 | 1483 | ||
| 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 not | 1507 | /// 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, |
| 1523 | 1532 | ||
| 1524 | /// All currently known errors that this error set contains. This includes | 1533 | /// All currently known errors that this error set contains. This includes |
| 1525 | /// direct additions via `return error.Foo;`, and possibly also errors that | 1534 | /// 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 | _, |
| 1545 | 1554 | ||
| 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 | }; |
| 1550 | 1559 | ||
| ... | @@ -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 | _, |
| 1554 | 1563 | ||
| 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 | } |
| 1558 | 1567 | ||
| 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 | }; |
| 1564 | 1573 | ||
| ... | @@ -1587,12 +1596,6 @@ pub const Fn = struct { | ... | @@ -1587,12 +1596,6 @@ pub const Fn = struct { |
| 1587 | } | 1596 | } |
| 1588 | }; | 1597 | }; |
| 1589 | 1598 | ||
| 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); |
| 1598 | 1601 | ||
| ... | @@ -1647,28 +1650,6 @@ pub const Fn = struct { | ... | @@ -1647,28 +1650,6 @@ pub const Fn = struct { |
| 1647 | } | 1650 | } |
| 1648 | }; | 1651 | }; |
| 1649 | 1652 | ||
| 1650 | pub 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 | |||
| 1672 | pub const DeclAdapter = struct { | 1653 | pub const DeclAdapter = struct { |
| 1673 | mod: *Module, | 1654 | mod: *Module, |
| 1674 | 1655 | ||
| ... | @@ -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 | } |
| 3474 | 3455 | ||
| 3456 | pub fn funcPtr(mod: *Module, index: Fn.Index) *Fn { | ||
| 3457 | return mod.intern_pool.funcPtr(index); | ||
| 3458 | } | ||
| 3459 | |||
| 3475 | pub fn inferredErrorSetPtr(mod: *Module, index: Fn.InferredErrorSet.Index) *Fn.InferredErrorSet { | 3460 | pub 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 not | 3464 | /// 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. |
| 3481 | pub fn structPtrUnwrap(mod: *Module, index: Struct.OptionalIndex) ?*Struct { | 3466 | pub 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 | |||
| 3470 | pub fn funcPtrUnwrap(mod: *Module, index: Fn.OptionalIndex) ?*Fn { | ||
| 3471 | return mod.funcPtr(index.unwrap() orelse return null); | ||
| 3483 | } | 3472 | } |
| 3484 | 3473 | ||
| 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 | } |
| 3954 | 3943 | ||
| 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); |
| 4140 | 4129 | ||
| 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 | } |
| 4145 | 4134 | ||
| ... | @@ -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 | } |
| 4231 | 4220 | ||
| 4232 | pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void { | 4221 | pub 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(); |
| 4235 | 4224 | ||
| 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); |
| 4238 | 4228 | ||
| ... | @@ -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(); |
| 4266 | 4256 | ||
| 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 would | 4260 | // 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 { |
| 4333 | 4323 | ||
| 4334 | if (no_bin_file and !dump_llvm_ir) return; | 4324 | if (no_bin_file and !dump_llvm_ir) return; |
| 4335 | 4325 | ||
| 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 (see | 4353 | /// analyzed, and for ensuring it can exist at runtime (see |
| 4364 | /// `sema.fnHasRuntimeBits`). This function does *not* guarantee that the body | 4354 | /// `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`. |
| 4366 | pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func: *Fn) !void { | 4356 | pub 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); |
| 4369 | 4360 | ||
| ... | @@ -4401,7 +4392,7 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func: *Fn) !void { | ... | @@ -4401,7 +4392,7 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func: *Fn) !void { |
| 4401 | 4392 | ||
| 4402 | // Decl itself is safely analyzed, and body analysis is not yet queued | 4393 | // Decl itself is safely analyzed, and body analysis is not yet queued |
| 4403 | 4394 | ||
| 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 changed | 4397 | // TODO: we ideally only want to do this if the function's type changed |
| 4407 | // since the last update | 4398 | // 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(); |
| 4539 | 4532 | ||
| ... | @@ -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(); |
| 4635 | 4630 | ||
| ... | @@ -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 | } |
| 4709 | 4704 | ||
| 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, |
| 4760 | 4755 | 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 | }, |
| 4780 | 4766 | ||
| 4781 | .function => {}, | 4767 | .func => {}, |
| 4782 | 4768 | ||
| 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 | } |
| 4793 | 4775 | ||
| 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 | }; |
| 4821 | 4800 | ||
| ... | @@ -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 state | 5373 | // 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 | } |
| 5574 | 5553 | ||
| 5575 | pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air { | 5554 | pub 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(); |
| 5578 | 5557 | ||
| 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); |
| 5582 | 5562 | ||
| ... | @@ -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 | } |
| 5854 | 5835 | ||
| 5836 | pub fn createFunc(mod: *Module, initialization: Fn) Allocator.Error!Fn.Index { | ||
| 5837 | return mod.intern_pool.createFunc(mod.gpa, initialization); | ||
| 5838 | } | ||
| 5839 | |||
| 5840 | pub fn destroyFunc(mod: *Module, index: Fn.Index) void { | ||
| 5841 | return mod.intern_pool.destroyFunc(mod.gpa, index); | ||
| 5842 | } | ||
| 5843 | |||
| 5855 | pub fn allocateNewDecl( | 5844 | pub 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 | } }); | ||
| 6503 | 6496 | ||
| 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_functions | 6498 | // 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); |
| 6542 | 6535 | ||
| 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 | }), // name | 6541 | } }), |
| 6549 | try Value.Tag.decl_ref.create(arena, test_decl_index), // func | 6542 | // func |
| 6550 | Value.null, // async_frame_size | 6543 | try mod.intern(.{ .ptr = .{ |
| 6544 | .ty = test_decl.ty.ip_index, | ||
| 6545 | .addr = .{ .decl = test_decl_index }, | ||
| 6546 | } }), | ||
| 6547 | // async_frame_size | ||
| 6548 | null_usize, | ||
| 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 | } |
| 6554 | 6555 | ||
| 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); |
| 6559 | 6560 | ||
| 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, |
| 6564 | 6565 | .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 | } | ||
| 6589 | 6574 | ||
| 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 | } |
| 6661 | 6651 | ||
| 6662 | pub fn markReferencedDeclsAlive(mod: *Module, val: Value) void { | 6652 | pub 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 | }, |
| 6670 | 6660 | .@"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 | } |
| 6709 | 6696 | ||
| ... | @@ -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 { |
| 7075 | 7062 | ||
| 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 | } |
| 7080 | 7073 |
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 function | 28 | /// 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`. |
| 30 | owner_func: ?*Module.Fn, | 30 | owner_func: ?*Module.Fn, |
| 31 | owner_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 of | 33 | /// 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. |
| 34 | func: ?*Module.Fn, | 35 | func: ?*Module.Fn, |
| 36 | func_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. |
| 36 | error_return_trace_index_on_fn_entry: Air.Inst.Ref = .none, | 38 | error_return_trace_index_on_fn_entry: Air.Inst.Ref = .none, |
| 37 | /// When semantic analysis needs to know the return type of the function whose body | 39 | /// 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 unnecessary | 67 | /// 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. |
| 68 | preallocated_new_func: ?*Module.Fn = null, | 70 | preallocated_new_func: Module.Fn.OptionalIndex = .none, |
| 69 | /// The key is types that must be fully resolved prior to machine code | 71 | /// The key is types that must be fully resolved prior to machine code |
| 70 | /// generation pass. Types are added to this set when resolving them | 72 | /// generation pass. Types are added to this set when resolving them |
| 71 | /// immediately could cause a dependency loop, but they do need to be resolved | 73 | /// 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) = .{} |
| 92 | const std = @import("std"); | 94 | const std = @import("std"); |
| 93 | const math = std.math; | 95 | const math = std.math; |
| 94 | const mem = std.mem; | 96 | const mem = std.mem; |
| 95 | const Allocator = std.mem.Allocator; | 97 | const Allocator = mem.Allocator; |
| 96 | const assert = std.debug.assert; | 98 | const assert = std.debug.assert; |
| 97 | const log = std.log.scoped(.sema); | 99 | const log = std.log.scoped(.sema); |
| 98 | 100 | ||
| ... | @@ -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 | } |
| 1938 | 1939 | ||
| ... | @@ -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 | } |
| 1967 | 1967 | ||
| 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 | } |
| 2950 | 2950 | ||
| 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; | ||
| 2954 | 2957 | ||
| 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; | ||
| 2958 | 2964 | ||
| 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; |
| 3736 | 3742 | ||
| 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_const | 3848 | // 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); |
| 4334 | 4342 | ||
| 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( |
| 4464 | 4476 | ||
| 4465 | // We collect the comptime field values in case the struct initialization | 4477 | // 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); | ||
| 4468 | 4481 | ||
| 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 | } |
| 4477 | 4490 | ||
| ... | @@ -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 | } |
| 4575 | 4588 | ||
| 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. |
| 4594 | 4607 | ||
| 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 | else | 4630 | 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 up | 4710 | // 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( |
| 4701 | 4721 | ||
| 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-known | 4728 | // 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( |
| 4780 | 4800 | ||
| 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 | } |
| 4788 | 4811 | ||
| ... | @@ -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 | } |
| 4795 | 4818 | ||
| 4796 | block.instructions.shrinkRetainingCapacity(first_block_index); | 4819 | block.instructions.shrinkRetainingCapacity(first_block_index); |
| 4797 | 4820 | ||
| 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 | } |
| 5789 | 5815 | ||
| 5790 | // TODO: some backends might support re-exporting extern decls | 5816 | // 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 | } |
| 5794 | 5820 | ||
| ... | @@ -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); |
| 5798 | 5824 | ||
| 5799 | const gpa = mod.gpa; | 5825 | const gpa = sema.gpa; |
| 5800 | 5826 | ||
| 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 orelse | 5881 | 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); | ||
| 5857 | 5884 | ||
| 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 | } |
| 5866 | 5893 | ||
| 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 | }; |
| 6578 | 6608 | ||
| 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 inserted | 6613 | // 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, the | 6614 | // 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; |
| 6585 | 6617 | ||
| 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)); |
| 6593 | 6625 | ||
| 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); |
| 6665 | 6697 | ||
| 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 rather | 6839 | // 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 | } |
| 6820 | 6856 | ||
| 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; | ||
| 6824 | 6863 | ||
| 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( |
| 6982 | 7021 | ||
| 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); |
| 6986 | 7025 | ||
| 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 | } |
| 7121 | 7160 | ||
| 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 | } |
| 7127 | 7166 | ||
| ... | @@ -7147,9 +7186,9 @@ fn analyzeCall( | ... | @@ -7147,9 +7186,9 @@ fn analyzeCall( |
| 7147 | // Function pointers and extern functions aren't guaranteed to | 7186 | // 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; |
| 7388 | 7427 | ||
| 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 we | 7434 | // 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 a | 7435 | // 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); | ||
| 7502 | 7542 | ||
| 7503 | // This ensures that we can operate on the hash map before the Module.Fn | 7543 | // 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; |
| 7509 | 7549 | ||
| 7510 | try namespace.anon_decls.ensureUnusedCapacity(gpa, 1); | 7550 | try namespace.anon_decls.ensureUnusedCapacity(gpa, 1); |
| 7511 | 7551 | ||
| ... | @@ -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); | ||
| 7593 | 7634 | ||
| 7594 | callee.branch_quota = @max(callee.branch_quota, sema.branch_quota); | 7635 | callee.branch_quota = @max(callee.branch_quota, sema.branch_quota); |
| 7595 | 7636 | ||
| ... | @@ -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 | } |
| 7647 | 7688 | ||
| 7648 | try sema.mod.ensureFuncBodyAnalysisQueued(callee); | 7689 | try sema.mod.ensureFuncBodyAnalysisQueued(callee_index); |
| 7649 | 7690 | ||
| 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; |
| 7693 | 7734 | ||
| ... | @@ -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( |
| 7802 | 7845 | ||
| 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); |
| 7808 | 7851 | ||
| 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 | } |
| 7869 | 7912 | ||
| 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) |
| 7900 | fn emitDbgInline( | 7946 | fn 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; |
| 7912 | 7958 | ||
| 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 | } |
| 8088 | 8136 | ||
| 8089 | fn zirErrorToInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { | 8137 | fn zirErrorToInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { |
| ... | @@ -8101,23 +8149,11 @@ fn zirErrorToInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat | ... | @@ -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 | } |
| 8122 | 8158 | ||
| 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(); |
| 8144 | 8180 | ||
| 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; | ||
| 8151 | 8187 | ||
| 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(); |
| 8236 | 8270 | ||
| 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 | } |
| 8244 | 8278 | ||
| 8245 | fn zirEnumToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 8279 | fn 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( |
| 8404 | 8438 | ||
| 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 | } |
| 8435 | 8463 | ||
| ... | @@ -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 | } |
| 8541 | 8571 | ||
| 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( |
| 8595 | 8625 | ||
| 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 | } |
| 8617 | 8644 | 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 | } |
| 8627 | 8650 | ||
| ... | @@ -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); |
| 8665 | 8688 | ||
| 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 | } |
| 8670 | 8693 | ||
| ... | @@ -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 |
| 8694 | 8717 | ||
| 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 | } |
| 8932 | 8955 | ||
| 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 ownership | 8961 | 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); |
| 8948 | 8972 | ||
| 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; |
| 9159 | 9183 | ||
| 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, |
| 9163 | 9187 | .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, |
| 9168 | 9192 | }, 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 | } |
| 9182 | 9196 | ||
| 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; |
| 9193 | 9207 | ||
| 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 | } |
| 9217 | 9230 | ||
| 9218 | fn analyzeParameter( | 9231 | fn 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 the | 9386 | // 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 | } |
| 9394 | 9407 | ||
| 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-comptime | 9410 | // 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( |
| 9640 | 9653 | ||
| 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 type | 9686 | // 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); |
| 9682 | 9692 | ||
| ... | @@ -9732,7 +9742,8 @@ fn intCast( | ... | @@ -9732,7 +9742,8 @@ fn intCast( |
| 9732 | // no shrinkage, yes sign loss | 9742 | // no shrinkage, yes sign loss |
| 9733 | // requirement: signed to unsigned >= 0 | 9743 | // 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 | }); |
| 10244 | 10256 | ||
| 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 succeed | 10285 | // 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 succeed | 10295 | // 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; |
| 10286 | 10297 | ||
| 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 |
| 10809 | 10820 | ||
| 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; |
| 11495 | 11503 | ||
| 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; |
| 11499 | 11510 | ||
| 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 { |
| 11665 | 11676 | ||
| 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); |
| 11670 | 11681 | ||
| 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.value | 11807 | prev.value |
| 11796 | else | 11808 | 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(); |
| 12006 | 12018 | ||
| 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 |
| 12172 | 12184 | ||
| 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 | } |
| 12181 | 12193 | ||
| 12182 | fn zirShl( | 12194 | fn 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); |
| 12467 | 12479 | ||
| 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 | } |
| 13181 | 13193 | ||
| 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 | } |
| 13189 | 13197 | ||
| ... | @@ -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 | } |
| 13205 | 13213 | ||
| 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 | } |
| 13213 | 13217 | ||
| ... | @@ -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 | }); |
| 13256 | 13260 | ||
| 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); |
| 13261 | 13263 | ||
| ... | @@ -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 | }); |
| 13429 | 13429 | ||
| 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); |
| 13434 | 13432 | ||
| ... | @@ -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 | }); |
| 13602 | 13598 | ||
| 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); |
| 13607 | 13601 | ||
| ... | @@ -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 | }); |
| 13723 | 13715 | ||
| 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); |
| 13728 | 13718 | ||
| ... | @@ -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 | } |
| 13845 | 13833 | ||
| 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; | ||
| 13852 | 13837 | ||
| 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 | else | 13909 | 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 | } |
| 14546 | 14532 | ||
| 14547 | fn maybeRepeated(sema: *Sema, ty: Type, val: Value) !Value { | 14533 | fn 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 | } |
| 14552 | 14542 | ||
| 14553 | fn overflowArithmeticTupleType(sema: *Sema, ty: Type) !Type { | 14543 | fn 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 | }); |
| 14605 | 14595 | ||
| 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); |
| 14610 | 14598 | ||
| ... | @@ -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; |
| 15188 | 15164 | ||
| 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 | }; |
| 15762 | 15733 | ||
| 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 | } |
| 15790 | 15761 | ||
| 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 alignment | 15847 | 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 | }; |
| 15880 | 15854 | ||
| 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 alignment | 15863 | 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 | }; |
| 15893 | 15870 | ||
| 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: u32 | 15876 | 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, |
| 15903 | 15880 | .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 | } |
| 15909 | 15890 | ||
| 15910 | fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 15891 | fn 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).?; |
| 15917 | 15899 | ||
| 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(); |
| 15988 | 15921 | ||
| 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 | } }); |
| 15996 | 15952 | ||
| ... | @@ -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 | }; |
| 16001 | 15957 | ||
| 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 | } |
| 16013 | 15971 | ||
| 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 alignment | 15988 | 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 | }; |
| 16052 | 15996 | ||
| 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 | } }); |
| 16057 | 16001 | ||
| 16058 | const callconv_ty = try sema.getBuiltinType("CallingConvention"); | 16002 | const callconv_ty = try sema.getBuiltinType("CallingConvention"); |
| 16059 | 16003 | ||
| 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 | }; |
| 16075 | 16018 | 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, |
| 16105 | 16048 | 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 | else | 16073 | else |
| 16119 | try info.pointee_type.lazyAbiAlignment(mod, sema.arena); | 16074 | try info.pointee_type.lazyAbiAlignment(mod); |
| 16120 | 16075 | ||
| 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 values | 16200 | // Build our list of Error values |
| 16246 | // Optional value is only null if anyerror | 16201 | // Optional value is only null if anyerror |
| 16247 | // Value can be zero-length slice otherwise | 16202 | // 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 alignment | 16216 | 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 | }; |
| 16264 | 16223 | ||
| 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 | }; |
| 16270 | 16228 | 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 | } |
| 16276 | 16233 | ||
| 16277 | break :blk vals; | 16234 | break :blk vals; |
| 16278 | }; | 16235 | }; |
| 16279 | 16236 | ||
| 16280 | // Build our ?[]const Error value | 16237 | // 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 alignment | 16256 | 0, // default alignment |
| 16293 | ); | 16257 | ); |
| 16294 | 16258 | 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 | } }); | ||
| 16302 | 16267 | ||
| 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 | }; | ||
| 16318 | 16288 | ||
| 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 | }; |
| 16348 | 16325 | ||
| 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); | ||
| 16350 | 16328 | ||
| 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 alignment | 16339 | 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 | }; |
| 16365 | 16346 | ||
| 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 | } |
| 16375 | 16358 | ||
| 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 alignment | 16371 | 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 | }; |
| 16391 | 16382 | ||
| 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); |
| 16393 | 16384 | ||
| 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 | }; |
| 16405 | 16408 | 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(); |
| 16419 | 16422 | ||
| 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); |
| 16436 | 16452 | ||
| 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); | ||
| 16439 | 16456 | ||
| 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 alignment | 16467 | 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 | }; |
| 16454 | 16474 | ||
| 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 | }; |
| 16460 | 16479 | ||
| 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 | } |
| 16471 | 16493 | ||
| 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 alignment | 16506 | 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 | }; |
| 16490 | 16518 | ||
| 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)); |
| 16492 | 16520 | ||
| 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 | } }); |
| 16497 | 16525 | ||
| 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 | }; |
| 16510 | 16538 | ||
| 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, |
| 16515 | 16542 | ||
| 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 | }; |
| 16523 | 16550 | 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(); |
| 16537 | 16564 | ||
| 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 layout | 16592 | try sema.resolveTypeLayout(ty); // Getting alignment requires type layout |
| 16552 | const layout = struct_ty.containerLayout(mod); | 16593 | const layout = struct_ty.containerLayout(mod); |
| 16553 | 16594 | ||
| 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 alignment | 16618 | 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 | }; |
| 16582 | 16626 | ||
| 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) orelse | 16652 | 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()); | ||
| 16609 | 16654 | ||
| 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 alignment | 16667 | 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 | }; |
| 16629 | 16675 | ||
| 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 | null | 16677 | null |
| 16633 | else | 16678 | 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); |
| 16637 | 16682 | ||
| 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 | }; | ||
| 16654 | 16701 | ||
| 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 alignment | 16714 | 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 | }; |
| 16673 | 16726 | ||
| 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)); |
| 16675 | 16728 | ||
| 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 | }; | ||
| 16687 | 16738 | ||
| 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 | }; |
| 16700 | 16751 | ||
| 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 | }; |
| 16714 | 16764 | 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. |
| 16725 | 16775 | ||
| 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)); |
| 16728 | 16791 | ||
| 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 | }; |
| 16734 | 16796 | 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); |
| 16772 | 16834 | ||
| 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(); |
| 16775 | 16837 | ||
| 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( |
| 16778 | 16840 | ||
| 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 | } |
| 16783 | 16845 | ||
| 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 alignment | 16857 | 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 | } |
| 16801 | 16869 | ||
| 16802 | fn typeInfoNamespaceDecls( | 16870 | fn 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 alignment | 16899 | 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 | }; |
| 16838 | 16907 | ||
| 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 | } |
| 16849 | 16920 | ||
| ... | @@ -17454,10 +17525,11 @@ fn zirRetErrValue( | ... | @@ -17454,10 +17525,11 @@ fn zirRetErrValue( |
| 17454 | 17525 | ||
| 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 | } |
| 17463 | 17535 | ||
| ... | @@ -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, in | 17855 | // 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 | } |
| 17920 | 17992 | ||
| 17921 | fn zirUnionInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 17993 | fn zirUnionInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | @@ -18679,8 +18751,8 @@ fn zirAlignOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -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 }; |
| 18705 | 18777 | ||
| 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 | } |
| 18710 | 18783 | ||
| ... | @@ -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); | ||
| 18891 | 18962 | ||
| 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); | ||
| 18904 | 18972 | ||
| 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); | ||
| 18921 | 18987 | ||
| 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); | ||
| 18952 | 19009 | ||
| 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); | ||
| 19042 | 19095 | ||
| 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; |
| 19052 | 19105 | ||
| 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); | ||
| 19061 | 19112 | ||
| 19062 | const child_ty = child_val.toType(); | 19113 | const child_ty = child_val.toType(); |
| 19063 | 19114 | ||
| ... | @@ -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); | ||
| 19074 | 19122 | ||
| 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) orelse | 19134 | 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; | ||
| 19089 | 19136 | ||
| 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 here | 19143 | // 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); | ||
| 19123 | 19164 | ||
| 19124 | const layout = mod.toEnum(std.builtin.Type.ContainerLayout, layout_val); | 19165 | const layout = mod.toEnum(std.builtin.Type.ContainerLayout, layout_val); |
| 19125 | 19166 | ||
| ... | @@ -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); | ||
| 19148 | 19184 | ||
| 19149 | // Decls | 19185 | // 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]; |
| 19196 | 19232 | ||
| 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); | ||
| 19243 | 19277 | ||
| 19244 | // Decls | 19278 | // 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); | ||
| 19295 | 19324 | ||
| 19296 | // Decls | 19325 | // 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]; |
| 19387 | 19416 | ||
| 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); | ||
| 19505 | 19527 | ||
| 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) orelse | 19550 | 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", .{}); |
| 19530 | 19552 | ||
| 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); |
| 19535 | 19555 | ||
| 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 here | 19560 | // 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 | } |
| 19677 | 19697 | ||
| 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 | } |
| 19708 | 19728 | ||
| 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).val | 19731 | mod.declPtr(opt_decl).val |
| 19712 | else | 19732 | 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 |
| 20137 | 20157 | ||
| 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( |
| 21159 | 21182 | ||
| 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); |
| 21164 | 21187 | ||
| 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( |
| 21168 | 21191 | ||
| 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 | else | 21197 | 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); |
| 21305 | 21328 | 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); |
| 21345 | 21370 | 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 | } |
| 21351 | 21372 | ||
| 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); |
| 22082 | 22103 | ||
| 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 | } |
| 22108 | 22134 | ||
| 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( |
| 22335 | 22361 | ||
| 22336 | // Compute the final bounds based on the runtime type and the comptime-known bound type | 22362 | // 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) >= ct | 22365 | .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) <= ct | 22369 | .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 | }; |
| 22347 | 22373 | ||
| ... | @@ -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 | } |
| 22465 | 22491 | ||
| 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 | } |
| 22620 | 22646 | ||
| 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( |
| 22737 | 22764 | ||
| 22738 | try sema.validateVarType(block, ty_src, var_ty, small.is_extern); | 22765 | try sema.validateVarType(block, ty_src, var_ty, small.is_extern); |
| 22739 | 22766 | ||
| 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, |
| 22742 | 22769 | .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, |
| 22746 | 22773 | 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 | } |
| 22767 | 22779 | ||
| 22768 | fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 22780 | fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | @@ -22861,7 +22873,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -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; |
| 22863 | 22875 | ||
| 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; | ||
| 23140 | 23152 | ||
| 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( |
| 23145 | 23157 | ||
| 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); |
| 23149 | 23161 | ||
| 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"); |
| 23159 | 23171 | ||
| 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); |
| 23228 | 23239 | ||
| 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, |
| 23233 | 23244 | .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 | }; | ||
| 23244 | 23250 | ||
| 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 created | 23252 | // We only access this decl through the decl_ref with the correct type created |
| 23247 | // below, so this type doesn't matter | 23253 | // 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 | } |
| 23258 | 23262 | ||
| 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); |
| 23261 | 23265 | ||
| 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 | } |
| 23265 | 23272 | ||
| 23266 | fn zirWorkItem( | 23273 | fn zirWorkItem( |
| ... | @@ -24117,7 +24124,6 @@ fn fieldVal( | ... | @@ -24117,7 +24124,6 @@ fn fieldVal( |
| 24117 | 24124 | ||
| 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 location | 24128 | 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 | } |
| 24223 | 24229 | ||
| 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_type | 24232 | else |
| 24227 | else | 24233 | 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 | }); |
| 24369 | 24376 | ||
| 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); |
| 24381 | 24387 | ||
| ... | @@ -24389,14 +24395,13 @@ fn fieldPtr( | ... | @@ -24389,14 +24395,13 @@ fn fieldPtr( |
| 24389 | }); | 24395 | }); |
| 24390 | 24396 | ||
| 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); |
| 24402 | 24407 | ||
| ... | @@ -24442,14 +24447,16 @@ fn fieldPtr( | ... | @@ -24442,14 +24447,16 @@ fn fieldPtr( |
| 24442 | 24447 | ||
| 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_type | 24456 | (try mod.intern(.{ .err = .{ |
| 24448 | else | 24457 | .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 alignment | 24460 | 0, // default alignment |
| 24454 | )); | 24461 | )); |
| 24455 | }, | 24462 | }, |
| ... | @@ -24714,14 +24721,13 @@ fn finishFieldCallBind( | ... | @@ -24714,14 +24721,13 @@ fn finishFieldCallBind( |
| 24714 | } | 24721 | } |
| 24715 | 24722 | ||
| 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 | } |
| 24727 | 24733 | ||
| ... | @@ -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); |
| 24902 | 24908 | ||
| 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 | } |
| 24910 | 24916 | ||
| 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 | } |
| 24921 | 24927 | ||
| 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 | } |
| 24960 | 24966 | ||
| 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 | } |
| 25121 | 25126 | ||
| 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 | }); |
| 25408 | 25413 | ||
| 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 | } |
| 25416 | 25420 | ||
| 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 | } |
| 25427 | 25430 | ||
| 25428 | if (!init) { | 25431 | if (!init) { |
| ... | @@ -25463,7 +25466,7 @@ fn tupleField( | ... | @@ -25463,7 +25466,7 @@ fn tupleField( |
| 25463 | 25466 | ||
| 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 | } |
| 25468 | 25471 | ||
| 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 so | 26084 | // 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 | else | 26090 | 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 | } |
| 26092 | 26095 | ||
| 26093 | // pointer to tuple to slice | 26096 | // 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 enum | 26259 | // 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 | } |
| 27031 | 27039 | ||
| 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's | 27041 | // 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 | } |
| 27594 | 27602 | ||
| 27595 | const ComptimePtrMutationKit = struct { | 27603 | const 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 direct | 27606 | /// 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, |
| 27620 | 27628 | ||
| 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 | } |
| 27625 | 27633 | ||
| 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 already | 28181 | .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( |
| 28189 | 28198 | ||
| 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); |
| 28195 | 28204 | ||
| ... | @@ -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(); |
| 28275 | 28284 | ||
| 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) { |
| 28280 | 28289 | .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; |
| 28294 | 28296 | ||
| 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); | ||
| 28303 | 28310 | ||
| 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); | ||
| 28308 | 28352 | ||
| 28309 | // This code assumes that elem_ptrs have been "flattened" in order for direct dereference | 28353 | // 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 that | 28354 | // 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 | } |
| 28315 | 28363 | ||
| 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 | } |
| 28329 | 28377 | ||
| 28330 | // If we're loading an elem_ptr that was derived from a different type | 28378 | // If we're loading an elem that was derived from a different type |
| 28331 | // than the true type of the underlying decl, we cannot deref directly | 28379 | // 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); | ||
| 28376 | 28428 | ||
| 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 addressable | 28432 | // 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 | } |
| 28402 | 28444 | ||
| 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 or | 28450 | (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 | } |
| 28414 | 28456 | ||
| 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 | }; |
| 28697 | 28485 | ||
| 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 | } |
| 29540 | 29328 | ||
| 29541 | fn ensureFuncBodyAnalyzed(sema: *Sema, func: *Module.Fn) CompileError!void { | 29329 | fn 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 | } |
| 29551 | 29339 | ||
| 29552 | fn refValue(sema: *Sema, block: *Block, ty: Type, val: Value) !Value { | 29340 | fn 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 alignment | 29347 | 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 | } |
| 29564 | 29357 | ||
| 29565 | fn optRefValue(sema: *Sema, block: *Block, ty: Type, opt_val: ?Value) !Value { | 29358 | fn 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 | } |
| 29571 | 29368 | ||
| 29572 | fn analyzeDeclRef(sema: *Sema, decl_index: Decl.Index) CompileError!Air.Inst.Ref { | 29369 | fn analyzeDeclRef(sema: *Sema, decl_index: Decl.Index) CompileError!Air.Inst.Ref { |
| ... | @@ -29587,10 +29384,7 @@ fn analyzeDeclRefInner(sema: *Sema, decl_index: Decl.Index, analyze_fn_body: boo | ... | @@ -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_fn | 29405 | 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 | } |
| 29614 | 29408 | ||
| 29615 | fn analyzeRef( | 29409 | fn analyzeRef( |
| ... | @@ -29622,14 +29416,12 @@ fn analyzeRef( | ... | @@ -29622,14 +29416,12 @@ fn analyzeRef( |
| 29622 | 29416 | ||
| 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( |
| 29854 | 29646 | ||
| 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 of | 29650 | // 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 value | 29651 | // 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); |
| 30139 | 29931 | ||
| 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( |
| 30233 | 30025 | ||
| 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 | } |
| 30758 | 30553 | ||
| 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; |
| 30807 | 30602 | ||
| 30808 | // We carefully do this in an order that avoids unnecessarily | 30603 | // 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; |
| 30811 | 30606 | ||
| 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 | } | ||
| 30818 | 30609 | ||
| 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. |
| 31463 | fn resolveLazyValue(sema: *Sema, val: Value) CompileError!void { | 31254 | fn 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 | } |
| 31504 | 31285 | ||
| ... | @@ -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(); |
| 31664 | 31445 | ||
| 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(); |
| 31678 | 31448 | ||
| 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(); |
| 31727 | 31499 | ||
| ... | @@ -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()), |
| 31975 | 31747 | ||
| 31976 | // values, not types | 31748 | // 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( |
| 32288 | 32067 | ||
| 32289 | if (ies.is_resolved) return; | 32068 | if (ies.is_resolved) return; |
| 32290 | 32069 | ||
| 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 | } |
| 32294 | 32074 | ||
| 32295 | // In order to ensure that all dependencies are properly added to the set, we | 32075 | // 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 same | 32078 | // 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 set | 32079 | // `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 failure | 32080 | // 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(); |
| 32421 | 32203 | ||
| ... | @@ -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(); |
| 32761 | 32545 | ||
| ... | @@ -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, |
| 33290 | 33074 | ||
| 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 | }, |
| 33467 | 33251 | ||
| 33468 | // values, not types | 33252 | // 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; |
| 33626 | 33417 | ||
| 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 | } |
| 33633 | 33427 | ||
| 33634 | /// The places where a user can specify an address space attribute | 33428 | /// 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()), |
| 33970 | 33764 | ||
| 33971 | // values, not types | 33765 | // 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, |
| 34348 | 34150 | ||
| 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 | }, |
| 34390 | 34160 | .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 | }, |
| 34401 | 34185 | .aggregate => |aggregate| { | |
| 34402 | else => unreachable, | 34186 | assert(ty.zigTypeTag(mod) == .Vector); |
| 34403 | }, | 34187 | return switch (aggregate.storage) { |
| 34404 | 34188 | .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( |
| 102 | 102 | ||
| 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 function | 111 | // 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( |
| 424 | 197 | ||
| 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(); |
| 328 | pub fn generate( | 328 | pub 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 | } |
| 340 | 340 | ||
| 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 depends | 4312 | // 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 { |
| 4627 | 4625 | ||
| 4628 | fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void { | 4626 | fn 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 change | 4630 | // 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(); |
| 334 | pub fn generate( | 334 | pub 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 | } |
| 346 | 346 | ||
| 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 depends | 4292 | // 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 { |
| 4573 | 4572 | ||
| 4574 | fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void { | 4573 | fn 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 change | 4577 | // 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(); |
| 217 | pub fn generate( | 217 | pub 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 | } |
| 229 | 229 | ||
| 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 | } |
| 1746 | 1747 | ||
| 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 { |
| 1879 | 1879 | ||
| 1880 | fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void { | 1880 | fn 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 change | 1884 | // 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 { |
| 260 | pub fn generate( | 260 | pub 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 | } |
| 272 | 272 | ||
| 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 { |
| 1663 | 1663 | ||
| 1664 | fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void { | 1664 | fn 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 change | 1668 | // 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( |
| 1203 | pub fn generate( | 1203 | pub 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; |
| 2198 | 2200 | ||
| 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 | } |
| 2934 | 2942 | ||
| 2935 | fn lowerParentPtr(func: *CodeGen, ptr_val: Value, offset: u32) InnerError!WValue { | 2943 | fn 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()); |
| 2953 | 2973 | ||
| 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; |
| 2965 | 2985 | ||
| 2966 | // tag is stored first so calculate offset from where payload starts | 2986 | // 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 | } |
| 2996 | 3020 | ||
| ... | @@ -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( |
| 3045 | fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue { | 3069 | fn 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 | } |
| 3165 | 3250 | ||
| ... | @@ -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 | } |
| 3230 | 3315 | ||
| 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 function | 3318 | 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 type | 3321 | else => unreachable, // Programmer called this function for an illegal type |
| 3237 | } | 3322 | } |
| 3238 | } | 3323 | } |
| 3239 | 3324 | ||
| 3240 | fn intIndexAsI32(ip: *const InternPool, int: InternPool.Index) i32 { | 3325 | fn 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 | } |
| 3243 | 3328 | ||
| 3244 | fn intStorageAsI32(storage: InternPool.Key.Int.Storage) i32 { | 3329 | fn 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 | } |
| 3251 | 3338 | ||
| ... | @@ -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 have | 5601 | // 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); |
| 5520 | 5607 | ||
| ... | @@ -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 body | 7022 | // finish function body |
| 6936 | try writer.writeByte(std.wasm.opcode(.end)); | 7023 | try writer.writeByte(std.wasm.opcode(.end)); |
| 6937 | 7024 | ||
| 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(); |
| 632 | pub fn generate( | 632 | pub 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 | } |
| 644 | 644 | ||
| 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.alignment | 692 | set_align_stack.alignment |
| 692 | else | 693 | 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)); |
| 2762 | 2763 | ||
| 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 | } }); | ||
| 2774 | 2774 | ||
| 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); |
| 4895 | 4895 | ||
| 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 | }); |
| 4909 | 4900 | ||
| 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 | }; |
| 4915 | 4906 | ||
| ... | @@ -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 depends | 8097 | // 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_decl | 8101 | 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.data | 8103 | .ptr => |ptr| switch (ptr.addr) { |
| 8113 | else | 8104 | .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 { |
| 8554 | 8546 | ||
| 8555 | fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void { | 8547 | fn 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 change | 8551 | // 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"); |
| 14 | const Allocator = mem.Allocator; | 14 | const Allocator = mem.Allocator; |
| 15 | const Compilation = @import("Compilation.zig"); | 15 | const Compilation = @import("Compilation.zig"); |
| 16 | const ErrorMsg = Module.ErrorMsg; | 16 | const ErrorMsg = Module.ErrorMsg; |
| 17 | const InternPool = @import("InternPool.zig"); | ||
| 17 | const Liveness = @import("Liveness.zig"); | 18 | const Liveness = @import("Liveness.zig"); |
| 18 | const Module = @import("Module.zig"); | 19 | const Module = @import("Module.zig"); |
| 19 | const Target = std.Target; | 20 | const Target = std.Target; |
| ... | @@ -66,7 +67,7 @@ pub const DebugInfoOutput = union(enum) { | ... | @@ -66,7 +67,7 @@ pub const DebugInfoOutput = union(enum) { |
| 66 | pub fn generateFunction( | 67 | pub 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(); |
| 184 | 185 | ||
| 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 | } |
| 189 | 192 | ||
| 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(); |
| 193 | 195 | ||
| ... | @@ -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 | } |
| 204 | 206 | ||
| 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( |
| 562 | 294 | ||
| 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 | }; | ||
| 568 | 350 | ||
| 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 | } |
| 575 | 413 | ||
| 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 | } |
| 586 | 422 | ||
| 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; | ||
| 601 | 439 | ||
| 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 | } |
| 607 | 444 | ||
| 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; |
| 628 | 503 | ||
| 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 | } |
| 654 | 528 | 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 | } | ||
| 657 | 551 | ||
| 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 | } | ||
| 669 | 580 | ||
| 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(); | ||
| 676 | 648 | ||
| 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 | } |
| 684 | 655 | ||
| 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 | } |
| 699 | 666 | ||
| 700 | // emit payload part of the error union | 667 | 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; | ||
| 714 | 681 | ||
| 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 | } |
| 719 | 687 | ||
| 720 | // Payload size is larger than error set, so emit our error set last | 688 | 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 | } |
| 828 | 701 | ||
| 829 | fn lowerParentPtr( | 702 | fn 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 | } |
| 930 | 789 | ||
| 931 | const RelocInfo = struct { | 790 | const RelocInfo = struct { |
| ... | @@ -940,36 +799,15 @@ const RelocInfo = struct { | ... | @@ -940,36 +799,15 @@ const RelocInfo = struct { |
| 940 | fn lowerDeclRef( | 799 | fn 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 | } | ||
| 973 | 811 | ||
| 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 | } |
| 1161 | 1001 | ||
| 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(); |
| 1173 | 1012 | ||
| 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 | } | ||
| 1185 | 1021 | ||
| 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); |
| 1255 | 1080 | ||
| 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 | } |
| 259 | 259 | ||
| 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. |
| 262 | pub const Function = struct { | 262 | pub 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 | } |
| 550 | 550 | ||
| 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); |
| 556 | 556 | ||
| 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 | } | ||
| 579 | 558 | ||
| 580 | // We shouldn't cast C function pointers as this is UB (when you call | 559 | // 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 function | 560 | // 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 { |
| 594 | 573 | ||
| 595 | /// Renders a "parent" pointer by recursing to the root decl/variable | 574 | /// 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; |
| 607 | 583 | 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("&("); |
| 629 | 610 | try dg.renderParentPtr(writer, elem.base, location); | |
| 611 | try writer.print(")[{d}]", .{elem.index}); | ||
| 612 | }, | ||
| 613 | .field => |field| { | ||
| 614 | const base_ty = mod.intern_pool.typeOf(field.base).toType().childType(mod); | ||
| 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); |
| 632 | 617 | 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), |
| 634 | 619 | .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); |
| 662 | 628 | ||
| 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 | } |
| 718 | 649 | ||
| ... | @@ -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 | }; | ||
| 956 | 863 | ||
| 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; |
| 1413 | 1523 | ||
| 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 | } |
| 1482 | 1576 | ||
| ... | @@ -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 "); |
| 1510 | 1603 | ||
| 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 { |
| 1747 | 1840 | ||
| 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 | } |
| 1763 | 1850 | ||
| 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 | } |
| 1835 | 1922 | ||
| 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 { |
| 1858 | 1945 | ||
| 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 { |
| 2451 | 2541 | ||
| 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 | }); |
| 2457 | 2547 | ||
| ... | @@ -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; |
| 2499 | 2589 | ||
| 2500 | const name_slice_ty = Type.const_slice_u8_sentinel_0; | 2590 | const name_slice_ty = Type.slice_const_u8_sentinel_0; |
| 2501 | 2591 | ||
| 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 }; |
| 2669 | 2759 | ||
| 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); |
| 2681 | 2770 | ||
| ... | @@ -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 { |
| 4231 | 4323 | ||
| 4232 | fn airDbgInline(f: *Function, inst: Air.Inst.Index) !CValue { | 4324 | fn 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(" = "); |
| 6636 | 6728 | ||
| 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); |
| 587 | 587 | ||
| 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 { |
| 886 | 887 | ||
| 887 | const llvm_func = try dg.resolveLlvmFunction(decl_index); | 888 | const llvm_func = try dg.resolveLlvmFunction(decl_index); |
| 888 | 889 | ||
| 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); |
| 1165 | 1166 | ||
| 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 and | 1168 | 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.NoReturn | 1171 | 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 and | 1275 | const decl_name = decl_name: { |
| 1275 | decl.getExternFn().?.lib_name != null and | 1276 | 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); | ||
| 1284 | 1287 | ||
| 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); |
| 1512 | 1515 | ||
| 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.storage | 1518 | enum_type.values[i].toValue().toBigInt(&bigint_space, mod) |
| 1516 | else | 1519 | 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); | ||
| 1519 | 1521 | ||
| 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 | } |
| 2443 | 2445 | ||
| 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 | ); |
| 2520 | 2520 | ||
| 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; |
| 2550 | 2550 | ||
| 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)); |
| 2697 | 2696 | ||
| 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); |
| 2701 | 2701 | ||
| 2702 | const target = dg.module.getTarget(); | 2702 | const target = mod.getTarget(); |
| 2703 | 2703 | ||
| 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; |
| 2713 | 2713 | ||
| 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); | ||
| 3235 | 3210 | ||
| 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()) { |
| 3238 | 3213 | .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( |
| 3241 | 3216 | 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); | ||
| 3480 | 3261 | ||
| 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 | } | ||
| 3488 | 3285 | ||
| 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 | } |
| 3493 | 3306 | ||
| 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); | ||
| 3557 | 3323 | ||
| 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 | } | ||
| 3565 | 3325 | ||
| 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; | ||
| 3570 | 3336 | ||
| 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 | } |
| 3592 | 3358 | ||
| 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); | ||
| 3617 | 3404 | ||
| 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); |
| 3664 | 3540 | ||
| 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; |
| 3682 | 3561 | ||
| ... | @@ -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; | ||
| 3703 | 3581 | ||
| 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); | ||
| 3708 | 3584 | ||
| 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); | ||
| 3710 | 3587 | ||
| 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); | ||
| 3715 | 3682 | ||
| 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); | ||
| 3719 | 3697 | ||
| 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); | ||
| 3724 | 3753 | ||
| 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 debug | 3757 | 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 | } | ||
| 3732 | 3761 | ||
| 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 | } |
| 3737 | 3766 | ||
| 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; | ||
| 3739 | 3804 | ||
| 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); | ||
| 3741 | 3809 | ||
| 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 | } | ||
| 3753 | 3816 | ||
| 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 | } |
| 3770 | 3833 | ||
| 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 | }); | ||
| 3772 | 3838 | ||
| 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; | ||
| 3783 | 3840 | ||
| 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 | } | ||
| 3805 | 3842 | ||
| 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 | } | ||
| 3809 | 3854 | ||
| 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 | }; | ||
| 3814 | 3871 | ||
| 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); | ||
| 3822 | 3873 | ||
| 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 debug | 3877 | 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 | } |
| 3830 | 3906 | ||
| 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 | }); | ||
| 3835 | 3910 | ||
| 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 | } | ||
| 3837 | 3931 | ||
| 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 | }); | ||
| 3839 | 3936 | ||
| 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 | } | ||
| 3851 | 3952 | ||
| 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 | } |
| 4045 | 4058 | ||
| ... | @@ -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 one | 4202 | // 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 | } |
| 4376 | 4246 | ||
| 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 | } | ||
| 4397 | 4253 | ||
| 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 | } |
| 4413 | 4269 | ||
| ... | @@ -6333,11 +6189,11 @@ pub const FuncGen = struct { | ... | @@ -6333,11 +6189,11 @@ pub const FuncGen = struct { |
| 6333 | } | 6189 | } |
| 6334 | 6190 | ||
| 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; |
| 6339 | 6194 | ||
| 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; |
| 6397 | 6253 | ||
| 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 | } |
| 8350 | 8206 | ||
| 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}); |
| 9149 | 9005 | ||
| 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 | } |
| 9862 | 9718 | ||
| 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 space | 9722 | const llvm_slice_ptr_ty = self.context.pointerType(0); // TODO: Address space |
| 9867 | 9723 |
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 | .func | 265 | .func |
| 266 | else | 266 | else |
| 267 | .global; | 267 | .global; |
| ... | @@ -573,6 +573,7 @@ pub const DeclGen = struct { | ... | @@ -573,6 +573,7 @@ pub const DeclGen = struct { |
| 573 | 573 | ||
| 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; | ||
| 576 | 577 | ||
| 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); |
| 582 | 583 | ||
| 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 and | 586 | // 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 dependency | 590 | // TODO: Add dependency |
| 590 | return; | 591 | return; |
| 591 | }, | 592 | }, |
| 592 | .extern_fn => unreachable, // TODO | 593 | .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 | } |
| 612 | 613 | ||
| 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; |
| 616 | 617 | ||
| 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 | } |
| 621 | 628 | ||
| 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; // TODO | 647 | 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); |
| 712 | 790 | ||
| 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; |
| 736 | 812 | ||
| 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).?; | ||
| 747 | 843 | ||
| 748 | const int_ty = try ty.intTagType(mod); | 844 | if (struct_ty.layout == .Packed) { |
| 845 | return dg.todo("packed struct constants", .{}); | ||
| 846 | } | ||
| 749 | 847 | ||
| 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); |
| 755 | 867 | ||
| 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 | } |
| 759 | 871 | ||
| 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 | } |
| 764 | 876 | ||
| 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; |
| 767 | 879 | ||
| 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; |
| 770 | 882 | ||
| 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 | } |
| 774 | 886 | ||
| 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; |
| 779 | 891 | ||
| ... | @@ -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); |
| 782 | 894 | ||
| 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 | } |
| 786 | 898 | ||
| 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 }); |
| 1544 | 1614 | ||
| 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.init | 1669 | payload.init.toValue() |
| 1600 | else | 1670 | else |
| 1601 | decl.val; | 1671 | decl.val; |
| 1602 | 1672 |
src/link.zig+10-9| ... | @@ -564,7 +564,8 @@ pub const File = struct { | ... | @@ -564,7 +564,8 @@ pub const File = struct { |
| 564 | } | 564 | } |
| 565 | 565 | ||
| 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: off | 578 | // 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: on | 587 | // 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 | } |
| 89 | 89 | ||
| 90 | pub fn updateFunc(self: *C, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void { | 90 | pub 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(); |
| 93 | 93 | ||
| 94 | const gpa = self.base.allocator; | 94 | const gpa = self.base.allocator; |
| 95 | 95 | ||
| 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 its | 561 | // Before flushing any particular Decl we must ensure its |
| 560 | // dependencies are already flushed, so that the order in the .c | 562 | // 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( |
| 569 | 571 | ||
| 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 | } |
| 575 | 577 |
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 | } |
| 1034 | 1034 | ||
| 1035 | pub fn updateFunc(self: *Coff, mod: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void { | 1035 | pub 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(); |
| 1046 | 1046 | ||
| 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); |
| 1049 | 1050 | ||
| ... | @@ -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( |
| 1155 | 1156 | ||
| 1156 | const decl = mod.declPtr(decl_index); | 1157 | const decl = mod.declPtr(decl_index); |
| 1157 | 1158 | ||
| 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(); |
| 1174 | 1174 | ||
| 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); |
| 973 | 973 | ||
| 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 | } |
| 1516 | 1516 | ||
| 1517 | pub fn updateDeclLineNumber(self: *Dwarf, module: *Module, decl_index: Module.Decl.Index) !void { | 1517 | pub 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(); |
| 1520 | 1520 | ||
| ... | @@ -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; |
| 1524 | 1524 | ||
| 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 | } |
| 2576 | 2576 | ||
| 2577 | pub fn updateFunc(self: *Elf, mod: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void { | 2577 | pub 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 | } |
| 2584 | 2584 | ||
| 2585 | const tracy = trace(@src()); | 2585 | const tracy = trace(@src()); |
| 2586 | defer tracy.end(); | 2586 | defer tracy.end(); |
| 2587 | 2587 | ||
| 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); |
| 2590 | 2591 | ||
| ... | @@ -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(); |
| 2600 | 2601 | ||
| 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 | else | 2606 | 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); |
| 2607 | 2608 | ||
| 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( |
| 2646 | 2647 | ||
| 2647 | const decl = mod.declPtr(decl_index); | 2648 | const decl = mod.declPtr(decl_index); |
| 2648 | 2649 | ||
| 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(); |
| 2668 | 2668 | ||
| 2669 | // TODO implement .debug_info for global variables | 2669 | // 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 | } |
| 1849 | 1849 | ||
| 1850 | pub fn updateFunc(self: *MachO, mod: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void { | 1850 | pub 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(); |
| 1859 | 1859 | ||
| 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); |
| 1862 | 1863 | ||
| ... | @@ -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(); |
| 1875 | 1876 | ||
| 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 | else | 1881 | 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); |
| 1882 | 1883 | ||
| 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 |
| 1983 | 1984 | ||
| 1984 | const decl = mod.declPtr(decl_index); | 1985 | const decl = mod.declPtr(decl_index); |
| 1985 | 1986 | ||
| 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 | } |
| 1995 | 1995 | ||
| 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_threaded | 1997 | variable.is_threadlocal and !self.base.options.single_threaded |
| 1998 | else | 1998 | 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(); |
| 2014 | 2014 | ||
| 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 |
| 2177 | 2177 | ||
| 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 | } |
| 2280 | 2280 | ||
| 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 | } |
| 70 | 70 | ||
| 71 | pub fn updateFunc(self: *NvPtx, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void { | 71 | pub 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 | } |
| 75 | 75 | ||
| 76 | pub fn updateDecl(self: *NvPtx, module: *Module, decl_index: Module.Decl.Index) !void { | 76 | pub 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 | } |
| 278 | 278 | ||
| 279 | pub fn updateFunc(self: *Plan9, mod: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void { | 279 | pub 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 | } |
| 283 | 283 | ||
| 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 |
| 391 | pub fn updateDecl(self: *Plan9, mod: *Module, decl_index: Module.Decl.Index) !void { | 392 | pub 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); |
| 393 | 394 | ||
| 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 |
| 407 | 407 | ||
| 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 atom | 411 | // 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 | } |
| 105 | 105 | ||
| 106 | pub fn updateFunc(self: *SpirV, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void { | 106 | pub 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 | } |
| 110 | 110 | ||
| 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(); |
| 113 | 115 | ||
| ... | @@ -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 | } |
| 1326 | 1326 | ||
| 1327 | pub fn updateFunc(wasm: *Wasm, mod: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void { | 1327 | pub 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 | } |
| 1334 | 1334 | ||
| 1335 | const tracy = trace(@src()); | 1335 | const tracy = trace(@src()); |
| 1336 | defer tracy.end(); | 1336 | defer tracy.end(); |
| 1337 | 1337 | ||
| 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(); |
| 1404 | 1405 | ||
| 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 | } |
| 1411 | 1412 | ||
| ... | @@ -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(); |
| 1415 | 1416 | ||
| 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; |
| 1422 | 1424 | ||
| 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 | } |
| 1793 | 1795 | ||
| 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 external | 1854 | /// 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 signature | 1858 | /// The index of the type that represents the function signature |
| 1857 | /// when the extern is a function. When this is null, a data-symbol | 1859 | /// 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 same | 1865 | // 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 and | 1867 | 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 { |
| 2931 | 2933 | ||
| 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-termianted | 2991 | const len = @intCast(u32, error_name.len + 1); // names are 0-termianted |
| 2990 | 2992 | ||
| 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 name | 2995 | // 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 relocated | 2996 | 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 or | 3382 | 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 { |
| 699 | 699 | ||
| 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 | } |
| 706 | 706 |
src/type.zig+290-173| ... | @@ -93,16 +93,23 @@ pub const Type = struct { | ... | @@ -93,16 +93,23 @@ pub const Type = struct { |
| 93 | }, | 93 | }, |
| 94 | 94 | ||
| 95 | // values, not types | 95 | // 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 | } |
| 108 | 115 | ||
| ... | @@ -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; |
| 359 | 366 | ||
| 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 | }, |
| 468 | 475 | ||
| 469 | // values, not types | 476 | // 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 | } |
| 482 | 496 | ||
| ... | @@ -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), |
| 676 | 690 | ||
| 677 | // values, not types | 691 | // 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 | }, |
| 778 | 799 | ||
| 779 | // values, not types | 800 | // 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 | } |
| 792 | 820 | ||
| ... | @@ -866,8 +894,8 @@ pub const Type = struct { | ... | @@ -866,8 +894,8 @@ pub const Type = struct { |
| 866 | 894 | ||
| 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 { |
| 880 | 908 | ||
| 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 | }; |
| 886 | 914 | ||
| ... | @@ -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 resolved | 1048 | .eager => unreachable, // struct layout not resolved |
| 1021 | .sema => unreachable, // handled above | 1049 | .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; |
| 1045 | 1078 | ||
| ... | @@ -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 resolved | 1084 | .eager => unreachable, // struct layout not resolved |
| 1052 | .sema => unreachable, // handled above | 1085 | .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 resolved | 1114 | .eager => unreachable, // field type alignment not resolved |
| 1079 | .sema => unreachable, // passed to abiAlignmentAdvanced above | 1115 | .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) }, |
| 1093 | 1132 | ||
| 1094 | // values, not types | 1133 | // 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 resolved | 1257 | .eager => unreachable, // union layout not resolved |
| 1200 | .sema => unreachable, // handled above | 1258 | .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; |
| 1218 | 1282 | ||
| ... | @@ -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 resolved | 1288 | .eager => unreachable, // struct layout not resolved |
| 1225 | .sema => unreachable, // handled above | 1289 | .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 | } |
| 1233 | 1300 | ||
| 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 | }; |
| 1339 | 1417 | ||
| ... | @@ -1420,11 +1498,10 @@ pub const Type = struct { | ... | @@ -1420,11 +1498,10 @@ pub const Type = struct { |
| 1420 | 1498 | ||
| 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) orelse | 1514 | 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) }, |
| 1470 | 1548 | ||
| 1471 | // values, not types | 1549 | // 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 | } |
| 1515 | 1599 | ||
| 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 }; |
| 1520 | 1607 | ||
| ... | @@ -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 | }; |
| 1533 | 1623 | ||
| ... | @@ -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), |
| 1691 | 1781 | ||
| 1692 | // values, not types | 1782 | // 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 | } |
| 1705 | 1802 | ||
| ... | @@ -2270,16 +2367,23 @@ pub const Type = struct { | ... | @@ -2270,16 +2367,23 @@ pub const Type = struct { |
| 2270 | .opaque_type => unreachable, | 2367 | .opaque_type => unreachable, |
| 2271 | 2368 | ||
| 2272 | // values, not types | 2369 | // 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, |
| 2445 | 2549 | ||
| 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 | }, |
| 2596 | 2701 | ||
| 2597 | // values, not types | 2702 | // 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), |
| 2734 | 2846 | ||
| 2735 | // values, not types | 2847 | // 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 | } |
| 2803 | 2922 | ||
| 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 | } |
| 2813 | 2931 | ||
| 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 { |
| 2832 | 2950 | ||
| 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 | } |
| 2843 | 2960 | ||
| 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 }; |
| 3388 | 3505 | ||
| 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 }; |
| 3396 | 3513 | ||
| 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.py | 33 | // 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. |
| 41 | 37 | ||
| 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_alloc | 52 | /// 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, | ||
| 111 | 55 | ||
| 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; | ||
| 114 | 57 | ||
| 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, | ||
| 139 | 61 | ||
| 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 | } |
| 160 | 70 | ||
| ... | @@ -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 | } |
| 544 | 262 | ||
| ... | @@ -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 | } |
| 735 | 405 | ||
| 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, u0 | 441 | .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) { |
| 779 | 443 | .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 | }, |
| 800 | 454 | .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 | } |
| 818 | 472 | ||
| 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 | } |
| 865 | 526 | ||
| 866 | /// Asserts the value is an integer and it fits in a u64 | 527 | /// 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 { |
| 870 | 531 | ||
| 871 | /// Asserts the value is an integer and it fits in a i64 | 532 | /// 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 | } |
| 902 | 550 | ||
| 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 | } |
| 917 | 558 | ||
| 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; |
| 955 | 598 | ||
| 956 | const int_val = try val.enumToInt(ty, mod); | 599 | var bigint_buffer: BigIntSpace = undefined; |
| 957 | 600 | 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 type | 645 | // 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.?); |
| 1145 | 778 | ||
| 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 type | 895 | // 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); |
| 1265 | 898 | 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 | } |
| 1384 | 1015 | ||
| 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 | } |
| 1422 | 1055 | ||
| 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 | } |
| 1452 | 1061 | ||
| 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 | } |
| 1485 | 1067 | ||
| 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 | } |
| 1503 | 1073 | ||
| 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); |
| 1508 | 1076 | ||
| 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 | } |
| 1521 | 1089 | ||
| 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); |
| 1526 | 1092 | ||
| 1527 | // Bit count must be evenly divisible by 8 | 1093 | // 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 | } |
| 1582 | 1116 | ||
| 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) { |
| 1624 | 1158 | .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 | } |
| 1698 | 1187 | ||
| 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 { |
| 1849 | 1338 | ||
| 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 | } | ||
| 2041 | 1473 | ||
| 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 | } |
| 2051 | 1483 | ||
| ... | @@ -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 | } |
| 2154 | 1572 | ||
| ... | @@ -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; |
| 2170 | 1588 | ||
| 2171 | switch (zig_ty_tag) { | 1589 | switch (zig_ty_tag) { |
| 2172 | .Opaque => unreachable, // Cannot hash opaque types | 1590 | .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 | => {}, |
| 2179 | 1597 | ||
| 2180 | .Type => unreachable, // handled via ip_index check above | 1598 | .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 | } |
| 2303 | 1652 | ||
| ... | @@ -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; |
| 2312 | 1661 | ||
| 2313 | if (val.ip_index != .none) { | 1662 | if (val.ip_index != .none) { |
| 2314 | // The InternPool data structure hashes based on Key to make interned objects | 1663 | // 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 check | 1678 | .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 | }; |
| 2399 | 1747 | ||
| 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 | } |
| 2415 | 1759 | ||
| 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 | } |
| 2439 | 1783 | ||
| 2440 | /// Gets the decl referenced by this pointer. If the pointer does not point | 1784 | /// 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 | } |
| 2465 | 1809 | ||
| 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 | } | ||
| 2512 | 1812 | ||
| 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 | } |
| 2522 | 1816 | ||
| 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 | } |
| 2556 | 1820 | ||
| 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 | }, |
| 2581 | 1837 | ||
| 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), | ||
| 2614 | 1839 | ||
| 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 | } |
| 2635 | 1872 | ||
| 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, |
| 2639 | 1876 | else => false, | |
| 2640 | pub fn isLazySize(val: Value) bool { | 1877 | }; |
| 2641 | return val.ip_index == .none and val.tag() == .lazy_size; | ||
| 2642 | } | 1878 | } |
| 2643 | 1879 | ||
| 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 | } |
| 2647 | 1886 | ||
| 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 | } |
| 2651 | 1890 | ||
| 2652 | /// Returns true if a Value is backed by a variable | 1891 | /// 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 | }, |
| 2672 | 1906 | .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 | } |
| 2679 | 1914 | ||
| 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 | }, |
| 2689 | 1924 | .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) { |
| 2729 | 1960 | .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 | } |
| 2745 | 1978 | ||
| 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 correct | 1989 | // 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 | }; |
| 2806 | 2045 | 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 | } |
| 2823 | 2053 | ||
| 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, |
| 2849 | 2079 | 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 | } |
| 2879 | 2097 | ||
| 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, |
| 2886 | 2104 | ||
| 2887 | .null_value => true, | 2105 | .null_value => true, |
| 2888 | 2106 | ||
| 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 whether | 2119 | /// 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 the | 2120 | /// 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 | } |
| 2932 | 2132 | ||
| 2933 | /// Assumes the type is an error union. Returns true if and only if the value is | 2133 | /// 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 | } |
| 2948 | 2138 | ||
| 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)) null | 2142 | .none => null, |
| 2953 | // Valid for optional representation to be the direct value | 2143 | 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 | } |
| 2966 | 2146 | ||
| ... | @@ -3001,28 +2181,8 @@ pub const Value = struct { | ... | @@ -3001,28 +2181,8 @@ pub const Value = struct { |
| 3001 | } | 2181 | } |
| 3002 | 2182 | ||
| 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 | } |
| 3038 | 2208 | ||
| 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, |
| 4770 | 3940 | ||
| 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 | }; |
| 4863 | 3958 | ||
| 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; |
| 4892 | 3961 |
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(.{})', |
| 534 | 534 | ||
| 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', |