| author | |
| committer | |
| log | 221fb30b3c961f81e99bfe9b25db8460e6231824 |
| tree | 5ac2c73284624453368d4e537b770b930b792b79 |
| parent | 53373c4c719ff6244d7099ad1ceeda18d40e09e3 |
12 files changed, 561 insertions(+), 222 deletions(-)
lib/std/zig/llvm/Builder.zig+300-136| ... | @@ -1284,7 +1284,7 @@ pub const Attribute = union(Kind) { | ... | @@ -1284,7 +1284,7 @@ pub const Attribute = union(Kind) { |
| 1284 | try w.print(" {t}(\"", .{attribute}); | 1284 | try w.print(" {t}(\"", .{attribute}); |
| 1285 | var any = false; | 1285 | var any = false; |
| 1286 | inline for (@typeInfo(AllocKind).@"struct".fields) |field| { | 1286 | inline for (@typeInfo(AllocKind).@"struct".fields) |field| { |
| 1287 | if (comptime std.mem.eql(u8, field.name, "_")) continue; | 1287 | if (comptime std.mem.eql(u8, field.name, "unused")) continue; |
| 1288 | if (@field(allockind, field.name)) { | 1288 | if (@field(allockind, field.name)) { |
| 1289 | if (!any) { | 1289 | if (!any) { |
| 1290 | try w.writeByte(','); | 1290 | try w.writeByte(','); |
| ... | @@ -1469,7 +1469,7 @@ pub const Attribute = union(Kind) { | ... | @@ -1469,7 +1469,7 @@ pub const Attribute = union(Kind) { |
| 1469 | positive_subnormal: bool = false, | 1469 | positive_subnormal: bool = false, |
| 1470 | positive_normal: bool = false, | 1470 | positive_normal: bool = false, |
| 1471 | positive_infinity: bool = false, | 1471 | positive_infinity: bool = false, |
| 1472 | _: u22 = 0, | 1472 | unused: enum(u22) { unused = 0 } = .unused, |
| 1473 | 1473 | ||
| 1474 | pub const all = FpClass{ | 1474 | pub const all = FpClass{ |
| 1475 | .signaling_nan = true, | 1475 | .signaling_nan = true, |
| ... | @@ -1512,7 +1512,7 @@ pub const Attribute = union(Kind) { | ... | @@ -1512,7 +1512,7 @@ pub const Attribute = union(Kind) { |
| 1512 | uninitialized: bool, | 1512 | uninitialized: bool, |
| 1513 | zeroed: bool, | 1513 | zeroed: bool, |
| 1514 | aligned: bool, | 1514 | aligned: bool, |
| 1515 | _: u26 = 0, | 1515 | unused: enum(u26) { unused = 0 } = .unused, |
| 1516 | }; | 1516 | }; |
| 1517 | 1517 | ||
| 1518 | pub const AllocSize = packed struct(u32) { | 1518 | pub const AllocSize = packed struct(u32) { |
| ... | @@ -1533,7 +1533,7 @@ pub const Attribute = union(Kind) { | ... | @@ -1533,7 +1533,7 @@ pub const Attribute = union(Kind) { |
| 1533 | argmem: Effect = .none, | 1533 | argmem: Effect = .none, |
| 1534 | inaccessiblemem: Effect = .none, | 1534 | inaccessiblemem: Effect = .none, |
| 1535 | other: Effect = .none, | 1535 | other: Effect = .none, |
| 1536 | _: u26 = 0, | 1536 | unused: enum(u26) { unused = 0 } = .unused, |
| 1537 | 1537 | ||
| 1538 | pub const Effect = enum(u2) { none, read, write, readwrite }; | 1538 | pub const Effect = enum(u2) { none, read, write, readwrite }; |
| 1539 | 1539 | ||
| ... | @@ -1553,7 +1553,7 @@ pub const Attribute = union(Kind) { | ... | @@ -1553,7 +1553,7 @@ pub const Attribute = union(Kind) { |
| 1553 | pub const VScaleRange = packed struct(u32) { | 1553 | pub const VScaleRange = packed struct(u32) { |
| 1554 | min: Alignment, | 1554 | min: Alignment, |
| 1555 | max: Alignment, | 1555 | max: Alignment, |
| 1556 | _: u20 = 0, | 1556 | unused: enum(u20) { unused = 0 } = .unused, |
| 1557 | 1557 | ||
| 1558 | fn toLlvm(self: VScaleRange) packed struct(u64) { max: u32, min: u32 } { | 1558 | fn toLlvm(self: VScaleRange) packed struct(u64) { max: u32, min: u32 } { |
| 1559 | return .{ | 1559 | return .{ |
| ... | @@ -1870,7 +1870,7 @@ pub const ThreadLocal = enum(u3) { | ... | @@ -1870,7 +1870,7 @@ pub const ThreadLocal = enum(u3) { |
| 1870 | 1870 | ||
| 1871 | pub fn format(p: Prefixed, w: *Writer) Writer.Error!void { | 1871 | pub fn format(p: Prefixed, w: *Writer) Writer.Error!void { |
| 1872 | switch (p.thread_local) { | 1872 | switch (p.thread_local) { |
| 1873 | .default => return, | 1873 | .default => {}, |
| 1874 | .generaldynamic => { | 1874 | .generaldynamic => { |
| 1875 | var vecs: [2][]const u8 = .{ p.prefix, "thread_local" }; | 1875 | var vecs: [2][]const u8 = .{ p.prefix, "thread_local" }; |
| 1876 | return w.writeVecAll(&vecs); | 1876 | return w.writeVecAll(&vecs); |
| ... | @@ -4221,7 +4221,6 @@ pub const Function = struct { | ... | @@ -4221,7 +4221,6 @@ pub const Function = struct { |
| 4221 | call, | 4221 | call, |
| 4222 | @"call fast", | 4222 | @"call fast", |
| 4223 | cmpxchg, | 4223 | cmpxchg, |
| 4224 | @"cmpxchg weak", | ||
| 4225 | extractelement, | 4224 | extractelement, |
| 4226 | extractvalue, | 4225 | extractvalue, |
| 4227 | fadd, | 4226 | fadd, |
| ... | @@ -4619,9 +4618,7 @@ pub const Function = struct { | ... | @@ -4619,9 +4618,7 @@ pub const Function = struct { |
| 4619 | .@"tail call", | 4618 | .@"tail call", |
| 4620 | .@"tail call fast", | 4619 | .@"tail call fast", |
| 4621 | => wip.extraData(Call, instruction.data).ty.functionReturn(wip.builder), | 4620 | => wip.extraData(Call, instruction.data).ty.functionReturn(wip.builder), |
| 4622 | .cmpxchg, | 4621 | .cmpxchg => wip.builder.structTypeAssumeCapacity(.normal, &.{ |
| 4623 | .@"cmpxchg weak", | ||
| 4624 | => wip.builder.structTypeAssumeCapacity(.normal, &.{ | ||
| 4625 | wip.extraData(CmpXchg, instruction.data).cmp.typeOfWip(wip), | 4622 | wip.extraData(CmpXchg, instruction.data).cmp.typeOfWip(wip), |
| 4626 | .i1, | 4623 | .i1, |
| 4627 | }), | 4624 | }), |
| ... | @@ -4806,9 +4803,7 @@ pub const Function = struct { | ... | @@ -4806,9 +4803,7 @@ pub const Function = struct { |
| 4806 | .@"tail call", | 4803 | .@"tail call", |
| 4807 | .@"tail call fast", | 4804 | .@"tail call fast", |
| 4808 | => function.extraData(Call, instruction.data).ty.functionReturn(builder), | 4805 | => function.extraData(Call, instruction.data).ty.functionReturn(builder), |
| 4809 | .cmpxchg, | 4806 | .cmpxchg => builder.structTypeAssumeCapacity(.normal, &.{ |
| 4810 | .@"cmpxchg weak", | ||
| 4811 | => builder.structTypeAssumeCapacity(.normal, &.{ | ||
| 4812 | function.extraData(CmpXchg, instruction.data) | 4807 | function.extraData(CmpXchg, instruction.data) |
| 4813 | .cmp.typeOf(function_index, builder), | 4808 | .cmp.typeOf(function_index, builder), |
| 4814 | .i1, | 4809 | .i1, |
| ... | @@ -5027,33 +5022,86 @@ pub const Function = struct { | ... | @@ -5027,33 +5022,86 @@ pub const Function = struct { |
| 5027 | pub const Info = packed struct(u32) { | 5022 | pub const Info = packed struct(u32) { |
| 5028 | alignment: Alignment, | 5023 | alignment: Alignment, |
| 5029 | addr_space: AddrSpace, | 5024 | addr_space: AddrSpace, |
| 5030 | _: u2 = undefined, | 5025 | unused: enum(u2) { unused = 0 } = .unused, |
| 5031 | }; | 5026 | }; |
| 5032 | }; | 5027 | }; |
| 5033 | 5028 | ||
| 5034 | pub const Load = struct { | 5029 | pub const Load = struct { |
| 5035 | info: MemoryAccessInfo, | 5030 | info: Info, |
| 5036 | type: Type, | 5031 | type: Type, |
| 5037 | ptr: Value, | 5032 | ptr: Value, |
| 5033 | //range: if (info.has_range) Metadata else void, | ||
| 5034 | |||
| 5035 | pub const Info = packed struct(u32) { | ||
| 5036 | access_kind: MemoryAccessKind, | ||
| 5037 | sync_scope: SyncScope, | ||
| 5038 | ordering: AtomicOrdering, | ||
| 5039 | alignment: Alignment, | ||
| 5040 | has_range: bool, | ||
| 5041 | unused: enum(u20) { unused = 0 } = .unused, | ||
| 5042 | }; | ||
| 5038 | }; | 5043 | }; |
| 5039 | 5044 | ||
| 5040 | pub const Store = struct { | 5045 | pub const Store = struct { |
| 5041 | info: MemoryAccessInfo, | 5046 | info: Info, |
| 5042 | val: Value, | 5047 | val: Value, |
| 5043 | ptr: Value, | 5048 | ptr: Value, |
| 5049 | |||
| 5050 | pub const Info = packed struct(u32) { | ||
| 5051 | access_kind: MemoryAccessKind, | ||
| 5052 | sync_scope: SyncScope, | ||
| 5053 | ordering: AtomicOrdering, | ||
| 5054 | alignment: Alignment, | ||
| 5055 | unused: enum(u21) { unused = 0 } = .unused, | ||
| 5056 | }; | ||
| 5044 | }; | 5057 | }; |
| 5045 | 5058 | ||
| 5046 | pub const CmpXchg = struct { | 5059 | pub const CmpXchg = struct { |
| 5047 | info: MemoryAccessInfo, | 5060 | info: Info, |
| 5048 | ptr: Value, | 5061 | ptr: Value, |
| 5049 | cmp: Value, | 5062 | cmp: Value, |
| 5050 | new: Value, | 5063 | new: Value, |
| 5051 | 5064 | ||
| 5052 | pub const Kind = enum { strong, weak }; | 5065 | pub const Kind = enum(u1) { |
| 5066 | strong, | ||
| 5067 | weak, | ||
| 5068 | |||
| 5069 | pub fn format(kind: Kind, w: *Writer) Writer.Error!void { | ||
| 5070 | return Prefixed.format(.{ .kind = kind, .prefix = "" }, w); | ||
| 5071 | } | ||
| 5072 | |||
| 5073 | pub const Prefixed = struct { | ||
| 5074 | kind: Kind, | ||
| 5075 | prefix: []const u8, | ||
| 5076 | |||
| 5077 | pub fn format(p: Prefixed, w: *Writer) Writer.Error!void { | ||
| 5078 | switch (p.kind) { | ||
| 5079 | .strong => {}, | ||
| 5080 | .weak => { | ||
| 5081 | var vecs: [2][]const u8 = .{ p.prefix, "weak" }; | ||
| 5082 | try w.writeVecAll(&vecs); | ||
| 5083 | }, | ||
| 5084 | } | ||
| 5085 | } | ||
| 5086 | }; | ||
| 5087 | |||
| 5088 | pub fn fmt(kind: Kind, prefix: []const u8) Prefixed { | ||
| 5089 | return .{ .kind = kind, .prefix = prefix }; | ||
| 5090 | } | ||
| 5091 | }; | ||
| 5092 | pub const Info = packed struct(u32) { | ||
| 5093 | kind: Kind, | ||
| 5094 | access_kind: MemoryAccessKind, | ||
| 5095 | sync_scope: SyncScope, | ||
| 5096 | success_ordering: AtomicOrdering, | ||
| 5097 | failure_ordering: AtomicOrdering, | ||
| 5098 | alignment: Alignment, | ||
| 5099 | unused: enum(u17) { unused = 0 } = .unused, | ||
| 5100 | }; | ||
| 5053 | }; | 5101 | }; |
| 5054 | 5102 | ||
| 5055 | pub const AtomicRmw = struct { | 5103 | pub const AtomicRmw = struct { |
| 5056 | info: MemoryAccessInfo, | 5104 | info: Info, |
| 5057 | ptr: Value, | 5105 | ptr: Value, |
| 5058 | val: Value, | 5106 | val: Value, |
| 5059 | 5107 | ||
| ... | @@ -5073,8 +5121,21 @@ pub const Function = struct { | ... | @@ -5073,8 +5121,21 @@ pub const Function = struct { |
| 5073 | fsub = 12, | 5121 | fsub = 12, |
| 5074 | fmax = 13, | 5122 | fmax = 13, |
| 5075 | fmin = 14, | 5123 | fmin = 14, |
| 5076 | none = maxInt(u5), | ||
| 5077 | }; | 5124 | }; |
| 5125 | pub const Info = packed struct(u32) { | ||
| 5126 | access_kind: MemoryAccessKind, | ||
| 5127 | operation: Operation, | ||
| 5128 | sync_scope: SyncScope, | ||
| 5129 | ordering: AtomicOrdering, | ||
| 5130 | alignment: Alignment, | ||
| 5131 | unused: enum(u16) { unused = 0 } = .unused, | ||
| 5132 | }; | ||
| 5133 | }; | ||
| 5134 | |||
| 5135 | pub const Fence = packed struct(u32) { | ||
| 5136 | sync_scope: SyncScope, | ||
| 5137 | success_ordering: AtomicOrdering, | ||
| 5138 | unused: enum(u28) { unused = 0 } = .unused, | ||
| 5078 | }; | 5139 | }; |
| 5079 | 5140 | ||
| 5080 | pub const GetElementPtr = struct { | 5141 | pub const GetElementPtr = struct { |
| ... | @@ -5112,6 +5173,7 @@ pub const Function = struct { | ... | @@ -5112,6 +5173,7 @@ pub const Function = struct { |
| 5112 | callee: Value, | 5173 | callee: Value, |
| 5113 | args_len: u32, | 5174 | args_len: u32, |
| 5114 | //args: [args_len]Value, | 5175 | //args: [args_len]Value, |
| 5176 | //callees: if (info.has_callees) Metadata else void, | ||
| 5115 | 5177 | ||
| 5116 | pub const Kind = enum { | 5178 | pub const Kind = enum { |
| 5117 | normal, | 5179 | normal, |
| ... | @@ -5125,8 +5187,9 @@ pub const Function = struct { | ... | @@ -5125,8 +5187,9 @@ pub const Function = struct { |
| 5125 | }; | 5187 | }; |
| 5126 | pub const Info = packed struct(u32) { | 5188 | pub const Info = packed struct(u32) { |
| 5127 | call_conv: CallConv, | 5189 | call_conv: CallConv, |
| 5190 | has_callees: bool, | ||
| 5128 | has_op_bundle_cold: bool, | 5191 | has_op_bundle_cold: bool, |
| 5129 | _: u21 = undefined, | 5192 | unused: enum(u20) { unused = 0 } = .unused, |
| 5130 | }; | 5193 | }; |
| 5131 | }; | 5194 | }; |
| 5132 | 5195 | ||
| ... | @@ -5195,8 +5258,11 @@ pub const Function = struct { | ... | @@ -5195,8 +5258,11 @@ pub const Function = struct { |
| 5195 | Value, | 5258 | Value, |
| 5196 | Instruction.BrCond.Weights, | 5259 | Instruction.BrCond.Weights, |
| 5197 | => @enumFromInt(value), | 5260 | => @enumFromInt(value), |
| 5198 | MemoryAccessInfo, | ||
| 5199 | Instruction.Alloca.Info, | 5261 | Instruction.Alloca.Info, |
| 5262 | Instruction.Load.Info, | ||
| 5263 | Instruction.Store.Info, | ||
| 5264 | Instruction.CmpXchg.Info, | ||
| 5265 | Instruction.AtomicRmw.Info, | ||
| 5200 | Instruction.Call.Info, | 5266 | Instruction.Call.Info, |
| 5201 | => @bitCast(value), | 5267 | => @bitCast(value), |
| 5202 | else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)), | 5268 | else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)), |
| ... | @@ -5706,6 +5772,10 @@ pub const WipFunction = struct { | ... | @@ -5706,6 +5772,10 @@ pub const WipFunction = struct { |
| 5706 | return instruction.toValue(); | 5772 | return instruction.toValue(); |
| 5707 | } | 5773 | } |
| 5708 | 5774 | ||
| 5775 | pub const LoadMetadata = struct { | ||
| 5776 | range: Metadata.Optional = .none, | ||
| 5777 | }; | ||
| 5778 | |||
| 5709 | pub fn load( | 5779 | pub fn load( |
| 5710 | self: *WipFunction, | 5780 | self: *WipFunction, |
| 5711 | access_kind: MemoryAccessKind, | 5781 | access_kind: MemoryAccessKind, |
| ... | @@ -5714,7 +5784,19 @@ pub const WipFunction = struct { | ... | @@ -5714,7 +5784,19 @@ pub const WipFunction = struct { |
| 5714 | alignment: Alignment, | 5784 | alignment: Alignment, |
| 5715 | name: []const u8, | 5785 | name: []const u8, |
| 5716 | ) Allocator.Error!Value { | 5786 | ) Allocator.Error!Value { |
| 5717 | return self.loadAtomic(access_kind, ty, ptr, .system, .none, alignment, name); | 5787 | return self.loadMetadata(access_kind, ty, ptr, alignment, .{}, name); |
| 5788 | } | ||
| 5789 | |||
| 5790 | pub fn loadMetadata( | ||
| 5791 | self: *WipFunction, | ||
| 5792 | access_kind: MemoryAccessKind, | ||
| 5793 | ty: Type, | ||
| 5794 | ptr: Value, | ||
| 5795 | alignment: Alignment, | ||
| 5796 | metadata: LoadMetadata, | ||
| 5797 | name: []const u8, | ||
| 5798 | ) Allocator.Error!Value { | ||
| 5799 | return self.loadAtomicMetadata(access_kind, ty, ptr, .system, .none, alignment, metadata, name); | ||
| 5718 | } | 5800 | } |
| 5719 | 5801 | ||
| 5720 | pub fn loadAtomic( | 5802 | pub fn loadAtomic( |
| ... | @@ -5726,6 +5808,20 @@ pub const WipFunction = struct { | ... | @@ -5726,6 +5808,20 @@ pub const WipFunction = struct { |
| 5726 | ordering: AtomicOrdering, | 5808 | ordering: AtomicOrdering, |
| 5727 | alignment: Alignment, | 5809 | alignment: Alignment, |
| 5728 | name: []const u8, | 5810 | name: []const u8, |
| 5811 | ) Allocator.Error!Value { | ||
| 5812 | return self.loadAtomicMetadata(access_kind, ty, ptr, sync_scope, ordering, alignment, .{}, name); | ||
| 5813 | } | ||
| 5814 | |||
| 5815 | pub fn loadAtomicMetadata( | ||
| 5816 | self: *WipFunction, | ||
| 5817 | access_kind: MemoryAccessKind, | ||
| 5818 | ty: Type, | ||
| 5819 | ptr: Value, | ||
| 5820 | sync_scope: SyncScope, | ||
| 5821 | ordering: AtomicOrdering, | ||
| 5822 | alignment: Alignment, | ||
| 5823 | metadata: LoadMetadata, | ||
| 5824 | name: []const u8, | ||
| 5729 | ) Allocator.Error!Value { | 5825 | ) Allocator.Error!Value { |
| 5730 | assert(ptr.typeOfWip(self).isPointer(self.builder)); | 5826 | assert(ptr.typeOfWip(self).isPointer(self.builder)); |
| 5731 | try self.ensureUnusedExtraCapacity(1, Instruction.Load, 0); | 5827 | try self.ensureUnusedExtraCapacity(1, Instruction.Load, 0); |
| ... | @@ -5741,13 +5837,15 @@ pub const WipFunction = struct { | ... | @@ -5741,13 +5837,15 @@ pub const WipFunction = struct { |
| 5741 | .none => .system, | 5837 | .none => .system, |
| 5742 | else => sync_scope, | 5838 | else => sync_scope, |
| 5743 | }, | 5839 | }, |
| 5744 | .success_ordering = ordering, | 5840 | .ordering = ordering, |
| 5745 | .alignment = alignment, | 5841 | .alignment = alignment, |
| 5842 | .has_range = !metadata.range.is_none, | ||
| 5746 | }, | 5843 | }, |
| 5747 | .type = ty, | 5844 | .type = ty, |
| 5748 | .ptr = ptr, | 5845 | .ptr = ptr, |
| 5749 | }), | 5846 | }), |
| 5750 | }); | 5847 | }); |
| 5848 | if (metadata.range.unwrap()) |range| self.extra.appendAssumeCapacity(@bitCast(range)); | ||
| 5751 | return instruction.toValue(); | 5849 | return instruction.toValue(); |
| 5752 | } | 5850 | } |
| 5753 | 5851 | ||
| ... | @@ -5784,7 +5882,7 @@ pub const WipFunction = struct { | ... | @@ -5784,7 +5882,7 @@ pub const WipFunction = struct { |
| 5784 | .none => .system, | 5882 | .none => .system, |
| 5785 | else => sync_scope, | 5883 | else => sync_scope, |
| 5786 | }, | 5884 | }, |
| 5787 | .success_ordering = ordering, | 5885 | .ordering = ordering, |
| 5788 | .alignment = alignment, | 5886 | .alignment = alignment, |
| 5789 | }, | 5887 | }, |
| 5790 | .val = val, | 5888 | .val = val, |
| ... | @@ -5803,7 +5901,7 @@ pub const WipFunction = struct { | ... | @@ -5803,7 +5901,7 @@ pub const WipFunction = struct { |
| 5803 | try self.ensureUnusedExtraCapacity(1, NoExtra, 0); | 5901 | try self.ensureUnusedExtraCapacity(1, NoExtra, 0); |
| 5804 | const instruction = try self.addInst(null, .{ | 5902 | const instruction = try self.addInst(null, .{ |
| 5805 | .tag = .fence, | 5903 | .tag = .fence, |
| 5806 | .data = @bitCast(MemoryAccessInfo{ | 5904 | .data = @bitCast(Instruction.Fence{ |
| 5807 | .sync_scope = sync_scope, | 5905 | .sync_scope = sync_scope, |
| 5808 | .success_ordering = ordering, | 5906 | .success_ordering = ordering, |
| 5809 | }), | 5907 | }), |
| ... | @@ -5833,12 +5931,10 @@ pub const WipFunction = struct { | ... | @@ -5833,12 +5931,10 @@ pub const WipFunction = struct { |
| 5833 | _ = try self.builder.structType(.normal, &.{ ty, .i1 }); | 5931 | _ = try self.builder.structType(.normal, &.{ ty, .i1 }); |
| 5834 | try self.ensureUnusedExtraCapacity(1, Instruction.CmpXchg, 0); | 5932 | try self.ensureUnusedExtraCapacity(1, Instruction.CmpXchg, 0); |
| 5835 | const instruction = try self.addInst(name, .{ | 5933 | const instruction = try self.addInst(name, .{ |
| 5836 | .tag = switch (kind) { | 5934 | .tag = .cmpxchg, |
| 5837 | .strong => .cmpxchg, | ||
| 5838 | .weak => .@"cmpxchg weak", | ||
| 5839 | }, | ||
| 5840 | .data = self.addExtraAssumeCapacity(Instruction.CmpXchg{ | 5935 | .data = self.addExtraAssumeCapacity(Instruction.CmpXchg{ |
| 5841 | .info = .{ | 5936 | .info = .{ |
| 5937 | .kind = kind, | ||
| 5842 | .access_kind = access_kind, | 5938 | .access_kind = access_kind, |
| 5843 | .sync_scope = sync_scope, | 5939 | .sync_scope = sync_scope, |
| 5844 | .success_ordering = success_ordering, | 5940 | .success_ordering = success_ordering, |
| ... | @@ -5873,9 +5969,9 @@ pub const WipFunction = struct { | ... | @@ -5873,9 +5969,9 @@ pub const WipFunction = struct { |
| 5873 | .data = self.addExtraAssumeCapacity(Instruction.AtomicRmw{ | 5969 | .data = self.addExtraAssumeCapacity(Instruction.AtomicRmw{ |
| 5874 | .info = .{ | 5970 | .info = .{ |
| 5875 | .access_kind = access_kind, | 5971 | .access_kind = access_kind, |
| 5876 | .atomic_rmw_operation = operation, | 5972 | .operation = operation, |
| 5877 | .sync_scope = sync_scope, | 5973 | .sync_scope = sync_scope, |
| 5878 | .success_ordering = ordering, | 5974 | .ordering = ordering, |
| 5879 | .alignment = alignment, | 5975 | .alignment = alignment, |
| 5880 | }, | 5976 | }, |
| 5881 | .ptr = ptr, | 5977 | .ptr = ptr, |
| ... | @@ -6079,6 +6175,11 @@ pub const WipFunction = struct { | ... | @@ -6079,6 +6175,11 @@ pub const WipFunction = struct { |
| 6079 | }, cond, lhs, rhs, name); | 6175 | }, cond, lhs, rhs, name); |
| 6080 | } | 6176 | } |
| 6081 | 6177 | ||
| 6178 | pub const CallMetadata = struct { | ||
| 6179 | callees: Metadata.Optional = .none, | ||
| 6180 | has_op_bundle_cold: bool = false, | ||
| 6181 | }; | ||
| 6182 | |||
| 6082 | pub fn call( | 6183 | pub fn call( |
| 6083 | self: *WipFunction, | 6184 | self: *WipFunction, |
| 6084 | kind: Instruction.Call.Kind, | 6185 | kind: Instruction.Call.Kind, |
| ... | @@ -6089,10 +6190,10 @@ pub const WipFunction = struct { | ... | @@ -6089,10 +6190,10 @@ pub const WipFunction = struct { |
| 6089 | args: []const Value, | 6190 | args: []const Value, |
| 6090 | name: []const u8, | 6191 | name: []const u8, |
| 6091 | ) Allocator.Error!Value { | 6192 | ) Allocator.Error!Value { |
| 6092 | return self.callInner(kind, call_conv, function_attributes, ty, callee, args, name, false); | 6193 | return self.callMetadata(kind, call_conv, function_attributes, ty, callee, args, .{}, name); |
| 6093 | } | 6194 | } |
| 6094 | 6195 | ||
| 6095 | fn callInner( | 6196 | pub fn callMetadata( |
| 6096 | self: *WipFunction, | 6197 | self: *WipFunction, |
| 6097 | kind: Instruction.Call.Kind, | 6198 | kind: Instruction.Call.Kind, |
| 6098 | call_conv: CallConv, | 6199 | call_conv: CallConv, |
| ... | @@ -6100,8 +6201,8 @@ pub const WipFunction = struct { | ... | @@ -6100,8 +6201,8 @@ pub const WipFunction = struct { |
| 6100 | ty: Type, | 6201 | ty: Type, |
| 6101 | callee: Value, | 6202 | callee: Value, |
| 6102 | args: []const Value, | 6203 | args: []const Value, |
| 6204 | metadata: CallMetadata, | ||
| 6103 | name: []const u8, | 6205 | name: []const u8, |
| 6104 | has_op_bundle_cold: bool, | ||
| 6105 | ) Allocator.Error!Value { | 6206 | ) Allocator.Error!Value { |
| 6106 | const ret_ty = ty.functionReturn(self.builder); | 6207 | const ret_ty = ty.functionReturn(self.builder); |
| 6107 | assert(ty.isFunction(self.builder)); | 6208 | assert(ty.isFunction(self.builder)); |
| ... | @@ -6109,7 +6210,8 @@ pub const WipFunction = struct { | ... | @@ -6109,7 +6210,8 @@ pub const WipFunction = struct { |
| 6109 | const params = ty.functionParameters(self.builder); | 6210 | const params = ty.functionParameters(self.builder); |
| 6110 | for (params, args[0..params.len]) |param, arg_val| assert(param == arg_val.typeOfWip(self)); | 6211 | for (params, args[0..params.len]) |param, arg_val| assert(param == arg_val.typeOfWip(self)); |
| 6111 | 6212 | ||
| 6112 | try self.ensureUnusedExtraCapacity(1, Instruction.Call, args.len); | 6213 | try self.ensureUnusedExtraCapacity(1, Instruction.Call, args.len + |
| 6214 | @intFromBool(!metadata.callees.is_none)); | ||
| 6113 | const instruction = try self.addInst(switch (ret_ty) { | 6215 | const instruction = try self.addInst(switch (ret_ty) { |
| 6114 | .void => null, | 6216 | .void => null, |
| 6115 | else => name, | 6217 | else => name, |
| ... | @@ -6127,7 +6229,8 @@ pub const WipFunction = struct { | ... | @@ -6127,7 +6229,8 @@ pub const WipFunction = struct { |
| 6127 | .data = self.addExtraAssumeCapacity(Instruction.Call{ | 6229 | .data = self.addExtraAssumeCapacity(Instruction.Call{ |
| 6128 | .info = .{ | 6230 | .info = .{ |
| 6129 | .call_conv = call_conv, | 6231 | .call_conv = call_conv, |
| 6130 | .has_op_bundle_cold = has_op_bundle_cold, | 6232 | .has_callees = !metadata.callees.is_none, |
| 6233 | .has_op_bundle_cold = metadata.has_op_bundle_cold, | ||
| 6131 | }, | 6234 | }, |
| 6132 | .attributes = function_attributes, | 6235 | .attributes = function_attributes, |
| 6133 | .ty = ty, | 6236 | .ty = ty, |
| ... | @@ -6136,6 +6239,7 @@ pub const WipFunction = struct { | ... | @@ -6136,6 +6239,7 @@ pub const WipFunction = struct { |
| 6136 | }), | 6239 | }), |
| 6137 | }); | 6240 | }); |
| 6138 | self.extra.appendSliceAssumeCapacity(@ptrCast(args)); | 6241 | self.extra.appendSliceAssumeCapacity(@ptrCast(args)); |
| 6242 | if (metadata.callees.unwrap()) |callees| self.extra.appendAssumeCapacity(@bitCast(callees)); | ||
| 6139 | return instruction.toValue(); | 6243 | return instruction.toValue(); |
| 6140 | } | 6244 | } |
| 6141 | 6245 | ||
| ... | @@ -6176,15 +6280,15 @@ pub const WipFunction = struct { | ... | @@ -6176,15 +6280,15 @@ pub const WipFunction = struct { |
| 6176 | 6280 | ||
| 6177 | pub fn callIntrinsicAssumeCold(self: *WipFunction) Allocator.Error!Value { | 6281 | pub fn callIntrinsicAssumeCold(self: *WipFunction) Allocator.Error!Value { |
| 6178 | const intrinsic = try self.builder.getIntrinsic(.assume, &.{}); | 6282 | const intrinsic = try self.builder.getIntrinsic(.assume, &.{}); |
| 6179 | return self.callInner( | 6283 | return self.callMetadata( |
| 6180 | .normal, | 6284 | .normal, |
| 6181 | CallConv.default, | 6285 | CallConv.default, |
| 6182 | .none, | 6286 | .none, |
| 6183 | intrinsic.typeOf(self.builder), | 6287 | intrinsic.typeOf(self.builder), |
| 6184 | intrinsic.toValue(self.builder), | 6288 | intrinsic.toValue(self.builder), |
| 6185 | &.{try self.builder.intValue(.i1, 1)}, | 6289 | &.{try self.builder.intValue(.i1, 1)}, |
| 6186 | "", | 6290 | .{ .has_op_bundle_cold = true }, |
| 6187 | true, | 6291 | undefined, |
| 6188 | ); | 6292 | ); |
| 6189 | } | 6293 | } |
| 6190 | 6294 | ||
| ... | @@ -6355,8 +6459,11 @@ pub const WipFunction = struct { | ... | @@ -6355,8 +6459,11 @@ pub const WipFunction = struct { |
| 6355 | Value, | 6459 | Value, |
| 6356 | Instruction.BrCond.Weights, | 6460 | Instruction.BrCond.Weights, |
| 6357 | => @intFromEnum(value), | 6461 | => @intFromEnum(value), |
| 6358 | MemoryAccessInfo, | ||
| 6359 | Instruction.Alloca.Info, | 6462 | Instruction.Alloca.Info, |
| 6463 | Instruction.Load.Info, | ||
| 6464 | Instruction.Store.Info, | ||
| 6465 | Instruction.CmpXchg.Info, | ||
| 6466 | Instruction.AtomicRmw.Info, | ||
| 6360 | Instruction.Call.Info, | 6467 | Instruction.Call.Info, |
| 6361 | => @bitCast(value), | 6468 | => @bitCast(value), |
| 6362 | else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)), | 6469 | else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)), |
| ... | @@ -6648,6 +6755,7 @@ pub const WipFunction = struct { | ... | @@ -6648,6 +6755,7 @@ pub const WipFunction = struct { |
| 6648 | => { | 6755 | => { |
| 6649 | var extra = self.extraDataTrail(Instruction.Call, instruction.data); | 6756 | var extra = self.extraDataTrail(Instruction.Call, instruction.data); |
| 6650 | const args = extra.trail.next(extra.data.args_len, Value, self); | 6757 | const args = extra.trail.next(extra.data.args_len, Value, self); |
| 6758 | const callees = extra.trail.next(@intFromBool(extra.data.info.has_callees), Metadata, self); | ||
| 6651 | instruction.data = wip_extra.addExtra(Instruction.Call{ | 6759 | instruction.data = wip_extra.addExtra(Instruction.Call{ |
| 6652 | .info = extra.data.info, | 6760 | .info = extra.data.info, |
| 6653 | .attributes = extra.data.attributes, | 6761 | .attributes = extra.data.attributes, |
| ... | @@ -6656,10 +6764,9 @@ pub const WipFunction = struct { | ... | @@ -6656,10 +6764,9 @@ pub const WipFunction = struct { |
| 6656 | .args_len = extra.data.args_len, | 6764 | .args_len = extra.data.args_len, |
| 6657 | }); | 6765 | }); |
| 6658 | wip_extra.appendMappedValues(args, instructions); | 6766 | wip_extra.appendMappedValues(args, instructions); |
| 6767 | wip_extra.appendSlice(callees); | ||
| 6659 | }, | 6768 | }, |
| 6660 | .cmpxchg, | 6769 | .cmpxchg => { |
| 6661 | .@"cmpxchg weak", | ||
| 6662 | => { | ||
| 6663 | const extra = self.extraData(Instruction.CmpXchg, instruction.data); | 6770 | const extra = self.extraData(Instruction.CmpXchg, instruction.data); |
| 6664 | instruction.data = wip_extra.addExtra(Instruction.CmpXchg{ | 6771 | instruction.data = wip_extra.addExtra(Instruction.CmpXchg{ |
| 6665 | .info = extra.info, | 6772 | .info = extra.info, |
| ... | @@ -6730,12 +6837,14 @@ pub const WipFunction = struct { | ... | @@ -6730,12 +6837,14 @@ pub const WipFunction = struct { |
| 6730 | .load, | 6837 | .load, |
| 6731 | .@"load atomic", | 6838 | .@"load atomic", |
| 6732 | => { | 6839 | => { |
| 6733 | const extra = self.extraData(Instruction.Load, instruction.data); | 6840 | var extra = self.extraDataTrail(Instruction.Load, instruction.data); |
| 6841 | const range = extra.trail.next(@intFromBool(extra.data.info.has_range), Metadata, self); | ||
| 6734 | instruction.data = wip_extra.addExtra(Instruction.Load{ | 6842 | instruction.data = wip_extra.addExtra(Instruction.Load{ |
| 6735 | .type = extra.type, | 6843 | .type = extra.data.type, |
| 6736 | .ptr = instructions.map(extra.ptr), | 6844 | .ptr = instructions.map(extra.data.ptr), |
| 6737 | .info = extra.info, | 6845 | .info = extra.data.info, |
| 6738 | }); | 6846 | }); |
| 6847 | wip_extra.appendSlice(range); | ||
| 6739 | }, | 6848 | }, |
| 6740 | .phi, | 6849 | .phi, |
| 6741 | .@"phi fast", | 6850 | .@"phi fast", |
| ... | @@ -7011,8 +7120,11 @@ pub const WipFunction = struct { | ... | @@ -7011,8 +7120,11 @@ pub const WipFunction = struct { |
| 7011 | Value, | 7120 | Value, |
| 7012 | Instruction.BrCond.Weights, | 7121 | Instruction.BrCond.Weights, |
| 7013 | => @intFromEnum(value), | 7122 | => @intFromEnum(value), |
| 7014 | MemoryAccessInfo, | ||
| 7015 | Instruction.Alloca.Info, | 7123 | Instruction.Alloca.Info, |
| 7124 | Instruction.Load.Info, | ||
| 7125 | Instruction.Store.Info, | ||
| 7126 | Instruction.CmpXchg.Info, | ||
| 7127 | Instruction.AtomicRmw.Info, | ||
| 7016 | Instruction.Call.Info, | 7128 | Instruction.Call.Info, |
| 7017 | => @bitCast(value), | 7129 | => @bitCast(value), |
| 7018 | else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)), | 7130 | else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)), |
| ... | @@ -7060,8 +7172,11 @@ pub const WipFunction = struct { | ... | @@ -7060,8 +7172,11 @@ pub const WipFunction = struct { |
| 7060 | Value, | 7172 | Value, |
| 7061 | Instruction.BrCond.Weights, | 7173 | Instruction.BrCond.Weights, |
| 7062 | => @enumFromInt(value), | 7174 | => @enumFromInt(value), |
| 7063 | MemoryAccessInfo, | ||
| 7064 | Instruction.Alloca.Info, | 7175 | Instruction.Alloca.Info, |
| 7176 | Instruction.Load.Info, | ||
| 7177 | Instruction.Store.Info, | ||
| 7178 | Instruction.CmpXchg.Info, | ||
| 7179 | Instruction.AtomicRmw.Info, | ||
| 7065 | Instruction.Call.Info, | 7180 | Instruction.Call.Info, |
| 7066 | => @bitCast(value), | 7181 | => @bitCast(value), |
| 7067 | else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)), | 7182 | else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)), |
| ... | @@ -7121,10 +7236,10 @@ pub const MemoryAccessKind = enum(u1) { | ... | @@ -7121,10 +7236,10 @@ pub const MemoryAccessKind = enum(u1) { |
| 7121 | 7236 | ||
| 7122 | pub fn format(p: Prefixed, w: *Writer) Writer.Error!void { | 7237 | pub fn format(p: Prefixed, w: *Writer) Writer.Error!void { |
| 7123 | switch (p.memory_access_kind) { | 7238 | switch (p.memory_access_kind) { |
| 7124 | .normal => return, | 7239 | .normal => {}, |
| 7125 | .@"volatile" => { | 7240 | .@"volatile" => { |
| 7126 | var vecs: [2][]const u8 = .{ p.prefix, "volatile" }; | 7241 | var vecs: [2][]const u8 = .{ p.prefix, "volatile" }; |
| 7127 | return w.writeVecAll(&vecs); | 7242 | try w.writeVecAll(&vecs); |
| 7128 | }, | 7243 | }, |
| 7129 | } | 7244 | } |
| 7130 | } | 7245 | } |
| ... | @@ -7149,10 +7264,10 @@ pub const SyncScope = enum(u1) { | ... | @@ -7149,10 +7264,10 @@ pub const SyncScope = enum(u1) { |
| 7149 | 7264 | ||
| 7150 | pub fn format(p: Prefixed, w: *Writer) Writer.Error!void { | 7265 | pub fn format(p: Prefixed, w: *Writer) Writer.Error!void { |
| 7151 | switch (p.sync_scope) { | 7266 | switch (p.sync_scope) { |
| 7152 | .system => return, | 7267 | .system => {}, |
| 7153 | .singlethread => { | 7268 | .singlethread => { |
| 7154 | var vecs: [2][]const u8 = .{ p.prefix, "syncscope(\"singlethread\")" }; | 7269 | var vecs: [2][]const u8 = .{ p.prefix, "syncscope(\"singlethread\")" }; |
| 7155 | return w.writeVecAll(&vecs); | 7270 | try w.writeVecAll(&vecs); |
| 7156 | }, | 7271 | }, |
| 7157 | } | 7272 | } |
| 7158 | } | 7273 | } |
| ... | @@ -7182,10 +7297,10 @@ pub const AtomicOrdering = enum(u3) { | ... | @@ -7182,10 +7297,10 @@ pub const AtomicOrdering = enum(u3) { |
| 7182 | 7297 | ||
| 7183 | pub fn format(p: Prefixed, w: *Writer) Writer.Error!void { | 7298 | pub fn format(p: Prefixed, w: *Writer) Writer.Error!void { |
| 7184 | switch (p.atomic_ordering) { | 7299 | switch (p.atomic_ordering) { |
| 7185 | .none => return, | 7300 | .none => {}, |
| 7186 | else => { | 7301 | else => { |
| 7187 | var vecs: [2][]const u8 = .{ p.prefix, @tagName(p.atomic_ordering) }; | 7302 | var vecs: [2][]const u8 = .{ p.prefix, @tagName(p.atomic_ordering) }; |
| 7188 | return w.writeVecAll(&vecs); | 7303 | try w.writeVecAll(&vecs); |
| 7189 | }, | 7304 | }, |
| 7190 | } | 7305 | } |
| 7191 | } | 7306 | } |
| ... | @@ -7196,16 +7311,6 @@ pub const AtomicOrdering = enum(u3) { | ... | @@ -7196,16 +7311,6 @@ pub const AtomicOrdering = enum(u3) { |
| 7196 | } | 7311 | } |
| 7197 | }; | 7312 | }; |
| 7198 | 7313 | ||
| 7199 | const MemoryAccessInfo = packed struct(u32) { | ||
| 7200 | access_kind: MemoryAccessKind = .normal, | ||
| 7201 | atomic_rmw_operation: Function.Instruction.AtomicRmw.Operation = .none, | ||
| 7202 | sync_scope: SyncScope, | ||
| 7203 | success_ordering: AtomicOrdering, | ||
| 7204 | failure_ordering: AtomicOrdering = .none, | ||
| 7205 | alignment: Alignment = .default, | ||
| 7206 | _: u13 = undefined, | ||
| 7207 | }; | ||
| 7208 | |||
| 7209 | pub const FastMath = packed struct(u8) { | 7314 | pub const FastMath = packed struct(u8) { |
| 7210 | unsafe_algebra: bool = false, // Legacy | 7315 | unsafe_algebra: bool = false, // Legacy |
| 7211 | nnan: bool = false, | 7316 | nnan: bool = false, |
| ... | @@ -7533,7 +7638,7 @@ pub const Constant = enum(u32) { | ... | @@ -7533,7 +7638,7 @@ pub const Constant = enum(u32) { |
| 7533 | const item = builder.constant_items.get(constant); | 7638 | const item = builder.constant_items.get(constant); |
| 7534 | return switch (item.tag) { | 7639 | return switch (item.tag) { |
| 7535 | .positive_integer => { | 7640 | .positive_integer => { |
| 7536 | const extra: *align(@alignOf(std.math.big.Limb)) Integer = | 7641 | const extra: *align(@alignOf(std.math.big.Limb)) const Integer = |
| 7537 | @ptrCast(builder.constant_limbs.items[item.data..][0..Integer.limbs]); | 7642 | @ptrCast(builder.constant_limbs.items[item.data..][0..Integer.limbs]); |
| 7538 | const limbs = builder.constant_limbs | 7643 | const limbs = builder.constant_limbs |
| 7539 | .items[item.data + Integer.limbs ..][0..extra.limbs_len]; | 7644 | .items[item.data + Integer.limbs ..][0..extra.limbs_len]; |
| ... | @@ -7568,6 +7673,21 @@ pub const Constant = enum(u32) { | ... | @@ -7568,6 +7673,21 @@ pub const Constant = enum(u32) { |
| 7568 | } | 7673 | } |
| 7569 | } | 7674 | } |
| 7570 | 7675 | ||
| 7676 | pub fn toInt(self: Constant, builder: *const Builder) ?std.math.big.int.Const { | ||
| 7677 | const item = builder.constant_items.get(self.unwrap().constant); | ||
| 7678 | switch (item.tag) { | ||
| 7679 | .positive_integer, .negative_integer => { | ||
| 7680 | const extra: *align(@alignOf(std.math.big.Limb)) const Integer = | ||
| 7681 | @ptrCast(builder.constant_limbs.items[item.data..][0..Integer.limbs]); | ||
| 7682 | return .{ | ||
| 7683 | .positive = item.tag == .positive_integer, | ||
| 7684 | .limbs = builder.constant_limbs.items[item.data + Integer.limbs ..][0..extra.limbs_len], | ||
| 7685 | }; | ||
| 7686 | }, | ||
| 7687 | else => return null, | ||
| 7688 | } | ||
| 7689 | } | ||
| 7690 | |||
| 7571 | pub fn getBase(self: Constant, builder: *const Builder) Global.Index { | 7691 | pub fn getBase(self: Constant, builder: *const Builder) Global.Index { |
| 7572 | var cur = self; | 7692 | var cur = self; |
| 7573 | while (true) switch (cur.unwrap()) { | 7693 | while (true) switch (cur.unwrap()) { |
| ... | @@ -8183,7 +8303,7 @@ pub const Metadata = packed struct(u32) { | ... | @@ -8183,7 +8303,7 @@ pub const Metadata = packed struct(u32) { |
| 8183 | }; | 8303 | }; |
| 8184 | 8304 | ||
| 8185 | pub const DIFlags = packed struct(u32) { | 8305 | pub const DIFlags = packed struct(u32) { |
| 8186 | Visibility: enum(u2) { Zero, Private, Protected, Public } = .Zero, | 8306 | Visibility: enum(u2) { None, Private, Protected, Public } = .None, |
| 8187 | FwdDecl: bool = false, | 8307 | FwdDecl: bool = false, |
| 8188 | AppleBlock: bool = false, | 8308 | AppleBlock: bool = false, |
| 8189 | ReservedBit4: u1 = 0, | 8309 | ReservedBit4: u1 = 0, |
| ... | @@ -8199,11 +8319,11 @@ pub const Metadata = packed struct(u32) { | ... | @@ -8199,11 +8319,11 @@ pub const Metadata = packed struct(u32) { |
| 8199 | RValueReference: bool = false, | 8319 | RValueReference: bool = false, |
| 8200 | ExportSymbols: bool = false, | 8320 | ExportSymbols: bool = false, |
| 8201 | Inheritance: enum(u2) { | 8321 | Inheritance: enum(u2) { |
| 8202 | Zero, | 8322 | None, |
| 8203 | SingleInheritance, | 8323 | SingleInheritance, |
| 8204 | MultipleInheritance, | 8324 | MultipleInheritance, |
| 8205 | VirtualInheritance, | 8325 | VirtualInheritance, |
| 8206 | } = .Zero, | 8326 | } = .None, |
| 8207 | IntroducedVirtual: bool = false, | 8327 | IntroducedVirtual: bool = false, |
| 8208 | BitField: bool = false, | 8328 | BitField: bool = false, |
| 8209 | NoReturn: bool = false, | 8329 | NoReturn: bool = false, |
| ... | @@ -8226,7 +8346,7 @@ pub const Metadata = packed struct(u32) { | ... | @@ -8226,7 +8346,7 @@ pub const Metadata = packed struct(u32) { |
| 8226 | if (need_pipe) try w.writeAll(" | ") else need_pipe = true; | 8346 | if (need_pipe) try w.writeAll(" | ") else need_pipe = true; |
| 8227 | try w.print("DIFlag{s}", .{field.name}); | 8347 | try w.print("DIFlag{s}", .{field.name}); |
| 8228 | }, | 8348 | }, |
| 8229 | .@"enum" => if (@field(self, field.name) != .Zero) { | 8349 | .@"enum" => if (@field(self, field.name) != .None) { |
| 8230 | if (need_pipe) try w.writeAll(" | ") else need_pipe = true; | 8350 | if (need_pipe) try w.writeAll(" | ") else need_pipe = true; |
| 8231 | try w.print("DIFlag{s}", .{@tagName(@field(self, field.name))}); | 8351 | try w.print("DIFlag{s}", .{@tagName(@field(self, field.name))}); |
| 8232 | }, | 8352 | }, |
| ... | @@ -8262,7 +8382,7 @@ pub const Metadata = packed struct(u32) { | ... | @@ -8262,7 +8382,7 @@ pub const Metadata = packed struct(u32) { |
| 8262 | }; | 8382 | }; |
| 8263 | 8383 | ||
| 8264 | pub const DISPFlags = packed struct(u32) { | 8384 | pub const DISPFlags = packed struct(u32) { |
| 8265 | Virtuality: enum(u2) { Zero, Virtual, PureVirtual } = .Zero, | 8385 | Virtuality: enum(u2) { None, Virtual, PureVirtual } = .None, |
| 8266 | LocalToUnit: bool = false, | 8386 | LocalToUnit: bool = false, |
| 8267 | Definition: bool = false, | 8387 | Definition: bool = false, |
| 8268 | Optimized: bool = false, | 8388 | Optimized: bool = false, |
| ... | @@ -8283,7 +8403,7 @@ pub const Metadata = packed struct(u32) { | ... | @@ -8283,7 +8403,7 @@ pub const Metadata = packed struct(u32) { |
| 8283 | if (need_pipe) try w.writeAll(" | ") else need_pipe = true; | 8403 | if (need_pipe) try w.writeAll(" | ") else need_pipe = true; |
| 8284 | try w.print("DISPFlag{s}", .{field.name}); | 8404 | try w.print("DISPFlag{s}", .{field.name}); |
| 8285 | }, | 8405 | }, |
| 8286 | .@"enum" => if (@field(self, field.name) != .Zero) { | 8406 | .@"enum" => if (@field(self, field.name) != .None) { |
| 8287 | if (need_pipe) try w.writeAll(" | ") else need_pipe = true; | 8407 | if (need_pipe) try w.writeAll(" | ") else need_pipe = true; |
| 8288 | try w.print("DISPFlag{s}", .{@tagName(@field(self, field.name))}); | 8408 | try w.print("DISPFlag{s}", .{@tagName(@field(self, field.name))}); |
| 8289 | }, | 8409 | }, |
| ... | @@ -10007,11 +10127,11 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void | ... | @@ -10007,11 +10127,11 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void |
| 10007 | instruction_index.name(&function).fmt(self), | 10127 | instruction_index.name(&function).fmt(self), |
| 10008 | tag, | 10128 | tag, |
| 10009 | extra.info.access_kind.fmt(" "), | 10129 | extra.info.access_kind.fmt(" "), |
| 10010 | extra.info.atomic_rmw_operation, | 10130 | extra.info.operation, |
| 10011 | extra.ptr.fmt(function_index, self, .{ .percent = true }), | 10131 | extra.ptr.fmt(function_index, self, .{ .percent = true }), |
| 10012 | extra.val.fmt(function_index, self, .{ .percent = true }), | 10132 | extra.val.fmt(function_index, self, .{ .percent = true }), |
| 10013 | extra.info.sync_scope.fmt(" "), | 10133 | extra.info.sync_scope.fmt(" "), |
| 10014 | extra.info.success_ordering.fmt(" "), | 10134 | extra.info.ordering.fmt(" "), |
| 10015 | extra.info.alignment.fmt(", "), | 10135 | extra.info.alignment.fmt(", "), |
| 10016 | }); | 10136 | }); |
| 10017 | }, | 10137 | }, |
| ... | @@ -10055,9 +10175,10 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void | ... | @@ -10055,9 +10175,10 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void |
| 10055 | .@"tail call", | 10175 | .@"tail call", |
| 10056 | .@"tail call fast", | 10176 | .@"tail call fast", |
| 10057 | => |tag| { | 10177 | => |tag| { |
| 10058 | var extra = | 10178 | var extra = function.extraDataTrail(Function.Instruction.Call, instruction.data); |
| 10059 | function.extraDataTrail(Function.Instruction.Call, instruction.data); | ||
| 10060 | const args = extra.trail.next(extra.data.args_len, Value, &function); | 10179 | const args = extra.trail.next(extra.data.args_len, Value, &function); |
| 10180 | const callees = | ||
| 10181 | extra.trail.next(@intFromBool(extra.data.info.has_callees), Metadata, &function); | ||
| 10061 | try w.writeAll(" "); | 10182 | try w.writeAll(" "); |
| 10062 | const ret_ty = extra.data.ty.functionReturn(self); | 10183 | const ret_ty = extra.data.ty.functionReturn(self); |
| 10063 | switch (ret_ty) { | 10184 | switch (ret_ty) { |
| ... | @@ -10089,9 +10210,6 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void | ... | @@ -10089,9 +10210,6 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void |
| 10089 | }); | 10210 | }); |
| 10090 | } | 10211 | } |
| 10091 | try w.writeByte(')'); | 10212 | try w.writeByte(')'); |
| 10092 | if (extra.data.info.has_op_bundle_cold) { | ||
| 10093 | try w.writeAll(" [ \"cold\"() ]"); | ||
| 10094 | } | ||
| 10095 | const call_function_attributes = extra.data.attributes.func(self); | 10213 | const call_function_attributes = extra.data.attributes.func(self); |
| 10096 | if (call_function_attributes != .none) try w.print(" #{d}", .{ | 10214 | if (call_function_attributes != .none) try w.print(" #{d}", .{ |
| 10097 | (try attribute_groups.getOrPutValue( | 10215 | (try attribute_groups.getOrPutValue( |
| ... | @@ -10100,15 +10218,19 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void | ... | @@ -10100,15 +10218,19 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void |
| 10100 | {}, | 10218 | {}, |
| 10101 | )).index, | 10219 | )).index, |
| 10102 | }); | 10220 | }); |
| 10221 | if (extra.data.info.has_op_bundle_cold) try w.writeAll(" [ \"cold\"() ]"); | ||
| 10222 | metadata_formatter.need_comma = true; | ||
| 10223 | defer metadata_formatter.need_comma = undefined; | ||
| 10224 | for (callees) |metadata| try w.print("{f}", .{ | ||
| 10225 | try metadata_formatter.fmt("!callees ", metadata, null), | ||
| 10226 | }); | ||
| 10103 | }, | 10227 | }, |
| 10104 | .cmpxchg, | 10228 | .cmpxchg => |tag| { |
| 10105 | .@"cmpxchg weak", | 10229 | const extra = function.extraData(Function.Instruction.CmpXchg, instruction.data); |
| 10106 | => |tag| { | 10230 | try w.print(" %{f} = {t}{f}{f} {f}, {f}, {f}{f}{f}{f}{f}", .{ |
| 10107 | const extra = | ||
| 10108 | function.extraData(Function.Instruction.CmpXchg, instruction.data); | ||
| 10109 | try w.print(" %{f} = {t}{f} {f}, {f}, {f}{f}{f}{f}{f}", .{ | ||
| 10110 | instruction_index.name(&function).fmt(self), | 10231 | instruction_index.name(&function).fmt(self), |
| 10111 | tag, | 10232 | tag, |
| 10233 | extra.info.kind.fmt(" "), | ||
| 10112 | extra.info.access_kind.fmt(" "), | 10234 | extra.info.access_kind.fmt(" "), |
| 10113 | extra.ptr.fmt(function_index, self, .{ .percent = true }), | 10235 | extra.ptr.fmt(function_index, self, .{ .percent = true }), |
| 10114 | extra.cmp.fmt(function_index, self, .{ .percent = true }), | 10236 | extra.cmp.fmt(function_index, self, .{ .percent = true }), |
| ... | @@ -10143,11 +10265,11 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void | ... | @@ -10143,11 +10265,11 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void |
| 10143 | for (indices) |index| try w.print(", {d}", .{index}); | 10265 | for (indices) |index| try w.print(", {d}", .{index}); |
| 10144 | }, | 10266 | }, |
| 10145 | .fence => |tag| { | 10267 | .fence => |tag| { |
| 10146 | const info: MemoryAccessInfo = @bitCast(instruction.data); | 10268 | const fence: Function.Instruction.Fence = @bitCast(instruction.data); |
| 10147 | try w.print(" {t}{f}{f}", .{ | 10269 | try w.print(" {t}{f}{f}", .{ |
| 10148 | tag, | 10270 | tag, |
| 10149 | info.sync_scope.fmt(" "), | 10271 | fence.sync_scope.fmt(" "), |
| 10150 | info.success_ordering.fmt(" "), | 10272 | fence.success_ordering.fmt(" "), |
| 10151 | }); | 10273 | }); |
| 10152 | }, | 10274 | }, |
| 10153 | .fneg, | 10275 | .fneg, |
| ... | @@ -10221,16 +10343,22 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void | ... | @@ -10221,16 +10343,22 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void |
| 10221 | .load, | 10343 | .load, |
| 10222 | .@"load atomic", | 10344 | .@"load atomic", |
| 10223 | => |tag| { | 10345 | => |tag| { |
| 10224 | const extra = function.extraData(Function.Instruction.Load, instruction.data); | 10346 | var extra = function.extraDataTrail(Function.Instruction.Load, instruction.data); |
| 10347 | const range = extra.trail.next(@intFromBool(extra.data.info.has_range), Metadata, &function); | ||
| 10225 | try w.print(" %{f} = {t}{f} {f}, {f}{f}{f}{f}", .{ | 10348 | try w.print(" %{f} = {t}{f} {f}, {f}{f}{f}{f}", .{ |
| 10226 | instruction_index.name(&function).fmt(self), | 10349 | instruction_index.name(&function).fmt(self), |
| 10227 | tag, | 10350 | tag, |
| 10228 | extra.info.access_kind.fmt(" "), | 10351 | extra.data.info.access_kind.fmt(" "), |
| 10229 | extra.type.fmt(self, .percent), | 10352 | extra.data.type.fmt(self, .percent), |
| 10230 | extra.ptr.fmt(function_index, self, .{ .percent = true }), | 10353 | extra.data.ptr.fmt(function_index, self, .{ .percent = true }), |
| 10231 | extra.info.sync_scope.fmt(" "), | 10354 | extra.data.info.sync_scope.fmt(" "), |
| 10232 | extra.info.success_ordering.fmt(" "), | 10355 | extra.data.info.ordering.fmt(" "), |
| 10233 | extra.info.alignment.fmt(", "), | 10356 | extra.data.info.alignment.fmt(", "), |
| 10357 | }); | ||
| 10358 | metadata_formatter.need_comma = true; | ||
| 10359 | defer metadata_formatter.need_comma = undefined; | ||
| 10360 | for (range) |metadata| if (metadata.unwrap(self) != Metadata.empty_tuple) try w.print("{f}", .{ | ||
| 10361 | try metadata_formatter.fmt("!range ", metadata, null), | ||
| 10234 | }); | 10362 | }); |
| 10235 | }, | 10363 | }, |
| 10236 | .phi, | 10364 | .phi, |
| ... | @@ -10296,7 +10424,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void | ... | @@ -10296,7 +10424,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void |
| 10296 | extra.val.fmt(function_index, self, .{ .percent = true }), | 10424 | extra.val.fmt(function_index, self, .{ .percent = true }), |
| 10297 | extra.ptr.fmt(function_index, self, .{ .percent = true }), | 10425 | extra.ptr.fmt(function_index, self, .{ .percent = true }), |
| 10298 | extra.info.sync_scope.fmt(" "), | 10426 | extra.info.sync_scope.fmt(" "), |
| 10299 | extra.info.success_ordering.fmt(" "), | 10427 | extra.info.ordering.fmt(" "), |
| 10300 | extra.info.alignment.fmt(", "), | 10428 | extra.info.alignment.fmt(", "), |
| 10301 | }); | 10429 | }); |
| 10302 | }, | 10430 | }, |
| ... | @@ -12291,9 +12419,12 @@ pub fn debugFloatType( | ... | @@ -12291,9 +12419,12 @@ pub fn debugFloatType( |
| 12291 | return self.debugFloatTypeAssumeCapacity(name, size_in_bits); | 12419 | return self.debugFloatTypeAssumeCapacity(name, size_in_bits); |
| 12292 | } | 12420 | } |
| 12293 | 12421 | ||
| 12294 | pub fn debugForwardReference(self: *Builder) Allocator.Error!Metadata { | 12422 | /// Deprecated, use `metadataForwardReference`. |
| 12423 | pub const debugForwardReference = metadataForwardReference; | ||
| 12424 | |||
| 12425 | pub fn metadataForwardReference(self: *Builder) Allocator.Error!Metadata { | ||
| 12295 | try self.metadata_forward_references.ensureUnusedCapacity(self.gpa, 1); | 12426 | try self.metadata_forward_references.ensureUnusedCapacity(self.gpa, 1); |
| 12296 | return self.debugForwardReferenceAssumeCapacity(); | 12427 | return self.metadataForwardReferenceAssumeCapacity(); |
| 12297 | } | 12428 | } |
| 12298 | 12429 | ||
| 12299 | pub fn debugStructType( | 12430 | pub fn debugStructType( |
| ... | @@ -12521,15 +12652,8 @@ pub fn debugExpression(self: *Builder, elements: []const u32) Allocator.Error!Me | ... | @@ -12521,15 +12652,8 @@ pub fn debugExpression(self: *Builder, elements: []const u32) Allocator.Error!Me |
| 12521 | } | 12652 | } |
| 12522 | 12653 | ||
| 12523 | pub fn metadataTuple(self: *Builder, elements: []const Metadata) Allocator.Error!Metadata { | 12654 | pub fn metadataTuple(self: *Builder, elements: []const Metadata) Allocator.Error!Metadata { |
| 12524 | return self.metadataTupleOptionals(@ptrCast(elements)); | ||
| 12525 | } | ||
| 12526 | |||
| 12527 | pub fn metadataTupleOptionals( | ||
| 12528 | self: *Builder, | ||
| 12529 | elements: []const Metadata.Optional, | ||
| 12530 | ) Allocator.Error!Metadata { | ||
| 12531 | try self.ensureUnusedMetadataCapacity(1, Metadata.Tuple, elements.len); | 12655 | try self.ensureUnusedMetadataCapacity(1, Metadata.Tuple, elements.len); |
| 12532 | return self.metadataTupleOptionalsAssumeCapacity(elements); | 12656 | return self.metadataTupleAssumeCapacity(elements); |
| 12533 | } | 12657 | } |
| 12534 | 12658 | ||
| 12535 | pub fn debugLocalVar( | 12659 | pub fn debugLocalVar( |
| ... | @@ -12595,9 +12719,12 @@ pub fn metadataConstant(self: *Builder, value: Constant) Allocator.Error!Metadat | ... | @@ -12595,9 +12719,12 @@ pub fn metadataConstant(self: *Builder, value: Constant) Allocator.Error!Metadat |
| 12595 | return self.metadataConstantAssumeCapacity(value); | 12719 | return self.metadataConstantAssumeCapacity(value); |
| 12596 | } | 12720 | } |
| 12597 | 12721 | ||
| 12722 | /// Deprecated, use `resolveMetadataForwardReference`. | ||
| 12723 | pub const resolveDebugForwardReference = resolveMetadataForwardReference; | ||
| 12724 | |||
| 12598 | /// Resolves the given forward reference to the given value (which is not itself a forward | 12725 | /// Resolves the given forward reference to the given value (which is not itself a forward |
| 12599 | /// reference). If the forward reference is already resolved, its target is replaced. | 12726 | /// reference). If the forward reference is already resolved, its target is replaced. |
| 12600 | pub fn resolveDebugForwardReference(self: *Builder, fwd_ref: Metadata, value: Metadata) void { | 12727 | pub fn resolveMetadataForwardReference(self: *Builder, fwd_ref: Metadata, value: Metadata) void { |
| 12601 | assert(fwd_ref.kind == .forward); | 12728 | assert(fwd_ref.kind == .forward); |
| 12602 | assert(value.kind != .forward); | 12729 | assert(value.kind != .forward); |
| 12603 | self.metadata_forward_references.items[fwd_ref.index] = value.toOptional(); | 12730 | self.metadata_forward_references.items[fwd_ref.index] = value.toOptional(); |
| ... | @@ -12790,8 +12917,7 @@ fn debugFloatTypeAssumeCapacity(self: *Builder, name: ?Metadata.String, size_in_ | ... | @@ -12790,8 +12917,7 @@ fn debugFloatTypeAssumeCapacity(self: *Builder, name: ?Metadata.String, size_in_ |
| 12790 | }); | 12917 | }); |
| 12791 | } | 12918 | } |
| 12792 | 12919 | ||
| 12793 | fn debugForwardReferenceAssumeCapacity(self: *Builder) Metadata { | 12920 | fn metadataForwardReferenceAssumeCapacity(self: *Builder) Metadata { |
| 12794 | assert(!self.strip); | ||
| 12795 | const index = self.metadata_forward_references.items.len; | 12921 | const index = self.metadata_forward_references.items.len; |
| 12796 | self.metadata_forward_references.appendAssumeCapacity(.none); | 12922 | self.metadata_forward_references.appendAssumeCapacity(.none); |
| 12797 | return .{ .index = @intCast(index), .kind = .forward }; | 12923 | return .{ .index = @intCast(index), .kind = .forward }; |
| ... | @@ -13164,9 +13290,9 @@ fn debugExpressionAssumeCapacity(self: *Builder, elements: []const u32) Metadata | ... | @@ -13164,9 +13290,9 @@ fn debugExpressionAssumeCapacity(self: *Builder, elements: []const u32) Metadata |
| 13164 | return .{ .index = @intCast(gop.index), .kind = .node }; | 13290 | return .{ .index = @intCast(gop.index), .kind = .node }; |
| 13165 | } | 13291 | } |
| 13166 | 13292 | ||
| 13167 | fn metadataTupleOptionalsAssumeCapacity(self: *Builder, elements: []const Metadata.Optional) Metadata { | 13293 | fn metadataTupleAssumeCapacity(self: *Builder, elements: []const Metadata) Metadata { |
| 13168 | const Key = struct { | 13294 | const Key = struct { |
| 13169 | elements: []const Metadata.Optional, | 13295 | elements: []const Metadata, |
| 13170 | }; | 13296 | }; |
| 13171 | const Adapter = struct { | 13297 | const Adapter = struct { |
| 13172 | builder: *const Builder, | 13298 | builder: *const Builder, |
| ... | @@ -13181,9 +13307,9 @@ fn metadataTupleOptionalsAssumeCapacity(self: *Builder, elements: []const Metada | ... | @@ -13181,9 +13307,9 @@ fn metadataTupleOptionalsAssumeCapacity(self: *Builder, elements: []const Metada |
| 13181 | const rhs_data = ctx.builder.metadata_items.items(.data)[rhs_index]; | 13307 | const rhs_data = ctx.builder.metadata_items.items(.data)[rhs_index]; |
| 13182 | var rhs_extra = ctx.builder.metadataExtraDataTrail(Metadata.Tuple, rhs_data); | 13308 | var rhs_extra = ctx.builder.metadataExtraDataTrail(Metadata.Tuple, rhs_data); |
| 13183 | return std.mem.eql( | 13309 | return std.mem.eql( |
| 13184 | Metadata.Optional, | 13310 | Metadata, |
| 13185 | lhs_key.elements, | 13311 | lhs_key.elements, |
| 13186 | rhs_extra.trail.next(rhs_extra.data.elements_len, Metadata.Optional, ctx.builder), | 13312 | rhs_extra.trail.next(rhs_extra.data.elements_len, Metadata, ctx.builder), |
| 13187 | ); | 13313 | ); |
| 13188 | } | 13314 | } |
| 13189 | }; | 13315 | }; |
| ... | @@ -13949,7 +14075,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco | ... | @@ -13949,7 +14075,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco |
| 13949 | .positive_integer, | 14075 | .positive_integer, |
| 13950 | .negative_integer, | 14076 | .negative_integer, |
| 13951 | => |tag| { | 14077 | => |tag| { |
| 13952 | const extra: *align(@alignOf(std.math.big.Limb)) Constant.Integer = | 14078 | const extra: *align(@alignOf(std.math.big.Limb)) const Constant.Integer = |
| 13953 | @ptrCast(self.constant_limbs.items[data..][0..Constant.Integer.limbs]); | 14079 | @ptrCast(self.constant_limbs.items[data..][0..Constant.Integer.limbs]); |
| 13954 | const bigint: std.math.big.int.Const = .{ | 14080 | const bigint: std.math.big.int.Const = .{ |
| 13955 | .limbs = self.constant_limbs | 14081 | .limbs = self.constant_limbs |
| ... | @@ -15109,7 +15235,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco | ... | @@ -15109,7 +15235,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco |
| 15109 | .ty = extra.type, | 15235 | .ty = extra.type, |
| 15110 | .alignment = extra.info.alignment.toLlvm(), | 15236 | .alignment = extra.info.alignment.toLlvm(), |
| 15111 | .is_volatile = extra.info.access_kind == .@"volatile", | 15237 | .is_volatile = extra.info.access_kind == .@"volatile", |
| 15112 | .success_ordering = extra.info.success_ordering, | 15238 | .ordering = extra.info.ordering, |
| 15113 | .sync_scope = extra.info.sync_scope, | 15239 | .sync_scope = extra.info.sync_scope, |
| 15114 | }); | 15240 | }); |
| 15115 | }, | 15241 | }, |
| ... | @@ -15129,7 +15255,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco | ... | @@ -15129,7 +15255,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco |
| 15129 | .val = adapter.getOffsetValueIndex(extra.val), | 15255 | .val = adapter.getOffsetValueIndex(extra.val), |
| 15130 | .alignment = extra.info.alignment.toLlvm(), | 15256 | .alignment = extra.info.alignment.toLlvm(), |
| 15131 | .is_volatile = extra.info.access_kind == .@"volatile", | 15257 | .is_volatile = extra.info.access_kind == .@"volatile", |
| 15132 | .success_ordering = extra.info.success_ordering, | 15258 | .ordering = extra.info.ordering, |
| 15133 | .sync_scope = extra.info.sync_scope, | 15259 | .sync_scope = extra.info.sync_scope, |
| 15134 | }); | 15260 | }); |
| 15135 | }, | 15261 | }, |
| ... | @@ -15212,18 +15338,15 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco | ... | @@ -15212,18 +15338,15 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco |
| 15212 | try function_block.writeAbbrev(FunctionBlock.AtomicRmw{ | 15338 | try function_block.writeAbbrev(FunctionBlock.AtomicRmw{ |
| 15213 | .ptr = adapter.getOffsetValueIndex(extra.ptr), | 15339 | .ptr = adapter.getOffsetValueIndex(extra.ptr), |
| 15214 | .val = adapter.getOffsetValueIndex(extra.val), | 15340 | .val = adapter.getOffsetValueIndex(extra.val), |
| 15215 | .operation = extra.info.atomic_rmw_operation, | 15341 | .operation = extra.info.operation, |
| 15216 | .is_volatile = extra.info.access_kind == .@"volatile", | 15342 | .is_volatile = extra.info.access_kind == .@"volatile", |
| 15217 | .success_ordering = extra.info.success_ordering, | 15343 | .ordering = extra.info.ordering, |
| 15218 | .sync_scope = extra.info.sync_scope, | 15344 | .sync_scope = extra.info.sync_scope, |
| 15219 | .alignment = extra.info.alignment.toLlvm(), | 15345 | .alignment = extra.info.alignment.toLlvm(), |
| 15220 | }); | 15346 | }); |
| 15221 | }, | 15347 | }, |
| 15222 | .cmpxchg, | 15348 | .cmpxchg => { |
| 15223 | .@"cmpxchg weak", | ||
| 15224 | => |kind| { | ||
| 15225 | const extra = func.extraData(Function.Instruction.CmpXchg, data); | 15349 | const extra = func.extraData(Function.Instruction.CmpXchg, data); |
| 15226 | |||
| 15227 | try function_block.writeAbbrev(FunctionBlock.CmpXchg{ | 15350 | try function_block.writeAbbrev(FunctionBlock.CmpXchg{ |
| 15228 | .ptr = adapter.getOffsetValueIndex(extra.ptr), | 15351 | .ptr = adapter.getOffsetValueIndex(extra.ptr), |
| 15229 | .cmp = adapter.getOffsetValueIndex(extra.cmp), | 15352 | .cmp = adapter.getOffsetValueIndex(extra.cmp), |
| ... | @@ -15232,15 +15355,15 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco | ... | @@ -15232,15 +15355,15 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco |
| 15232 | .success_ordering = extra.info.success_ordering, | 15355 | .success_ordering = extra.info.success_ordering, |
| 15233 | .sync_scope = extra.info.sync_scope, | 15356 | .sync_scope = extra.info.sync_scope, |
| 15234 | .failure_ordering = extra.info.failure_ordering, | 15357 | .failure_ordering = extra.info.failure_ordering, |
| 15235 | .is_weak = kind == .@"cmpxchg weak", | 15358 | .is_weak = extra.info.kind == .weak, |
| 15236 | .alignment = extra.info.alignment.toLlvm(), | 15359 | .alignment = extra.info.alignment.toLlvm(), |
| 15237 | }); | 15360 | }); |
| 15238 | }, | 15361 | }, |
| 15239 | .fence => { | 15362 | .fence => { |
| 15240 | const info: MemoryAccessInfo = @bitCast(data); | 15363 | const fence: Function.Instruction.Fence = @bitCast(data); |
| 15241 | try function_block.writeAbbrev(FunctionBlock.Fence{ | 15364 | try function_block.writeAbbrev(FunctionBlock.Fence{ |
| 15242 | .ordering = info.success_ordering, | 15365 | .ordering = fence.success_ordering, |
| 15243 | .sync_scope = info.sync_scope, | 15366 | .sync_scope = fence.sync_scope, |
| 15244 | }); | 15367 | }); |
| 15245 | }, | 15368 | }, |
| 15246 | } | 15369 | } |
| ... | @@ -15313,17 +15436,58 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco | ... | @@ -15313,17 +15436,58 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco |
| 15313 | }; | 15436 | }; |
| 15314 | switch (weights) { | 15437 | switch (weights) { |
| 15315 | .none => {}, | 15438 | .none => {}, |
| 15316 | .unpredictable => try metadata_attach_block.writeAbbrevAdapted(MetadataAttachmentBlock.AttachmentInstructionSingle{ | 15439 | .unpredictable => try metadata_attach_block.writeAbbrevAdapted( |
| 15440 | MetadataAttachmentBlock.AttachmentInstructionSingle{ | ||
| 15441 | .inst = instr_index, | ||
| 15442 | .kind = .unpredictable, | ||
| 15443 | .metadata = .empty_tuple, | ||
| 15444 | }, | ||
| 15445 | metadata_adapter, | ||
| 15446 | ), | ||
| 15447 | _ => try metadata_attach_block.writeAbbrevAdapted( | ||
| 15448 | MetadataAttachmentBlock.AttachmentInstructionSingle{ | ||
| 15449 | .inst = instr_index, | ||
| 15450 | .kind = .prof, | ||
| 15451 | .metadata = weights.toMetadata(), | ||
| 15452 | }, | ||
| 15453 | metadata_adapter, | ||
| 15454 | ), | ||
| 15455 | } | ||
| 15456 | instr_index += 1; | ||
| 15457 | }, | ||
| 15458 | .call, | ||
| 15459 | .@"call fast", | ||
| 15460 | .@"musttail call", | ||
| 15461 | .@"musttail call fast", | ||
| 15462 | .@"notail call", | ||
| 15463 | .@"notail call fast", | ||
| 15464 | .@"tail call", | ||
| 15465 | .@"tail call fast", | ||
| 15466 | => { | ||
| 15467 | var extra = func.extraDataTrail(Function.Instruction.Call, data); | ||
| 15468 | _ = extra.trail.next(extra.data.args_len, Value, &func); | ||
| 15469 | const callees = extra.trail.next(@intFromBool(extra.data.info.has_callees), Metadata, &func); | ||
| 15470 | for (callees) |metadata| try metadata_attach_block.writeAbbrevAdapted( | ||
| 15471 | MetadataAttachmentBlock.AttachmentInstructionSingle{ | ||
| 15317 | .inst = instr_index, | 15472 | .inst = instr_index, |
| 15318 | .kind = .unpredictable, | 15473 | .kind = .callees, |
| 15319 | .metadata = .empty_tuple, | 15474 | .metadata = metadata, |
| 15320 | }, metadata_adapter), | 15475 | }, |
| 15321 | _ => try metadata_attach_block.writeAbbrevAdapted(MetadataAttachmentBlock.AttachmentInstructionSingle{ | 15476 | metadata_adapter, |
| 15477 | ); | ||
| 15478 | instr_index += 1; | ||
| 15479 | }, | ||
| 15480 | .load, .@"load atomic" => { | ||
| 15481 | var extra = func.extraDataTrail(Function.Instruction.Load, data); | ||
| 15482 | const range = extra.trail.next(@intFromBool(extra.data.info.has_range), Metadata, &func); | ||
| 15483 | for (range) |metadata| if (metadata.unwrap(self) != Metadata.empty_tuple) try metadata_attach_block.writeAbbrevAdapted( | ||
| 15484 | MetadataAttachmentBlock.AttachmentInstructionSingle{ | ||
| 15322 | .inst = instr_index, | 15485 | .inst = instr_index, |
| 15323 | .kind = .prof, | 15486 | .kind = .range, |
| 15324 | .metadata = weights.toMetadata(), | 15487 | .metadata = metadata, |
| 15325 | }, metadata_adapter), | 15488 | }, |
| 15326 | } | 15489 | metadata_adapter, |
| 15490 | ); | ||
| 15327 | instr_index += 1; | 15491 | instr_index += 1; |
| 15328 | }, | 15492 | }, |
| 15329 | }; | 15493 | }; |
lib/std/zig/llvm/ir.zig+5-5| ... | @@ -79,7 +79,7 @@ pub const FixedMetadataKind = enum(u6) { | ... | @@ -79,7 +79,7 @@ pub const FixedMetadataKind = enum(u6) { |
| 79 | //tbaa = 1, | 79 | //tbaa = 1, |
| 80 | prof = 2, | 80 | prof = 2, |
| 81 | //fpmath = 3, | 81 | //fpmath = 3, |
| 82 | //range = 4, | 82 | range = 4, |
| 83 | //@"tbaa.struct" = 5, | 83 | //@"tbaa.struct" = 5, |
| 84 | //@"invariant.load" = 6, | 84 | //@"invariant.load" = 6, |
| 85 | //@"alias.scope" = 7, | 85 | //@"alias.scope" = 7, |
| ... | @@ -98,7 +98,7 @@ pub const FixedMetadataKind = enum(u6) { | ... | @@ -98,7 +98,7 @@ pub const FixedMetadataKind = enum(u6) { |
| 98 | //section_prefix = 20, | 98 | //section_prefix = 20, |
| 99 | //absolute_symbol = 21, | 99 | //absolute_symbol = 21, |
| 100 | //associated = 22, | 100 | //associated = 22, |
| 101 | //callees = 23, | 101 | callees = 23, |
| 102 | //irr_loop = 24, | 102 | //irr_loop = 24, |
| 103 | //@"llvm.access.group" = 25, | 103 | //@"llvm.access.group" = 25, |
| 104 | //callback = 26, | 104 | //callback = 26, |
| ... | @@ -1232,7 +1232,7 @@ pub const ModuleBlock = struct { | ... | @@ -1232,7 +1232,7 @@ pub const ModuleBlock = struct { |
| 1232 | ty: Builder.Type, | 1232 | ty: Builder.Type, |
| 1233 | alignment: std.meta.Int(.unsigned, @bitSizeOf(Builder.Alignment)), | 1233 | alignment: std.meta.Int(.unsigned, @bitSizeOf(Builder.Alignment)), |
| 1234 | is_volatile: bool, | 1234 | is_volatile: bool, |
| 1235 | success_ordering: Builder.AtomicOrdering, | 1235 | ordering: Builder.AtomicOrdering, |
| 1236 | sync_scope: Builder.SyncScope, | 1236 | sync_scope: Builder.SyncScope, |
| 1237 | }; | 1237 | }; |
| 1238 | 1238 | ||
| ... | @@ -1264,7 +1264,7 @@ pub const ModuleBlock = struct { | ... | @@ -1264,7 +1264,7 @@ pub const ModuleBlock = struct { |
| 1264 | val: u32, | 1264 | val: u32, |
| 1265 | alignment: std.meta.Int(.unsigned, @bitSizeOf(Builder.Alignment)), | 1265 | alignment: std.meta.Int(.unsigned, @bitSizeOf(Builder.Alignment)), |
| 1266 | is_volatile: bool, | 1266 | is_volatile: bool, |
| 1267 | success_ordering: Builder.AtomicOrdering, | 1267 | ordering: Builder.AtomicOrdering, |
| 1268 | sync_scope: Builder.SyncScope, | 1268 | sync_scope: Builder.SyncScope, |
| 1269 | }; | 1269 | }; |
| 1270 | 1270 | ||
| ... | @@ -1315,7 +1315,7 @@ pub const ModuleBlock = struct { | ... | @@ -1315,7 +1315,7 @@ pub const ModuleBlock = struct { |
| 1315 | val: u32, | 1315 | val: u32, |
| 1316 | operation: Builder.Function.Instruction.AtomicRmw.Operation, | 1316 | operation: Builder.Function.Instruction.AtomicRmw.Operation, |
| 1317 | is_volatile: bool, | 1317 | is_volatile: bool, |
| 1318 | success_ordering: Builder.AtomicOrdering, | 1318 | ordering: Builder.AtomicOrdering, |
| 1319 | sync_scope: Builder.SyncScope, | 1319 | sync_scope: Builder.SyncScope, |
| 1320 | alignment: std.meta.Int(.unsigned, @bitSizeOf(Builder.Alignment)), | 1320 | alignment: std.meta.Int(.unsigned, @bitSizeOf(Builder.Alignment)), |
| 1321 | }; | 1321 | }; |
src/InternPool.zig+5-2| ... | @@ -7998,7 +7998,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: | ... | @@ -7998,7 +7998,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: |
| 7998 | }); | 7998 | }); |
| 7999 | }, | 7999 | }, |
| 8000 | .restricted_value => |restricted_value| { | 8000 | .restricted_value => |restricted_value| { |
| 8001 | assert(restricted_value.ty.unwrap(ip).getTag(ip) == .type_restricted); | 8001 | assert(ip.isRestrictedType(restricted_value.ty)); |
| 8002 | assert(!ip.isUndef(restricted_value.unrestricted_value)); | 8002 | assert(!ip.isUndef(restricted_value.unrestricted_value)); |
| 8003 | items.appendAssumeCapacity(.{ | 8003 | items.appendAssumeCapacity(.{ |
| 8004 | .tag = .restricted_value, | 8004 | .tag = .restricted_value, |
| ... | @@ -9019,7 +9019,10 @@ pub fn getUnion( | ... | @@ -9019,7 +9019,10 @@ pub fn getUnion( |
| 9019 | ) Allocator.Error!Index { | 9019 | ) Allocator.Error!Index { |
| 9020 | assert(un.ty != .none); | 9020 | assert(un.ty != .none); |
| 9021 | assert(un.val != .none); | 9021 | assert(un.val != .none); |
| 9022 | assert(ip.loadUnionType(un.ty).layout != .@"packed"); | 9022 | |
| 9023 | const loaded_union = ip.loadUnionType(un.ty); | ||
| 9024 | assert(loaded_union.layout != .@"packed"); | ||
| 9025 | assert(loaded_union.enum_tag_type == ip.typeOf(un.tag)); | ||
| 9023 | 9026 | ||
| 9024 | var gop = try ip.getOrPutKey(gpa, io, tid, .{ .un = un }); | 9027 | var gop = try ip.getOrPutKey(gpa, io, tid, .{ .un = un }); |
| 9025 | defer gop.deinit(); | 9028 | defer gop.deinit(); |
src/Sema.zig+41-18| ... | @@ -10053,6 +10053,7 @@ fn analyzeSwitchBlock( | ... | @@ -10053,6 +10053,7 @@ fn analyzeSwitchBlock( |
| 10053 | ) CompileError!?Air.Inst.Ref { | 10053 | ) CompileError!?Air.Inst.Ref { |
| 10054 | const pt = sema.pt; | 10054 | const pt = sema.pt; |
| 10055 | const zcu = pt.zcu; | 10055 | const zcu = pt.zcu; |
| 10056 | const ip = &zcu.intern_pool; | ||
| 10056 | const gpa = sema.gpa; | 10057 | const gpa = sema.gpa; |
| 10057 | 10058 | ||
| 10058 | const src_node_offset = zir_switch.switch_src_node_offset; | 10059 | const src_node_offset = zir_switch.switch_src_node_offset; |
| ... | @@ -10076,7 +10077,13 @@ fn analyzeSwitchBlock( | ... | @@ -10076,7 +10077,13 @@ fn analyzeSwitchBlock( |
| 10076 | operand_ty.containerLayout(zcu) != .@"packed") | 10077 | operand_ty.containerLayout(zcu) != .@"packed") |
| 10077 | { | 10078 | { |
| 10078 | const tag_val = try sema.unionToTag(block, val); | 10079 | const tag_val = try sema.unionToTag(block, val); |
| 10079 | break :init .{ tag_val, sema.typeOf(tag_val) }; | 10080 | const tag_ty = sema.typeOf(tag_val); |
| 10081 | const unrestricted_tag_ty = tag_ty.unrestrictedType(zcu) orelse tag_ty; | ||
| 10082 | const unrestricted_tag_val = if (unrestricted_tag_ty.toIntern() != tag_ty.toIntern()) | ||
| 10083 | try sema.unwrapRestricted(block, unrestricted_tag_ty, tag_val, src) | ||
| 10084 | else | ||
| 10085 | tag_val; | ||
| 10086 | break :init .{ unrestricted_tag_val, unrestricted_tag_ty }; | ||
| 10080 | } | 10087 | } |
| 10081 | break :init .{ | 10088 | break :init .{ |
| 10082 | if (maybe_operand_opv) |operand_opv| .fromValue(operand_opv) else val, | 10089 | if (maybe_operand_opv) |operand_opv| .fromValue(operand_opv) else val, |
| ... | @@ -10269,7 +10276,7 @@ fn analyzeSwitchBlock( | ... | @@ -10269,7 +10276,7 @@ fn analyzeSwitchBlock( |
| 10269 | break :item_val item_opv; | 10276 | break :item_val item_opv; |
| 10270 | } | 10277 | } |
| 10271 | if (maybe_operand_opv) |operand_opv| { | 10278 | if (maybe_operand_opv) |operand_opv| { |
| 10272 | break :item_val .fromInterned(zcu.intern_pool.indexToKey(operand_opv.toIntern()).un.val); | 10279 | break :item_val .fromInterned(ip.indexToKey(operand_opv.toIntern()).un.val); |
| 10273 | } | 10280 | } |
| 10274 | assert(zir_switch.any_maybe_runtime_capture); // there's a payload capture | 10281 | assert(zir_switch.any_maybe_runtime_capture); // there's a payload capture |
| 10275 | const operand_val, const operand_ref = switch (operand) { | 10282 | const operand_val, const operand_ref = switch (operand) { |
| ... | @@ -11211,7 +11218,8 @@ fn validateSwitchBlock( | ... | @@ -11211,7 +11218,8 @@ fn validateSwitchBlock( |
| 11211 | const union_obj = ip.loadUnionType(operand_ty.toIntern()); | 11218 | const union_obj = ip.loadUnionType(operand_ty.toIntern()); |
| 11212 | switch (union_obj.tag_usage) { | 11219 | switch (union_obj.tag_usage) { |
| 11213 | .tagged => { | 11220 | .tagged => { |
| 11214 | break :item_ty .fromInterned(union_obj.enum_tag_type); | 11221 | const enum_tag_ty: Type = .fromInterned(union_obj.enum_tag_type); |
| 11222 | break :item_ty enum_tag_ty.unrestrictedType(zcu) orelse enum_tag_ty; | ||
| 11215 | }, | 11223 | }, |
| 11216 | .none => { | 11224 | .none => { |
| 11217 | if (union_obj.layout == .@"packed") { | 11225 | if (union_obj.layout == .@"packed") { |
| ... | @@ -16636,7 +16644,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -16636,7 +16644,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 16636 | const union_field_ty = try sema.getBuiltinType(src, .@"Type.UnionField"); | 16644 | const union_field_ty = try sema.getBuiltinType(src, .@"Type.UnionField"); |
| 16637 | 16645 | ||
| 16638 | const union_obj = ip.loadUnionType(unrestricted_ty.toIntern()); | 16646 | const union_obj = ip.loadUnionType(unrestricted_ty.toIntern()); |
| 16639 | const enum_obj = ip.loadEnumType(union_obj.enum_tag_type); | 16647 | const enum_tag_ty: Type = .fromInterned(union_obj.enum_tag_type); |
| 16648 | const enum_obj = ip.loadEnumType((enum_tag_ty.unrestrictedType(zcu) orelse enum_tag_ty).toIntern()); | ||
| 16640 | const layout = union_obj.layout; | 16649 | const layout = union_obj.layout; |
| 16641 | 16650 | ||
| 16642 | const union_field_vals = try gpa.alloc(InternPool.Index, enum_obj.field_names.len); | 16651 | const union_field_vals = try gpa.alloc(InternPool.Index, enum_obj.field_names.len); |
| ... | @@ -18220,7 +18229,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -18220,7 +18229,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 18220 | break :blk ty; | 18229 | break :blk ty; |
| 18221 | }; | 18230 | }; |
| 18222 | 18231 | ||
| 18223 | if (elem_ty.zigTypeTag(zcu) == .noreturn) | 18232 | if (elem_ty.toIntern() == .noreturn_type) |
| 18224 | return sema.fail(block, elem_ty_src, "pointer to noreturn not allowed", .{}); | 18233 | return sema.fail(block, elem_ty_src, "pointer to noreturn not allowed", .{}); |
| 18225 | 18234 | ||
| 18226 | const target = zcu.getTarget(); | 18235 | const target = zcu.getTarget(); |
| ... | @@ -18253,7 +18262,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -18253,7 +18262,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 18253 | const ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_i]); | 18262 | const ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_i]); |
| 18254 | extra_i += 1; | 18263 | extra_i += 1; |
| 18255 | break :blk try sema.resolveAddressSpace(block, addrspace_src, ref, .pointer); | 18264 | break :blk try sema.resolveAddressSpace(block, addrspace_src, ref, .pointer); |
| 18256 | } else if (elem_ty.zigTypeTag(zcu) == .@"fn" and target.cpu.arch == .avr) .flash else .generic; | 18265 | } else if (target.cpu.arch == .avr and ip.isFunctionType(elem_ty.toIntern())) .flash else .generic; |
| 18257 | 18266 | ||
| 18258 | const bit_offset: u16 = if (inst_data.flags.has_bit_range) blk: { | 18267 | const bit_offset: u16 = if (inst_data.flags.has_bit_range) blk: { |
| 18259 | const ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_i]); | 18268 | const ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_i]); |
| ... | @@ -18284,7 +18293,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -18284,7 +18293,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 18284 | } | 18293 | } |
| 18285 | } | 18294 | } |
| 18286 | 18295 | ||
| 18287 | if (elem_ty.zigTypeTag(zcu) == .@"fn") { | 18296 | if (ip.isFunctionType(elem_ty.toIntern())) { |
| 18288 | if (inst_data.size != .one) { | 18297 | if (inst_data.size != .one) { |
| 18289 | return sema.fail(block, elem_ty_src, "function pointers must be single pointers", .{}); | 18298 | return sema.fail(block, elem_ty_src, "function pointers must be single pointers", .{}); |
| 18290 | } | 18299 | } |
| ... | @@ -18594,7 +18603,8 @@ fn zirStructInit( | ... | @@ -18594,7 +18603,8 @@ fn zirStructInit( |
| 18594 | ); | 18603 | ); |
| 18595 | const field_index = try sema.unionFieldIndex(block, resolved_ty, field_name, field_src); | 18604 | const field_index = try sema.unionFieldIndex(block, resolved_ty, field_name, field_src); |
| 18596 | const tag_ty = resolved_ty.unionTagTypeHypothetical(zcu); | 18605 | const tag_ty = resolved_ty.unionTagTypeHypothetical(zcu); |
| 18597 | const tag_val = try pt.enumValueFieldIndex(tag_ty, field_index); | 18606 | const unrestricted_tag_ty = tag_ty.unrestrictedType(zcu) orelse tag_ty; |
| 18607 | const tag_val = try pt.enumValueFieldIndex(unrestricted_tag_ty, field_index); | ||
| 18598 | const field_ty: Type = .fromInterned(zcu.typeToUnion(resolved_ty).?.field_types.get(ip)[field_index]); | 18608 | const field_ty: Type = .fromInterned(zcu.typeToUnion(resolved_ty).?.field_types.get(ip)[field_index]); |
| 18599 | 18609 | ||
| 18600 | if (field_ty.classify(zcu) == .no_possible_value) { | 18610 | if (field_ty.classify(zcu) == .no_possible_value) { |
| ... | @@ -18626,7 +18636,10 @@ fn zirStructInit( | ... | @@ -18626,7 +18636,10 @@ fn zirStructInit( |
| 18626 | if (sema.resolveValue(init_inst)) |val| { | 18636 | if (sema.resolveValue(init_inst)) |val| { |
| 18627 | const struct_val = Value.fromInterned(try pt.internUnion(.{ | 18637 | const struct_val = Value.fromInterned(try pt.internUnion(.{ |
| 18628 | .ty = resolved_ty.toIntern(), | 18638 | .ty = resolved_ty.toIntern(), |
| 18629 | .tag = tag_val.toIntern(), | 18639 | .tag = if (unrestricted_tag_ty.toIntern() != tag_ty.toIntern()) |
| 18640 | try pt.intern(.{ .restricted_value = .{ .ty = tag_ty.toIntern(), .unrestricted_value = tag_val.toIntern() } }) | ||
| 18641 | else | ||
| 18642 | tag_val.toIntern(), | ||
| 18630 | .val = val.toIntern(), | 18643 | .val = val.toIntern(), |
| 18631 | })); | 18644 | })); |
| 18632 | const final_val_inst = try sema.coerce(block, result_ty, Air.internedToRef(struct_val.toIntern()), src); | 18645 | const final_val_inst = try sema.coerce(block, result_ty, Air.internedToRef(struct_val.toIntern()), src); |
| ... | @@ -19358,7 +19371,8 @@ fn fieldType( | ... | @@ -19358,7 +19371,8 @@ fn fieldType( |
| 19358 | }, | 19371 | }, |
| 19359 | .@"union" => { | 19372 | .@"union" => { |
| 19360 | const union_obj = zcu.typeToUnion(cur_ty).?; | 19373 | const union_obj = zcu.typeToUnion(cur_ty).?; |
| 19361 | const enum_obj = ip.loadEnumType(union_obj.enum_tag_type); | 19374 | const enum_tag_ty: Type = .fromInterned(union_obj.enum_tag_type); |
| 19375 | const enum_obj = ip.loadEnumType((enum_tag_ty.unrestrictedType(zcu) orelse enum_tag_ty).toIntern()); | ||
| 19362 | const field_index = enum_obj.nameIndex(ip, field_name) orelse | 19376 | const field_index = enum_obj.nameIndex(ip, field_name) orelse |
| 19363 | return sema.failWithBadUnionFieldAccess(block, cur_ty, union_obj, field_src, field_name); | 19377 | return sema.failWithBadUnionFieldAccess(block, cur_ty, union_obj, field_src, field_name); |
| 19364 | const field_ty = union_obj.field_types.get(ip)[field_index]; | 19378 | const field_ty = union_obj.field_types.get(ip)[field_index]; |
| ... | @@ -26604,6 +26618,7 @@ fn unionFieldPtr( | ... | @@ -26604,6 +26618,7 @@ fn unionFieldPtr( |
| 26604 | 26618 | ||
| 26605 | const union_obj = zcu.typeToUnion(union_ty).?; | 26619 | const union_obj = zcu.typeToUnion(union_ty).?; |
| 26606 | const tag_ty: Type = .fromInterned(union_obj.enum_tag_type); | 26620 | const tag_ty: Type = .fromInterned(union_obj.enum_tag_type); |
| 26621 | const unrestricted_tag_ty = tag_ty.unrestrictedType(zcu) orelse tag_ty; | ||
| 26607 | 26622 | ||
| 26608 | const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_name_src); | 26623 | const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_name_src); |
| 26609 | const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]); | 26624 | const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]); |
| ... | @@ -26630,17 +26645,17 @@ fn unionFieldPtr( | ... | @@ -26630,17 +26645,17 @@ fn unionFieldPtr( |
| 26630 | break :ct; | 26645 | break :ct; |
| 26631 | } | 26646 | } |
| 26632 | // Store to the union to initialize the tag. | 26647 | // Store to the union to initialize the tag. |
| 26633 | const field_tag = try pt.enumValueFieldIndex(tag_ty, field_index); | 26648 | const field_tag = try pt.enumValueFieldIndex(unrestricted_tag_ty, field_index); |
| 26634 | const payload_val = try field_ty.onePossibleValue(pt) orelse try pt.undefValue(field_ty); | 26649 | const payload_val = try field_ty.onePossibleValue(pt) orelse try pt.undefValue(field_ty); |
| 26635 | const new_union_val = try pt.unionValue(union_ty, field_tag, payload_val); | 26650 | const new_union_val = try pt.unionValue(union_ty, field_tag, payload_val); |
| 26636 | try sema.storePtrVal(block, src, union_ptr_val, new_union_val, union_ty); | 26651 | try sema.storePtrVal(block, src, union_ptr_val, new_union_val, union_ty); |
| 26637 | } else { | 26652 | } else { |
| 26638 | const union_val = try sema.pointerDeref(block, src, union_ptr_val, union_ptr_val.typeOf(zcu)) orelse break :ct; | 26653 | const union_val = try sema.pointerDeref(block, src, union_ptr_val, union_ptr_val.typeOf(zcu)) orelse break :ct; |
| 26639 | if (union_val.isUndef(zcu)) return sema.failWithUseOfUndef(block, src, null); | 26654 | if (union_val.isUndef(zcu)) return sema.failWithUseOfUndef(block, src, null); |
| 26640 | const active_index = tag_ty.enumTagFieldIndex(union_val.unionTag(zcu).?, zcu).?; | 26655 | const active_index = unrestricted_tag_ty.enumTagFieldIndex(union_val.unionTag(zcu).?, zcu).?; |
| 26641 | if (active_index != field_index) { | 26656 | if (active_index != field_index) { |
| 26642 | const msg = msg: { | 26657 | const msg = msg: { |
| 26643 | const active_field_name = tag_ty.enumFieldName(active_index, zcu); | 26658 | const active_field_name = unrestricted_tag_ty.enumFieldName(active_index, zcu); |
| 26644 | const msg = try sema.errMsg(src, "access of union field '{f}' while field '{f}' is active", .{ | 26659 | const msg = try sema.errMsg(src, "access of union field '{f}' while field '{f}' is active", .{ |
| 26645 | field_name.fmt(ip), | 26660 | field_name.fmt(ip), |
| 26646 | active_field_name.fmt(ip), | 26661 | active_field_name.fmt(ip), |
| ... | @@ -26660,19 +26675,26 @@ fn unionFieldPtr( | ... | @@ -26660,19 +26675,26 @@ fn unionFieldPtr( |
| 26660 | // If the union has a tag, we must either set or or safety check it depending on `initializing`. | 26675 | // If the union has a tag, we must either set or or safety check it depending on `initializing`. |
| 26661 | tag: { | 26676 | tag: { |
| 26662 | if (union_ty.containerLayout(zcu) != .auto) break :tag; | 26677 | if (union_ty.containerLayout(zcu) != .auto) break :tag; |
| 26663 | if (tag_ty.classify(zcu) == .one_possible_value) break :tag; | 26678 | if (unrestricted_tag_ty.classify(zcu) == .one_possible_value) break :tag; |
| 26664 | // There is a hypothetical non-trivial tag. We must set it even if not there at runtime, but | 26679 | // There is a hypothetical non-trivial tag. We must set it even if not there at runtime, but |
| 26665 | // only emit a safety check if it's available at runtime (i.e. it's safety-tagged). | 26680 | // only emit a safety check if it's available at runtime (i.e. it's safety-tagged). |
| 26666 | const want_tag = try pt.enumValueFieldIndex(tag_ty, field_index); | 26681 | const want_tag = try pt.enumValueFieldIndex(unrestricted_tag_ty, field_index); |
| 26667 | if (initializing) { | 26682 | if (initializing) { |
| 26668 | const set_tag_inst = try block.addBinOp(.set_union_tag, union_ptr, .fromValue(want_tag)); | 26683 | const set_tag_inst = try block.addBinOp(.set_union_tag, union_ptr, if (unrestricted_tag_ty.toIntern() != tag_ty.toIntern()) |
| 26684 | .fromIntern(try pt.intern(.{ .restricted_value = .{ .ty = tag_ty.toIntern(), .unrestricted_value = want_tag.toIntern() } })) | ||
| 26685 | else | ||
| 26686 | .fromValue(want_tag)); | ||
| 26669 | try sema.checkComptimeKnownStore(block, set_tag_inst, .unneeded); // `unneeded` since this isn't a "proper" store | 26687 | try sema.checkComptimeKnownStore(block, set_tag_inst, .unneeded); // `unneeded` since this isn't a "proper" store |
| 26670 | } else if (block.wantSafety() and union_obj.has_runtime_tag) { | 26688 | } else if (block.wantSafety() and union_obj.has_runtime_tag) { |
| 26671 | // The tag exists at runtime (actual or safety tag), so emit a safety check. | 26689 | // The tag exists at runtime (actual or safety tag), so emit a safety check. |
| 26672 | // TODO would it be better if get_union_tag supported pointers to unions? | 26690 | // TODO would it be better if get_union_tag supported pointers to unions? |
| 26673 | const union_val = try block.addTyOp(.load, union_ty, union_ptr); | 26691 | const union_val = try block.addTyOp(.load, union_ty, union_ptr); |
| 26674 | const active_tag = try block.addTyOp(.get_union_tag, tag_ty, union_val); | 26692 | const active_tag = try block.addTyOp(.get_union_tag, tag_ty, union_val); |
| 26675 | try sema.addSafetyCheckInactiveUnionField(block, src, active_tag, .fromValue(want_tag)); | 26693 | const unrestricted_active_tag = if (unrestricted_tag_ty.toIntern() != tag_ty.toIntern()) |
| 26694 | try sema.unwrapRestricted(block, unrestricted_tag_ty, active_tag, src) | ||
| 26695 | else | ||
| 26696 | active_tag; | ||
| 26697 | try sema.addSafetyCheckInactiveUnionField(block, src, unrestricted_active_tag, .fromValue(want_tag)); | ||
| 26676 | } | 26698 | } |
| 26677 | } | 26699 | } |
| 26678 | if (field_ty.classify(zcu) == .no_possible_value) { | 26700 | if (field_ty.classify(zcu) == .no_possible_value) { |
| ... | @@ -33539,7 +33561,8 @@ fn unionFieldIndex( | ... | @@ -33539,7 +33561,8 @@ fn unionFieldIndex( |
| 33539 | const zcu = pt.zcu; | 33561 | const zcu = pt.zcu; |
| 33540 | const ip = &zcu.intern_pool; | 33562 | const ip = &zcu.intern_pool; |
| 33541 | const union_obj = zcu.typeToUnion(union_ty).?; | 33563 | const union_obj = zcu.typeToUnion(union_ty).?; |
| 33542 | const enum_obj = ip.loadEnumType(union_obj.enum_tag_type); | 33564 | const enum_tag_ty: Type = .fromInterned(union_obj.enum_tag_type); |
| 33565 | const enum_obj = ip.loadEnumType((enum_tag_ty.unrestrictedType(zcu) orelse enum_tag_ty).toIntern()); | ||
| 33543 | const field_index = enum_obj.nameIndex(ip, field_name) orelse | 33566 | const field_index = enum_obj.nameIndex(ip, field_name) orelse |
| 33544 | return sema.failWithBadUnionFieldAccess(block, union_ty, union_obj, field_src, field_name); | 33567 | return sema.failWithBadUnionFieldAccess(block, union_ty, union_obj, field_src, field_name); |
| 33545 | return @intCast(field_index); | 33568 | return @intCast(field_index); |
src/Sema/type_resolution.zig+5-3| ... | @@ -694,8 +694,9 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void { | ... | @@ -694,8 +694,9 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void { |
| 694 | break :tag_ty try sema.analyzeAsType(&block, tag_type_src, .union_enum_tag_type, type_ref); | 694 | break :tag_ty try sema.analyzeAsType(&block, tag_type_src, .union_enum_tag_type, type_ref); |
| 695 | }, | 695 | }, |
| 696 | }; | 696 | }; |
| 697 | const unrestricted_tag_ty = tag_ty.unrestrictedType(zcu) orelse tag_ty; | ||
| 697 | // Because the type is explicitly specified, we need to validate it. | 698 | // Because the type is explicitly specified, we need to validate it. |
| 698 | if (tag_ty.zigTypeTag(zcu) != .@"enum") return sema.fail( | 699 | if (unrestricted_tag_ty.zigTypeTag(zcu) != .@"enum") return sema.fail( |
| 699 | &block, | 700 | &block, |
| 700 | block.src(.container_arg), | 701 | block.src(.container_arg), |
| 701 | "expected enum tag type, found '{f}'", | 702 | "expected enum tag type, found '{f}'", |
| ... | @@ -738,9 +739,10 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void { | ... | @@ -738,9 +739,10 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void { |
| 738 | }, | 739 | }, |
| 739 | }, | 740 | }, |
| 740 | }; | 741 | }; |
| 742 | const unrestricted_enum_tag_ty = enum_tag_ty.unrestrictedType(zcu) orelse enum_tag_ty; | ||
| 741 | 743 | ||
| 742 | try sema.ensureLayoutResolved(enum_tag_ty, block.src(.container_arg), .backing_enum); | 744 | try sema.ensureLayoutResolved(unrestricted_enum_tag_ty, block.src(.container_arg), .backing_enum); |
| 743 | const enum_obj = ip.loadEnumType(enum_tag_ty.toIntern()); | 745 | const enum_obj = ip.loadEnumType(unrestricted_enum_tag_ty.toIntern()); |
| 744 | 746 | ||
| 745 | if (union_obj.is_reified) { | 747 | if (union_obj.is_reified) { |
| 746 | // We have field names in `union_obj.reified_field_names`, but we haven't | 748 | // We have field names in `union_obj.reified_field_names`, but we haven't |
src/Type.zig+1-1| ... | @@ -3241,7 +3241,7 @@ pub fn validateExtern(ty: Type, position: ExternPosition, zcu: *const Zcu) bool | ... | @@ -3241,7 +3241,7 @@ pub fn validateExtern(ty: Type, position: ExternPosition, zcu: *const Zcu) bool |
| 3241 | .pointer => { | 3241 | .pointer => { |
| 3242 | if (ty.isSlice(zcu)) return false; | 3242 | if (ty.isSlice(zcu)) return false; |
| 3243 | const child_ty = ty.childType(zcu); | 3243 | const child_ty = ty.childType(zcu); |
| 3244 | if (child_ty.zigTypeTag(zcu) == .@"fn") { | 3244 | if (zcu.intern_pool.isFunctionType(child_ty.toIntern())) { |
| 3245 | return ty.isConstPtr(zcu) and validateExternCallconv(child_ty.fnCallingConvention(zcu)); | 3245 | return ty.isConstPtr(zcu) and validateExternCallconv(child_ty.fnCallingConvention(zcu)); |
| 3246 | } | 3246 | } |
| 3247 | return true; | 3247 | return true; |
src/Zcu.zig+8-3| ... | @@ -4165,9 +4165,14 @@ pub const UnionLayout = struct { | ... | @@ -4165,9 +4165,14 @@ pub const UnionLayout = struct { |
| 4165 | pub fn unionTagFieldIndex(zcu: *const Zcu, loaded_union: InternPool.LoadedUnionType, enum_tag: Value) ?u32 { | 4165 | pub fn unionTagFieldIndex(zcu: *const Zcu, loaded_union: InternPool.LoadedUnionType, enum_tag: Value) ?u32 { |
| 4166 | const ip = &zcu.intern_pool; | 4166 | const ip = &zcu.intern_pool; |
| 4167 | if (enum_tag.toIntern() == .none) return null; | 4167 | if (enum_tag.toIntern() == .none) return null; |
| 4168 | const enum_tag_key = ip.indexToKey(enum_tag.toIntern()).enum_tag; | 4168 | const enum_tag_key = switch (ip.indexToKey(enum_tag.toIntern())) { |
| 4169 | assert(enum_tag_key.ty == loaded_union.enum_tag_type); | 4169 | else => unreachable, |
| 4170 | const loaded_enum = ip.loadEnumType(loaded_union.enum_tag_type); | 4170 | .enum_tag => |enum_tag_key| enum_tag_key, |
| 4171 | .restricted_value => |restricted_value| ip.indexToKey(restricted_value.unrestricted_value).enum_tag, | ||
| 4172 | }; | ||
| 4173 | const enum_tag_ty: Type = .fromInterned(loaded_union.enum_tag_type); | ||
| 4174 | assert(enum_tag_key.ty == (enum_tag_ty.unrestrictedType(zcu) orelse enum_tag_ty).toIntern()); | ||
| 4175 | const loaded_enum = ip.loadEnumType(enum_tag_key.ty); | ||
| 4171 | return loaded_enum.tagValueIndex(ip, enum_tag_key.int); | 4176 | return loaded_enum.tagValueIndex(ip, enum_tag_key.int); |
| 4172 | } | 4177 | } |
| 4173 | 4178 |
src/codegen/llvm.zig+114-31| ... | @@ -626,8 +626,8 @@ pub const Object = struct { | ... | @@ -626,8 +626,8 @@ pub const Object = struct { |
| 626 | try builder.metadataString(compile_unit_dir), | 626 | try builder.metadataString(compile_unit_dir), |
| 627 | ); | 627 | ); |
| 628 | 628 | ||
| 629 | const debug_enums_fwd_ref = try builder.debugForwardReference(); | 629 | const debug_enums_fwd_ref = try builder.metadataForwardReference(); |
| 630 | const debug_globals_fwd_ref = try builder.debugForwardReference(); | 630 | const debug_globals_fwd_ref = try builder.metadataForwardReference(); |
| 631 | 631 | ||
| 632 | const debug_compile_unit = try builder.debugCompileUnit( | 632 | const debug_compile_unit = try builder.debugCompileUnit( |
| 633 | debug_file, | 633 | debug_file, |
| ... | @@ -701,9 +701,12 @@ pub const Object = struct { | ... | @@ -701,9 +701,12 @@ pub const Object = struct { |
| 701 | const RestrictedDecls = struct { | 701 | const RestrictedDecls = struct { |
| 702 | len: Builder.Variable.Index, | 702 | len: Builder.Variable.Index, |
| 703 | array: Builder.Variable.Index, | 703 | array: Builder.Variable.Index, |
| 704 | enum_seen: []const Builder.Variable.Index, | ||
| 704 | values: std.array_hash_map.Auto(InternPool.Index, Builder.Constant), | 705 | values: std.array_hash_map.Auto(InternPool.Index, Builder.Constant), |
| 706 | metadata: Builder.Metadata.Optional, | ||
| 705 | 707 | ||
| 706 | fn deinit(rd: *RestrictedDecls, gpa: Allocator) void { | 708 | fn deinit(rd: *RestrictedDecls, gpa: Allocator) void { |
| 709 | gpa.free(rd.enum_seen); | ||
| 707 | rd.values.deinit(gpa); | 710 | rd.values.deinit(gpa); |
| 708 | rd.* = undefined; | 711 | rd.* = undefined; |
| 709 | } | 712 | } |
| ... | @@ -716,7 +719,8 @@ pub const Object = struct { | ... | @@ -716,7 +719,8 @@ pub const Object = struct { |
| 716 | const zcu = o.zcu; | 719 | const zcu = o.zcu; |
| 717 | const target = zcu.getTarget(); | 720 | const target = zcu.getTarget(); |
| 718 | const ip = &zcu.intern_pool; | 721 | const ip = &zcu.intern_pool; |
| 719 | const unrestricted_ty = restricted_ty.unrestrictedType(zcu).?; | 722 | const restricted_type_key = ip.indexToKey(restricted_ty.toIntern()).restricted_type; |
| 723 | const unrestricted_type = restricted_type_key.unrestricted_type; | ||
| 720 | 724 | ||
| 721 | const ty_name = ip.loadRestrictedType(restricted_ty.toIntern()).name.toSlice(ip); | 725 | const ty_name = ip.loadRestrictedType(restricted_ty.toIntern()).name.toSlice(ip); |
| 722 | gop.value_ptr.* = .{ | 726 | gop.value_ptr.* = .{ |
| ... | @@ -730,7 +734,28 @@ pub const Object = struct { | ... | @@ -730,7 +734,28 @@ pub const Object = struct { |
| 730 | .void, | 734 | .void, |
| 731 | .default, | 735 | .default, |
| 732 | ), | 736 | ), |
| 737 | .enum_seen = if (ip.isEnumType(unrestricted_type)) enum_seen: { | ||
| 738 | const owner_mod = zcu.fileByIndex(restricted_type_key.zir_index.resolveFile(ip)).mod.?; | ||
| 739 | if (owner_mod.optimize_mode != .ReleaseSmall) break :enum_seen &.{}; | ||
| 740 | const field_names = ip.loadEnumType(unrestricted_type).field_names; | ||
| 741 | const enum_seen = try o.gpa.alloc(Builder.Variable.Index, field_names.len); | ||
| 742 | errdefer o.gpa.free(enum_seen); | ||
| 743 | for (enum_seen, field_names.get(ip)) |*global, field_name| { | ||
| 744 | global.* = try o.builder.addVariable( | ||
| 745 | try o.builder.strtabStringFmt("{s}.{f}", .{ ty_name, field_name.fmt(ip) }), | ||
| 746 | .i1, | ||
| 747 | .default, | ||
| 748 | ); | ||
| 749 | global.setLinkage(.private, &o.builder); | ||
| 750 | global.setMutability(.global, &o.builder); | ||
| 751 | global.setAlignment(InternPool.Alignment.@"1".toLlvm(), &o.builder); | ||
| 752 | global.setUnnamedAddr(.unnamed_addr, &o.builder); | ||
| 753 | try global.setInitializer(.false, &o.builder); | ||
| 754 | } | ||
| 755 | break :enum_seen enum_seen; | ||
| 756 | } else &.{}, | ||
| 733 | .values = .empty, | 757 | .values = .empty, |
| 758 | .metadata = .none, | ||
| 734 | }; | 759 | }; |
| 735 | gop.value_ptr.len.setLinkage(.private, &o.builder); | 760 | gop.value_ptr.len.setLinkage(.private, &o.builder); |
| 736 | gop.value_ptr.len.setMutability(.constant, &o.builder); | 761 | gop.value_ptr.len.setMutability(.constant, &o.builder); |
| ... | @@ -738,23 +763,80 @@ pub const Object = struct { | ... | @@ -738,23 +763,80 @@ pub const Object = struct { |
| 738 | gop.value_ptr.len.setUnnamedAddr(.unnamed_addr, &o.builder); | 763 | gop.value_ptr.len.setUnnamedAddr(.unnamed_addr, &o.builder); |
| 739 | gop.value_ptr.array.setLinkage(.private, &o.builder); | 764 | gop.value_ptr.array.setLinkage(.private, &o.builder); |
| 740 | gop.value_ptr.array.setMutability(.constant, &o.builder); | 765 | gop.value_ptr.array.setMutability(.constant, &o.builder); |
| 741 | gop.value_ptr.array.setAlignment(unrestricted_ty.abiAlignment(zcu).toLlvm(), &o.builder); | 766 | gop.value_ptr.array.setAlignment(Type.fromInterned(unrestricted_type).abiAlignment(zcu).toLlvm(), &o.builder); |
| 742 | // Setting unnamed_addr here would reduce safety, and the module emitting the safety checks may not be the same module | 767 | gop.value_ptr.array.setUnnamedAddr(.unnamed_addr, &o.builder); |
| 743 | // that defined the restricted type. In any case, llvm will add unnamed_addr itself if no safety checks end up being emitted. | ||
| 744 | gop.value_ptr.array.setUnnamedAddr(.default, &o.builder); | ||
| 745 | return gop.value_ptr; | 768 | return gop.value_ptr; |
| 746 | } | 769 | } |
| 747 | fn genRestrictedDecls(o: *Object) Allocator.Error!void { | 770 | fn genRestrictedDecls(o: *Object) Allocator.Error!void { |
| 748 | for (o.restricted_map.values()) |restricted_decls| { | 771 | const zcu = o.zcu; |
| 772 | const ip = &zcu.intern_pool; | ||
| 773 | for (o.restricted_map.keys(), o.restricted_map.values()) |restricted_ty, restricted_decls| { | ||
| 749 | const len = restricted_decls.values.count(); | 774 | const len = restricted_decls.values.count(); |
| 750 | try restricted_decls.len.setInitializer(try o.builder.intConst(.i32, len), &o.builder); | 775 | try restricted_decls.len.setInitializer(try o.builder.intConst(.i32, len), &o.builder); |
| 751 | try restricted_decls.array.setInitializer(switch (len) { | 776 | try restricted_decls.array.setInitializer(switch (len) { |
| 752 | 0 => try o.builder.zeroInitConst(.i8), // ensure unique address | 777 | 0 => try o.builder.structConst(try o.builder.structType(.normal, &.{}), &.{}), |
| 753 | else => try o.builder.arrayConst( | 778 | else => try o.builder.arrayConst( |
| 754 | try o.builder.arrayType(len, restricted_decls.values.values()[0].typeOf(&o.builder)), | 779 | try o.builder.arrayType(len, restricted_decls.values.values()[0].typeOf(&o.builder)), |
| 755 | restricted_decls.values.values(), | 780 | restricted_decls.values.values(), |
| 756 | ), | 781 | ), |
| 757 | }, &o.builder); | 782 | }, &o.builder); |
| 783 | if (restricted_decls.metadata.unwrap()) |metadata| { | ||
| 784 | const gpa = zcu.gpa; | ||
| 785 | const unrestricted_ty = ip.indexToKey(restricted_ty).restricted_type.unrestricted_type; | ||
| 786 | if (ip.isPointerType(unrestricted_ty)) { | ||
| 787 | assert(ip.isFunctionType(ip.indexToKey(unrestricted_ty).ptr_type.child)); | ||
| 788 | const callees = try gpa.alloc(Builder.Metadata, len); | ||
| 789 | defer gpa.free(callees); | ||
| 790 | for (callees, restricted_decls.values.values()) |*callee, value| | ||
| 791 | callee.* = try o.builder.metadataConstant(value); | ||
| 792 | o.builder.resolveMetadataForwardReference(metadata, try o.builder.metadataTuple(callees)); | ||
| 793 | } else { | ||
| 794 | assert(Type.fromInterned(unrestricted_ty).isAbiInt(zcu)); | ||
| 795 | const ints = try gpa.alloc(std.math.big.int.Const, len); | ||
| 796 | defer gpa.free(ints); | ||
| 797 | var range: std.ArrayList(Builder.Metadata) = .empty; | ||
| 798 | defer range.deinit(gpa); | ||
| 799 | o.builder.resolveMetadataForwardReference(metadata, range: { | ||
| 800 | if (len == 0) break :range .empty_tuple; | ||
| 801 | const values = restricted_decls.values.values(); | ||
| 802 | for (ints, values) |*int, value| int.* = value.toInt(&o.builder) orelse | ||
| 803 | break :range .empty_tuple; | ||
| 804 | std.mem.sortUnstable(std.math.big.int.Const, ints, {}, struct { | ||
| 805 | fn lessThan(_: void, lhs: std.math.big.int.Const, rhs: std.math.big.int.Const) bool { | ||
| 806 | return lhs.order(rhs).compare(.lt); | ||
| 807 | } | ||
| 808 | }.lessThan); | ||
| 809 | var int_ty = values[0].typeOf(&o.builder); | ||
| 810 | var start = ints[0]; | ||
| 811 | var end: std.math.big.int.Mutable = .{ | ||
| 812 | .limbs = try gpa.alloc( | ||
| 813 | std.math.big.Limb, | ||
| 814 | std.math.big.int.calcNonZeroTwosCompLimbCount(int_ty.scalarBits(&o.builder)), | ||
| 815 | ), | ||
| 816 | .len = undefined, | ||
| 817 | .positive = undefined, | ||
| 818 | }; | ||
| 819 | defer gpa.free(end.limbs); | ||
| 820 | end.copy(start); | ||
| 821 | for (ints[1..]) |int| { | ||
| 822 | end.addScalar(end.toConst(), 1); | ||
| 823 | if (end.toConst().eql(int)) continue; | ||
| 824 | try range.appendSlice(gpa, &.{ | ||
| 825 | try o.builder.metadataConstant(try o.builder.bigIntConst(int_ty, start)), | ||
| 826 | try o.builder.metadataConstant(try o.builder.bigIntConst(int_ty, end.toConst())), | ||
| 827 | }); | ||
| 828 | start = int; | ||
| 829 | end.copy(int); | ||
| 830 | } | ||
| 831 | end.addScalar(end.toConst(), 1); | ||
| 832 | try range.appendSlice(gpa, &.{ | ||
| 833 | try o.builder.metadataConstant(try o.builder.bigIntConst(int_ty, start)), | ||
| 834 | try o.builder.metadataConstant(try o.builder.bigIntConst(int_ty, end.toConst())), | ||
| 835 | }); | ||
| 836 | break :range try o.builder.metadataTuple(range.items); | ||
| 837 | }); | ||
| 838 | } | ||
| 839 | } | ||
| 758 | } | 840 | } |
| 759 | } | 841 | } |
| 760 | 842 | ||
| ... | @@ -861,17 +943,17 @@ pub const Object = struct { | ... | @@ -861,17 +943,17 @@ pub const Object = struct { |
| 861 | if (!o.builder.strip) { | 943 | if (!o.builder.strip) { |
| 862 | if (o.debug_anyerror_fwd_ref.unwrap()) |fwd_ref| { | 944 | if (o.debug_anyerror_fwd_ref.unwrap()) |fwd_ref| { |
| 863 | const debug_anyerror_type = try o.lowerDebugAnyerrorType(); | 945 | const debug_anyerror_type = try o.lowerDebugAnyerrorType(); |
| 864 | o.builder.resolveDebugForwardReference(fwd_ref, debug_anyerror_type); | 946 | o.builder.resolveMetadataForwardReference(fwd_ref, debug_anyerror_type); |
| 865 | } | 947 | } |
| 866 | 948 | ||
| 867 | try o.flushTypePool(pt); | 949 | try o.flushTypePool(pt); |
| 868 | 950 | ||
| 869 | o.builder.resolveDebugForwardReference( | 951 | o.builder.resolveMetadataForwardReference( |
| 870 | o.debug_enums_fwd_ref.unwrap().?, | 952 | o.debug_enums_fwd_ref.unwrap().?, |
| 871 | try o.builder.metadataTuple(o.debug_enums.items), | 953 | try o.builder.metadataTuple(o.debug_enums.items), |
| 872 | ); | 954 | ); |
| 873 | 955 | ||
| 874 | o.builder.resolveDebugForwardReference( | 956 | o.builder.resolveMetadataForwardReference( |
| 875 | o.debug_globals_fwd_ref.unwrap().?, | 957 | o.debug_globals_fwd_ref.unwrap().?, |
| 876 | try o.builder.metadataTuple(o.debug_globals.items), | 958 | try o.builder.metadataTuple(o.debug_globals.items), |
| 877 | ); | 959 | ); |
| ... | @@ -1936,7 +2018,7 @@ pub const Object = struct { | ... | @@ -1936,7 +2018,7 @@ pub const Object = struct { |
| 1936 | if (!o.builder.strip) { | 2018 | if (!o.builder.strip) { |
| 1937 | assert(@intFromEnum(index) == o.debug_types.items.len); | 2019 | assert(@intFromEnum(index) == o.debug_types.items.len); |
| 1938 | try o.debug_types.ensureUnusedCapacity(gpa, 1); | 2020 | try o.debug_types.ensureUnusedCapacity(gpa, 1); |
| 1939 | const fwd_ref = try o.builder.debugForwardReference(); | 2021 | const fwd_ref = try o.builder.metadataForwardReference(); |
| 1940 | o.debug_types.appendAssumeCapacity(fwd_ref); | 2022 | o.debug_types.appendAssumeCapacity(fwd_ref); |
| 1941 | if (val == .anyerror_type) { | 2023 | if (val == .anyerror_type) { |
| 1942 | assert(o.debug_anyerror_fwd_ref.is_none); | 2024 | assert(o.debug_anyerror_fwd_ref.is_none); |
| ... | @@ -1968,7 +2050,7 @@ pub const Object = struct { | ... | @@ -1968,7 +2050,7 @@ pub const Object = struct { |
| 1968 | .@"fn" => try o.builder.debugSubroutineType(null), | 2050 | .@"fn" => try o.builder.debugSubroutineType(null), |
| 1969 | else => try o.builder.debugSignedType(name_str, 0), | 2051 | else => try o.builder.debugSignedType(name_str, 0), |
| 1970 | }; | 2052 | }; |
| 1971 | o.builder.resolveDebugForwardReference(fwd_ref, debug_incomplete_type); | 2053 | o.builder.resolveMetadataForwardReference(fwd_ref, debug_incomplete_type); |
| 1972 | } | 2054 | } |
| 1973 | } | 2055 | } |
| 1974 | /// Should only be called by the `link.ConstPool` implementation. | 2056 | /// Should only be called by the `link.ConstPool` implementation. |
| ... | @@ -1992,7 +2074,7 @@ pub const Object = struct { | ... | @@ -1992,7 +2074,7 @@ pub const Object = struct { |
| 1992 | assert(o.debug_anyerror_fwd_ref == fwd_ref.toOptional()); | 2074 | assert(o.debug_anyerror_fwd_ref == fwd_ref.toOptional()); |
| 1993 | } else { | 2075 | } else { |
| 1994 | const debug_type = try o.lowerDebugType(pt, ty, fwd_ref); | 2076 | const debug_type = try o.lowerDebugType(pt, ty, fwd_ref); |
| 1995 | o.builder.resolveDebugForwardReference(fwd_ref, debug_type); | 2077 | o.builder.resolveMetadataForwardReference(fwd_ref, debug_type); |
| 1996 | } | 2078 | } |
| 1997 | } | 2079 | } |
| 1998 | } | 2080 | } |
| ... | @@ -2527,7 +2609,7 @@ pub const Object = struct { | ... | @@ -2527,7 +2609,7 @@ pub const Object = struct { |
| 2527 | const payload_fwd_ref = if (layout.tag_size == 0) | 2609 | const payload_fwd_ref = if (layout.tag_size == 0) |
| 2528 | ty_fwd_ref | 2610 | ty_fwd_ref |
| 2529 | else | 2611 | else |
| 2530 | try o.builder.debugForwardReference(); | 2612 | try o.builder.metadataForwardReference(); |
| 2531 | 2613 | ||
| 2532 | for (0..union_type.field_types.len) |field_index| { | 2614 | for (0..union_type.field_types.len) |field_index| { |
| 2533 | const field_ty = union_type.field_types.get(ip)[field_index]; | 2615 | const field_ty = union_type.field_types.get(ip)[field_index]; |
| ... | @@ -2566,7 +2648,7 @@ pub const Object = struct { | ... | @@ -2566,7 +2648,7 @@ pub const Object = struct { |
| 2566 | return debug_payload_type; | 2648 | return debug_payload_type; |
| 2567 | } | 2649 | } |
| 2568 | 2650 | ||
| 2569 | o.builder.resolveDebugForwardReference(payload_fwd_ref, debug_payload_type); | 2651 | o.builder.resolveMetadataForwardReference(payload_fwd_ref, debug_payload_type); |
| 2570 | 2652 | ||
| 2571 | const tag_offset: u64, const payload_offset: u64 = offsets: { | 2653 | const tag_offset: u64, const payload_offset: u64 = offsets: { |
| 2572 | if (layout.tag_align.compare(.gte, layout.payload_align)) { | 2654 | if (layout.tag_align.compare(.gte, layout.payload_align)) { |
| ... | @@ -3988,6 +4070,11 @@ pub const Object = struct { | ... | @@ -3988,6 +4070,11 @@ pub const Object = struct { |
| 3988 | const restricted_decls = try o.getRestrictedDecls(ty); | 4070 | const restricted_decls = try o.getRestrictedDecls(ty); |
| 3989 | const gop = try restricted_decls.values.getOrPut(o.gpa, arg_val); | 4071 | const gop = try restricted_decls.values.getOrPut(o.gpa, arg_val); |
| 3990 | if (!gop.found_existing) gop.value_ptr.* = try o.lowerValue(restricted_value.unrestricted_value); | 4072 | if (!gop.found_existing) gop.value_ptr.* = try o.lowerValue(restricted_value.unrestricted_value); |
| 4073 | if (restricted_decls.enum_seen.len > 0) enum_seen: { | ||
| 4074 | const unrestricted_val: Value = .fromInterned(restricted_value.unrestricted_value); | ||
| 4075 | const tag_index = unrestricted_val.typeOf(zcu).enumTagFieldIndex(unrestricted_val, zcu) orelse break :enum_seen; | ||
| 4076 | try restricted_decls.enum_seen[tag_index].setInitializer(.true, &o.builder); | ||
| 4077 | } | ||
| 3991 | return o.builder.intConst(.i32, gop.index); | 4078 | return o.builder.intConst(.i32, gop.index); |
| 3992 | }, | 4079 | }, |
| 3993 | .memoized_call => unreachable, | 4080 | .memoized_call => unreachable, |
| ... | @@ -4002,37 +4089,29 @@ pub const Object = struct { | ... | @@ -4002,37 +4089,29 @@ pub const Object = struct { |
| 4002 | const zcu = o.zcu; | 4089 | const zcu = o.zcu; |
| 4003 | const ptr = zcu.intern_pool.indexToKey(ptr_val).ptr; | 4090 | const ptr = zcu.intern_pool.indexToKey(ptr_val).ptr; |
| 4004 | const offset: u64 = prev_offset + ptr.byte_offset; | 4091 | const offset: u64 = prev_offset + ptr.byte_offset; |
| 4005 | return switch (ptr.base_addr) { | 4092 | const base_ptr = base_ptr: switch (ptr.base_addr) { |
| 4006 | .nav => |nav| { | 4093 | .nav => |nav| try o.lowerNavRef(nav), |
| 4007 | const base_ptr = try o.lowerNavRef(nav); | ||
| 4008 | return o.builder.gepConst(.inbounds, .i8, base_ptr, null, &.{ | ||
| 4009 | try o.builder.intConst(.i64, offset), | ||
| 4010 | }); | ||
| 4011 | }, | ||
| 4012 | .uav => |uav| { | 4094 | .uav => |uav| { |
| 4013 | const orig_ptr_ty: Type = .fromInterned(uav.orig_ty); | 4095 | const orig_ptr_ty: Type = .fromInterned(uav.orig_ty); |
| 4014 | const base_ptr = try o.lowerUavRef( | 4096 | break :base_ptr try o.lowerUavRef( |
| 4015 | uav.val, | 4097 | uav.val, |
| 4016 | orig_ptr_ty.ptrAlignment(zcu), | 4098 | orig_ptr_ty.ptrAlignment(zcu), |
| 4017 | orig_ptr_ty.ptrAddressSpace(zcu), | 4099 | orig_ptr_ty.ptrAddressSpace(zcu), |
| 4018 | ); | 4100 | ); |
| 4019 | return o.builder.gepConst(.inbounds, .i8, base_ptr, null, &.{ | ||
| 4020 | try o.builder.intConst(.i64, offset), | ||
| 4021 | }); | ||
| 4022 | }, | 4101 | }, |
| 4023 | .int => try o.builder.castConst( | 4102 | .int => return o.builder.castConst( |
| 4024 | .inttoptr, | 4103 | .inttoptr, |
| 4025 | try o.builder.intConst(try o.lowerType(.usize), offset), | 4104 | try o.builder.intConst(try o.lowerType(.usize), offset), |
| 4026 | try o.lowerType(.fromInterned(ptr.ty)), | 4105 | try o.lowerType(.fromInterned(ptr.ty)), |
| 4027 | ), | 4106 | ), |
| 4028 | .eu_payload => |eu_ptr| try o.lowerPtr( | 4107 | .eu_payload => |eu_ptr| return o.lowerPtr( |
| 4029 | eu_ptr, | 4108 | eu_ptr, |
| 4030 | offset + codegen.errUnionPayloadOffset( | 4109 | offset + codegen.errUnionPayloadOffset( |
| 4031 | Value.fromInterned(eu_ptr).typeOf(zcu).childType(zcu), | 4110 | Value.fromInterned(eu_ptr).typeOf(zcu).childType(zcu), |
| 4032 | zcu, | 4111 | zcu, |
| 4033 | ), | 4112 | ), |
| 4034 | ), | 4113 | ), |
| 4035 | .opt_payload => |opt_ptr| try o.lowerPtr(opt_ptr, offset), | 4114 | .opt_payload => |opt_ptr| return o.lowerPtr(opt_ptr, offset), |
| 4036 | .field => |field| { | 4115 | .field => |field| { |
| 4037 | const agg_ty = Value.fromInterned(field.base).typeOf(zcu).childType(zcu); | 4116 | const agg_ty = Value.fromInterned(field.base).typeOf(zcu).childType(zcu); |
| 4038 | const field_off: u64 = switch (agg_ty.zigTypeTag(zcu)) { | 4117 | const field_off: u64 = switch (agg_ty.zigTypeTag(zcu)) { |
| ... | @@ -4061,6 +4140,10 @@ pub const Object = struct { | ... | @@ -4061,6 +4140,10 @@ pub const Object = struct { |
| 4061 | .comptime_field => unreachable, | 4140 | .comptime_field => unreachable, |
| 4062 | .comptime_alloc => unreachable, | 4141 | .comptime_alloc => unreachable, |
| 4063 | }; | 4142 | }; |
| 4143 | if (offset == 0) return base_ptr; | ||
| 4144 | return o.builder.gepConst(.inbounds, .i8, base_ptr, null, &.{ | ||
| 4145 | try o.builder.intConst(.i64, offset), | ||
| 4146 | }); | ||
| 4064 | } | 4147 | } |
| 4065 | 4148 | ||
| 4066 | pub fn lowerPtrToVoid( | 4149 | pub fn lowerPtrToVoid( |
src/codegen/llvm/FuncGen.zig+68-21| ... | @@ -826,7 +826,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif | ... | @@ -826,7 +826,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif |
| 826 | }; | 826 | }; |
| 827 | } | 827 | } |
| 828 | 828 | ||
| 829 | const call = try self.wip.call( | 829 | const call = try self.wip.callMetadata( |
| 830 | switch (modifier) { | 830 | switch (modifier) { |
| 831 | .auto, .never_inline => .normal, | 831 | .auto, .never_inline => .normal, |
| 832 | .never_tail => .notail, | 832 | .never_tail => .notail, |
| ... | @@ -838,6 +838,17 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif | ... | @@ -838,6 +838,17 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif |
| 838 | try o.lowerType(zig_fn_ty), | 838 | try o.lowerType(zig_fn_ty), |
| 839 | llvm_fn, | 839 | llvm_fn, |
| 840 | llvm_args.items, | 840 | llvm_args.items, |
| 841 | .{ | ||
| 842 | .callees = if (air_call.callee.toIndex()) |callee_inst| switch (self.air.instructions.items(.tag)[@intFromEnum(callee_inst)]) { | ||
| 843 | else => .none, | ||
| 844 | .unwrap_restricted, .unwrap_restricted_safe => callees: { | ||
| 845 | const restricted_ty = self.typeOf(self.air.instructions.items(.data)[@intFromEnum(callee_inst)].ty_op.operand); | ||
| 846 | const restricted_decls = try o.getRestrictedDecls(restricted_ty); | ||
| 847 | if (restricted_decls.metadata.is_none) restricted_decls.metadata = .wrap(try o.builder.metadataForwardReference()); | ||
| 848 | break :callees restricted_decls.metadata; | ||
| 849 | }, | ||
| 850 | } else .none, | ||
| 851 | }, | ||
| 841 | "", | 852 | "", |
| 842 | ); | 853 | ); |
| 843 | 854 | ||
| ... | @@ -1667,6 +1678,7 @@ fn lowerTry( | ... | @@ -1667,6 +1678,7 @@ fn lowerTry( |
| 1667 | fn airSwitchBr(self: *FuncGen, inst: Air.Inst.Index, is_dispatch_loop: bool) TodoError!void { | 1678 | fn airSwitchBr(self: *FuncGen, inst: Air.Inst.Index, is_dispatch_loop: bool) TodoError!void { |
| 1668 | const o = self.object; | 1679 | const o = self.object; |
| 1669 | const zcu = o.zcu; | 1680 | const zcu = o.zcu; |
| 1681 | const ip = &zcu.intern_pool; | ||
| 1670 | 1682 | ||
| 1671 | const switch_br = self.air.unwrapSwitch(inst); | 1683 | const switch_br = self.air.unwrapSwitch(inst); |
| 1672 | 1684 | ||
| ... | @@ -1694,6 +1706,7 @@ fn airSwitchBr(self: *FuncGen, inst: Air.Inst.Index, is_dispatch_loop: bool) Tod | ... | @@ -1694,6 +1706,7 @@ fn airSwitchBr(self: *FuncGen, inst: Air.Inst.Index, is_dispatch_loop: bool) Tod |
| 1694 | // This asm is really, really, not what we want. As such, we will construct the jump table manually where | 1706 | // This asm is really, really, not what we want. As such, we will construct the jump table manually where |
| 1695 | // appropriate (the values are dense and relatively few), and use it when lowering dispatches. | 1707 | // appropriate (the values are dense and relatively few), and use it when lowering dispatches. |
| 1696 | 1708 | ||
| 1709 | const cond_ty = self.typeOf(switch_br.operand); | ||
| 1697 | const jmp_table: ?SwitchDispatchInfo.JmpTable = jmp_table: { | 1710 | const jmp_table: ?SwitchDispatchInfo.JmpTable = jmp_table: { |
| 1698 | if (!is_dispatch_loop) break :jmp_table null; | 1711 | if (!is_dispatch_loop) break :jmp_table null; |
| 1699 | 1712 | ||
| ... | @@ -1706,7 +1719,6 @@ fn airSwitchBr(self: *FuncGen, inst: Air.Inst.Index, is_dispatch_loop: bool) Tod | ... | @@ -1706,7 +1719,6 @@ fn airSwitchBr(self: *FuncGen, inst: Air.Inst.Index, is_dispatch_loop: bool) Tod |
| 1706 | // about acceptable - it won't fill L1d cache on most CPUs. | 1719 | // about acceptable - it won't fill L1d cache on most CPUs. |
| 1707 | const max_table_len = 1024; | 1720 | const max_table_len = 1024; |
| 1708 | 1721 | ||
| 1709 | const cond_ty = self.typeOf(switch_br.operand); | ||
| 1710 | switch (cond_ty.zigTypeTag(zcu)) { | 1722 | switch (cond_ty.zigTypeTag(zcu)) { |
| 1711 | .bool, .pointer => break :jmp_table null, | 1723 | .bool, .pointer => break :jmp_table null, |
| 1712 | .@"enum", .int, .error_set, .@"struct", .@"union" => {}, | 1724 | .@"enum", .int, .error_set, .@"struct", .@"union" => {}, |
| ... | @@ -1859,6 +1871,18 @@ fn airSwitchBr(self: *FuncGen, inst: Air.Inst.Index, is_dispatch_loop: bool) Tod | ... | @@ -1859,6 +1871,18 @@ fn airSwitchBr(self: *FuncGen, inst: Air.Inst.Index, is_dispatch_loop: bool) Tod |
| 1859 | assert(self.switch_dispatch_info.remove(inst)); | 1871 | assert(self.switch_dispatch_info.remove(inst)); |
| 1860 | }; | 1872 | }; |
| 1861 | 1873 | ||
| 1874 | const restricted_enum_seen = if (ip.isEnumType(cond_ty.toIntern())) restricted_enum_seen: { | ||
| 1875 | const operand_inst = switch_br.operand.toIndex() orelse break :restricted_enum_seen &.{}; | ||
| 1876 | switch (self.air.instructions.items(.tag)[@intFromEnum(operand_inst)]) { | ||
| 1877 | else => break :restricted_enum_seen &.{}, | ||
| 1878 | .unwrap_restricted, .unwrap_restricted_safe => { | ||
| 1879 | const restricted_ty = self.typeOf(self.air.instructions.items(.data)[@intFromEnum(operand_inst)].ty_op.operand); | ||
| 1880 | const restricted_decls = try o.getRestrictedDecls(restricted_ty); | ||
| 1881 | break :restricted_enum_seen restricted_decls.enum_seen; | ||
| 1882 | }, | ||
| 1883 | } | ||
| 1884 | } else &.{}; | ||
| 1885 | |||
| 1862 | // Generate the initial dispatch. | 1886 | // Generate the initial dispatch. |
| 1863 | // If this is a simple `switch_br`, this is the only dispatch. | 1887 | // If this is a simple `switch_br`, this is the only dispatch. |
| 1864 | try self.lowerSwitchDispatch(inst, switch_br.operand, dispatch_info); | 1888 | try self.lowerSwitchDispatch(inst, switch_br.operand, dispatch_info); |
| ... | @@ -1869,6 +1893,16 @@ fn airSwitchBr(self: *FuncGen, inst: Air.Inst.Index, is_dispatch_loop: bool) Tod | ... | @@ -1869,6 +1893,16 @@ fn airSwitchBr(self: *FuncGen, inst: Air.Inst.Index, is_dispatch_loop: bool) Tod |
| 1869 | const case_block = case_blocks[case.idx]; | 1893 | const case_block = case_blocks[case.idx]; |
| 1870 | self.wip.cursor = .{ .block = case_block }; | 1894 | self.wip.cursor = .{ .block = case_block }; |
| 1871 | if (switch_br.getHint(case.idx) == .cold) _ = try self.wip.callIntrinsicAssumeCold(); | 1895 | if (switch_br.getHint(case.idx) == .cold) _ = try self.wip.callIntrinsicAssumeCold(); |
| 1896 | if (restricted_enum_seen.len > 0) restricted_enum_seen: { | ||
| 1897 | var maybe_any_seen: ?Builder.Value = null; | ||
| 1898 | for (case.items) |item| { | ||
| 1899 | const tag_index = cond_ty.enumTagFieldIndex(.fromInterned(item.toInterned().?), zcu) orelse break :restricted_enum_seen; | ||
| 1900 | const tag_seen = try self.wip.load(.normal, .i1, restricted_enum_seen[tag_index].toValue(&o.builder), InternPool.Alignment.@"1".toLlvm(), ""); | ||
| 1901 | maybe_any_seen = if (maybe_any_seen) |any_seen| try self.wip.bin(.@"or", any_seen, tag_seen, "") else tag_seen; | ||
| 1902 | } | ||
| 1903 | assert(case.ranges.len == 0); // not supported by Sema yet | ||
| 1904 | _ = try self.wip.callIntrinsic(.normal, .none, .assume, &.{}, &.{maybe_any_seen.?}, ""); | ||
| 1905 | } | ||
| 1872 | try self.genBodyDebugScope(null, case.body, .none); | 1906 | try self.genBodyDebugScope(null, case.body, .none); |
| 1873 | } | 1907 | } |
| 1874 | self.wip.cursor = .{ .block = case_blocks[case_blocks.len - 1] }; | 1908 | self.wip.cursor = .{ .block = case_blocks[case_blocks.len - 1] }; |
| ... | @@ -2124,11 +2158,7 @@ fn airSliceElemVal(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder | ... | @@ -2124,11 +2158,7 @@ fn airSliceElemVal(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder |
| 2124 | const elem_align = slice_ty.ptrAlignment(zcu).min(elem_ty.abiAlignment(zcu)); | 2158 | const elem_align = slice_ty.ptrAlignment(zcu).min(elem_ty.abiAlignment(zcu)); |
| 2125 | const access_kind: Builder.MemoryAccessKind = if (slice_info.flags.is_volatile) .@"volatile" else .normal; | 2159 | const access_kind: Builder.MemoryAccessKind = if (slice_info.flags.is_volatile) .@"volatile" else .normal; |
| 2126 | self.maybeMarkAllowZeroAccess(slice_info); | 2160 | self.maybeMarkAllowZeroAccess(slice_info); |
| 2127 | if (isByRef(elem_ty, zcu)) { | 2161 | return self.load(ptr, elem_ty, elem_align.toLlvm(), access_kind); |
| 2128 | return self.loadByRef(ptr, elem_ty, elem_align.toLlvm(), access_kind); | ||
| 2129 | } else { | ||
| 2130 | return self.loadTruncate(access_kind, elem_ty, ptr, elem_align.toLlvm()); | ||
| 2131 | } | ||
| 2132 | } | 2162 | } |
| 2133 | 2163 | ||
| 2134 | fn airSliceElemPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { | 2164 | fn airSliceElemPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { |
| ... | @@ -2153,12 +2183,7 @@ fn airArrayElemVal(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder | ... | @@ -2153,12 +2183,7 @@ fn airArrayElemVal(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder |
| 2153 | const elem_ty = array_ty.childType(zcu); | 2183 | const elem_ty = array_ty.childType(zcu); |
| 2154 | if (isByRef(array_ty, zcu)) { | 2184 | if (isByRef(array_ty, zcu)) { |
| 2155 | const elem_ptr = try self.ptraddScaled(array_llvm_val, rhs, elem_ty.abiSize(zcu)); | 2185 | const elem_ptr = try self.ptraddScaled(array_llvm_val, rhs, elem_ty.abiSize(zcu)); |
| 2156 | if (isByRef(elem_ty, zcu)) { | 2186 | return self.load(elem_ptr, elem_ty, elem_ty.abiAlignment(zcu).toLlvm(), .normal); |
| 2157 | const elem_align = elem_ty.abiAlignment(zcu).toLlvm(); | ||
| 2158 | return self.loadByRef(elem_ptr, elem_ty, elem_align, .normal); | ||
| 2159 | } else { | ||
| 2160 | return self.loadTruncate(.normal, elem_ty, elem_ptr, .default); | ||
| 2161 | } | ||
| 2162 | } | 2187 | } |
| 2163 | 2188 | ||
| 2164 | // This branch can be reached for vectors, which are always by-value. | 2189 | // This branch can be reached for vectors, which are always by-value. |
| ... | @@ -2277,11 +2302,7 @@ fn airStructFieldVal(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Build | ... | @@ -2277,11 +2302,7 @@ fn airStructFieldVal(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Build |
| 2277 | else => struct_ptr_align.minStrict(.fromLog2Units(@ctz(offset))), | 2302 | else => struct_ptr_align.minStrict(.fromLog2Units(@ctz(offset))), |
| 2278 | }; | 2303 | }; |
| 2279 | 2304 | ||
| 2280 | if (isByRef(field_ty, zcu)) { | 2305 | return self.load(field_ptr, field_ty, field_ptr_align.toLlvm(), .normal); |
| 2281 | return self.loadByRef(field_ptr, field_ty, field_ptr_align.toLlvm(), .normal); | ||
| 2282 | } else { | ||
| 2283 | return self.loadTruncate(.normal, field_ty, field_ptr, field_ptr_align.toLlvm()); | ||
| 2284 | } | ||
| 2285 | } | 2306 | } |
| 2286 | 2307 | ||
| 2287 | fn airFieldParentPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { | 2308 | fn airFieldParentPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { |
| ... | @@ -3259,6 +3280,7 @@ fn airUnwrapRestricted(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocat | ... | @@ -3259,6 +3280,7 @@ fn airUnwrapRestricted(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocat |
| 3259 | const target = zcu.getTarget(); | 3280 | const target = zcu.getTarget(); |
| 3260 | const ty_op = fg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 3281 | const ty_op = fg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 3261 | const unrestricted_ty = ty_op.ty.toType(); | 3282 | const unrestricted_ty = ty_op.ty.toType(); |
| 3283 | const unrestricted_align = unrestricted_ty.abiAlignment(zcu); | ||
| 3262 | const restricted_ty = fg.typeOf(ty_op.operand); | 3284 | const restricted_ty = fg.typeOf(ty_op.operand); |
| 3263 | const operand = try fg.resolveInst(ty_op.operand); | 3285 | const operand = try fg.resolveInst(ty_op.operand); |
| 3264 | const restricted_decls = try o.getRestrictedDecls(restricted_ty); | 3286 | const restricted_decls = try o.getRestrictedDecls(restricted_ty); |
| ... | @@ -3281,7 +3303,13 @@ fn airUnwrapRestricted(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocat | ... | @@ -3281,7 +3303,13 @@ fn airUnwrapRestricted(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocat |
| 3281 | fg.wip.cursor = .{ .block = valid_block }; | 3303 | fg.wip.cursor = .{ .block = valid_block }; |
| 3282 | } | 3304 | } |
| 3283 | const ptr = try fg.ptraddScaled(restricted_decls.array.toValue(&o.builder), operand, unrestricted_ty.abiSize(zcu)); | 3305 | const ptr = try fg.ptraddScaled(restricted_decls.array.toValue(&o.builder), operand, unrestricted_ty.abiSize(zcu)); |
| 3284 | return fg.load(ptr, unrestricted_ty, unrestricted_ty.abiAlignment(zcu).toLlvm(), .normal); | 3306 | if (isByRef(unrestricted_ty, zcu)) return fg.loadByRef(ptr, unrestricted_ty, unrestricted_align.toLlvm(), .normal); |
| 3307 | return fg.wip.loadMetadata(.normal, try o.lowerType(unrestricted_ty), ptr, unrestricted_align.toLlvm(), .{ | ||
| 3308 | .range = if (unrestricted_ty.isAbiInt(zcu)) range: { | ||
| 3309 | if (restricted_decls.metadata.is_none) restricted_decls.metadata = .wrap(try o.builder.metadataForwardReference()); | ||
| 3310 | break :range restricted_decls.metadata; | ||
| 3311 | } else .none, | ||
| 3312 | }, ""); | ||
| 3285 | } | 3313 | } |
| 3286 | 3314 | ||
| 3287 | fn airWasmMemorySize(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { | 3315 | fn airWasmMemorySize(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { |
| ... | @@ -6042,8 +6070,27 @@ fn airUnionInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va | ... | @@ -6042,8 +6070,27 @@ fn airUnionInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va |
| 6042 | } | 6070 | } |
| 6043 | 6071 | ||
| 6044 | if (layout.tag_size != 0) { | 6072 | if (layout.tag_size != 0) { |
| 6045 | const loaded_enum = ip.loadEnumType(union_obj.enum_tag_type); | 6073 | const tag_ty: Type = .fromInterned(union_obj.enum_tag_type); |
| 6046 | const llvm_tag_val = switch (loaded_enum.field_values.getOrNone(ip, extra.field_index)) { | 6074 | const llvm_tag_val = if (tag_ty.unrestrictedType(zcu)) |unrestricted_tag_ty| llvm_tag_val: { |
| 6075 | const restricted_decls = try o.getRestrictedDecls(tag_ty); | ||
| 6076 | const unrestricted_tag_val = try self.pt.enumValueFieldIndex(unrestricted_tag_ty, extra.field_index); | ||
| 6077 | const tag_val = try self.pt.intern(.{ .restricted_value = .{ | ||
| 6078 | .ty = union_obj.enum_tag_type, | ||
| 6079 | .unrestricted_value = unrestricted_tag_val.toIntern(), | ||
| 6080 | } }); | ||
| 6081 | const gop = try restricted_decls.values.getOrPut(o.gpa, tag_val); | ||
| 6082 | if (!gop.found_existing) gop.value_ptr.* = try o.lowerValue(unrestricted_tag_val.toIntern()); | ||
| 6083 | if (restricted_decls.enum_seen.len > 0) enum_seen: { | ||
| 6084 | const tag_index = unrestricted_tag_ty.enumTagFieldIndex(unrestricted_tag_val, zcu) orelse break :enum_seen; | ||
| 6085 | _ = try self.wip.store( | ||
| 6086 | .normal, | ||
| 6087 | .true, | ||
| 6088 | restricted_decls.enum_seen[tag_index].toValue(&o.builder), | ||
| 6089 | InternPool.Alignment.@"1".toLlvm(), | ||
| 6090 | ); | ||
| 6091 | } | ||
| 6092 | break :llvm_tag_val try o.builder.intConst(.i32, gop.index); | ||
| 6093 | } else switch (ip.loadEnumType(union_obj.enum_tag_type).field_values.getOrNone(ip, extra.field_index)) { | ||
| 6047 | .none => try o.builder.intConst( | 6094 | .none => try o.builder.intConst( |
| 6048 | try o.lowerType(.fromInterned(union_obj.enum_tag_type)), | 6095 | try o.lowerType(.fromInterned(union_obj.enum_tag_type)), |
| 6049 | extra.field_index, // auto-numbered | 6096 | extra.field_index, // auto-numbered |
src/codegen/x86_64/CodeGen.zig+2-1| ... | @@ -172764,8 +172764,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -172764,8 +172764,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 172764 | var res = try cg.tempAllocMem(union_ty); | 172764 | var res = try cg.tempAllocMem(union_ty); |
| 172765 | const union_layout = union_ty.unionGetLayout(zcu); | 172765 | const union_layout = union_ty.unionGetLayout(zcu); |
| 172766 | if (union_layout.tag_size > 0) { | 172766 | if (union_layout.tag_size > 0) { |
| 172767 | const tag_ty = union_ty.unionTagTypeRuntime(zcu).?; | ||
| 172767 | var tag_temp = try cg.tempFromValue(try pt.enumValueFieldIndex( | 172768 | var tag_temp = try cg.tempFromValue(try pt.enumValueFieldIndex( |
| 172768 | union_ty.unionTagTypeRuntime(zcu).?, | 172769 | tag_ty.unrestrictedType(zcu) orelse tag_ty, |
| 172769 | union_init.field_index, | 172770 | union_init.field_index, |
| 172770 | )); | 172771 | )); |
| 172771 | try res.write(&tag_temp, .{ | 172772 | try res.write(&tag_temp, .{ |
src/link/Dwarf.zig+2-1| ... | @@ -4046,7 +4046,8 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co | ... | @@ -4046,7 +4046,8 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co |
| 4046 | const union_layout = Type.getUnionLayout(loaded_union, zcu); | 4046 | const union_layout = Type.getUnionLayout(loaded_union, zcu); |
| 4047 | try diw.writeUleb128(union_layout.abi_size); | 4047 | try diw.writeUleb128(union_layout.abi_size); |
| 4048 | try diw.writeUleb128(union_layout.abi_align.toByteUnits().?); | 4048 | try diw.writeUleb128(union_layout.abi_align.toByteUnits().?); |
| 4049 | const loaded_tag = ip.loadEnumType(loaded_union.enum_tag_type); | 4049 | const enum_tag_ty: Type = .fromInterned(loaded_union.enum_tag_type); |
| 4050 | const loaded_tag = ip.loadEnumType((enum_tag_ty.unrestrictedType(zcu) orelse enum_tag_ty).toIntern()); | ||
| 4050 | if (loaded_union.has_runtime_tag) { | 4051 | if (loaded_union.has_runtime_tag) { |
| 4051 | try wip_nav.abbrevCode(.tagged_union); | 4052 | try wip_nav.abbrevCode(.tagged_union); |
| 4052 | try wip_nav.infoSectionOffset( | 4053 | try wip_nav.infoSectionOffset( |
src/zig_llvm.cpp+10| ... | @@ -51,6 +51,7 @@ | ... | @@ -51,6 +51,7 @@ |
| 51 | #include <llvm/Target/CodeGenCWrappers.h> | 51 | #include <llvm/Target/CodeGenCWrappers.h> |
| 52 | #include <llvm/Transforms/IPO.h> | 52 | #include <llvm/Transforms/IPO.h> |
| 53 | #include <llvm/Transforms/IPO/AlwaysInliner.h> | 53 | #include <llvm/Transforms/IPO/AlwaysInliner.h> |
| 54 | #include <llvm/Transforms/IPO/GlobalOpt.h> | ||
| 54 | #include <llvm/Transforms/Instrumentation/ThreadSanitizer.h> | 55 | #include <llvm/Transforms/Instrumentation/ThreadSanitizer.h> |
| 55 | #include <llvm/Transforms/Instrumentation/SanitizerCoverage.h> | 56 | #include <llvm/Transforms/Instrumentation/SanitizerCoverage.h> |
| 56 | #include <llvm/Transforms/Scalar.h> | 57 | #include <llvm/Transforms/Scalar.h> |
| ... | @@ -348,6 +349,10 @@ ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machi | ... | @@ -348,6 +349,10 @@ ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machi |
| 348 | }); | 349 | }); |
| 349 | 350 | ||
| 350 | pass_builder.registerOptimizerLastEPCallback([&](ModulePassManager &module_pm, OptimizationLevel level, ThinOrFullLTOPhase lto_phase) { | 351 | pass_builder.registerOptimizerLastEPCallback([&](ModulePassManager &module_pm, OptimizationLevel level, ThinOrFullLTOPhase lto_phase) { |
| 352 | // Restricted enums require an extra global optimization pass sometime after | ||
| 353 | // DropUnnecessaryAssumesPass to fully eliminate the helper global variables. | ||
| 354 | if (level.isOptimizingForSize()) module_pm.addPass(GlobalOptPass()); | ||
| 355 | |||
| 351 | if (!early_san) { | 356 | if (!early_san) { |
| 352 | // Code coverage instrumentation. | 357 | // Code coverage instrumentation. |
| 353 | if (options->sancov) { | 358 | if (options->sancov) { |
| ... | @@ -404,6 +409,11 @@ ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machi | ... | @@ -404,6 +409,11 @@ ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machi |
| 404 | } | 409 | } |
| 405 | } | 410 | } |
| 406 | 411 | ||
| 412 | if (false) { | ||
| 413 | module_pm.printPipeline(outs(), [](StringRef S) { return S; }); | ||
| 414 | outs() << '\n'; | ||
| 415 | } | ||
| 416 | |||
| 407 | // Optimization phase | 417 | // Optimization phase |
| 408 | module_pm.run(llvm_module, module_am); | 418 | module_pm.run(llvm_module, module_am); |
| 409 | 419 |