| ... | ... | @@ -1625,13 +1625,7 @@ pub const Object = struct { |
| 1625 | 1625 | .pt = pt, |
| 1626 | 1626 | .err_msg = null, |
| 1627 | 1627 | }; |
| 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 | | }; |
| 1628 | try ng.genDecl(); |
| 1635 | 1629 | try self.flushTypePool(pt); |
| 1636 | 1630 | } |
| 1637 | 1631 | |
| ... | ... | @@ -1713,10 +1707,7 @@ pub const Object = struct { |
| 1713 | 1707 | const global_index = variable_index.ptrConst(&o.builder).global; |
| 1714 | 1708 | gop.value_ptr.* = global_index; |
| 1715 | 1709 | // 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 | | }; |
| 1710 | const init_val = try o.lowerValue(pt, exported_value); |
| 1720 | 1711 | try variable_index.setInitializer(init_val, &o.builder); |
| 1721 | 1712 | break :i global_index; |
| 1722 | 1713 | }; |
| ... | ... | @@ -1834,6 +1825,9 @@ pub const Object = struct { |
| 1834 | 1825 | |
| 1835 | 1826 | pub fn updateContainerType(o: *Object, pt: Zcu.PerThread, ty: InternPool.Index, success: bool) Allocator.Error!void { |
| 1836 | 1827 | try o.type_pool.updateContainerType(pt, .{ .llvm = o }, ty, success); |
| 1828 | if (o.named_enum_map.get(ty)) |function_index| { |
| 1829 | try o.updateIsNamedEnumValueFunction(pt, .fromInterned(ty), function_index); |
| 1830 | } |
| 1837 | 1831 | } |
| 1838 | 1832 | |
| 1839 | 1833 | /// Should only be called by the `link.ConstPool` implementation. |
| ... | ... | @@ -2907,7 +2901,7 @@ pub const Object = struct { |
| 2907 | 2901 | uav: InternPool.Index, |
| 2908 | 2902 | llvm_addr_space: Builder.AddrSpace, |
| 2909 | 2903 | alignment: InternPool.Alignment, |
| 2910 | | ) Error!Builder.Variable.Index { |
| 2904 | ) Allocator.Error!Builder.Variable.Index { |
| 2911 | 2905 | assert(alignment != .none); |
| 2912 | 2906 | // TODO: Add address space to the anon_decl_map |
| 2913 | 2907 | const gop = try o.uav_map.getOrPut(o.gpa, uav); |
| ... | ... | @@ -3506,7 +3500,7 @@ pub const Object = struct { |
| 3506 | 3500 | ); |
| 3507 | 3501 | } |
| 3508 | 3502 | |
| 3509 | | fn lowerValue(o: *Object, pt: Zcu.PerThread, arg_val: InternPool.Index) Error!Builder.Constant { |
| 3503 | fn lowerValue(o: *Object, pt: Zcu.PerThread, arg_val: InternPool.Index) Allocator.Error!Builder.Constant { |
| 3510 | 3504 | const zcu = pt.zcu; |
| 3511 | 3505 | const ip = &zcu.intern_pool; |
| 3512 | 3506 | const target = zcu.getTarget(); |
| ... | ... | @@ -4019,7 +4013,7 @@ pub const Object = struct { |
| 4019 | 4013 | pt: Zcu.PerThread, |
| 4020 | 4014 | ptr_val: InternPool.Index, |
| 4021 | 4015 | prev_offset: u64, |
| 4022 | | ) Error!Builder.Constant { |
| 4016 | ) Allocator.Error!Builder.Constant { |
| 4023 | 4017 | const zcu = pt.zcu; |
| 4024 | 4018 | const ptr = zcu.intern_pool.indexToKey(ptr_val).ptr; |
| 4025 | 4019 | const offset: u64 = prev_offset + ptr.byte_offset; |
| ... | ... | @@ -4086,7 +4080,7 @@ pub const Object = struct { |
| 4086 | 4080 | o: *Object, |
| 4087 | 4081 | pt: Zcu.PerThread, |
| 4088 | 4082 | uav: InternPool.Key.Ptr.BaseAddr.Uav, |
| 4089 | | ) Error!Builder.Constant { |
| 4083 | ) Allocator.Error!Builder.Constant { |
| 4090 | 4084 | const zcu = pt.zcu; |
| 4091 | 4085 | const ip = &zcu.intern_pool; |
| 4092 | 4086 | const uav_val = uav.val; |
| ... | ... | @@ -4363,6 +4357,58 @@ pub const Object = struct { |
| 4363 | 4357 | const index = try o.type_pool.get(pt, .{ .llvm = o }, ty.toIntern()); |
| 4364 | 4358 | return o.lazy_abi_aligns.items[@intFromEnum(index)]; |
| 4365 | 4359 | } |
| 4360 | |
| 4361 | fn updateIsNamedEnumValueFunction( |
| 4362 | o: *Object, |
| 4363 | pt: Zcu.PerThread, |
| 4364 | enum_ty: Type, |
| 4365 | function_index: Builder.Function.Index, |
| 4366 | ) Allocator.Error!void { |
| 4367 | const zcu = pt.zcu; |
| 4368 | const builder = &o.builder; |
| 4369 | const loaded_enum = zcu.intern_pool.loadEnumType(enum_ty.toIntern()); |
| 4370 | function_index.ptrConst(builder).global.ptr(builder).type = try builder.fnType( |
| 4371 | .i1, |
| 4372 | &.{try o.lowerType(pt, .fromInterned(loaded_enum.int_tag_type))}, |
| 4373 | .normal, |
| 4374 | ); |
| 4375 | |
| 4376 | var attributes: Builder.FunctionAttributes.Wip = .{}; |
| 4377 | defer attributes.deinit(builder); |
| 4378 | try o.addCommonFnAttributes(&attributes, zcu.root_mod, zcu.root_mod.omit_frame_pointer); |
| 4379 | |
| 4380 | function_index.setLinkage(.internal, builder); |
| 4381 | function_index.setCallConv(.fastcc, builder); |
| 4382 | function_index.setAttributes(try attributes.finish(builder), builder); |
| 4383 | |
| 4384 | var wip: Builder.WipFunction = try .init(builder, .{ |
| 4385 | .function = function_index, |
| 4386 | .strip = true, |
| 4387 | }); |
| 4388 | defer wip.deinit(); |
| 4389 | wip.cursor = .{ .block = try wip.block(0, "Entry") }; |
| 4390 | |
| 4391 | const named_block = try wip.block(@intCast(loaded_enum.field_names.len), "Named"); |
| 4392 | const unnamed_block = try wip.block(1, "Unnamed"); |
| 4393 | const tag_int_value = wip.arg(0); |
| 4394 | var wip_switch = try wip.@"switch"(tag_int_value, unnamed_block, @intCast(loaded_enum.field_names.len), .none); |
| 4395 | defer wip_switch.finish(&wip); |
| 4396 | |
| 4397 | for (0..loaded_enum.field_names.len) |field_index| { |
| 4398 | const this_tag_int_value = try o.lowerValue( |
| 4399 | pt, |
| 4400 | (try pt.enumValueFieldIndex(enum_ty, @intCast(field_index))).toIntern(), |
| 4401 | ); |
| 4402 | try wip_switch.addCase(this_tag_int_value, named_block, &wip); |
| 4403 | } |
| 4404 | wip.cursor = .{ .block = named_block }; |
| 4405 | _ = try wip.ret(.true); |
| 4406 | |
| 4407 | wip.cursor = .{ .block = unnamed_block }; |
| 4408 | _ = try wip.ret(.false); |
| 4409 | |
| 4410 | try wip.finish(); |
| 4411 | } |
| 4366 | 4412 | }; |
| 4367 | 4413 | |
| 4368 | 4414 | pub const NavGen = struct { |
| ... | ... | @@ -10106,56 +10152,19 @@ pub const FuncGen = struct { |
| 10106 | 10152 | const pt = self.ng.pt; |
| 10107 | 10153 | const zcu = pt.zcu; |
| 10108 | 10154 | const ip = &zcu.intern_pool; |
| 10109 | | const enum_type = ip.loadEnumType(enum_ty.toIntern()); |
| 10110 | 10155 | |
| 10111 | | // TODO: detect when the type changes (`updateContainerType` will be called) and re-emit this function |
| 10112 | 10156 | const gop = try o.named_enum_map.getOrPut(o.gpa, enum_ty.toIntern()); |
| 10113 | 10157 | if (gop.found_existing) return gop.value_ptr.*; |
| 10114 | 10158 | errdefer assert(o.named_enum_map.remove(enum_ty.toIntern())); |
| 10115 | | |
| 10116 | | const target = &zcu.root_mod.resolved_target.result; |
| 10117 | 10159 | 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), |
| 10160 | // Dummy function type; `updateIsNamedEnumValue` will replace it with the correct type. |
| 10161 | // TODO: change the builder API so we don't need to do this. |
| 10162 | try o.builder.fnType(.void, &.{}, .normal), |
| 10163 | try o.builder.strtabStringFmt("__zig_is_named_enum_value_{f}", .{enum_ty.containerTypeName(ip).fmt(ip)}), |
| 10164 | toLlvmAddressSpace(.generic, zcu.getTarget()), |
| 10121 | 10165 | ); |
| 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 | 10166 | 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(); |
| 10167 | try o.updateIsNamedEnumValueFunction(pt, enum_ty, function_index); |
| 10159 | 10168 | return function_index; |
| 10160 | 10169 | } |
| 10161 | 10170 | |