| ... | @@ -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 | } |
| 1445 | | 1444 | |
| ... | @@ -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 | } |
| 1637 | | 1630 | |
| ... | @@ -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 { |
| 1834 | | 1824 | |
| 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 | } |
| 1838 | | 1831 | |
| 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_map | 2905 | // 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 | } |
| 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 | 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 | }; |
| 4367 | | 4412 | |
| 4368 | pub const NavGen = struct { | 4413 | pub 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 | } |
| 6110 | | 6155 | |
| 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); |
| 6118 | | 6164 | |
| 6119 | self.maybeMarkAllowZeroAccess(self.typeOf(unwrapped_try.error_union_ptr).ptrInfo(zcu)); | 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 | 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); |
| 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 | 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; |
| 6146 | | 6198 | |
| 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 | else | 6202 | 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; |
| 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 | 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); |
| 6676 | | 6730 | } 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 | } |
| 6685 | | 6734 | |
| 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 { |
| 7461 | | 7510 | |
| 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 | else | 7514 | 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 { |
| 7479 | | 7528 | |
| 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 | else | 7532 | 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 { |
| 7522 | | 7571 | |
| 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 | else | 7575 | 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 { |
| 7532 | | 7581 | |
| 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)); |
| 7580 | | 7633 | |
| 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 { |
| 7594 | | 7648 | |
| 7595 | self.maybeMarkAllowZeroAccess(optional_ptr_ty.ptrInfo(zcu)); | 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 | _ = 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); |
| 7599 | | 7653 | |
| 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 { |
| 7682 | | 7736 | |
| 7683 | self.maybeMarkAllowZeroAccess(operand_ty.ptrInfo(zcu)); | 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 | 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); |
| 7709 | | 7764 | |
| 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 { |
| 7715 | | 7770 | |
| 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)); |
| 7718 | | 7773 | _ = 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)); |
| 7725 | | 7779 | |
| 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 | } |
| 8412 | | 8465 | |
| 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 { |
| 9925 | | 9977 | |
| 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 store | 9982 | _ = 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 store | 9987 | 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 | } |
| 9939 | | 9994 | |
| ... | @@ -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()); | | |
| 10110 | | 10164 | |
| 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; |
| 10131 | | 10176 | 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 | } |
| 10161 | | 10179 | |
| ... | @@ -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); |
| 10826 | | 10844 | |
| 10827 | // TODO these two asserts should be able to be comptime because the type is a u2 | 10845 | comptime assert(prefetch.locality >= 0); |
| 10828 | assert(prefetch.locality >= 0); | 10846 | comptime assert(prefetch.locality <= 3); |
| 10829 | assert(prefetch.locality <= 3); | | |
| 10830 | | 10847 | |
| 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); |