| author | |
| committer | |
| log | 7bab406c790566781406a7968be22961ed7c305d |
| tree | e2f778d1c66dd62bf41da837bb76a882b792ec6e |
| parent | 5aa82ed477b85cf8681bc0dc65f97e813990a2ed |
Commit 5393e56500d499753dbc39704c0161b47d1e4d5c has a flaw pointed out
by @mlugg: the `ty` field of pointer values changes when comptime values
are pointer-casted. This commit introduces a new encoding which
additionally stores the "original pointer type" which is used to store
the alignment of the anonymous decl, and potentially other information
in the future such as section and pointer address space. However, this
new encoding is only used when the original pointer type differs from
the casted pointer type in a meaningful way.
I was able to make the LLVM backend and the C backend lower anonymous
decls with the appropriate alignment, however I will need some help
figuring out how to do this for the backends that lower anonymous decls
via src/codegen.zig and the wasm backend.13 files changed, 189 insertions(+), 44 deletions(-)
src/Compilation.zig+1| ... | @@ -3545,6 +3545,7 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v | ... | @@ -3545,6 +3545,7 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v |
| 3545 | .fwd_decl = fwd_decl.toManaged(gpa), | 3545 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 3546 | .ctypes = .{}, | 3546 | .ctypes = .{}, |
| 3547 | .anon_decl_deps = .{}, | 3547 | .anon_decl_deps = .{}, |
| 3548 | .aligned_anon_decls = .{}, | ||
| 3548 | }; | 3549 | }; |
| 3549 | defer { | 3550 | defer { |
| 3550 | dg.ctypes.deinit(gpa); | 3551 | dg.ctypes.deinit(gpa); |
src/InternPool.zig+86-14| ... | @@ -1074,7 +1074,7 @@ pub const Key = union(enum) { | ... | @@ -1074,7 +1074,7 @@ pub const Key = union(enum) { |
| 1074 | 1074 | ||
| 1075 | decl: Module.Decl.Index, | 1075 | decl: Module.Decl.Index, |
| 1076 | mut_decl: MutDecl, | 1076 | mut_decl: MutDecl, |
| 1077 | anon_decl: Index, | 1077 | anon_decl: AnonDecl, |
| 1078 | comptime_field: Index, | 1078 | comptime_field: Index, |
| 1079 | int: Index, | 1079 | int: Index, |
| 1080 | eu_payload: Index, | 1080 | eu_payload: Index, |
| ... | @@ -1090,6 +1090,14 @@ pub const Key = union(enum) { | ... | @@ -1090,6 +1090,14 @@ pub const Key = union(enum) { |
| 1090 | base: Index, | 1090 | base: Index, |
| 1091 | index: u64, | 1091 | index: u64, |
| 1092 | }; | 1092 | }; |
| 1093 | pub const AnonDecl = extern struct { | ||
| 1094 | val: Index, | ||
| 1095 | /// Contains the canonical pointer type of the anonymous | ||
| 1096 | /// declaration. This may equal `ty` of the `Ptr` or it may be | ||
| 1097 | /// different. Importantly, when lowering the anonymous decl, | ||
| 1098 | /// the original pointer type alignment must be used. | ||
| 1099 | orig_ty: Index, | ||
| 1100 | }; | ||
| 1093 | }; | 1101 | }; |
| 1094 | }; | 1102 | }; |
| 1095 | 1103 | ||
| ... | @@ -1231,7 +1239,8 @@ pub const Key = union(enum) { | ... | @@ -1231,7 +1239,8 @@ pub const Key = union(enum) { |
| 1231 | common ++ asBytes(&x.decl) ++ asBytes(&x.runtime_index), | 1239 | common ++ asBytes(&x.decl) ++ asBytes(&x.runtime_index), |
| 1232 | ), | 1240 | ), |
| 1233 | 1241 | ||
| 1234 | .anon_decl, | 1242 | .anon_decl => |x| Hash.hash(seed2, common ++ asBytes(&x)), |
| 1243 | |||
| 1235 | .int, | 1244 | .int, |
| 1236 | .eu_payload, | 1245 | .eu_payload, |
| 1237 | .opt_payload, | 1246 | .opt_payload, |
| ... | @@ -1500,7 +1509,8 @@ pub const Key = union(enum) { | ... | @@ -1500,7 +1509,8 @@ pub const Key = union(enum) { |
| 1500 | return switch (a_info.addr) { | 1509 | return switch (a_info.addr) { |
| 1501 | .decl => |a_decl| a_decl == b_info.addr.decl, | 1510 | .decl => |a_decl| a_decl == b_info.addr.decl, |
| 1502 | .mut_decl => |a_mut_decl| std.meta.eql(a_mut_decl, b_info.addr.mut_decl), | 1511 | .mut_decl => |a_mut_decl| std.meta.eql(a_mut_decl, b_info.addr.mut_decl), |
| 1503 | .anon_decl => |a_decl| a_decl == b_info.addr.anon_decl, | 1512 | .anon_decl => |ad| ad.val == b_info.addr.anon_decl.val and |
| 1513 | ad.orig_ty == b_info.addr.anon_decl.orig_ty, | ||
| 1504 | .int => |a_int| a_int == b_info.addr.int, | 1514 | .int => |a_int| a_int == b_info.addr.int, |
| 1505 | .eu_payload => |a_eu_payload| a_eu_payload == b_info.addr.eu_payload, | 1515 | .eu_payload => |a_eu_payload| a_eu_payload == b_info.addr.eu_payload, |
| 1506 | .opt_payload => |a_opt_payload| a_opt_payload == b_info.addr.opt_payload, | 1516 | .opt_payload => |a_opt_payload| a_opt_payload == b_info.addr.opt_payload, |
| ... | @@ -2133,6 +2143,7 @@ pub const Index = enum(u32) { | ... | @@ -2133,6 +2143,7 @@ pub const Index = enum(u32) { |
| 2133 | ptr_decl: struct { data: *PtrDecl }, | 2143 | ptr_decl: struct { data: *PtrDecl }, |
| 2134 | ptr_mut_decl: struct { data: *PtrMutDecl }, | 2144 | ptr_mut_decl: struct { data: *PtrMutDecl }, |
| 2135 | ptr_anon_decl: struct { data: *PtrAnonDecl }, | 2145 | ptr_anon_decl: struct { data: *PtrAnonDecl }, |
| 2146 | ptr_anon_decl_aligned: struct { data: *PtrAnonDeclAligned }, | ||
| 2136 | ptr_comptime_field: struct { data: *PtrComptimeField }, | 2147 | ptr_comptime_field: struct { data: *PtrComptimeField }, |
| 2137 | ptr_int: struct { data: *PtrBase }, | 2148 | ptr_int: struct { data: *PtrBase }, |
| 2138 | ptr_eu_payload: struct { data: *PtrBase }, | 2149 | ptr_eu_payload: struct { data: *PtrBase }, |
| ... | @@ -2583,8 +2594,16 @@ pub const Tag = enum(u8) { | ... | @@ -2583,8 +2594,16 @@ pub const Tag = enum(u8) { |
| 2583 | /// data is extra index of `PtrMutDecl`, which contains the type and address. | 2594 | /// data is extra index of `PtrMutDecl`, which contains the type and address. |
| 2584 | ptr_mut_decl, | 2595 | ptr_mut_decl, |
| 2585 | /// A pointer to an anonymous decl. | 2596 | /// A pointer to an anonymous decl. |
| 2586 | /// data is extra index of `PtrAnonDecl`, which contains the type and decl value. | 2597 | /// data is extra index of `PtrAnonDecl`, which contains the pointer type and decl value. |
| 2598 | /// The alignment of the anonymous decl is communicated via the pointer type. | ||
| 2587 | ptr_anon_decl, | 2599 | ptr_anon_decl, |
| 2600 | /// A pointer to an anonymous decl. | ||
| 2601 | /// data is extra index of `PtrAnonDeclAligned`, which contains the pointer | ||
| 2602 | /// type and decl value. | ||
| 2603 | /// The original pointer type is also provided, which will be different than `ty`. | ||
| 2604 | /// This encoding is only used when a pointer to an anonymous decl is | ||
| 2605 | /// coerced to a different pointer type with a different alignment. | ||
| 2606 | ptr_anon_decl_aligned, | ||
| 2588 | /// data is extra index of `PtrComptimeField`, which contains the pointer type and field value. | 2607 | /// data is extra index of `PtrComptimeField`, which contains the pointer type and field value. |
| 2589 | ptr_comptime_field, | 2608 | ptr_comptime_field, |
| 2590 | /// A pointer with an integer value. | 2609 | /// A pointer with an integer value. |
| ... | @@ -2781,6 +2800,7 @@ pub const Tag = enum(u8) { | ... | @@ -2781,6 +2800,7 @@ pub const Tag = enum(u8) { |
| 2781 | .ptr_decl => PtrDecl, | 2800 | .ptr_decl => PtrDecl, |
| 2782 | .ptr_mut_decl => PtrMutDecl, | 2801 | .ptr_mut_decl => PtrMutDecl, |
| 2783 | .ptr_anon_decl => PtrAnonDecl, | 2802 | .ptr_anon_decl => PtrAnonDecl, |
| 2803 | .ptr_anon_decl_aligned => PtrAnonDeclAligned, | ||
| 2784 | .ptr_comptime_field => PtrComptimeField, | 2804 | .ptr_comptime_field => PtrComptimeField, |
| 2785 | .ptr_int => PtrBase, | 2805 | .ptr_int => PtrBase, |
| 2786 | .ptr_eu_payload => PtrBase, | 2806 | .ptr_eu_payload => PtrBase, |
| ... | @@ -3383,6 +3403,13 @@ pub const PtrAnonDecl = struct { | ... | @@ -3383,6 +3403,13 @@ pub const PtrAnonDecl = struct { |
| 3383 | val: Index, | 3403 | val: Index, |
| 3384 | }; | 3404 | }; |
| 3385 | 3405 | ||
| 3406 | pub const PtrAnonDeclAligned = struct { | ||
| 3407 | ty: Index, | ||
| 3408 | val: Index, | ||
| 3409 | /// Must be nonequal to `ty`. Only the alignment from this value is important. | ||
| 3410 | orig_ty: Index, | ||
| 3411 | }; | ||
| 3412 | |||
| 3386 | pub const PtrMutDecl = struct { | 3413 | pub const PtrMutDecl = struct { |
| 3387 | ty: Index, | 3414 | ty: Index, |
| 3388 | decl: Module.Decl.Index, | 3415 | decl: Module.Decl.Index, |
| ... | @@ -3736,7 +3763,20 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { | ... | @@ -3736,7 +3763,20 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 3736 | const info = ip.extraData(PtrAnonDecl, data); | 3763 | const info = ip.extraData(PtrAnonDecl, data); |
| 3737 | return .{ .ptr = .{ | 3764 | return .{ .ptr = .{ |
| 3738 | .ty = info.ty, | 3765 | .ty = info.ty, |
| 3739 | .addr = .{ .anon_decl = info.val }, | 3766 | .addr = .{ .anon_decl = .{ |
| 3767 | .val = info.val, | ||
| 3768 | .orig_ty = info.ty, | ||
| 3769 | } }, | ||
| 3770 | } }; | ||
| 3771 | }, | ||
| 3772 | .ptr_anon_decl_aligned => { | ||
| 3773 | const info = ip.extraData(PtrAnonDeclAligned, data); | ||
| 3774 | return .{ .ptr = .{ | ||
| 3775 | .ty = info.ty, | ||
| 3776 | .addr = .{ .anon_decl = .{ | ||
| 3777 | .val = info.val, | ||
| 3778 | .orig_ty = info.orig_ty, | ||
| 3779 | } }, | ||
| 3740 | } }; | 3780 | } }; |
| 3741 | }, | 3781 | }, |
| 3742 | .ptr_comptime_field => { | 3782 | .ptr_comptime_field => { |
| ... | @@ -3817,7 +3857,17 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { | ... | @@ -3817,7 +3857,17 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 3817 | } }; | 3857 | } }; |
| 3818 | }, | 3858 | }, |
| 3819 | .ptr_anon_decl => .{ | 3859 | .ptr_anon_decl => .{ |
| 3820 | .anon_decl = ip.extraData(PtrAnonDecl, ptr_item.data).val, | 3860 | .anon_decl = .{ |
| 3861 | .val = ip.extraData(PtrAnonDecl, ptr_item.data).val, | ||
| 3862 | .orig_ty = info.ty, | ||
| 3863 | }, | ||
| 3864 | }, | ||
| 3865 | .ptr_anon_decl_aligned => b: { | ||
| 3866 | const sub_info = ip.extraData(PtrAnonDeclAligned, ptr_item.data); | ||
| 3867 | break :b .{ .anon_decl = .{ | ||
| 3868 | .val = sub_info.val, | ||
| 3869 | .orig_ty = sub_info.orig_ty, | ||
| 3870 | } }; | ||
| 3821 | }, | 3871 | }, |
| 3822 | .ptr_comptime_field => .{ | 3872 | .ptr_comptime_field => .{ |
| 3823 | .comptime_field = ip.extraData(PtrComptimeField, ptr_item.data).field_val, | 3873 | .comptime_field = ip.extraData(PtrComptimeField, ptr_item.data).field_val, |
| ... | @@ -4571,13 +4621,22 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { | ... | @@ -4571,13 +4621,22 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 4571 | .runtime_index = mut_decl.runtime_index, | 4621 | .runtime_index = mut_decl.runtime_index, |
| 4572 | }), | 4622 | }), |
| 4573 | }), | 4623 | }), |
| 4574 | .anon_decl => |anon_decl| ip.items.appendAssumeCapacity(.{ | 4624 | .anon_decl => |anon_decl| ip.items.appendAssumeCapacity( |
| 4575 | .tag = .ptr_anon_decl, | 4625 | if (ptrsHaveSameAlignment(ip, ptr.ty, ptr_type, anon_decl.orig_ty)) .{ |
| 4576 | .data = try ip.addExtra(gpa, PtrAnonDecl{ | 4626 | .tag = .ptr_anon_decl, |
| 4577 | .ty = ptr.ty, | 4627 | .data = try ip.addExtra(gpa, PtrAnonDecl{ |
| 4578 | .val = anon_decl, | 4628 | .ty = ptr.ty, |
| 4579 | }), | 4629 | .val = anon_decl.val, |
| 4580 | }), | 4630 | }), |
| 4631 | } else .{ | ||
| 4632 | .tag = .ptr_anon_decl_aligned, | ||
| 4633 | .data = try ip.addExtra(gpa, PtrAnonDeclAligned{ | ||
| 4634 | .ty = ptr.ty, | ||
| 4635 | .val = anon_decl.val, | ||
| 4636 | .orig_ty = anon_decl.orig_ty, | ||
| 4637 | }), | ||
| 4638 | }, | ||
| 4639 | ), | ||
| 4581 | .comptime_field => |field_val| { | 4640 | .comptime_field => |field_val| { |
| 4582 | assert(field_val != .none); | 4641 | assert(field_val != .none); |
| 4583 | ip.items.appendAssumeCapacity(.{ | 4642 | ip.items.appendAssumeCapacity(.{ |
| ... | @@ -7184,6 +7243,7 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { | ... | @@ -7184,6 +7243,7 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { |
| 7184 | .ptr_decl => @sizeOf(PtrDecl), | 7243 | .ptr_decl => @sizeOf(PtrDecl), |
| 7185 | .ptr_mut_decl => @sizeOf(PtrMutDecl), | 7244 | .ptr_mut_decl => @sizeOf(PtrMutDecl), |
| 7186 | .ptr_anon_decl => @sizeOf(PtrAnonDecl), | 7245 | .ptr_anon_decl => @sizeOf(PtrAnonDecl), |
| 7246 | .ptr_anon_decl_aligned => @sizeOf(PtrAnonDeclAligned), | ||
| 7187 | .ptr_comptime_field => @sizeOf(PtrComptimeField), | 7247 | .ptr_comptime_field => @sizeOf(PtrComptimeField), |
| 7188 | .ptr_int => @sizeOf(PtrBase), | 7248 | .ptr_int => @sizeOf(PtrBase), |
| 7189 | .ptr_eu_payload => @sizeOf(PtrBase), | 7249 | .ptr_eu_payload => @sizeOf(PtrBase), |
| ... | @@ -7314,6 +7374,7 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void { | ... | @@ -7314,6 +7374,7 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void { |
| 7314 | .ptr_decl, | 7374 | .ptr_decl, |
| 7315 | .ptr_mut_decl, | 7375 | .ptr_mut_decl, |
| 7316 | .ptr_anon_decl, | 7376 | .ptr_anon_decl, |
| 7377 | .ptr_anon_decl_aligned, | ||
| 7317 | .ptr_comptime_field, | 7378 | .ptr_comptime_field, |
| 7318 | .ptr_int, | 7379 | .ptr_int, |
| 7319 | .ptr_eu_payload, | 7380 | .ptr_eu_payload, |
| ... | @@ -7695,6 +7756,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index { | ... | @@ -7695,6 +7756,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index { |
| 7695 | inline .ptr_decl, | 7756 | inline .ptr_decl, |
| 7696 | .ptr_mut_decl, | 7757 | .ptr_mut_decl, |
| 7697 | .ptr_anon_decl, | 7758 | .ptr_anon_decl, |
| 7759 | .ptr_anon_decl_aligned, | ||
| 7698 | .ptr_comptime_field, | 7760 | .ptr_comptime_field, |
| 7699 | .ptr_int, | 7761 | .ptr_int, |
| 7700 | .ptr_eu_payload, | 7762 | .ptr_eu_payload, |
| ... | @@ -7855,7 +7917,7 @@ pub fn getBackingAddrTag(ip: *const InternPool, val: Index) ?Key.Ptr.Addr.Tag { | ... | @@ -7855,7 +7917,7 @@ pub fn getBackingAddrTag(ip: *const InternPool, val: Index) ?Key.Ptr.Addr.Tag { |
| 7855 | switch (ip.items.items(.tag)[base]) { | 7917 | switch (ip.items.items(.tag)[base]) { |
| 7856 | .ptr_decl => return .decl, | 7918 | .ptr_decl => return .decl, |
| 7857 | .ptr_mut_decl => return .mut_decl, | 7919 | .ptr_mut_decl => return .mut_decl, |
| 7858 | .ptr_anon_decl => return .anon_decl, | 7920 | .ptr_anon_decl, .ptr_anon_decl_aligned => return .anon_decl, |
| 7859 | .ptr_comptime_field => return .comptime_field, | 7921 | .ptr_comptime_field => return .comptime_field, |
| 7860 | .ptr_int => return .int, | 7922 | .ptr_int => return .int, |
| 7861 | inline .ptr_eu_payload, | 7923 | inline .ptr_eu_payload, |
| ... | @@ -8032,6 +8094,7 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois | ... | @@ -8032,6 +8094,7 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois |
| 8032 | .ptr_decl, | 8094 | .ptr_decl, |
| 8033 | .ptr_mut_decl, | 8095 | .ptr_mut_decl, |
| 8034 | .ptr_anon_decl, | 8096 | .ptr_anon_decl, |
| 8097 | .ptr_anon_decl_aligned, | ||
| 8035 | .ptr_comptime_field, | 8098 | .ptr_comptime_field, |
| 8036 | .ptr_int, | 8099 | .ptr_int, |
| 8037 | .ptr_eu_payload, | 8100 | .ptr_eu_payload, |
| ... | @@ -8281,3 +8344,12 @@ pub fn addFieldName( | ... | @@ -8281,3 +8344,12 @@ pub fn addFieldName( |
| 8281 | ip.extra.items[names_start + field_index] = @intFromEnum(name); | 8344 | ip.extra.items[names_start + field_index] = @intFromEnum(name); |
| 8282 | return null; | 8345 | return null; |
| 8283 | } | 8346 | } |
| 8347 | |||
| 8348 | /// Used only by `get` for pointer values, and mainly intended to use `Tag.ptr_anon_decl` | ||
| 8349 | /// encoding instead of `Tag.ptr_anon_decl_aligned` when possible. | ||
| 8350 | fn ptrsHaveSameAlignment(ip: *InternPool, a_ty: Index, a_info: Key.PtrType, b_ty: Index) bool { | ||
| 8351 | if (a_ty == b_ty) return true; | ||
| 8352 | const b_info = ip.indexToKey(b_ty).ptr_type; | ||
| 8353 | return a_info.flags.alignment == b_info.flags.alignment and | ||
| 8354 | (a_info.child == b_info.child or a_info.flags.alignment != .none); | ||
| 8355 | } |
src/Sema.zig+11-3| ... | @@ -3659,7 +3659,10 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro | ... | @@ -3659,7 +3659,10 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 3659 | if (try sema.resolveComptimeKnownAllocValue(block, alloc, null)) |val| { | 3659 | if (try sema.resolveComptimeKnownAllocValue(block, alloc, null)) |val| { |
| 3660 | const new_mut_ptr = Air.internedToRef((try mod.intern(.{ .ptr = .{ | 3660 | const new_mut_ptr = Air.internedToRef((try mod.intern(.{ .ptr = .{ |
| 3661 | .ty = alloc_ty.toIntern(), | 3661 | .ty = alloc_ty.toIntern(), |
| 3662 | .addr = .{ .anon_decl = val }, | 3662 | .addr = .{ .anon_decl = .{ |
| 3663 | .val = val, | ||
| 3664 | .orig_ty = alloc_ty.toIntern(), | ||
| 3665 | } }, | ||
| 3663 | } }))); | 3666 | } }))); |
| 3664 | return sema.makePtrConst(block, new_mut_ptr); | 3667 | return sema.makePtrConst(block, new_mut_ptr); |
| 3665 | } | 3668 | } |
| ... | @@ -5540,7 +5543,10 @@ fn addStrLitNoAlias(sema: *Sema, bytes: []const u8) CompileError!Air.Inst.Ref { | ... | @@ -5540,7 +5543,10 @@ fn addStrLitNoAlias(sema: *Sema, bytes: []const u8) CompileError!Air.Inst.Ref { |
| 5540 | }); | 5543 | }); |
| 5541 | return Air.internedToRef((try mod.intern(.{ .ptr = .{ | 5544 | return Air.internedToRef((try mod.intern(.{ .ptr = .{ |
| 5542 | .ty = ptr_ty.toIntern(), | 5545 | .ty = ptr_ty.toIntern(), |
| 5543 | .addr = .{ .anon_decl = val }, | 5546 | .addr = .{ .anon_decl = .{ |
| 5547 | .val = val, | ||
| 5548 | .orig_ty = ptr_ty.toIntern(), | ||
| 5549 | } }, | ||
| 5544 | } }))); | 5550 | } }))); |
| 5545 | } | 5551 | } |
| 5546 | 5552 | ||
| ... | @@ -30546,7 +30552,8 @@ fn beginComptimePtrLoad( | ... | @@ -30546,7 +30552,8 @@ fn beginComptimePtrLoad( |
| 30546 | .ty_without_well_defined_layout = if (!layout_defined) decl.ty else null, | 30552 | .ty_without_well_defined_layout = if (!layout_defined) decl.ty else null, |
| 30547 | }; | 30553 | }; |
| 30548 | }, | 30554 | }, |
| 30549 | .anon_decl => |decl_val| blk: { | 30555 | .anon_decl => |anon_decl| blk: { |
| 30556 | const decl_val = anon_decl.val; | ||
| 30550 | if (decl_val.toValue().getVariable(mod) != null) return error.RuntimeLoad; | 30557 | if (decl_val.toValue().getVariable(mod) != null) return error.RuntimeLoad; |
| 30551 | const decl_ty = ip.typeOf(decl_val).toType(); | 30558 | const decl_ty = ip.typeOf(decl_val).toType(); |
| 30552 | const decl_tv: TypedValue = .{ .ty = decl_ty, .val = decl_val.toValue() }; | 30559 | const decl_tv: TypedValue = .{ .ty = decl_ty, .val = decl_val.toValue() }; |
| ... | @@ -36650,6 +36657,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { | ... | @@ -36650,6 +36657,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 36650 | .simple_value, | 36657 | .simple_value, |
| 36651 | .ptr_decl, | 36658 | .ptr_decl, |
| 36652 | .ptr_anon_decl, | 36659 | .ptr_anon_decl, |
| 36660 | .ptr_anon_decl_aligned, | ||
| 36653 | .ptr_mut_decl, | 36661 | .ptr_mut_decl, |
| 36654 | .ptr_comptime_field, | 36662 | .ptr_comptime_field, |
| 36655 | .ptr_int, | 36663 | .ptr_int, |
src/TypedValue.zig+2-1| ... | @@ -321,7 +321,8 @@ pub fn print( | ... | @@ -321,7 +321,8 @@ pub fn print( |
| 321 | .val = decl.val, | 321 | .val = decl.val, |
| 322 | }, writer, level - 1, mod); | 322 | }, writer, level - 1, mod); |
| 323 | }, | 323 | }, |
| 324 | .anon_decl => |decl_val| { | 324 | .anon_decl => |anon_decl| { |
| 325 | const decl_val = anon_decl.val; | ||
| 325 | if (level == 0) return writer.print("(anon decl '{d}')", .{ | 326 | if (level == 0) return writer.print("(anon decl '{d}')", .{ |
| 326 | @intFromEnum(decl_val), | 327 | @intFromEnum(decl_val), |
| 327 | }); | 328 | }); |
src/arch/wasm/CodeGen.zig+13-4| ... | @@ -3139,16 +3139,25 @@ fn lowerParentPtrDecl(func: *CodeGen, ptr_val: Value, decl_index: Module.Decl.In | ... | @@ -3139,16 +3139,25 @@ fn lowerParentPtrDecl(func: *CodeGen, ptr_val: Value, decl_index: Module.Decl.In |
| 3139 | return func.lowerDeclRefValue(.{ .ty = ptr_ty, .val = ptr_val }, decl_index, offset); | 3139 | return func.lowerDeclRefValue(.{ .ty = ptr_ty, .val = ptr_val }, decl_index, offset); |
| 3140 | } | 3140 | } |
| 3141 | 3141 | ||
| 3142 | fn lowerAnonDeclRef(func: *CodeGen, anon_decl: InternPool.Index, offset: u32) InnerError!WValue { | 3142 | fn lowerAnonDeclRef( |
| 3143 | func: *CodeGen, | ||
| 3144 | anon_decl: InternPool.Key.Ptr.Addr.AnonDecl, | ||
| 3145 | offset: u32, | ||
| 3146 | ) InnerError!WValue { | ||
| 3143 | const mod = func.bin_file.base.options.module.?; | 3147 | const mod = func.bin_file.base.options.module.?; |
| 3144 | const ty = mod.intern_pool.typeOf(anon_decl).toType(); | 3148 | const decl_val = anon_decl.val; |
| 3149 | const ty = mod.intern_pool.typeOf(decl_val).toType(); | ||
| 3145 | 3150 | ||
| 3146 | const is_fn_body = ty.zigTypeTag(mod) == .Fn; | 3151 | const is_fn_body = ty.zigTypeTag(mod) == .Fn; |
| 3147 | if (!is_fn_body and !ty.hasRuntimeBitsIgnoreComptime(mod)) { | 3152 | if (!is_fn_body and !ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 3148 | return WValue{ .imm32 = 0xaaaaaaaa }; | 3153 | return WValue{ .imm32 = 0xaaaaaaaa }; |
| 3149 | } | 3154 | } |
| 3150 | 3155 | ||
| 3151 | const res = try func.bin_file.lowerAnonDecl(anon_decl, func.decl.srcLoc(mod)); | 3156 | const alignment = mod.intern_pool.indexToKey(anon_decl.orig_ty).ptr_type.flags.alignment; |
| 3157 | if (alignment != .none) { | ||
| 3158 | @panic("TODO how to make this anon decl be aligned?"); | ||
| 3159 | } | ||
| 3160 | const res = try func.bin_file.lowerAnonDecl(decl_val, func.decl.srcLoc(mod)); | ||
| 3152 | switch (res) { | 3161 | switch (res) { |
| 3153 | .ok => {}, | 3162 | .ok => {}, |
| 3154 | .fail => |em| { | 3163 | .fail => |em| { |
| ... | @@ -3156,7 +3165,7 @@ fn lowerAnonDeclRef(func: *CodeGen, anon_decl: InternPool.Index, offset: u32) In | ... | @@ -3156,7 +3165,7 @@ fn lowerAnonDeclRef(func: *CodeGen, anon_decl: InternPool.Index, offset: u32) In |
| 3156 | return error.CodegenFail; | 3165 | return error.CodegenFail; |
| 3157 | }, | 3166 | }, |
| 3158 | } | 3167 | } |
| 3159 | const target_atom_index = func.bin_file.anon_decls.get(anon_decl).?; | 3168 | const target_atom_index = func.bin_file.anon_decls.get(decl_val).?; |
| 3160 | const target_sym_index = func.bin_file.getAtom(target_atom_index).getSymbolIndex().?; | 3169 | const target_sym_index = func.bin_file.getAtom(target_atom_index).getSymbolIndex().?; |
| 3161 | if (is_fn_body) { | 3170 | if (is_fn_body) { |
| 3162 | return WValue{ .function_index = target_sym_index }; | 3171 | return WValue{ .function_index = target_sym_index }; |
src/codegen.zig+6-1| ... | @@ -713,7 +713,7 @@ const RelocInfo = struct { | ... | @@ -713,7 +713,7 @@ const RelocInfo = struct { |
| 713 | fn lowerAnonDeclRef( | 713 | fn lowerAnonDeclRef( |
| 714 | bin_file: *link.File, | 714 | bin_file: *link.File, |
| 715 | src_loc: Module.SrcLoc, | 715 | src_loc: Module.SrcLoc, |
| 716 | decl_val: InternPool.Index, | 716 | anon_decl: InternPool.Key.Ptr.Addr.AnonDecl, |
| 717 | code: *std.ArrayList(u8), | 717 | code: *std.ArrayList(u8), |
| 718 | debug_output: DebugInfoOutput, | 718 | debug_output: DebugInfoOutput, |
| 719 | reloc_info: RelocInfo, | 719 | reloc_info: RelocInfo, |
| ... | @@ -723,6 +723,7 @@ fn lowerAnonDeclRef( | ... | @@ -723,6 +723,7 @@ fn lowerAnonDeclRef( |
| 723 | const mod = bin_file.options.module.?; | 723 | const mod = bin_file.options.module.?; |
| 724 | 724 | ||
| 725 | const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8); | 725 | const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8); |
| 726 | const decl_val = anon_decl.val; | ||
| 726 | const decl_ty = mod.intern_pool.typeOf(decl_val).toType(); | 727 | const decl_ty = mod.intern_pool.typeOf(decl_val).toType(); |
| 727 | const is_fn_body = decl_ty.zigTypeTag(mod) == .Fn; | 728 | const is_fn_body = decl_ty.zigTypeTag(mod) == .Fn; |
| 728 | if (!is_fn_body and !decl_ty.hasRuntimeBits(mod)) { | 729 | if (!is_fn_body and !decl_ty.hasRuntimeBits(mod)) { |
| ... | @@ -736,6 +737,10 @@ fn lowerAnonDeclRef( | ... | @@ -736,6 +737,10 @@ fn lowerAnonDeclRef( |
| 736 | .fail => |em| return .{ .fail = em }, | 737 | .fail => |em| return .{ .fail = em }, |
| 737 | } | 738 | } |
| 738 | 739 | ||
| 740 | const alignment = mod.intern_pool.indexToKey(anon_decl.orig_ty).ptr_type.flags.alignment; | ||
| 741 | if (alignment != .none) { | ||
| 742 | @panic("TODO how to make this anon decl be aligned?"); | ||
| 743 | } | ||
| 739 | const vaddr = try bin_file.getAnonDeclVAddr(decl_val, .{ | 744 | const vaddr = try bin_file.getAnonDeclVAddr(decl_val, .{ |
| 740 | .parent_atom_index = reloc_info.parent_atom_index, | 745 | .parent_atom_index = reloc_info.parent_atom_index, |
| 741 | .offset = code.items.len, | 746 | .offset = code.items.len, |
src/codegen/c.zig+19-2| ... | @@ -531,6 +531,7 @@ pub const DeclGen = struct { | ... | @@ -531,6 +531,7 @@ pub const DeclGen = struct { |
| 531 | /// Keeps track of anonymous decls that need to be rendered before this | 531 | /// Keeps track of anonymous decls that need to be rendered before this |
| 532 | /// (named) Decl in the output C code. | 532 | /// (named) Decl in the output C code. |
| 533 | anon_decl_deps: std.AutoArrayHashMapUnmanaged(InternPool.Index, C.DeclBlock), | 533 | anon_decl_deps: std.AutoArrayHashMapUnmanaged(InternPool.Index, C.DeclBlock), |
| 534 | aligned_anon_decls: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment), | ||
| 534 | 535 | ||
| 535 | fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } { | 536 | fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } { |
| 536 | @setCold(true); | 537 | @setCold(true); |
| ... | @@ -548,11 +549,12 @@ pub const DeclGen = struct { | ... | @@ -548,11 +549,12 @@ pub const DeclGen = struct { |
| 548 | writer: anytype, | 549 | writer: anytype, |
| 549 | ty: Type, | 550 | ty: Type, |
| 550 | ptr_val: Value, | 551 | ptr_val: Value, |
| 551 | decl_val: InternPool.Index, | 552 | anon_decl: InternPool.Key.Ptr.Addr.AnonDecl, |
| 552 | location: ValueRenderLocation, | 553 | location: ValueRenderLocation, |
| 553 | ) error{ OutOfMemory, AnalysisFail }!void { | 554 | ) error{ OutOfMemory, AnalysisFail }!void { |
| 554 | const mod = dg.module; | 555 | const mod = dg.module; |
| 555 | const ip = &mod.intern_pool; | 556 | const ip = &mod.intern_pool; |
| 557 | const decl_val = anon_decl.val; | ||
| 556 | const decl_ty = ip.typeOf(decl_val).toType(); | 558 | const decl_ty = ip.typeOf(decl_val).toType(); |
| 557 | 559 | ||
| 558 | // Render an undefined pointer if we have a pointer to a zero-bit or comptime type. | 560 | // Render an undefined pointer if we have a pointer to a zero-bit or comptime type. |
| ... | @@ -592,8 +594,23 @@ pub const DeclGen = struct { | ... | @@ -592,8 +594,23 @@ pub const DeclGen = struct { |
| 592 | 594 | ||
| 593 | // Indicate that the anon decl should be rendered to the output so that | 595 | // Indicate that the anon decl should be rendered to the output so that |
| 594 | // our reference above is not undefined. | 596 | // our reference above is not undefined. |
| 597 | const ptr_type = ip.indexToKey(anon_decl.orig_ty).ptr_type; | ||
| 595 | const gop = try dg.anon_decl_deps.getOrPut(dg.gpa, decl_val); | 598 | const gop = try dg.anon_decl_deps.getOrPut(dg.gpa, decl_val); |
| 596 | if (!gop.found_existing) gop.value_ptr.* = .{}; | 599 | if (!gop.found_existing) gop.value_ptr.* = .{}; |
| 600 | |||
| 601 | // Only insert an alignment entry if the alignment is greater than ABI | ||
| 602 | // alignment. If there is already an entry, keep the greater alignment. | ||
| 603 | const explicit_alignment = ptr_type.flags.alignment; | ||
| 604 | if (explicit_alignment != .none) { | ||
| 605 | const abi_alignment = ptr_type.child.toType().abiAlignment(mod); | ||
| 606 | if (explicit_alignment.compareStrict(.gt, abi_alignment)) { | ||
| 607 | const aligned_gop = try dg.aligned_anon_decls.getOrPut(dg.gpa, decl_val); | ||
| 608 | aligned_gop.value_ptr.* = if (aligned_gop.found_existing) | ||
| 609 | aligned_gop.value_ptr.maxStrict(explicit_alignment) | ||
| 610 | else | ||
| 611 | explicit_alignment; | ||
| 612 | } | ||
| 613 | } | ||
| 597 | } | 614 | } |
| 598 | 615 | ||
| 599 | fn renderDeclValue( | 616 | fn renderDeclValue( |
| ... | @@ -651,7 +668,7 @@ pub const DeclGen = struct { | ... | @@ -651,7 +668,7 @@ pub const DeclGen = struct { |
| 651 | switch (ptr.addr) { | 668 | switch (ptr.addr) { |
| 652 | .decl => |d| try dg.renderDeclValue(writer, ptr_ty, ptr_val.toValue(), d, location), | 669 | .decl => |d| try dg.renderDeclValue(writer, ptr_ty, ptr_val.toValue(), d, location), |
| 653 | .mut_decl => |md| try dg.renderDeclValue(writer, ptr_ty, ptr_val.toValue(), md.decl, location), | 670 | .mut_decl => |md| try dg.renderDeclValue(writer, ptr_ty, ptr_val.toValue(), md.decl, location), |
| 654 | .anon_decl => |decl_val| try dg.renderAnonDeclValue(writer, ptr_ty, ptr_val.toValue(), decl_val, location), | 671 | .anon_decl => |anon_decl| try dg.renderAnonDeclValue(writer, ptr_ty, ptr_val.toValue(), anon_decl, location), |
| 655 | .int => |int| { | 672 | .int => |int| { |
| 656 | try writer.writeByte('('); | 673 | try writer.writeByte('('); |
| 657 | try dg.renderCType(writer, ptr_cty); | 674 | try dg.renderCType(writer, ptr_cty); |
src/codegen/llvm.zig+16-15| ... | @@ -3051,9 +3051,17 @@ pub const Object = struct { | ... | @@ -3051,9 +3051,17 @@ pub const Object = struct { |
| 3051 | llvm_addr_space: Builder.AddrSpace, | 3051 | llvm_addr_space: Builder.AddrSpace, |
| 3052 | alignment: InternPool.Alignment, | 3052 | alignment: InternPool.Alignment, |
| 3053 | ) Error!Builder.Variable.Index { | 3053 | ) Error!Builder.Variable.Index { |
| 3054 | assert(alignment != .none); | ||
| 3054 | // TODO: Add address space to the anon_decl_map | 3055 | // TODO: Add address space to the anon_decl_map |
| 3055 | const gop = try o.anon_decl_map.getOrPut(o.gpa, decl_val); | 3056 | const gop = try o.anon_decl_map.getOrPut(o.gpa, decl_val); |
| 3056 | if (gop.found_existing) return gop.value_ptr.ptr(&o.builder).kind.variable; | 3057 | if (gop.found_existing) { |
| 3058 | // Keep the greater of the two alignments. | ||
| 3059 | const variable_index = gop.value_ptr.ptr(&o.builder).kind.variable; | ||
| 3060 | const old_alignment = InternPool.Alignment.fromLlvm(variable_index.getAlignment(&o.builder)); | ||
| 3061 | const max_alignment = old_alignment.maxStrict(alignment); | ||
| 3062 | variable_index.setAlignment(max_alignment.toLlvm(), &o.builder); | ||
| 3063 | return variable_index; | ||
| 3064 | } | ||
| 3057 | errdefer assert(o.anon_decl_map.remove(decl_val)); | 3065 | errdefer assert(o.anon_decl_map.remove(decl_val)); |
| 3058 | 3066 | ||
| 3059 | const mod = o.module; | 3067 | const mod = o.module; |
| ... | @@ -3069,8 +3077,7 @@ pub const Object = struct { | ... | @@ -3069,8 +3077,7 @@ pub const Object = struct { |
| 3069 | try variable_index.setInitializer(try o.lowerValue(decl_val), &o.builder); | 3077 | try variable_index.setInitializer(try o.lowerValue(decl_val), &o.builder); |
| 3070 | variable_index.setLinkage(.internal, &o.builder); | 3078 | variable_index.setLinkage(.internal, &o.builder); |
| 3071 | variable_index.setUnnamedAddr(.unnamed_addr, &o.builder); | 3079 | variable_index.setUnnamedAddr(.unnamed_addr, &o.builder); |
| 3072 | if (alignment != .none) | 3080 | variable_index.setAlignment(alignment.toLlvm(), &o.builder); |
| 3073 | variable_index.setAlignment(alignment.toLlvm(), &o.builder); | ||
| 3074 | return variable_index; | 3081 | return variable_index; |
| 3075 | } | 3082 | } |
| 3076 | 3083 | ||
| ... | @@ -4253,13 +4260,6 @@ pub const Object = struct { | ... | @@ -4253,13 +4260,6 @@ pub const Object = struct { |
| 4253 | return o.builder.bigIntConst(try o.builder.intType(ty.intInfo(mod).bits), bigint); | 4260 | return o.builder.bigIntConst(try o.builder.intType(ty.intInfo(mod).bits), bigint); |
| 4254 | } | 4261 | } |
| 4255 | 4262 | ||
| 4256 | fn lowerParentPtrAnonDecl(o: *Object, decl_val: InternPool.Index) Error!Builder.Constant { | ||
| 4257 | const mod = o.module; | ||
| 4258 | const decl_ty = mod.intern_pool.typeOf(decl_val).toType(); | ||
| 4259 | const ptr_ty = try mod.singleMutPtrType(decl_ty); | ||
| 4260 | return o.lowerAnonDeclRef(ptr_ty, decl_val); | ||
| 4261 | } | ||
| 4262 | |||
| 4263 | fn lowerParentPtrDecl(o: *Object, decl_index: Module.Decl.Index) Allocator.Error!Builder.Constant { | 4263 | fn lowerParentPtrDecl(o: *Object, decl_index: Module.Decl.Index) Allocator.Error!Builder.Constant { |
| 4264 | const mod = o.module; | 4264 | const mod = o.module; |
| 4265 | const decl = mod.declPtr(decl_index); | 4265 | const decl = mod.declPtr(decl_index); |
| ... | @@ -4275,7 +4275,7 @@ pub const Object = struct { | ... | @@ -4275,7 +4275,7 @@ pub const Object = struct { |
| 4275 | return switch (ptr.addr) { | 4275 | return switch (ptr.addr) { |
| 4276 | .decl => |decl| try o.lowerParentPtrDecl(decl), | 4276 | .decl => |decl| try o.lowerParentPtrDecl(decl), |
| 4277 | .mut_decl => |mut_decl| try o.lowerParentPtrDecl(mut_decl.decl), | 4277 | .mut_decl => |mut_decl| try o.lowerParentPtrDecl(mut_decl.decl), |
| 4278 | .anon_decl => |anon_decl| try o.lowerParentPtrAnonDecl(anon_decl), | 4278 | .anon_decl => |ad| try o.lowerAnonDeclRef(ad.orig_ty.toType(), ad), |
| 4279 | .int => |int| try o.lowerIntAsPtr(int), | 4279 | .int => |int| try o.lowerIntAsPtr(int), |
| 4280 | .eu_payload => |eu_ptr| { | 4280 | .eu_payload => |eu_ptr| { |
| 4281 | const parent_ptr = try o.lowerParentPtr(eu_ptr.toValue()); | 4281 | const parent_ptr = try o.lowerParentPtr(eu_ptr.toValue()); |
| ... | @@ -4394,10 +4394,11 @@ pub const Object = struct { | ... | @@ -4394,10 +4394,11 @@ pub const Object = struct { |
| 4394 | fn lowerAnonDeclRef( | 4394 | fn lowerAnonDeclRef( |
| 4395 | o: *Object, | 4395 | o: *Object, |
| 4396 | ptr_ty: Type, | 4396 | ptr_ty: Type, |
| 4397 | decl_val: InternPool.Index, | 4397 | anon_decl: InternPool.Key.Ptr.Addr.AnonDecl, |
| 4398 | ) Error!Builder.Constant { | 4398 | ) Error!Builder.Constant { |
| 4399 | const mod = o.module; | 4399 | const mod = o.module; |
| 4400 | const ip = &mod.intern_pool; | 4400 | const ip = &mod.intern_pool; |
| 4401 | const decl_val = anon_decl.val; | ||
| 4401 | const decl_ty = ip.typeOf(decl_val).toType(); | 4402 | const decl_ty = ip.typeOf(decl_val).toType(); |
| 4402 | const target = mod.getTarget(); | 4403 | const target = mod.getTarget(); |
| 4403 | 4404 | ||
| ... | @@ -4416,9 +4417,9 @@ pub const Object = struct { | ... | @@ -4416,9 +4417,9 @@ pub const Object = struct { |
| 4416 | if (is_fn_body) | 4417 | if (is_fn_body) |
| 4417 | @panic("TODO"); | 4418 | @panic("TODO"); |
| 4418 | 4419 | ||
| 4419 | const addr_space = target_util.defaultAddressSpace(target, .global_constant); | 4420 | const orig_ty = anon_decl.orig_ty.toType(); |
| 4420 | const llvm_addr_space = toLlvmAddressSpace(addr_space, target); | 4421 | const llvm_addr_space = toLlvmAddressSpace(orig_ty.ptrAddressSpace(mod), target); |
| 4421 | const alignment = ptr_ty.ptrAlignment(mod); | 4422 | const alignment = orig_ty.ptrAlignment(mod); |
| 4422 | const llvm_global = (try o.resolveGlobalAnonDecl(decl_val, llvm_addr_space, alignment)).ptrConst(&o.builder).global; | 4423 | const llvm_global = (try o.resolveGlobalAnonDecl(decl_val, llvm_addr_space, alignment)).ptrConst(&o.builder).global; |
| 4423 | 4424 | ||
| 4424 | const llvm_val = try o.builder.convConst( | 4425 | const llvm_val = try o.builder.convConst( |
src/codegen/llvm/Builder.zig+6| ... | @@ -2477,6 +2477,12 @@ pub const Variable = struct { | ... | @@ -2477,6 +2477,12 @@ pub const Variable = struct { |
| 2477 | self.ptr(builder).alignment = alignment; | 2477 | self.ptr(builder).alignment = alignment; |
| 2478 | } | 2478 | } |
| 2479 | 2479 | ||
| 2480 | pub fn getAlignment(self: Index, builder: *Builder) Alignment { | ||
| 2481 | if (builder.useLibLlvm()) | ||
| 2482 | return Alignment.fromByteUnits(self.toLlvm(builder).getAlignment()); | ||
| 2483 | return self.ptr(builder).alignment; | ||
| 2484 | } | ||
| 2485 | |||
| 2480 | pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value { | 2486 | pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value { |
| 2481 | return self.ptrConst(builder).global.toLlvm(builder); | 2487 | return self.ptrConst(builder).global.toLlvm(builder); |
| 2482 | } | 2488 | } |
src/codegen/llvm/bindings.zig+3| ... | @@ -273,6 +273,9 @@ pub const Value = opaque { | ... | @@ -273,6 +273,9 @@ pub const Value = opaque { |
| 273 | pub const setAlignment = LLVMSetAlignment; | 273 | pub const setAlignment = LLVMSetAlignment; |
| 274 | extern fn LLVMSetAlignment(V: *Value, Bytes: c_uint) void; | 274 | extern fn LLVMSetAlignment(V: *Value, Bytes: c_uint) void; |
| 275 | 275 | ||
| 276 | pub const getAlignment = LLVMGetAlignment; | ||
| 277 | extern fn LLVMGetAlignment(V: *Value) c_uint; | ||
| 278 | |||
| 276 | pub const setFunctionCallConv = LLVMSetFunctionCallConv; | 279 | pub const setFunctionCallConv = LLVMSetFunctionCallConv; |
| 277 | extern fn LLVMSetFunctionCallConv(Fn: *Value, CC: CallConv) void; | 280 | extern fn LLVMSetFunctionCallConv(Fn: *Value, CC: CallConv) void; |
| 278 | 281 |
src/codegen/spirv.zig+6-1| ... | @@ -959,12 +959,17 @@ const DeclGen = struct { | ... | @@ -959,12 +959,17 @@ const DeclGen = struct { |
| 959 | } | 959 | } |
| 960 | } | 960 | } |
| 961 | 961 | ||
| 962 | fn constantAnonDeclRef(self: *DeclGen, ty: Type, decl_val: InternPool.Index) !IdRef { | 962 | fn constantAnonDeclRef( |
| 963 | self: *DeclGen, | ||
| 964 | ty: Type, | ||
| 965 | anon_decl: InternPool.Key.Ptr.Addr.AnonDecl, | ||
| 966 | ) !IdRef { | ||
| 963 | // TODO: Merge this function with constantDeclRef. | 967 | // TODO: Merge this function with constantDeclRef. |
| 964 | 968 | ||
| 965 | const mod = self.module; | 969 | const mod = self.module; |
| 966 | const ip = &mod.intern_pool; | 970 | const ip = &mod.intern_pool; |
| 967 | const ty_ref = try self.resolveType(ty, .direct); | 971 | const ty_ref = try self.resolveType(ty, .direct); |
| 972 | const decl_val = anon_decl.val; | ||
| 968 | const decl_ty = ip.typeOf(decl_val).toType(); | 973 | const decl_ty = ip.typeOf(decl_val).toType(); |
| 969 | 974 | ||
| 970 | if (decl_val.toValue().getFunction(mod)) |func| { | 975 | if (decl_val.toValue().getFunction(mod)) |func| { |
src/link/C.zig+18-1| ... | @@ -7,6 +7,7 @@ const fs = std.fs; | ... | @@ -7,6 +7,7 @@ const fs = std.fs; |
| 7 | const C = @This(); | 7 | const C = @This(); |
| 8 | const Module = @import("../Module.zig"); | 8 | const Module = @import("../Module.zig"); |
| 9 | const InternPool = @import("../InternPool.zig"); | 9 | const InternPool = @import("../InternPool.zig"); |
| 10 | const Alignment = InternPool.Alignment; | ||
| 10 | const Compilation = @import("../Compilation.zig"); | 11 | const Compilation = @import("../Compilation.zig"); |
| 11 | const codegen = @import("../codegen/c.zig"); | 12 | const codegen = @import("../codegen/c.zig"); |
| 12 | const link = @import("../link.zig"); | 13 | const link = @import("../link.zig"); |
| ... | @@ -30,6 +31,10 @@ string_bytes: std.ArrayListUnmanaged(u8) = .{}, | ... | @@ -30,6 +31,10 @@ string_bytes: std.ArrayListUnmanaged(u8) = .{}, |
| 30 | /// Tracks all the anonymous decls that are used by all the decls so they can | 31 | /// Tracks all the anonymous decls that are used by all the decls so they can |
| 31 | /// be rendered during flush(). | 32 | /// be rendered during flush(). |
| 32 | anon_decls: std.AutoArrayHashMapUnmanaged(InternPool.Index, DeclBlock) = .{}, | 33 | anon_decls: std.AutoArrayHashMapUnmanaged(InternPool.Index, DeclBlock) = .{}, |
| 34 | /// Sparse set of anon decls that are overaligned. Underaligned anon decls are | ||
| 35 | /// lowered the same as ABI-aligned anon decls. The keys here are a subset of | ||
| 36 | /// the keys of `anon_decls`. | ||
| 37 | aligned_anon_decls: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment) = .{}, | ||
| 33 | 38 | ||
| 34 | /// Optimization, `updateDecl` reuses this buffer rather than creating a new | 39 | /// Optimization, `updateDecl` reuses this buffer rather than creating a new |
| 35 | /// one with every call. | 40 | /// one with every call. |
| ... | @@ -125,6 +130,7 @@ pub fn deinit(self: *C) void { | ... | @@ -125,6 +130,7 @@ pub fn deinit(self: *C) void { |
| 125 | db.deinit(gpa); | 130 | db.deinit(gpa); |
| 126 | } | 131 | } |
| 127 | self.anon_decls.deinit(gpa); | 132 | self.anon_decls.deinit(gpa); |
| 133 | self.aligned_anon_decls.deinit(gpa); | ||
| 128 | 134 | ||
| 129 | self.string_bytes.deinit(gpa); | 135 | self.string_bytes.deinit(gpa); |
| 130 | self.fwd_decl_buf.deinit(gpa); | 136 | self.fwd_decl_buf.deinit(gpa); |
| ... | @@ -179,6 +185,7 @@ pub fn updateFunc( | ... | @@ -179,6 +185,7 @@ pub fn updateFunc( |
| 179 | .fwd_decl = fwd_decl.toManaged(gpa), | 185 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 180 | .ctypes = ctypes.*, | 186 | .ctypes = ctypes.*, |
| 181 | .anon_decl_deps = self.anon_decls, | 187 | .anon_decl_deps = self.anon_decls, |
| 188 | .aligned_anon_decls = self.aligned_anon_decls, | ||
| 182 | }, | 189 | }, |
| 183 | .code = code.toManaged(gpa), | 190 | .code = code.toManaged(gpa), |
| 184 | .indent_writer = undefined, // set later so we can get a pointer to object.code | 191 | .indent_writer = undefined, // set later so we can get a pointer to object.code |
| ... | @@ -189,6 +196,7 @@ pub fn updateFunc( | ... | @@ -189,6 +196,7 @@ pub fn updateFunc( |
| 189 | function.object.indent_writer = .{ .underlying_writer = function.object.code.writer() }; | 196 | function.object.indent_writer = .{ .underlying_writer = function.object.code.writer() }; |
| 190 | defer { | 197 | defer { |
| 191 | self.anon_decls = function.object.dg.anon_decl_deps; | 198 | self.anon_decls = function.object.dg.anon_decl_deps; |
| 199 | self.aligned_anon_decls = function.object.dg.aligned_anon_decls; | ||
| 192 | fwd_decl.* = function.object.dg.fwd_decl.moveToUnmanaged(); | 200 | fwd_decl.* = function.object.dg.fwd_decl.moveToUnmanaged(); |
| 193 | code.* = function.object.code.moveToUnmanaged(); | 201 | code.* = function.object.code.moveToUnmanaged(); |
| 194 | function.deinit(); | 202 | function.deinit(); |
| ... | @@ -232,6 +240,7 @@ fn updateAnonDecl(self: *C, module: *Module, i: usize) !void { | ... | @@ -232,6 +240,7 @@ fn updateAnonDecl(self: *C, module: *Module, i: usize) !void { |
| 232 | .fwd_decl = fwd_decl.toManaged(gpa), | 240 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 233 | .ctypes = .{}, | 241 | .ctypes = .{}, |
| 234 | .anon_decl_deps = self.anon_decls, | 242 | .anon_decl_deps = self.anon_decls, |
| 243 | .aligned_anon_decls = self.aligned_anon_decls, | ||
| 235 | }, | 244 | }, |
| 236 | .code = code.toManaged(gpa), | 245 | .code = code.toManaged(gpa), |
| 237 | .indent_writer = undefined, // set later so we can get a pointer to object.code | 246 | .indent_writer = undefined, // set later so we can get a pointer to object.code |
| ... | @@ -240,6 +249,7 @@ fn updateAnonDecl(self: *C, module: *Module, i: usize) !void { | ... | @@ -240,6 +249,7 @@ fn updateAnonDecl(self: *C, module: *Module, i: usize) !void { |
| 240 | 249 | ||
| 241 | defer { | 250 | defer { |
| 242 | self.anon_decls = object.dg.anon_decl_deps; | 251 | self.anon_decls = object.dg.anon_decl_deps; |
| 252 | self.aligned_anon_decls = object.dg.aligned_anon_decls; | ||
| 243 | object.dg.ctypes.deinit(object.dg.gpa); | 253 | object.dg.ctypes.deinit(object.dg.gpa); |
| 244 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); | 254 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); |
| 245 | code.* = object.code.moveToUnmanaged(); | 255 | code.* = object.code.moveToUnmanaged(); |
| ... | @@ -250,7 +260,8 @@ fn updateAnonDecl(self: *C, module: *Module, i: usize) !void { | ... | @@ -250,7 +260,8 @@ fn updateAnonDecl(self: *C, module: *Module, i: usize) !void { |
| 250 | .val = anon_decl.toValue(), | 260 | .val = anon_decl.toValue(), |
| 251 | }; | 261 | }; |
| 252 | const c_value: codegen.CValue = .{ .constant = anon_decl }; | 262 | const c_value: codegen.CValue = .{ .constant = anon_decl }; |
| 253 | codegen.genDeclValue(&object, tv, false, c_value, .none, .none) catch |err| switch (err) { | 263 | const alignment: Alignment = self.aligned_anon_decls.get(anon_decl) orelse .none; |
| 264 | codegen.genDeclValue(&object, tv, false, c_value, alignment, .none) catch |err| switch (err) { | ||
| 254 | error.AnalysisFail => { | 265 | error.AnalysisFail => { |
| 255 | @panic("TODO: C backend AnalysisFail on anonymous decl"); | 266 | @panic("TODO: C backend AnalysisFail on anonymous decl"); |
| 256 | //try module.failed_decls.put(gpa, decl_index, object.dg.error_msg.?); | 267 | //try module.failed_decls.put(gpa, decl_index, object.dg.error_msg.?); |
| ... | @@ -296,6 +307,7 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !voi | ... | @@ -296,6 +307,7 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !voi |
| 296 | .fwd_decl = fwd_decl.toManaged(gpa), | 307 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 297 | .ctypes = ctypes.*, | 308 | .ctypes = ctypes.*, |
| 298 | .anon_decl_deps = self.anon_decls, | 309 | .anon_decl_deps = self.anon_decls, |
| 310 | .aligned_anon_decls = self.aligned_anon_decls, | ||
| 299 | }, | 311 | }, |
| 300 | .code = code.toManaged(gpa), | 312 | .code = code.toManaged(gpa), |
| 301 | .indent_writer = undefined, // set later so we can get a pointer to object.code | 313 | .indent_writer = undefined, // set later so we can get a pointer to object.code |
| ... | @@ -303,6 +315,7 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !voi | ... | @@ -303,6 +315,7 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !voi |
| 303 | object.indent_writer = .{ .underlying_writer = object.code.writer() }; | 315 | object.indent_writer = .{ .underlying_writer = object.code.writer() }; |
| 304 | defer { | 316 | defer { |
| 305 | self.anon_decls = object.dg.anon_decl_deps; | 317 | self.anon_decls = object.dg.anon_decl_deps; |
| 318 | self.aligned_anon_decls = object.dg.aligned_anon_decls; | ||
| 306 | object.dg.ctypes.deinit(object.dg.gpa); | 319 | object.dg.ctypes.deinit(object.dg.gpa); |
| 307 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); | 320 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); |
| 308 | code.* = object.code.moveToUnmanaged(); | 321 | code.* = object.code.moveToUnmanaged(); |
| ... | @@ -602,6 +615,7 @@ fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void { | ... | @@ -602,6 +615,7 @@ fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void { |
| 602 | .fwd_decl = fwd_decl.toManaged(gpa), | 615 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 603 | .ctypes = ctypes.*, | 616 | .ctypes = ctypes.*, |
| 604 | .anon_decl_deps = self.anon_decls, | 617 | .anon_decl_deps = self.anon_decls, |
| 618 | .aligned_anon_decls = self.aligned_anon_decls, | ||
| 605 | }, | 619 | }, |
| 606 | .code = code.toManaged(gpa), | 620 | .code = code.toManaged(gpa), |
| 607 | .indent_writer = undefined, // set later so we can get a pointer to object.code | 621 | .indent_writer = undefined, // set later so we can get a pointer to object.code |
| ... | @@ -609,6 +623,7 @@ fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void { | ... | @@ -609,6 +623,7 @@ fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void { |
| 609 | object.indent_writer = .{ .underlying_writer = object.code.writer() }; | 623 | object.indent_writer = .{ .underlying_writer = object.code.writer() }; |
| 610 | defer { | 624 | defer { |
| 611 | self.anon_decls = object.dg.anon_decl_deps; | 625 | self.anon_decls = object.dg.anon_decl_deps; |
| 626 | self.aligned_anon_decls = object.dg.aligned_anon_decls; | ||
| 612 | object.dg.ctypes.deinit(gpa); | 627 | object.dg.ctypes.deinit(gpa); |
| 613 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); | 628 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); |
| 614 | code.* = object.code.moveToUnmanaged(); | 629 | code.* = object.code.moveToUnmanaged(); |
| ... | @@ -642,6 +657,7 @@ fn flushLazyFn( | ... | @@ -642,6 +657,7 @@ fn flushLazyFn( |
| 642 | .fwd_decl = fwd_decl.toManaged(gpa), | 657 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 643 | .ctypes = ctypes.*, | 658 | .ctypes = ctypes.*, |
| 644 | .anon_decl_deps = .{}, | 659 | .anon_decl_deps = .{}, |
| 660 | .aligned_anon_decls = .{}, | ||
| 645 | }, | 661 | }, |
| 646 | .code = code.toManaged(gpa), | 662 | .code = code.toManaged(gpa), |
| 647 | .indent_writer = undefined, // set later so we can get a pointer to object.code | 663 | .indent_writer = undefined, // set later so we can get a pointer to object.code |
| ... | @@ -651,6 +667,7 @@ fn flushLazyFn( | ... | @@ -651,6 +667,7 @@ fn flushLazyFn( |
| 651 | // If this assert trips just handle the anon_decl_deps the same as | 667 | // If this assert trips just handle the anon_decl_deps the same as |
| 652 | // `updateFunc()` does. | 668 | // `updateFunc()` does. |
| 653 | assert(object.dg.anon_decl_deps.count() == 0); | 669 | assert(object.dg.anon_decl_deps.count() == 0); |
| 670 | assert(object.dg.aligned_anon_decls.count() == 0); | ||
| 654 | object.dg.ctypes.deinit(gpa); | 671 | object.dg.ctypes.deinit(gpa); |
| 655 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); | 672 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); |
| 656 | code.* = object.code.moveToUnmanaged(); | 673 | code.* = object.code.moveToUnmanaged(); |
src/value.zig+2-2| ... | @@ -1571,7 +1571,7 @@ pub const Value = struct { | ... | @@ -1571,7 +1571,7 @@ pub const Value = struct { |
| 1571 | .none => switch (ip.indexToKey(switch (ptr.addr) { | 1571 | .none => switch (ip.indexToKey(switch (ptr.addr) { |
| 1572 | .decl => |decl| mod.declPtr(decl).ty.toIntern(), | 1572 | .decl => |decl| mod.declPtr(decl).ty.toIntern(), |
| 1573 | .mut_decl => |mut_decl| mod.declPtr(mut_decl.decl).ty.toIntern(), | 1573 | .mut_decl => |mut_decl| mod.declPtr(mut_decl.decl).ty.toIntern(), |
| 1574 | .anon_decl => |anon_decl| ip.typeOf(anon_decl), | 1574 | .anon_decl => |anon_decl| ip.typeOf(anon_decl.val), |
| 1575 | .comptime_field => |comptime_field| ip.typeOf(comptime_field), | 1575 | .comptime_field => |comptime_field| ip.typeOf(comptime_field), |
| 1576 | else => unreachable, | 1576 | else => unreachable, |
| 1577 | })) { | 1577 | })) { |
| ... | @@ -1604,7 +1604,7 @@ pub const Value = struct { | ... | @@ -1604,7 +1604,7 @@ pub const Value = struct { |
| 1604 | })).toValue(), | 1604 | })).toValue(), |
| 1605 | .ptr => |ptr| switch (ptr.addr) { | 1605 | .ptr => |ptr| switch (ptr.addr) { |
| 1606 | .decl => |decl| mod.declPtr(decl).val.maybeElemValue(mod, index), | 1606 | .decl => |decl| mod.declPtr(decl).val.maybeElemValue(mod, index), |
| 1607 | .anon_decl => |anon_decl| anon_decl.toValue().maybeElemValue(mod, index), | 1607 | .anon_decl => |anon_decl| anon_decl.val.toValue().maybeElemValue(mod, index), |
| 1608 | .mut_decl => |mut_decl| (try mod.declPtr(mut_decl.decl).internValue(mod)) | 1608 | .mut_decl => |mut_decl| (try mod.declPtr(mut_decl.decl).internValue(mod)) |
| 1609 | .toValue().maybeElemValue(mod, index), | 1609 | .toValue().maybeElemValue(mod, index), |
| 1610 | .int, .eu_payload => null, | 1610 | .int, .eu_payload => null, |