| ... | @@ -345,7 +345,7 @@ pub fn resolveTargetQuery(query: Target.Query) DetectError!Target { | ... | @@ -345,7 +345,7 @@ pub fn resolveTargetQuery(query: Target.Query) DetectError!Target { |
| 345 | os.version_range.linux.android = android; | 345 | os.version_range.linux.android = android; |
| 346 | } | 346 | } |
| 347 | | 347 | |
| 348 | const cpu = switch (query.cpu_model) { | 348 | var cpu = switch (query.cpu_model) { |
| 349 | .native => detectNativeCpuAndFeatures(query_cpu_arch, os, query), | 349 | .native => detectNativeCpuAndFeatures(query_cpu_arch, os, query), |
| 350 | .baseline => Target.Cpu.baseline(query_cpu_arch, os), | 350 | .baseline => Target.Cpu.baseline(query_cpu_arch, os), |
| 351 | .determined_by_arch_os => if (query.cpu_arch == null) | 351 | .determined_by_arch_os => if (query.cpu_arch == null) |
| ... | @@ -357,55 +357,22 @@ pub fn resolveTargetQuery(query: Target.Query) DetectError!Target { | ... | @@ -357,55 +357,22 @@ pub fn resolveTargetQuery(query: Target.Query) DetectError!Target { |
| 357 | break :backup_cpu_detection Target.Cpu.baseline(query_cpu_arch, os); | 357 | break :backup_cpu_detection Target.Cpu.baseline(query_cpu_arch, os); |
| 358 | }; | 358 | }; |
| 359 | | 359 | |
| 360 | var result = try detectAbiAndDynamicLinker(cpu, os, query); | | |
| 361 | | | |
| 362 | // It's possible that we detect the native ABI, but fail to detect the OS version or were told | | |
| 363 | // to use the default OS version range. In that case, while we can't determine the exact native | | |
| 364 | // OS version, we do at least know that some ABIs require a particular OS version (by way of | | |
| 365 | // `std.zig.target.available_libcs`). So in this case, adjust the OS version to the minimum that | | |
| 366 | // we know is required. | | |
| 367 | if (result.abi != query_abi and query.os_version_min == null) { | | |
| 368 | const result_ver_range = &result.os.version_range; | | |
| 369 | const abi_ver_range = result.os.tag.defaultVersionRange(result.cpu.arch, result.abi).version_range; | | |
| 370 | | | |
| 371 | switch (result.os.tag.versionRangeTag()) { | | |
| 372 | .none => {}, | | |
| 373 | .semver => if (result_ver_range.semver.min.order(abi_ver_range.semver.min) == .lt) { | | |
| 374 | result_ver_range.semver.min = abi_ver_range.semver.min; | | |
| 375 | }, | | |
| 376 | inline .hurd, .linux => |t| { | | |
| 377 | if (@field(result_ver_range, @tagName(t)).range.min.order(@field(abi_ver_range, @tagName(t)).range.min) == .lt) { | | |
| 378 | @field(result_ver_range, @tagName(t)).range.min = @field(abi_ver_range, @tagName(t)).range.min; | | |
| 379 | } | | |
| 380 | | | |
| 381 | if (@field(result_ver_range, @tagName(t)).glibc.order(@field(abi_ver_range, @tagName(t)).glibc) == .lt and | | |
| 382 | query.glibc_version == null) | | |
| 383 | { | | |
| 384 | @field(result_ver_range, @tagName(t)).glibc = @field(abi_ver_range, @tagName(t)).glibc; | | |
| 385 | } | | |
| 386 | }, | | |
| 387 | .windows => if (!result_ver_range.windows.min.isAtLeast(abi_ver_range.windows.min)) { | | |
| 388 | result_ver_range.windows.min = abi_ver_range.windows.min; | | |
| 389 | }, | | |
| 390 | } | | |
| 391 | } | | |
| 392 | | | |
| 393 | // For x86, we need to populate some CPU feature flags depending on architecture | 360 | // For x86, we need to populate some CPU feature flags depending on architecture |
| 394 | // and mode: | 361 | // and mode: |
| 395 | // * 16bit_mode => if the abi is code16 | 362 | // * 16bit_mode => if the abi is code16 |
| 396 | // * 32bit_mode => if the arch is x86 | 363 | // * 32bit_mode => if the arch is x86 |
| 397 | // However, the "mode" flags can be used as overrides, so if the user explicitly | 364 | // However, the "mode" flags can be used as overrides, so if the user explicitly |
| 398 | // sets one of them, that takes precedence. | 365 | // sets one of them, that takes precedence. |
| 399 | switch (result.cpu.arch) { | 366 | switch (query_cpu_arch) { |
| 400 | .x86 => { | 367 | .x86 => { |
| 401 | if (!Target.x86.featureSetHasAny(query.cpu_features_add, .{ | 368 | if (!Target.x86.featureSetHasAny(query.cpu_features_add, .{ |
| 402 | .@"16bit_mode", .@"32bit_mode", | 369 | .@"16bit_mode", .@"32bit_mode", |
| 403 | })) { | 370 | })) { |
| 404 | switch (result.abi) { | 371 | switch (query_abi) { |
| 405 | .code16 => result.cpu.features.addFeature( | 372 | .code16 => cpu.features.addFeature( |
| 406 | @intFromEnum(Target.x86.Feature.@"16bit_mode"), | 373 | @intFromEnum(Target.x86.Feature.@"16bit_mode"), |
| 407 | ), | 374 | ), |
| 408 | else => result.cpu.features.addFeature( | 375 | else => cpu.features.addFeature( |
| 409 | @intFromEnum(Target.x86.Feature.@"32bit_mode"), | 376 | @intFromEnum(Target.x86.Feature.@"32bit_mode"), |
| 410 | ), | 377 | ), |
| 411 | } | 378 | } |
| ... | @@ -416,32 +383,65 @@ pub fn resolveTargetQuery(query: Target.Query) DetectError!Target { | ... | @@ -416,32 +383,65 @@ pub fn resolveTargetQuery(query: Target.Query) DetectError!Target { |
| 416 | // What do we do if the user specifies +thumb_mode? | 383 | // What do we do if the user specifies +thumb_mode? |
| 417 | }, | 384 | }, |
| 418 | .thumb, .thumbeb => { | 385 | .thumb, .thumbeb => { |
| 419 | result.cpu.features.addFeature( | 386 | cpu.features.addFeature( |
| 420 | @intFromEnum(Target.arm.Feature.thumb_mode), | 387 | @intFromEnum(Target.arm.Feature.thumb_mode), |
| 421 | ); | 388 | ); |
| 422 | }, | 389 | }, |
| 423 | else => {}, | 390 | else => {}, |
| 424 | } | 391 | } |
| 425 | updateCpuFeatures( | 392 | updateCpuFeatures( |
| 426 | &result.cpu.features, | 393 | &cpu.features, |
| 427 | result.cpu.arch.allFeaturesList(), | 394 | cpu.arch.allFeaturesList(), |
| 428 | query.cpu_features_add, | 395 | query.cpu_features_add, |
| 429 | query.cpu_features_sub, | 396 | query.cpu_features_sub, |
| 430 | ); | 397 | ); |
| 431 | | 398 | |
| 432 | if (result.cpu.arch == .hexagon) { | 399 | if (cpu.arch == .hexagon) { |
| 433 | // Both LLVM and LLD have broken support for the small data area. Yet LLVM has the feature | 400 | // Both LLVM and LLD have broken support for the small data area. Yet LLVM has the feature |
| 434 | // on by default for all Hexagon CPUs. Clang sort of solves this by defaulting the `-gpsize` | 401 | // on by default for all Hexagon CPUs. Clang sort of solves this by defaulting the `-gpsize` |
| 435 | // command line parameter for the Hexagon backend to 0, so that no constants get placed in | 402 | // command line parameter for the Hexagon backend to 0, so that no constants get placed in |
| 436 | // the SDA. (This of course breaks down if the user passes `-G <n>` to Clang...) We can't do | 403 | // the SDA. (This of course breaks down if the user passes `-G <n>` to Clang...) We can't do |
| 437 | // the `-gpsize` hack because we can have multiple concurrent LLVM emit jobs, and command | 404 | // the `-gpsize` hack because we can have multiple concurrent LLVM emit jobs, and command |
| 438 | // line options in LLVM are shared globally. So just force this feature off. Lovely stuff. | 405 | // line options in LLVM are shared globally. So just force this feature off. Lovely stuff. |
| 439 | result.cpu.features.removeFeature(@intFromEnum(Target.hexagon.Feature.small_data)); | 406 | cpu.features.removeFeature(@intFromEnum(Target.hexagon.Feature.small_data)); |
| 440 | } | 407 | } |
| 441 | | 408 | |
| 442 | // https://github.com/llvm/llvm-project/issues/105978 | 409 | // https://github.com/llvm/llvm-project/issues/105978 |
| 443 | if (result.cpu.arch.isArm() and result.floatAbi() == .soft) { | 410 | if (cpu.arch.isArm() and query_abi.floatAbi() == .soft) { |
| 444 | result.cpu.features.removeFeature(@intFromEnum(Target.arm.Feature.vfp2)); | 411 | cpu.features.removeFeature(@intFromEnum(Target.arm.Feature.vfp2)); |
| | 412 | } |
| | 413 | |
| | 414 | var result = try detectAbiAndDynamicLinker(cpu, os, query); |
| | 415 | |
| | 416 | // It's possible that we detect the native ABI, but fail to detect the OS version or were told |
| | 417 | // to use the default OS version range. In that case, while we can't determine the exact native |
| | 418 | // OS version, we do at least know that some ABIs require a particular OS version (by way of |
| | 419 | // `std.zig.target.available_libcs`). So in this case, adjust the OS version to the minimum that |
| | 420 | // we know is required. |
| | 421 | if (result.abi != query_abi and query.os_version_min == null) { |
| | 422 | const result_ver_range = &result.os.version_range; |
| | 423 | const abi_ver_range = result.os.tag.defaultVersionRange(result.cpu.arch, result.abi).version_range; |
| | 424 | |
| | 425 | switch (result.os.tag.versionRangeTag()) { |
| | 426 | .none => {}, |
| | 427 | .semver => if (result_ver_range.semver.min.order(abi_ver_range.semver.min) == .lt) { |
| | 428 | result_ver_range.semver.min = abi_ver_range.semver.min; |
| | 429 | }, |
| | 430 | inline .hurd, .linux => |t| { |
| | 431 | if (@field(result_ver_range, @tagName(t)).range.min.order(@field(abi_ver_range, @tagName(t)).range.min) == .lt) { |
| | 432 | @field(result_ver_range, @tagName(t)).range.min = @field(abi_ver_range, @tagName(t)).range.min; |
| | 433 | } |
| | 434 | |
| | 435 | if (@field(result_ver_range, @tagName(t)).glibc.order(@field(abi_ver_range, @tagName(t)).glibc) == .lt and |
| | 436 | query.glibc_version == null) |
| | 437 | { |
| | 438 | @field(result_ver_range, @tagName(t)).glibc = @field(abi_ver_range, @tagName(t)).glibc; |
| | 439 | } |
| | 440 | }, |
| | 441 | .windows => if (!result_ver_range.windows.min.isAtLeast(abi_ver_range.windows.min)) { |
| | 442 | result_ver_range.windows.min = abi_ver_range.windows.min; |
| | 443 | }, |
| | 444 | } |
| 445 | } | 445 | } |
| 446 | | 446 | |
| 447 | return result; | 447 | return result; |