authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-03-18 01:02:55+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-03-18 01:02:55+01:00
logf8997aca8f62eef4968e4abf817ece4eb4e91c38
tree727f3d0fb0581aa5e5d77652f84e832dda90879e
parent032319c94257e650abc7a4743298154c218dba89
parent85837de476a919e42da101d42da848a5f181fb38

Merge pull request 'llvm: some random fixes' (#31552) from llvm-fixes into master

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/31552 Reviewed-by: Andrew Kelley <andrew@ziglang.org>

1 files changed, 116 insertions(+), 99 deletions(-)

src/codegen/llvm.zig+116-99
...@@ -1438,8 +1438,7 @@ pub const Object = struct {...@@ -1438,8 +1438,7 @@ pub const Object = struct {
1438 const param = wip.arg(llvm_arg_i);1438 const param = wip.arg(llvm_arg_i);
1439 llvm_arg_i += 1;1439 llvm_arg_i += 1;
1440 const field_ptr = try wip.gepStruct(llvm_ty, arg_ptr, field_i, "");1440 const field_ptr = try wip.gepStruct(llvm_ty, arg_ptr, field_i, "");
1441 const alignment =1441 const alignment = Builder.Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8));
1442 Builder.Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8));
1443 _ = try wip.store(.normal, param, field_ptr, alignment);1442 _ = try wip.store(.normal, param, field_ptr, alignment);
1444 }1443 }
14451444
...@@ -1625,13 +1624,7 @@ pub const Object = struct {...@@ -1625,13 +1624,7 @@ pub const Object = struct {
1625 .pt = pt,1624 .pt = pt,
1626 .err_msg = null,1625 .err_msg = null,
1627 };1626 };
1628 ng.genDecl() catch |err| switch (err) {1627 try ng.genDecl();
1629 error.CodegenFail => switch (pt.zcu.codegenFailMsg(nav_index, ng.err_msg.?)) {
1630 error.CodegenFail => return,
1631 error.OutOfMemory => |e| return e,
1632 },
1633 else => |e| return e,
1634 };
1635 try self.flushTypePool(pt);1628 try self.flushTypePool(pt);
1636 }1629 }
16371630
...@@ -1713,10 +1706,7 @@ pub const Object = struct {...@@ -1713,10 +1706,7 @@ pub const Object = struct {
1713 const global_index = variable_index.ptrConst(&o.builder).global;1706 const global_index = variable_index.ptrConst(&o.builder).global;
1714 gop.value_ptr.* = global_index;1707 gop.value_ptr.* = global_index;
1715 // This line invalidates `gop`.1708 // This line invalidates `gop`.
1716 const init_val = o.lowerValue(pt, exported_value) catch |err| switch (err) {1709 const init_val = try o.lowerValue(pt, exported_value);
1717 error.OutOfMemory => return error.OutOfMemory,
1718 error.CodegenFail => return error.AnalysisFail,
1719 };
1720 try variable_index.setInitializer(init_val, &o.builder);1710 try variable_index.setInitializer(init_val, &o.builder);
1721 break :i global_index;1711 break :i global_index;
1722 };1712 };
...@@ -1834,6 +1824,9 @@ pub const Object = struct {...@@ -1834,6 +1824,9 @@ pub const Object = struct {
18341824
1835 pub fn updateContainerType(o: *Object, pt: Zcu.PerThread, ty: InternPool.Index, success: bool) Allocator.Error!void {1825 pub fn updateContainerType(o: *Object, pt: Zcu.PerThread, ty: InternPool.Index, success: bool) Allocator.Error!void {
1836 try o.type_pool.updateContainerType(pt, .{ .llvm = o }, ty, success);1826 try o.type_pool.updateContainerType(pt, .{ .llvm = o }, ty, success);
1827 if (o.named_enum_map.get(ty)) |function_index| {
1828 try o.updateIsNamedEnumValueFunction(pt, .fromInterned(ty), function_index);
1829 }
1837 }1830 }
18381831
1839 /// Should only be called by the `link.ConstPool` implementation.1832 /// Should only be called by the `link.ConstPool` implementation.
...@@ -2907,7 +2900,7 @@ pub const Object = struct {...@@ -2907,7 +2900,7 @@ pub const Object = struct {
2907 uav: InternPool.Index,2900 uav: InternPool.Index,
2908 llvm_addr_space: Builder.AddrSpace,2901 llvm_addr_space: Builder.AddrSpace,
2909 alignment: InternPool.Alignment,2902 alignment: InternPool.Alignment,
2910 ) Error!Builder.Variable.Index {2903 ) Allocator.Error!Builder.Variable.Index {
2911 assert(alignment != .none);2904 assert(alignment != .none);
2912 // TODO: Add address space to the anon_decl_map2905 // TODO: Add address space to the anon_decl_map
2913 const gop = try o.uav_map.getOrPut(o.gpa, uav);2906 const gop = try o.uav_map.getOrPut(o.gpa, uav);
...@@ -3506,7 +3499,7 @@ pub const Object = struct {...@@ -3506,7 +3499,7 @@ pub const Object = struct {
3506 );3499 );
3507 }3500 }
35083501
3509 fn lowerValue(o: *Object, pt: Zcu.PerThread, arg_val: InternPool.Index) Error!Builder.Constant {3502 fn lowerValue(o: *Object, pt: Zcu.PerThread, arg_val: InternPool.Index) Allocator.Error!Builder.Constant {
3510 const zcu = pt.zcu;3503 const zcu = pt.zcu;
3511 const ip = &zcu.intern_pool;3504 const ip = &zcu.intern_pool;
3512 const target = zcu.getTarget();3505 const target = zcu.getTarget();
...@@ -4019,7 +4012,7 @@ pub const Object = struct {...@@ -4019,7 +4012,7 @@ pub const Object = struct {
4019 pt: Zcu.PerThread,4012 pt: Zcu.PerThread,
4020 ptr_val: InternPool.Index,4013 ptr_val: InternPool.Index,
4021 prev_offset: u64,4014 prev_offset: u64,
4022 ) Error!Builder.Constant {4015 ) Allocator.Error!Builder.Constant {
4023 const zcu = pt.zcu;4016 const zcu = pt.zcu;
4024 const ptr = zcu.intern_pool.indexToKey(ptr_val).ptr;4017 const ptr = zcu.intern_pool.indexToKey(ptr_val).ptr;
4025 const offset: u64 = prev_offset + ptr.byte_offset;4018 const offset: u64 = prev_offset + ptr.byte_offset;
...@@ -4086,7 +4079,7 @@ pub const Object = struct {...@@ -4086,7 +4079,7 @@ pub const Object = struct {
4086 o: *Object,4079 o: *Object,
4087 pt: Zcu.PerThread,4080 pt: Zcu.PerThread,
4088 uav: InternPool.Key.Ptr.BaseAddr.Uav,4081 uav: InternPool.Key.Ptr.BaseAddr.Uav,
4089 ) Error!Builder.Constant {4082 ) Allocator.Error!Builder.Constant {
4090 const zcu = pt.zcu;4083 const zcu = pt.zcu;
4091 const ip = &zcu.intern_pool;4084 const ip = &zcu.intern_pool;
4092 const uav_val = uav.val;4085 const uav_val = uav.val;
...@@ -4363,6 +4356,58 @@ pub const Object = struct {...@@ -4363,6 +4356,58 @@ pub const Object = struct {
4363 const index = try o.type_pool.get(pt, .{ .llvm = o }, ty.toIntern());4356 const index = try o.type_pool.get(pt, .{ .llvm = o }, ty.toIntern());
4364 return o.lazy_abi_aligns.items[@intFromEnum(index)];4357 return o.lazy_abi_aligns.items[@intFromEnum(index)];
4365 }4358 }
4359
4360 fn updateIsNamedEnumValueFunction(
4361 o: *Object,
4362 pt: Zcu.PerThread,
4363 enum_ty: Type,
4364 function_index: Builder.Function.Index,
4365 ) Allocator.Error!void {
4366 const zcu = pt.zcu;
4367 const builder = &o.builder;
4368 const loaded_enum = zcu.intern_pool.loadEnumType(enum_ty.toIntern());
4369 function_index.ptrConst(builder).global.ptr(builder).type = try builder.fnType(
4370 .i1,
4371 &.{try o.lowerType(pt, .fromInterned(loaded_enum.int_tag_type))},
4372 .normal,
4373 );
4374
4375 var attributes: Builder.FunctionAttributes.Wip = .{};
4376 defer attributes.deinit(builder);
4377 try o.addCommonFnAttributes(&attributes, zcu.root_mod, zcu.root_mod.omit_frame_pointer);
4378
4379 function_index.setLinkage(.internal, builder);
4380 function_index.setCallConv(.fastcc, builder);
4381 function_index.setAttributes(try attributes.finish(builder), builder);
4382
4383 var wip: Builder.WipFunction = try .init(builder, .{
4384 .function = function_index,
4385 .strip = true,
4386 });
4387 defer wip.deinit();
4388 wip.cursor = .{ .block = try wip.block(0, "Entry") };
4389
4390 const named_block = try wip.block(@intCast(loaded_enum.field_names.len), "Named");
4391 const unnamed_block = try wip.block(1, "Unnamed");
4392 const tag_int_value = wip.arg(0);
4393 var wip_switch = try wip.@"switch"(tag_int_value, unnamed_block, @intCast(loaded_enum.field_names.len), .none);
4394 defer wip_switch.finish(&wip);
4395
4396 for (0..loaded_enum.field_names.len) |field_index| {
4397 const this_tag_int_value = try o.lowerValue(
4398 pt,
4399 (try pt.enumValueFieldIndex(enum_ty, @intCast(field_index))).toIntern(),
4400 );
4401 try wip_switch.addCase(this_tag_int_value, named_block, &wip);
4402 }
4403 wip.cursor = .{ .block = named_block };
4404 _ = try wip.ret(.true);
4405
4406 wip.cursor = .{ .block = unnamed_block };
4407 _ = try wip.ret(.false);
4408
4409 try wip.finish();
4410 }
4366};4411};
43674412
4368pub const NavGen = struct {4413pub const NavGen = struct {
...@@ -6105,7 +6150,7 @@ pub const FuncGen = struct {...@@ -6105,7 +6150,7 @@ pub const FuncGen = struct {
6105 const body = unwrapped_try.else_body;6150 const body = unwrapped_try.else_body;
6106 const err_union_ty = self.typeOf(unwrapped_try.error_union);6151 const err_union_ty = self.typeOf(unwrapped_try.error_union);
6107 const is_unused = self.liveness.isUnused(inst);6152 const is_unused = self.liveness.isUnused(inst);
6108 return lowerTry(self, err_union, body, err_union_ty, false, false, is_unused, err_cold);6153 return lowerTry(self, err_union, body, err_union_ty, false, .none, false, is_unused, err_cold);
6109 }6154 }
61106155
6111 fn airTryPtr(self: *FuncGen, inst: Air.Inst.Index, err_cold: bool) !Builder.Value {6156 fn airTryPtr(self: *FuncGen, inst: Air.Inst.Index, err_cold: bool) !Builder.Value {
...@@ -6113,12 +6158,13 @@ pub const FuncGen = struct {...@@ -6113,12 +6158,13 @@ pub const FuncGen = struct {
6113 const unwrapped_try = self.air.unwrapTryPtr(inst);6158 const unwrapped_try = self.air.unwrapTryPtr(inst);
6114 const err_union_ptr = try self.resolveInst(unwrapped_try.error_union_ptr);6159 const err_union_ptr = try self.resolveInst(unwrapped_try.error_union_ptr);
6115 const body = unwrapped_try.else_body;6160 const body = unwrapped_try.else_body;
6116 const err_union_ty = self.typeOf(unwrapped_try.error_union_ptr).childType(zcu);6161 const err_union_ptr_ty = self.typeOf(unwrapped_try.error_union_ptr);
6162 const err_union_ty = err_union_ptr_ty.childType(zcu);
6117 const is_unused = self.liveness.isUnused(inst);6163 const is_unused = self.liveness.isUnused(inst);
61186164
6119 self.maybeMarkAllowZeroAccess(self.typeOf(unwrapped_try.error_union_ptr).ptrInfo(zcu));6165 self.maybeMarkAllowZeroAccess(self.typeOf(unwrapped_try.error_union_ptr).ptrInfo(zcu));
61206166
6121 return lowerTry(self, err_union_ptr, body, err_union_ty, true, true, is_unused, err_cold);6167 return lowerTry(self, err_union_ptr, body, err_union_ty, true, err_union_ptr_ty.ptrAlignment(zcu), true, is_unused, err_cold);
6122 }6168 }
61236169
6124 fn lowerTry(6170 fn lowerTry(
...@@ -6127,6 +6173,7 @@ pub const FuncGen = struct {...@@ -6127,6 +6173,7 @@ pub const FuncGen = struct {
6127 body: []const Air.Inst.Index,6173 body: []const Air.Inst.Index,
6128 err_union_ty: Type,6174 err_union_ty: Type,
6129 operand_is_ptr: bool,6175 operand_is_ptr: bool,
6176 operand_ptr_align: InternPool.Alignment,
6130 can_elide_load: bool,6177 can_elide_load: bool,
6131 is_unused: bool,6178 is_unused: bool,
6132 err_cold: bool,6179 err_cold: bool,
...@@ -6139,15 +6186,19 @@ pub const FuncGen = struct {...@@ -6139,15 +6186,19 @@ pub const FuncGen = struct {
6139 const err_union_llvm_ty = try o.lowerType(pt, err_union_ty);6186 const err_union_llvm_ty = try o.lowerType(pt, err_union_ty);
6140 const error_type = try o.errorIntType(pt);6187 const error_type = try o.errorIntType(pt);
61416188
6189 const err_set_align: InternPool.Alignment, const payload_align: InternPool.Alignment = if (operand_is_ptr) .{
6190 operand_ptr_align.minStrict(Type.anyerror.abiAlignment(zcu)),
6191 operand_ptr_align.minStrict(payload_ty.abiAlignment(zcu)),
6192 } else .{ .none, .none };
6193
6142 if (!err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu)) {6194 if (!err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu)) {
6143 const loaded = loaded: {6195 const loaded = loaded: {
6144 const access_kind: Builder.MemoryAccessKind =6196 const access_kind: Builder.MemoryAccessKind =
6145 if (err_union_ty.isVolatilePtr(zcu)) .@"volatile" else .normal;6197 if (err_union_ty.isVolatilePtr(zcu)) .@"volatile" else .normal;
61466198
6147 if (!payload_has_bits) {6199 if (!payload_has_bits) {
6148 // TODO add alignment to this load
6149 break :loaded if (operand_is_ptr)6200 break :loaded if (operand_is_ptr)
6150 try fg.wip.load(access_kind, error_type, err_union, .default, "")6201 try fg.wip.load(access_kind, error_type, err_union, err_set_align.toLlvm(), "")
6151 else6202 else
6152 err_union;6203 err_union;
6153 }6204 }
...@@ -6155,12 +6206,11 @@ pub const FuncGen = struct {...@@ -6155,12 +6206,11 @@ pub const FuncGen = struct {
6155 if (operand_is_ptr or isByRef(err_union_ty, zcu)) {6206 if (operand_is_ptr or isByRef(err_union_ty, zcu)) {
6156 const err_field_ptr =6207 const err_field_ptr =
6157 try fg.wip.gepStruct(err_union_llvm_ty, err_union, err_field_index, "");6208 try fg.wip.gepStruct(err_union_llvm_ty, err_union, err_field_index, "");
6158 // TODO add alignment to this load
6159 break :loaded try fg.wip.load(6209 break :loaded try fg.wip.load(
6160 if (operand_is_ptr) access_kind else .normal,6210 if (operand_is_ptr) access_kind else .normal,
6161 error_type,6211 error_type,
6162 err_field_ptr,6212 err_field_ptr,
6163 .default,6213 err_set_align.toLlvm(),
6164 "",6214 "",
6165 );6215 );
6166 }6216 }
...@@ -6186,15 +6236,14 @@ pub const FuncGen = struct {...@@ -6186,15 +6236,14 @@ pub const FuncGen = struct {
6186 return fg.wip.gepStruct(err_union_llvm_ty, err_union, offset, "");6236 return fg.wip.gepStruct(err_union_llvm_ty, err_union, offset, "");
6187 } else if (isByRef(err_union_ty, zcu)) {6237 } else if (isByRef(err_union_ty, zcu)) {
6188 const payload_ptr = try fg.wip.gepStruct(err_union_llvm_ty, err_union, offset, "");6238 const payload_ptr = try fg.wip.gepStruct(err_union_llvm_ty, err_union, offset, "");
6189 const payload_alignment = payload_ty.abiAlignment(zcu).toLlvm();
6190 if (isByRef(payload_ty, zcu)) {6239 if (isByRef(payload_ty, zcu)) {
6191 if (can_elide_load)6240 if (can_elide_load)
6192 return payload_ptr;6241 return payload_ptr;
61936242
6194 return fg.loadByRef(payload_ptr, payload_ty, payload_alignment, .normal);6243 return fg.loadByRef(payload_ptr, payload_ty, payload_align.toLlvm(), .normal);
6195 }6244 }
6196 const load_ty = err_union_llvm_ty.structFields(&o.builder)[offset];6245 const load_ty = err_union_llvm_ty.structFields(&o.builder)[offset];
6197 return fg.wip.load(.normal, load_ty, payload_ptr, payload_alignment, "");6246 return fg.wip.load(.normal, load_ty, payload_ptr, payload_align.toLlvm(), "");
6198 }6247 }
6199 return fg.wip.extractValue(err_union, &.{offset}, "");6248 return fg.wip.extractValue(err_union, &.{offset}, "");
6200 }6249 }
...@@ -6667,20 +6716,20 @@ pub const FuncGen = struct {...@@ -6667,20 +6716,20 @@ pub const FuncGen = struct {
6667 const slice_ty = self.typeOf(bin_op.lhs);6716 const slice_ty = self.typeOf(bin_op.lhs);
6668 const slice = try self.resolveInst(bin_op.lhs);6717 const slice = try self.resolveInst(bin_op.lhs);
6669 const index = try self.resolveInst(bin_op.rhs);6718 const index = try self.resolveInst(bin_op.rhs);
6670 const elem_ty = slice_ty.childType(zcu);6719 const slice_info = slice_ty.ptrInfo(zcu);
6720 assert(slice_info.flags.size == .slice);
6721 const elem_ty: Type = .fromInterned(slice_info.child);
6671 const llvm_elem_ty = try o.lowerType(pt, elem_ty);6722 const llvm_elem_ty = try o.lowerType(pt, elem_ty);
6672 const base_ptr = try self.wip.extractValue(slice, &.{0}, "");6723 const base_ptr = try self.wip.extractValue(slice, &.{0}, "");
6673 const ptr = try self.wip.gep(.inbounds, llvm_elem_ty, base_ptr, &.{index}, "");6724 const ptr = try self.wip.gep(.inbounds, llvm_elem_ty, base_ptr, &.{index}, "");
6725 const elem_align = slice_ty.ptrAlignment(zcu).min(elem_ty.abiAlignment(zcu));
6726 const access_kind: Builder.MemoryAccessKind = if (slice_info.flags.is_volatile) .@"volatile" else .normal;
6727 self.maybeMarkAllowZeroAccess(slice_info);
6674 if (isByRef(elem_ty, zcu)) {6728 if (isByRef(elem_ty, zcu)) {
6675 self.maybeMarkAllowZeroAccess(slice_ty.ptrInfo(zcu));6729 return self.loadByRef(ptr, elem_ty, elem_align.toLlvm(), access_kind);
66766730 } else {
6677 const slice_align = (slice_ty.ptrAlignment(zcu).min(elem_ty.abiAlignment(zcu))).toLlvm();6731 return self.loadTruncate(access_kind, elem_ty, ptr, elem_align.toLlvm());
6678 return self.loadByRef(ptr, elem_ty, slice_align, if (slice_ty.isVolatilePtr(zcu)) .@"volatile" else .normal);
6679 }6732 }
6680
6681 self.maybeMarkAllowZeroAccess(slice_ty.ptrInfo(zcu));
6682
6683 return self.load(ptr, slice_ty);
6684 }6733 }
66856734
6686 fn airSliceElemPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {6735 fn airSliceElemPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
...@@ -7461,7 +7510,7 @@ pub const FuncGen = struct {...@@ -7461,7 +7510,7 @@ pub const FuncGen = struct {
74617510
7462 if (optional_ty.optionalReprIsPayload(zcu)) {7511 if (optional_ty.optionalReprIsPayload(zcu)) {
7463 const loaded = if (operand_is_ptr)7512 const loaded = if (operand_is_ptr)
7464 try self.wip.load(access_kind, optional_llvm_ty, operand, .default, "")7513 try self.wip.load(access_kind, optional_llvm_ty, operand, operand_ty.ptrAlignment(zcu).toLlvm(), "")
7465 else7514 else
7466 operand;7515 operand;
7467 if (payload_ty.isSlice(zcu)) {7516 if (payload_ty.isSlice(zcu)) {
...@@ -7479,7 +7528,7 @@ pub const FuncGen = struct {...@@ -7479,7 +7528,7 @@ pub const FuncGen = struct {
74797528
7480 if (!payload_ty.hasRuntimeBits(zcu)) {7529 if (!payload_ty.hasRuntimeBits(zcu)) {
7481 const loaded = if (operand_is_ptr)7530 const loaded = if (operand_is_ptr)
7482 try self.wip.load(access_kind, optional_llvm_ty, operand, .default, "")7531 try self.wip.load(access_kind, optional_llvm_ty, operand, operand_ty.ptrAlignment(zcu).toLlvm(), "")
7483 else7532 else
7484 operand;7533 operand;
7485 return self.wip.icmp(cond, loaded, try o.builder.intValue(.i8, 0), "");7534 return self.wip.icmp(cond, loaded, try o.builder.intValue(.i8, 0), "");
...@@ -7522,7 +7571,7 @@ pub const FuncGen = struct {...@@ -7522,7 +7571,7 @@ pub const FuncGen = struct {
75227571
7523 if (!payload_ty.hasRuntimeBits(zcu)) {7572 if (!payload_ty.hasRuntimeBits(zcu)) {
7524 const loaded = if (operand_is_ptr)7573 const loaded = if (operand_is_ptr)
7525 try self.wip.load(access_kind, try o.lowerType(pt, err_union_ty), operand, .default, "")7574 try self.wip.load(access_kind, try o.lowerType(pt, err_union_ty), operand, operand_ty.ptrAlignment(zcu).toLlvm(), "")
7526 else7575 else
7527 operand;7576 operand;
7528 return self.wip.icmp(cond, loaded, zero, "");7577 return self.wip.icmp(cond, loaded, zero, "");
...@@ -7532,9 +7581,13 @@ pub const FuncGen = struct {...@@ -7532,9 +7581,13 @@ pub const FuncGen = struct {
75327581
7533 const loaded = if (operand_is_ptr or isByRef(err_union_ty, zcu)) loaded: {7582 const loaded = if (operand_is_ptr or isByRef(err_union_ty, zcu)) loaded: {
7534 const err_union_llvm_ty = try o.lowerType(pt, err_union_ty);7583 const err_union_llvm_ty = try o.lowerType(pt, err_union_ty);
7584 const err_alignment = if (operand_is_ptr)
7585 operand_ty.ptrAlignment(zcu).minStrict(Type.anyerror.abiAlignment(zcu))
7586 else
7587 .none;
7535 const err_field_ptr =7588 const err_field_ptr =
7536 try self.wip.gepStruct(err_union_llvm_ty, operand, err_field_index, "");7589 try self.wip.gepStruct(err_union_llvm_ty, operand, err_field_index, "");
7537 break :loaded try self.wip.load(access_kind, error_type, err_field_ptr, .default, "");7590 break :loaded try self.wip.load(access_kind, error_type, err_field_ptr, err_alignment.toLlvm(), "");
7538 } else try self.wip.extractValue(operand, &.{err_field_index}, "");7591 } else try self.wip.extractValue(operand, &.{err_field_index}, "");
7539 return self.wip.icmp(cond, loaded, zero, "");7592 return self.wip.icmp(cond, loaded, zero, "");
7540 }7593 }
...@@ -7579,6 +7632,7 @@ pub const FuncGen = struct {...@@ -7579,6 +7632,7 @@ pub const FuncGen = struct {
7579 self.maybeMarkAllowZeroAccess(optional_ptr_ty.ptrInfo(zcu));7632 self.maybeMarkAllowZeroAccess(optional_ptr_ty.ptrInfo(zcu));
75807633
7581 // We have a pointer to a i8. We need to set it to 1 and then return the same pointer.7634 // We have a pointer to a i8. We need to set it to 1 and then return the same pointer.
7635 // Default alignment store because align of the non null bit is 1 anyway.
7582 _ = try self.wip.store(access_kind, non_null_bit, operand, .default);7636 _ = try self.wip.store(access_kind, non_null_bit, operand, .default);
7583 return operand;7637 return operand;
7584 }7638 }
...@@ -7594,7 +7648,7 @@ pub const FuncGen = struct {...@@ -7594,7 +7648,7 @@ pub const FuncGen = struct {
75947648
7595 self.maybeMarkAllowZeroAccess(optional_ptr_ty.ptrInfo(zcu));7649 self.maybeMarkAllowZeroAccess(optional_ptr_ty.ptrInfo(zcu));
75967650
7597 // TODO set alignment on this store7651 // Default alignment store because align of the non null bit is 1 anyway.
7598 _ = try self.wip.store(access_kind, non_null_bit, non_null_ptr, .default);7652 _ = try self.wip.store(access_kind, non_null_bit, non_null_ptr, .default);
75997653
7600 // Then return the payload pointer (only if it's used).7654 // Then return the payload pointer (only if it's used).
...@@ -7682,7 +7736,7 @@ pub const FuncGen = struct {...@@ -7682,7 +7736,7 @@ pub const FuncGen = struct {
76827736
7683 self.maybeMarkAllowZeroAccess(operand_ty.ptrInfo(zcu));7737 self.maybeMarkAllowZeroAccess(operand_ty.ptrInfo(zcu));
76847738
7685 return self.wip.load(access_kind, error_type, operand, .default, "");7739 return self.wip.load(access_kind, error_type, operand, operand_ty.ptrAlignment(zcu).toLlvm(), "");
7686 }7740 }
76877741
7688 const offset = try errUnionErrorOffset(payload_ty, pt);7742 const offset = try errUnionErrorOffset(payload_ty, pt);
...@@ -7706,6 +7760,7 @@ pub const FuncGen = struct {...@@ -7706,6 +7760,7 @@ pub const FuncGen = struct {
7706 const operand = try self.resolveInst(ty_op.operand);7760 const operand = try self.resolveInst(ty_op.operand);
7707 const err_union_ptr_ty = self.typeOf(ty_op.operand);7761 const err_union_ptr_ty = self.typeOf(ty_op.operand);
7708 const err_union_ty = err_union_ptr_ty.childType(zcu);7762 const err_union_ty = err_union_ptr_ty.childType(zcu);
7763 const err_union_ptr_align = err_union_ptr_ty.ptrAlignment(zcu);
77097764
7710 const payload_ty = err_union_ty.errorUnionPayload(zcu);7765 const payload_ty = err_union_ty.errorUnionPayload(zcu);
7711 const non_error_val = try o.builder.intValue(try o.errorIntType(pt), 0);7766 const non_error_val = try o.builder.intValue(try o.errorIntType(pt), 0);
...@@ -7715,8 +7770,7 @@ pub const FuncGen = struct {...@@ -7715,8 +7770,7 @@ pub const FuncGen = struct {
77157770
7716 if (!payload_ty.hasRuntimeBits(zcu)) {7771 if (!payload_ty.hasRuntimeBits(zcu)) {
7717 self.maybeMarkAllowZeroAccess(err_union_ptr_ty.ptrInfo(zcu));7772 self.maybeMarkAllowZeroAccess(err_union_ptr_ty.ptrInfo(zcu));
77187773 _ = try self.wip.store(access_kind, non_error_val, operand, err_union_ptr_align.toLlvm());
7719 _ = try self.wip.store(access_kind, non_error_val, operand, .default);
7720 return operand;7774 return operand;
7721 }7775 }
7722 const err_union_llvm_ty = try o.lowerType(pt, err_union_ty);7776 const err_union_llvm_ty = try o.lowerType(pt, err_union_ty);
...@@ -7724,7 +7778,7 @@ pub const FuncGen = struct {...@@ -7724,7 +7778,7 @@ pub const FuncGen = struct {
7724 self.maybeMarkAllowZeroAccess(err_union_ptr_ty.ptrInfo(zcu));7778 self.maybeMarkAllowZeroAccess(err_union_ptr_ty.ptrInfo(zcu));
77257779
7726 const err_int_ty = try pt.errorIntType();7780 const err_int_ty = try pt.errorIntType();
7727 const error_alignment = err_int_ty.abiAlignment(zcu).toLlvm();7781 const error_alignment = err_int_ty.abiAlignment(zcu).minStrict(err_union_ptr_align).toLlvm();
7728 const error_offset = try errUnionErrorOffset(payload_ty, pt);7782 const error_offset = try errUnionErrorOffset(payload_ty, pt);
7729 // First set the non-error value.7783 // First set the non-error value.
7730 const non_null_ptr = try self.wip.gepStruct(err_union_llvm_ty, operand, error_offset, "");7784 const non_null_ptr = try self.wip.gepStruct(err_union_llvm_ty, operand, error_offset, "");
...@@ -8405,9 +8459,8 @@ pub const FuncGen = struct {...@@ -8405,9 +8459,8 @@ pub const FuncGen = struct {
8405 _ = try self.wip.store(.normal, result_val, field_ptr, result_alignment);8459 _ = try self.wip.store(.normal, result_val, field_ptr, result_alignment);
8406 }8460 }
8407 {8461 {
8408 const overflow_alignment = comptime Builder.Alignment.fromByteUnits(1);
8409 const field_ptr = try self.wip.gepStruct(llvm_inst_ty, alloca_inst, overflow_index, "");8462 const field_ptr = try self.wip.gepStruct(llvm_inst_ty, alloca_inst, overflow_index, "");
8410 _ = try self.wip.store(.normal, overflow_bit, field_ptr, overflow_alignment);8463 _ = try self.wip.store(.normal, overflow_bit, field_ptr, comptime .fromByteUnits(1));
8411 }8464 }
84128465
8413 return alloca_inst;8466 return alloca_inst;
...@@ -8767,9 +8820,8 @@ pub const FuncGen = struct {...@@ -8767,9 +8820,8 @@ pub const FuncGen = struct {
8767 _ = try self.wip.store(.normal, result, field_ptr, result_alignment);8820 _ = try self.wip.store(.normal, result, field_ptr, result_alignment);
8768 }8821 }
8769 {8822 {
8770 const field_alignment = comptime Builder.Alignment.fromByteUnits(1);
8771 const field_ptr = try self.wip.gepStruct(llvm_dest_ty, alloca_inst, overflow_index, "");8823 const field_ptr = try self.wip.gepStruct(llvm_dest_ty, alloca_inst, overflow_index, "");
8772 _ = try self.wip.store(.normal, overflow_bit, field_ptr, field_alignment);8824 _ = try self.wip.store(.normal, overflow_bit, field_ptr, comptime .fromByteUnits(1));
8773 }8825 }
8774 return alloca_inst;8826 return alloca_inst;
8775 }8827 }
...@@ -9925,15 +9977,18 @@ pub const FuncGen = struct {...@@ -9925,15 +9977,18 @@ pub const FuncGen = struct {
99259977
9926 const union_ptr = try self.resolveInst(bin_op.lhs);9978 const union_ptr = try self.resolveInst(bin_op.lhs);
9927 const new_tag = try self.resolveInst(bin_op.rhs);9979 const new_tag = try self.resolveInst(bin_op.rhs);
9980 const union_ptr_align = un_ptr_ty.ptrAlignment(zcu);
9928 if (layout.payload_size == 0) {9981 if (layout.payload_size == 0) {
9929 // TODO alignment on this store9982 _ = try self.wip.store(access_kind, new_tag, union_ptr, union_ptr_align.toLlvm());
9930 _ = try self.wip.store(access_kind, new_tag, union_ptr, .default);
9931 return .none;9983 return .none;
9932 }9984 }
9933 const tag_index = @intFromBool(layout.tag_align.compare(.lt, layout.payload_align));9985 const tag_index = @intFromBool(layout.tag_align.compare(.lt, layout.payload_align));
9934 const tag_field_ptr = try self.wip.gepStruct(try o.lowerType(pt, un_ty), union_ptr, tag_index, "");9986 const tag_field_ptr = try self.wip.gepStruct(try o.lowerType(pt, un_ty), union_ptr, tag_index, "");
9935 // TODO alignment on this store9987 const tag_ptr_align: InternPool.Alignment = switch (layout.tagOffset()) {
9936 _ = try self.wip.store(access_kind, new_tag, tag_field_ptr, .default);9988 0 => union_ptr_align,
9989 else => |off| .minStrict(union_ptr_align, .fromLog2Units(@ctz(off))),
9990 };
9991 _ = try self.wip.store(access_kind, new_tag, tag_field_ptr, tag_ptr_align.toLlvm());
9937 return .none;9992 return .none;
9938 }9993 }
99399994
...@@ -10106,56 +10161,19 @@ pub const FuncGen = struct {...@@ -10106,56 +10161,19 @@ pub const FuncGen = struct {
10106 const pt = self.ng.pt;10161 const pt = self.ng.pt;
10107 const zcu = pt.zcu;10162 const zcu = pt.zcu;
10108 const ip = &zcu.intern_pool;10163 const ip = &zcu.intern_pool;
10109 const enum_type = ip.loadEnumType(enum_ty.toIntern());
1011010164
10111 // TODO: detect when the type changes (`updateContainerType` will be called) and re-emit this function
10112 const gop = try o.named_enum_map.getOrPut(o.gpa, enum_ty.toIntern());10165 const gop = try o.named_enum_map.getOrPut(o.gpa, enum_ty.toIntern());
10113 if (gop.found_existing) return gop.value_ptr.*;10166 if (gop.found_existing) return gop.value_ptr.*;
10114 errdefer assert(o.named_enum_map.remove(enum_ty.toIntern()));10167 errdefer assert(o.named_enum_map.remove(enum_ty.toIntern()));
10115
10116 const target = &zcu.root_mod.resolved_target.result;
10117 const function_index = try o.builder.addFunction(10168 const function_index = try o.builder.addFunction(
10118 try o.builder.fnType(.i1, &.{try o.lowerType(pt, Type.fromInterned(enum_type.int_tag_type))}, .normal),10169 // Dummy function type; `updateIsNamedEnumValue` will replace it with the correct type.
10119 try o.builder.strtabStringFmt("__zig_is_named_enum_value_{f}", .{enum_type.name.fmt(ip)}),10170 // TODO: change the builder API so we don't need to do this.
10120 toLlvmAddressSpace(.generic, target),10171 try o.builder.fnType(.void, &.{}, .normal),
10172 try o.builder.strtabStringFmt("__zig_is_named_enum_value_{f}", .{enum_ty.containerTypeName(ip).fmt(ip)}),
10173 toLlvmAddressSpace(.generic, zcu.getTarget()),
10121 );10174 );
10122
10123 var attributes: Builder.FunctionAttributes.Wip = .{};
10124 defer attributes.deinit(&o.builder);
10125 try o.addCommonFnAttributes(&attributes, zcu.root_mod, zcu.root_mod.omit_frame_pointer);
10126
10127 function_index.setLinkage(.internal, &o.builder);
10128 function_index.setCallConv(.fastcc, &o.builder);
10129 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
10130 gop.value_ptr.* = function_index;10175 gop.value_ptr.* = function_index;
1013110176 try o.updateIsNamedEnumValueFunction(pt, enum_ty, function_index);
10132 var wip = try Builder.WipFunction.init(&o.builder, .{
10133 .function = function_index,
10134 .strip = true,
10135 });
10136 defer wip.deinit();
10137 wip.cursor = .{ .block = try wip.block(0, "Entry") };
10138
10139 const named_block = try wip.block(@intCast(enum_type.field_names.len), "Named");
10140 const unnamed_block = try wip.block(1, "Unnamed");
10141 const tag_int_value = wip.arg(0);
10142 var wip_switch = try wip.@"switch"(tag_int_value, unnamed_block, @intCast(enum_type.field_names.len), .none);
10143 defer wip_switch.finish(&wip);
10144
10145 for (0..enum_type.field_names.len) |field_index| {
10146 const this_tag_int_value = try o.lowerValue(
10147 pt,
10148 (try pt.enumValueFieldIndex(enum_ty, @intCast(field_index))).toIntern(),
10149 );
10150 try wip_switch.addCase(this_tag_int_value, named_block, &wip);
10151 }
10152 wip.cursor = .{ .block = named_block };
10153 _ = try wip.ret(.true);
10154
10155 wip.cursor = .{ .block = unnamed_block };
10156 _ = try wip.ret(.false);
10157
10158 try wip.finish();
10159 return function_index;10177 return function_index;
10160 }10178 }
1016110179
...@@ -10824,9 +10842,8 @@ pub const FuncGen = struct {...@@ -10824,9 +10842,8 @@ pub const FuncGen = struct {
10824 comptime assert(@intFromEnum(std.builtin.PrefetchOptions.Rw.read) == 0);10842 comptime assert(@intFromEnum(std.builtin.PrefetchOptions.Rw.read) == 0);
10825 comptime assert(@intFromEnum(std.builtin.PrefetchOptions.Rw.write) == 1);10843 comptime assert(@intFromEnum(std.builtin.PrefetchOptions.Rw.write) == 1);
1082610844
10827 // TODO these two asserts should be able to be comptime because the type is a u210845 comptime assert(prefetch.locality >= 0);
10828 assert(prefetch.locality >= 0);10846 comptime assert(prefetch.locality <= 3);
10829 assert(prefetch.locality <= 3);
1083010847
10831 comptime assert(@intFromEnum(std.builtin.PrefetchOptions.Cache.instruction) == 0);10848 comptime assert(@intFromEnum(std.builtin.PrefetchOptions.Cache.instruction) == 0);
10832 comptime assert(@intFromEnum(std.builtin.PrefetchOptions.Cache.data) == 1);10849 comptime assert(@intFromEnum(std.builtin.PrefetchOptions.Cache.data) == 1);