| ... | ... | @@ -1438,8 +1438,7 @@ pub const Object = struct { |
| 1438 | 1438 | const param = wip.arg(llvm_arg_i); |
| 1439 | 1439 | llvm_arg_i += 1; |
| 1440 | 1440 | const field_ptr = try wip.gepStruct(llvm_ty, arg_ptr, field_i, ""); |
| 1441 | | const alignment = |
| 1442 | | Builder.Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8)); |
| 1441 | const alignment = Builder.Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8)); |
| 1443 | 1442 | _ = try wip.store(.normal, param, field_ptr, alignment); |
| 1444 | 1443 | } |
| 1445 | 1444 | |
| ... | ... | @@ -1625,13 +1624,7 @@ pub const Object = struct { |
| 1625 | 1624 | .pt = pt, |
| 1626 | 1625 | .err_msg = null, |
| 1627 | 1626 | }; |
| 1628 | | ng.genDecl() catch |err| switch (err) { |
| 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 | | }; |
| 1627 | try ng.genDecl(); |
| 1635 | 1628 | try self.flushTypePool(pt); |
| 1636 | 1629 | } |
| 1637 | 1630 | |
| ... | ... | @@ -1713,10 +1706,7 @@ pub const Object = struct { |
| 1713 | 1706 | const global_index = variable_index.ptrConst(&o.builder).global; |
| 1714 | 1707 | gop.value_ptr.* = global_index; |
| 1715 | 1708 | // This line invalidates `gop`. |
| 1716 | | const init_val = o.lowerValue(pt, exported_value) catch |err| switch (err) { |
| 1717 | | error.OutOfMemory => return error.OutOfMemory, |
| 1718 | | error.CodegenFail => return error.AnalysisFail, |
| 1719 | | }; |
| 1709 | const init_val = try o.lowerValue(pt, exported_value); |
| 1720 | 1710 | try variable_index.setInitializer(init_val, &o.builder); |
| 1721 | 1711 | break :i global_index; |
| 1722 | 1712 | }; |
| ... | ... | @@ -1834,6 +1824,9 @@ pub const Object = struct { |
| 1834 | 1824 | |
| 1835 | 1825 | pub fn updateContainerType(o: *Object, pt: Zcu.PerThread, ty: InternPool.Index, success: bool) Allocator.Error!void { |
| 1836 | 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 | } |
| 1838 | 1831 | |
| 1839 | 1832 | /// Should only be called by the `link.ConstPool` implementation. |
| ... | ... | @@ -2907,7 +2900,7 @@ pub const Object = struct { |
| 2907 | 2900 | uav: InternPool.Index, |
| 2908 | 2901 | llvm_addr_space: Builder.AddrSpace, |
| 2909 | 2902 | alignment: InternPool.Alignment, |
| 2910 | | ) Error!Builder.Variable.Index { |
| 2903 | ) Allocator.Error!Builder.Variable.Index { |
| 2911 | 2904 | assert(alignment != .none); |
| 2912 | 2905 | // TODO: Add address space to the anon_decl_map |
| 2913 | 2906 | const gop = try o.uav_map.getOrPut(o.gpa, uav); |
| ... | ... | @@ -3506,7 +3499,7 @@ pub const Object = struct { |
| 3506 | 3499 | ); |
| 3507 | 3500 | } |
| 3508 | 3501 | |
| 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 | 3503 | const zcu = pt.zcu; |
| 3511 | 3504 | const ip = &zcu.intern_pool; |
| 3512 | 3505 | const target = zcu.getTarget(); |
| ... | ... | @@ -4019,7 +4012,7 @@ pub const Object = struct { |
| 4019 | 4012 | pt: Zcu.PerThread, |
| 4020 | 4013 | ptr_val: InternPool.Index, |
| 4021 | 4014 | prev_offset: u64, |
| 4022 | | ) Error!Builder.Constant { |
| 4015 | ) Allocator.Error!Builder.Constant { |
| 4023 | 4016 | const zcu = pt.zcu; |
| 4024 | 4017 | const ptr = zcu.intern_pool.indexToKey(ptr_val).ptr; |
| 4025 | 4018 | const offset: u64 = prev_offset + ptr.byte_offset; |
| ... | ... | @@ -4086,7 +4079,7 @@ pub const Object = struct { |
| 4086 | 4079 | o: *Object, |
| 4087 | 4080 | pt: Zcu.PerThread, |
| 4088 | 4081 | uav: InternPool.Key.Ptr.BaseAddr.Uav, |
| 4089 | | ) Error!Builder.Constant { |
| 4082 | ) Allocator.Error!Builder.Constant { |
| 4090 | 4083 | const zcu = pt.zcu; |
| 4091 | 4084 | const ip = &zcu.intern_pool; |
| 4092 | 4085 | const uav_val = uav.val; |
| ... | ... | @@ -4363,6 +4356,58 @@ pub const Object = struct { |
| 4363 | 4356 | const index = try o.type_pool.get(pt, .{ .llvm = o }, ty.toIntern()); |
| 4364 | 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 | }; |
| 4367 | 4412 | |
| 4368 | 4413 | pub const NavGen = struct { |
| ... | ... | @@ -6105,7 +6150,7 @@ pub const FuncGen = struct { |
| 6105 | 6150 | const body = unwrapped_try.else_body; |
| 6106 | 6151 | const err_union_ty = self.typeOf(unwrapped_try.error_union); |
| 6107 | 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 | } |
| 6110 | 6155 | |
| 6111 | 6156 | fn airTryPtr(self: *FuncGen, inst: Air.Inst.Index, err_cold: bool) !Builder.Value { |
| ... | ... | @@ -6113,12 +6158,13 @@ pub const FuncGen = struct { |
| 6113 | 6158 | const unwrapped_try = self.air.unwrapTryPtr(inst); |
| 6114 | 6159 | const err_union_ptr = try self.resolveInst(unwrapped_try.error_union_ptr); |
| 6115 | 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 | 6163 | const is_unused = self.liveness.isUnused(inst); |
| 6118 | 6164 | |
| 6119 | 6165 | self.maybeMarkAllowZeroAccess(self.typeOf(unwrapped_try.error_union_ptr).ptrInfo(zcu)); |
| 6120 | 6166 | |
| 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 | } |
| 6123 | 6169 | |
| 6124 | 6170 | fn lowerTry( |
| ... | ... | @@ -6127,6 +6173,7 @@ pub const FuncGen = struct { |
| 6127 | 6173 | body: []const Air.Inst.Index, |
| 6128 | 6174 | err_union_ty: Type, |
| 6129 | 6175 | operand_is_ptr: bool, |
| 6176 | operand_ptr_align: InternPool.Alignment, |
| 6130 | 6177 | can_elide_load: bool, |
| 6131 | 6178 | is_unused: bool, |
| 6132 | 6179 | err_cold: bool, |
| ... | ... | @@ -6139,15 +6186,19 @@ pub const FuncGen = struct { |
| 6139 | 6186 | const err_union_llvm_ty = try o.lowerType(pt, err_union_ty); |
| 6140 | 6187 | const error_type = try o.errorIntType(pt); |
| 6141 | 6188 | |
| 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 | 6194 | if (!err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu)) { |
| 6143 | 6195 | const loaded = loaded: { |
| 6144 | 6196 | const access_kind: Builder.MemoryAccessKind = |
| 6145 | 6197 | if (err_union_ty.isVolatilePtr(zcu)) .@"volatile" else .normal; |
| 6146 | 6198 | |
| 6147 | 6199 | if (!payload_has_bits) { |
| 6148 | | // TODO add alignment to this load |
| 6149 | 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 | 6202 | else |
| 6152 | 6203 | err_union; |
| 6153 | 6204 | } |
| ... | ... | @@ -6155,12 +6206,11 @@ pub const FuncGen = struct { |
| 6155 | 6206 | if (operand_is_ptr or isByRef(err_union_ty, zcu)) { |
| 6156 | 6207 | const err_field_ptr = |
| 6157 | 6208 | try fg.wip.gepStruct(err_union_llvm_ty, err_union, err_field_index, ""); |
| 6158 | | // TODO add alignment to this load |
| 6159 | 6209 | break :loaded try fg.wip.load( |
| 6160 | 6210 | if (operand_is_ptr) access_kind else .normal, |
| 6161 | 6211 | error_type, |
| 6162 | 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 | 6236 | return fg.wip.gepStruct(err_union_llvm_ty, err_union, offset, ""); |
| 6187 | 6237 | } else if (isByRef(err_union_ty, zcu)) { |
| 6188 | 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 | 6239 | if (isByRef(payload_ty, zcu)) { |
| 6191 | 6240 | if (can_elide_load) |
| 6192 | 6241 | return payload_ptr; |
| 6193 | 6242 | |
| 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 | 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 | 6248 | return fg.wip.extractValue(err_union, &.{offset}, ""); |
| 6200 | 6249 | } |
| ... | ... | @@ -6667,20 +6716,20 @@ pub const FuncGen = struct { |
| 6667 | 6716 | const slice_ty = self.typeOf(bin_op.lhs); |
| 6668 | 6717 | const slice = try self.resolveInst(bin_op.lhs); |
| 6669 | 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 | 6722 | const llvm_elem_ty = try o.lowerType(pt, elem_ty); |
| 6672 | 6723 | const base_ptr = try self.wip.extractValue(slice, &.{0}, ""); |
| 6673 | 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 | 6728 | if (isByRef(elem_ty, zcu)) { |
| 6675 | | self.maybeMarkAllowZeroAccess(slice_ty.ptrInfo(zcu)); |
| 6676 | | |
| 6677 | | const slice_align = (slice_ty.ptrAlignment(zcu).min(elem_ty.abiAlignment(zcu))).toLlvm(); |
| 6678 | | return self.loadByRef(ptr, elem_ty, slice_align, if (slice_ty.isVolatilePtr(zcu)) .@"volatile" else .normal); |
| 6729 | return self.loadByRef(ptr, elem_ty, elem_align.toLlvm(), access_kind); |
| 6730 | } else { |
| 6731 | return self.loadTruncate(access_kind, elem_ty, ptr, elem_align.toLlvm()); |
| 6679 | 6732 | } |
| 6680 | | |
| 6681 | | self.maybeMarkAllowZeroAccess(slice_ty.ptrInfo(zcu)); |
| 6682 | | |
| 6683 | | return self.load(ptr, slice_ty); |
| 6684 | 6733 | } |
| 6685 | 6734 | |
| 6686 | 6735 | fn airSliceElemPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| ... | ... | @@ -7461,7 +7510,7 @@ pub const FuncGen = struct { |
| 7461 | 7510 | |
| 7462 | 7511 | if (optional_ty.optionalReprIsPayload(zcu)) { |
| 7463 | 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 | 7514 | else |
| 7466 | 7515 | operand; |
| 7467 | 7516 | if (payload_ty.isSlice(zcu)) { |
| ... | ... | @@ -7479,7 +7528,7 @@ pub const FuncGen = struct { |
| 7479 | 7528 | |
| 7480 | 7529 | if (!payload_ty.hasRuntimeBits(zcu)) { |
| 7481 | 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 | 7532 | else |
| 7484 | 7533 | operand; |
| 7485 | 7534 | return self.wip.icmp(cond, loaded, try o.builder.intValue(.i8, 0), ""); |
| ... | ... | @@ -7522,7 +7571,7 @@ pub const FuncGen = struct { |
| 7522 | 7571 | |
| 7523 | 7572 | if (!payload_ty.hasRuntimeBits(zcu)) { |
| 7524 | 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 | 7575 | else |
| 7527 | 7576 | operand; |
| 7528 | 7577 | return self.wip.icmp(cond, loaded, zero, ""); |
| ... | ... | @@ -7532,9 +7581,13 @@ pub const FuncGen = struct { |
| 7532 | 7581 | |
| 7533 | 7582 | const loaded = if (operand_is_ptr or isByRef(err_union_ty, zcu)) loaded: { |
| 7534 | 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 | 7588 | const err_field_ptr = |
| 7536 | 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 | 7591 | } else try self.wip.extractValue(operand, &.{err_field_index}, ""); |
| 7539 | 7592 | return self.wip.icmp(cond, loaded, zero, ""); |
| 7540 | 7593 | } |
| ... | ... | @@ -7579,6 +7632,7 @@ pub const FuncGen = struct { |
| 7579 | 7632 | self.maybeMarkAllowZeroAccess(optional_ptr_ty.ptrInfo(zcu)); |
| 7580 | 7633 | |
| 7581 | 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 | 7636 | _ = try self.wip.store(access_kind, non_null_bit, operand, .default); |
| 7583 | 7637 | return operand; |
| 7584 | 7638 | } |
| ... | ... | @@ -7594,7 +7648,7 @@ pub const FuncGen = struct { |
| 7594 | 7648 | |
| 7595 | 7649 | self.maybeMarkAllowZeroAccess(optional_ptr_ty.ptrInfo(zcu)); |
| 7596 | 7650 | |
| 7597 | | // TODO set alignment on this store |
| 7651 | // Default alignment store because align of the non null bit is 1 anyway. |
| 7598 | 7652 | _ = try self.wip.store(access_kind, non_null_bit, non_null_ptr, .default); |
| 7599 | 7653 | |
| 7600 | 7654 | // Then return the payload pointer (only if it's used). |
| ... | ... | @@ -7682,7 +7736,7 @@ pub const FuncGen = struct { |
| 7682 | 7736 | |
| 7683 | 7737 | self.maybeMarkAllowZeroAccess(operand_ty.ptrInfo(zcu)); |
| 7684 | 7738 | |
| 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 | } |
| 7687 | 7741 | |
| 7688 | 7742 | const offset = try errUnionErrorOffset(payload_ty, pt); |
| ... | ... | @@ -7706,6 +7760,7 @@ pub const FuncGen = struct { |
| 7706 | 7760 | const operand = try self.resolveInst(ty_op.operand); |
| 7707 | 7761 | const err_union_ptr_ty = self.typeOf(ty_op.operand); |
| 7708 | 7762 | const err_union_ty = err_union_ptr_ty.childType(zcu); |
| 7763 | const err_union_ptr_align = err_union_ptr_ty.ptrAlignment(zcu); |
| 7709 | 7764 | |
| 7710 | 7765 | const payload_ty = err_union_ty.errorUnionPayload(zcu); |
| 7711 | 7766 | const non_error_val = try o.builder.intValue(try o.errorIntType(pt), 0); |
| ... | ... | @@ -7715,8 +7770,7 @@ pub const FuncGen = struct { |
| 7715 | 7770 | |
| 7716 | 7771 | if (!payload_ty.hasRuntimeBits(zcu)) { |
| 7717 | 7772 | self.maybeMarkAllowZeroAccess(err_union_ptr_ty.ptrInfo(zcu)); |
| 7718 | | |
| 7719 | | _ = try self.wip.store(access_kind, non_error_val, operand, .default); |
| 7773 | _ = try self.wip.store(access_kind, non_error_val, operand, err_union_ptr_align.toLlvm()); |
| 7720 | 7774 | return operand; |
| 7721 | 7775 | } |
| 7722 | 7776 | const err_union_llvm_ty = try o.lowerType(pt, err_union_ty); |
| ... | ... | @@ -7724,7 +7778,7 @@ pub const FuncGen = struct { |
| 7724 | 7778 | self.maybeMarkAllowZeroAccess(err_union_ptr_ty.ptrInfo(zcu)); |
| 7725 | 7779 | |
| 7726 | 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 | 7782 | const error_offset = try errUnionErrorOffset(payload_ty, pt); |
| 7729 | 7783 | // First set the non-error value. |
| 7730 | 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 | 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 | 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 | } |
| 8412 | 8465 | |
| 8413 | 8466 | return alloca_inst; |
| ... | ... | @@ -8767,9 +8820,8 @@ pub const FuncGen = struct { |
| 8767 | 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 | 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 | 8826 | return alloca_inst; |
| 8775 | 8827 | } |
| ... | ... | @@ -9925,15 +9977,18 @@ pub const FuncGen = struct { |
| 9925 | 9977 | |
| 9926 | 9978 | const union_ptr = try self.resolveInst(bin_op.lhs); |
| 9927 | 9979 | const new_tag = try self.resolveInst(bin_op.rhs); |
| 9980 | const union_ptr_align = un_ptr_ty.ptrAlignment(zcu); |
| 9928 | 9981 | if (layout.payload_size == 0) { |
| 9929 | | // TODO alignment on this store |
| 9930 | | _ = try self.wip.store(access_kind, new_tag, union_ptr, .default); |
| 9982 | _ = try self.wip.store(access_kind, new_tag, union_ptr, union_ptr_align.toLlvm()); |
| 9931 | 9983 | return .none; |
| 9932 | 9984 | } |
| 9933 | 9985 | const tag_index = @intFromBool(layout.tag_align.compare(.lt, layout.payload_align)); |
| 9934 | 9986 | const tag_field_ptr = try self.wip.gepStruct(try o.lowerType(pt, un_ty), union_ptr, tag_index, ""); |
| 9935 | | // TODO alignment on this store |
| 9936 | | _ = try self.wip.store(access_kind, new_tag, tag_field_ptr, .default); |
| 9987 | const tag_ptr_align: InternPool.Alignment = switch (layout.tagOffset()) { |
| 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 | 9992 | return .none; |
| 9938 | 9993 | } |
| 9939 | 9994 | |
| ... | ... | @@ -10106,56 +10161,19 @@ pub const FuncGen = struct { |
| 10106 | 10161 | const pt = self.ng.pt; |
| 10107 | 10162 | const zcu = pt.zcu; |
| 10108 | 10163 | const ip = &zcu.intern_pool; |
| 10109 | | const enum_type = ip.loadEnumType(enum_ty.toIntern()); |
| 10110 | 10164 | |
| 10111 | | // TODO: detect when the type changes (`updateContainerType` will be called) and re-emit this function |
| 10112 | 10165 | const gop = try o.named_enum_map.getOrPut(o.gpa, enum_ty.toIntern()); |
| 10113 | 10166 | if (gop.found_existing) return gop.value_ptr.*; |
| 10114 | 10167 | errdefer assert(o.named_enum_map.remove(enum_ty.toIntern())); |
| 10115 | | |
| 10116 | | const target = &zcu.root_mod.resolved_target.result; |
| 10117 | 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), |
| 10119 | | try o.builder.strtabStringFmt("__zig_is_named_enum_value_{f}", .{enum_type.name.fmt(ip)}), |
| 10120 | | toLlvmAddressSpace(.generic, target), |
| 10169 | // Dummy function type; `updateIsNamedEnumValue` will replace it with the correct type. |
| 10170 | // TODO: change the builder API so we don't need to do this. |
| 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 | 10175 | gop.value_ptr.* = function_index; |
| 10131 | | |
| 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(); |
| 10176 | try o.updateIsNamedEnumValueFunction(pt, enum_ty, function_index); |
| 10159 | 10177 | return function_index; |
| 10160 | 10178 | } |
| 10161 | 10179 | |
| ... | ... | @@ -10824,9 +10842,8 @@ pub const FuncGen = struct { |
| 10824 | 10842 | comptime assert(@intFromEnum(std.builtin.PrefetchOptions.Rw.read) == 0); |
| 10825 | 10843 | comptime assert(@intFromEnum(std.builtin.PrefetchOptions.Rw.write) == 1); |
| 10826 | 10844 | |
| 10827 | | // TODO these two asserts should be able to be comptime because the type is a u2 |
| 10828 | | assert(prefetch.locality >= 0); |
| 10829 | | assert(prefetch.locality <= 3); |
| 10845 | comptime assert(prefetch.locality >= 0); |
| 10846 | comptime assert(prefetch.locality <= 3); |
| 10830 | 10847 | |
| 10831 | 10848 | comptime assert(@intFromEnum(std.builtin.PrefetchOptions.Cache.instruction) == 0); |
| 10832 | 10849 | comptime assert(@intFromEnum(std.builtin.PrefetchOptions.Cache.data) == 1); |