authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-11-29 12:05:21+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-11-29 19:24:42+01:00
log152202da777ac90693181226ceb164ef6e30cf89
tree01aa9a7a547cb49d6085fec97d4cd5a4e1111b25
parent1829b6eab8dc52ad2961467e23bfb36055cc8583

windows: if detecting CPU feature set and model fails, use generic with overrides


1 files changed, 32 insertions(+), 51 deletions(-)

lib/std/zig/system/windows.zig+32-51
......@@ -121,12 +121,12 @@ fn getCpuInfoFromRegistry(
121121 else => unreachable,
122122 }
123123 };
124 const key_namee = std.unicode.utf8ToUtf16LeStringLiteral(pair.key);
124 const key_name = std.unicode.utf8ToUtf16LeStringLiteral(pair.key);
125125
126126 table[i + 1] = .{
127127 .QueryRoutine = null,
128128 .Flags = std.os.windows.RTL_QUERY_REGISTRY_DIRECT | std.os.windows.RTL_QUERY_REGISTRY_REQUIRED,
129 .Name = @intToPtr([*:0]u16, @ptrToInt(key_namee)),
129 .Name = @intToPtr([*:0]u16, @ptrToInt(key_name)),
130130 .EntryContext = ctx,
131131 .DefaultType = REG.NONE,
132132 .DefaultData = null,
......@@ -155,8 +155,6 @@ fn getCpuInfoFromRegistry(
155155 switch (res) {
156156 .SUCCESS => {
157157 inline for (pairs) |pair, i| switch (pair.value) {
158 REG.NONE => unreachable,
159
160158 REG.SZ,
161159 REG.EXPAND_SZ,
162160 REG.MULTI_SZ,
......@@ -189,6 +187,12 @@ fn getCpuInfoFromRegistry(
189187 }
190188}
191189
190fn setFeature(comptime Feature: type, cpu: *Target.Cpu, feature: Feature, enabled: bool) void {
191 const idx = @as(Target.Cpu.Feature.Set.Index, @enumToInt(feature));
192
193 if (enabled) cpu.features.addFeature(idx) else cpu.features.removeFeature(idx);
194}
195
192196fn getCpuCount() usize {
193197 return std.os.windows.peb().NumberOfProcessors;
194198}
......@@ -298,64 +302,41 @@ fn CpuInfoParser(comptime impl: anytype) type {
298302 };
299303}
300304
301fn genericCpu(comptime arch: Target.Cpu.Arch) Target.Cpu {
302 return .{
305/// If the fine-grained detection of CPU features via Win registry fails,
306/// we fallback to a generic CPU model but we override the feature set
307/// using `SharedUserData` contents.
308/// This is effectively what LLVM does for all ARM chips on Windows.
309fn genericCpuAndNativeFeatures(arch: Target.Cpu.Arch) Target.Cpu {
310 var cpu = Target.Cpu{
303311 .arch = arch,
304312 .model = Target.Cpu.Model.generic(arch),
305313 .features = Target.Cpu.Feature.Set.empty,
306314 };
307}
308315
309pub fn detectNativeCpuAndFeatures() ?Target.Cpu {
310 const current_arch = builtin.cpu.arch;
311 switch (current_arch) {
316 switch (arch) {
312317 .aarch64, .aarch64_be, .aarch64_32 => {
313 var cpu = cpu: {
314 var maybe_cpu = ArmCpuInfoParser.parse(current_arch) catch break :cpu genericCpu(current_arch);
315 break :cpu maybe_cpu orelse genericCpu(current_arch);
316 };
317
318318 const Feature = Target.aarch64.Feature;
319319
320320 // Override any features that are either present or absent
321 if (IsProcessorFeaturePresent(PF.ARM_NEON_INSTRUCTIONS_AVAILABLE)) {
322 cpu.features.addFeature(@enumToInt(Feature.neon));
323 } else {
324 cpu.features.removeFeature(@enumToInt(Feature.neon));
325 }
326
327 if (IsProcessorFeaturePresent(PF.ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE)) {
328 cpu.features.addFeature(@enumToInt(Feature.crc));
329 } else {
330 cpu.features.removeFeature(@enumToInt(Feature.crc));
331 }
332
333 if (IsProcessorFeaturePresent(PF.ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE)) {
334 cpu.features.addFeature(@enumToInt(Feature.crypto));
335 } else {
336 cpu.features.removeFeature(@enumToInt(Feature.crypto));
337 }
338
339 if (IsProcessorFeaturePresent(PF.ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE)) {
340 cpu.features.addFeature(@enumToInt(Feature.lse));
341 } else {
342 cpu.features.removeFeature(@enumToInt(Feature.lse));
343 }
344
345 if (IsProcessorFeaturePresent(PF.ARM_V82_DP_INSTRUCTIONS_AVAILABLE)) {
346 cpu.features.addFeature(@enumToInt(Feature.dotprod));
347 } else {
348 cpu.features.removeFeature(@enumToInt(Feature.dotprod));
349 }
321 setFeature(Feature, &cpu, .neon, IsProcessorFeaturePresent(PF.ARM_NEON_INSTRUCTIONS_AVAILABLE));
322 setFeature(Feature, &cpu, .crc, IsProcessorFeaturePresent(PF.ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE));
323 setFeature(Feature, &cpu, .crypto, IsProcessorFeaturePresent(PF.ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE));
324 setFeature(Feature, &cpu, .lse, IsProcessorFeaturePresent(PF.ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE));
325 setFeature(Feature, &cpu, .dotprod, IsProcessorFeaturePresent(PF.ARM_V82_DP_INSTRUCTIONS_AVAILABLE));
326 setFeature(Feature, &cpu, .jsconv, IsProcessorFeaturePresent(PF.ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE));
327 },
328 else => {},
329 }
350330
351 if (IsProcessorFeaturePresent(PF.ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE)) {
352 cpu.features.addFeature(@enumToInt(Feature.jsconv));
353 } else {
354 cpu.features.removeFeature(@enumToInt(Feature.jsconv));
355 }
331 return cpu;
332}
356333
357 return cpu;
334pub fn detectNativeCpuAndFeatures() ?Target.Cpu {
335 const current_arch = builtin.cpu.arch;
336 switch (current_arch) {
337 .aarch64, .aarch64_be, .aarch64_32 => {
338 return ArmCpuInfoParser.parse(current_arch) catch genericCpuAndNativeFeatures(current_arch);
358339 },
359 else => {},
340 else => return null,
360341 }
361342}