os: x86 cpuid natives and pure decoders (OS slice 3, step 2a) #538

Closed
opened 2026-10-28 05:11:14 +00:00 by orion · 10 comments
Collaborator

Goal

Step 2a of #127 (OS slice 3): the x86/ module of std/os with its two natives and the pure decoders, plus the public types describe will return. Processor.describe itself and the per-system halves (Windows topology, Linux/macOS counts and caches, Arm64 features from the system) are not in this issue: they are step 2b, filed when this one lands.

Why the cut: step 2 as written in #127 spans runtime/os/x86.c, the decoders, three per-system halves and the Arm64 feature sources. That is more than one PR of one or two commits, so only the first sub-step is filed (per the definition of ready).

Design record

docs/design/OS.md section 7 ("x86 — runtime/os/x86.c, native type X86, on .X64"), section 5.2 (ProcessorDescription, ProcessorCache, ProcessorFeature), the feature-list paragraph after 5.2, slice 3 of section 10.

Scope

  • runtime/os/x86.c: X86.cpuid(leaf, subleaf, var eax, var ebx, var ecx, var edx) and X86.extendedControlRegister(var low, var high): Bool (xgetbv(0), false where OSXSAVE is not set), guarded for .X64 like the other per-system files, no #ifdef inside a function.
  • std/os/src/x86/native.trb (native type X86) and std/os/src/x86/processor.trb: pure decoders over register integers: vendor (leaf 0), brand string (leaves 0x80000002 to 0x80000004), feature bits (leaves 1 and 7, plus xgetbv for AVX/AVX-512 usability), caches (leaf 4, or 0x8000001D on AMD), and topology (packages, cores, logical processors from leaves 1, 4, 0xB/0x1F, 0x80000008).
  • ProcessorCache and ProcessorFeature as in OS.md 5.2 (the list stays closed; Arm64 cases are declared now, filled in step 2b), ProcessorDescription only if the decoders need it as the carrier; otherwise it comes with 2b.
  • std/os/tests/x86.test.trb: tests that feed the decoders register values captured from real processors (at least one Intel and one AMD, one without AVX-512, one with; a hybrid-core Intel for leaf 0x1A/0x1F if capturable), runnable on every machine and architecture.
  • docs/standard-library/os.md documents the new public types; the skills/ copy is regenerated.

Acceptance criteria

  • On x86-64 X86.cpuid(0, 0, ...) returns a vendor string that equals the decoder's output for the same registers; on other architectures the module is absent and the std still builds (no new Unsupported leaks into public API).
  • Each decoder is a pure function of integers: no native call inside, one test per decoder with captured register values and the expected vendor, brand, feature set, cache list and topology.
  • A brand string with leading spaces and NUL padding decodes trimmed; an absent leaf (max leaf too low) decodes to an empty/default result, never a trap.
  • ProcessorFeature.Avx/Avx2/Fma/Avx512Foundation are reported only when OSXSAVE and the matching xgetbv bits say the OS saves the registers (tested with a register set where the CPU has the bit but the OS does not).
  • torb format --check clean on touched files; sh tools/gates.sh a green in forge CI; docs check and skills/ regeneration clean.

Seed impact

None expected: new std names and one new native type; the compiler imports none of them by string. If CI shows a seed dependency, fall back to the two-commit rule (native and std first, consumer second); the seed refresh itself stays with the owner.

Size

One PR, two Conventional Commits: feat(os): x86 cpuid and extendedControlRegister natives and feat(os): x86 decoders for vendor, brand, topology, caches and features (docs and tests ride with the second).

Dependencies

Step 1 (#488) landed (f12a2a4d). Part of #127; step 3 (frequencies) is not filed yet.

## Goal Step 2a of #127 (OS slice 3): the `x86/` module of `std/os` with its two natives and the pure decoders, plus the public types `describe` will return. `Processor.describe` itself and the per-system halves (Windows topology, Linux/macOS counts and caches, Arm64 features from the system) are **not** in this issue: they are step 2b, filed when this one lands. Why the cut: step 2 as written in #127 spans `runtime/os/x86.c`, the decoders, three per-system halves and the Arm64 feature sources. That is more than one PR of one or two commits, so only the first sub-step is filed (per the definition of ready). ## Design record `docs/design/OS.md` section 7 ("x86 — `runtime/os/x86.c`, `native type X86`, on `.X64`"), section 5.2 (`ProcessorDescription`, `ProcessorCache`, `ProcessorFeature`), the feature-list paragraph after 5.2, slice 3 of section 10. ## Scope - `runtime/os/x86.c`: `X86.cpuid(leaf, subleaf, var eax, var ebx, var ecx, var edx)` and `X86.extendedControlRegister(var low, var high): Bool` (`xgetbv(0)`, false where `OSXSAVE` is not set), guarded for `.X64` like the other per-system files, no `#ifdef` inside a function. - `std/os/src/x86/native.trb` (`native type X86`) and `std/os/src/x86/processor.trb`: pure decoders over register integers: vendor (leaf 0), brand string (leaves `0x80000002` to `0x80000004`), feature bits (leaves 1 and 7, plus `xgetbv` for AVX/AVX-512 usability), caches (leaf 4, or `0x8000001D` on AMD), and topology (packages, cores, logical processors from leaves 1, 4, `0xB`/`0x1F`, `0x80000008`). - `ProcessorCache` and `ProcessorFeature` as in OS.md 5.2 (the list stays closed; Arm64 cases are declared now, filled in step 2b), `ProcessorDescription` only if the decoders need it as the carrier; otherwise it comes with 2b. - `std/os/tests/x86.test.trb`: tests that feed the decoders register values captured from real processors (at least one Intel and one AMD, one without AVX-512, one with; a hybrid-core Intel for leaf `0x1A`/`0x1F` if capturable), runnable on every machine and architecture. - `docs/standard-library/os.md` documents the new public types; the `skills/` copy is regenerated. ## Acceptance criteria - [ ] On x86-64 `X86.cpuid(0, 0, ...)` returns a vendor string that equals the decoder's output for the same registers; on other architectures the module is absent and the std still builds (no new `Unsupported` leaks into public API). - [ ] Each decoder is a pure function of integers: no native call inside, one test per decoder with captured register values and the expected vendor, brand, feature set, cache list and topology. - [ ] A brand string with leading spaces and NUL padding decodes trimmed; an absent leaf (max leaf too low) decodes to an empty/default result, never a trap. - [ ] `ProcessorFeature.Avx`/`Avx2`/`Fma`/`Avx512Foundation` are reported only when `OSXSAVE` and the matching `xgetbv` bits say the OS saves the registers (tested with a register set where the CPU has the bit but the OS does not). - [ ] `torb format --check` clean on touched files; `sh tools/gates.sh a` green in forge CI; docs check and `skills/` regeneration clean. ## Seed impact None expected: new std names and one new native type; the compiler imports none of them by string. If CI shows a seed dependency, fall back to the two-commit rule (native and std first, consumer second); the seed refresh itself stays with the owner. ## Size One PR, two Conventional Commits: `feat(os): x86 cpuid and extendedControlRegister natives` and `feat(os): x86 decoders for vendor, brand, topology, caches and features` (docs and tests ride with the second). ## Dependencies Step 1 (#488) landed (`f12a2a4d`). Part of #127; step 3 (frequencies) is not filed yet.
Author
Collaborator

[loop:torbscript] claim implement by session:loop-torbscript-20261028 until 2026-10-28T11:30Z

[loop:torbscript] claim implement by session:loop-torbscript-20261028 until 2026-10-28T11:30Z
Author
Collaborator

[loop:torbscript] release implement: worker lost its execution context before pushing anything (no branch exists). Respawning.

[loop:torbscript] release implement: worker lost its execution context before pushing anything (no branch exists). Respawning.
Author
Collaborator

[loop:torbscript] claim implement (respawn) by session:loop-torbscript-20261028 until 2026-10-28T11:40Z

[loop:torbscript] claim implement (respawn) by session:loop-torbscript-20261028 until 2026-10-28T11:40Z
Author
Collaborator

[loop:torbscript] release implement: PR #541 (loop/538-os-x86-decoders, head 81d388a) is open and mergeable. Commits: cpuid/extendedControlRegister natives, x86 decoders (vendor, brand, topology, caches, features), runtime README stamp, and a fix making the ProcessorCache/ProcessorFeature doc examples self-contained (addresses the tier A failure on d80c806, run 2044). CI run 2050 on 81d388a is queued behind the single linux-x64 runner. Tier B is expected red (pre-existing on main, fixed by #536). The follow-up worker lost its execution context; remaining CI verdict goes to the merge gate. Claim released.

[loop:torbscript] release implement: PR #541 (`loop/538-os-x86-decoders`, head `81d388a`) is open and mergeable. Commits: cpuid/extendedControlRegister natives, x86 decoders (vendor, brand, topology, caches, features), runtime README stamp, and a fix making the ProcessorCache/ProcessorFeature doc examples self-contained (addresses the tier A failure on `d80c806`, run 2044). CI run 2050 on `81d388a` is queued behind the single linux-x64 runner. Tier B is expected red (pre-existing on main, fixed by #536). The follow-up worker lost its execution context; remaining CI verdict goes to the merge gate. Claim released.
Author
Collaborator

[loop:torbscript] claim implement (fix: tier A red on PR #541) by session:loop-torbscript-20261028 until 2026-10-28T14:40Z

[loop:torbscript] claim implement (fix: tier A red on PR #541) by session:loop-torbscript-20261028 until 2026-10-28T14:40Z
Author
Collaborator

[loop:torbscript] release implement: the fix worker was killed after pushing head b9aec30 to PR #541 (tier A fix); CI on that head is pending behind the single linux-x64 runner. Nothing left to implement until CI settles. next: waiting (CI on PR #541 and merge gate)

[loop:torbscript] release implement: the fix worker was killed after pushing head b9aec30 to PR #541 (tier A fix); CI on that head is pending behind the single linux-x64 runner. Nothing left to implement until CI settles. next: waiting (CI on PR #541 and merge gate)
Author
Collaborator

[loop:torbscript] claim implement (fix: PR #541 tier B and gates red on b9aec30; #536 landed on main, rebase and re-read) by session:loop-torbscript-20261028 until 2026-10-28T17:35Z

[loop:torbscript] claim implement (fix: PR #541 tier B and gates red on b9aec30; #536 landed on main, rebase and re-read) by session:loop-torbscript-20261028 until 2026-10-28T17:35Z
Author
Collaborator

[loop:torbscript] review: tier B and gates on b9aec30 failed only on the four inherited resource conformance programs (resource-bytes/-name/-text budgets, resource-missing); 330 of 334 passed, none of this PR. #536 has landed on main (403ee176), so I rebased the five commits onto it (linear, no merge commits, check-commits clean) and force-pushed with lease to loop/538-os-x86-decoders, new head acf8510. No code change was needed. Forge CI run 2061 on acf8510: tier A, tier B, gates, bootstrap, same-C, playground, release-sync and pdisc all green. I dropped the WIP prefix from the PR title since it is ready. Worktree removed. next: waiting (merge gate review of PR #541). Worker tokens: not exposed to the worker; roughly 60k, most of it spent waiting on the CI queue.

[loop:torbscript] review: tier B and gates on b9aec30 failed only on the four inherited resource conformance programs (resource-bytes/-name/-text budgets, resource-missing); 330 of 334 passed, none of this PR. #536 has landed on main (403ee176), so I rebased the five commits onto it (linear, no merge commits, check-commits clean) and force-pushed with lease to loop/538-os-x86-decoders, new head acf8510. No code change was needed. Forge CI run 2061 on acf8510: tier A, tier B, gates, bootstrap, same-C, playground, release-sync and pdisc all green. I dropped the WIP prefix from the PR title since it is ready. Worktree removed. next: waiting (merge gate review of PR #541). Worker tokens: not exposed to the worker; roughly 60k, most of it spent waiting on the CI queue.
Author
Collaborator

[loop:torbscript] close: PR #541 landed on main (acf85102). Its tier A, tier B and gates were green on the PR head; the push CI of the landed commit is still pending. next: waiting (main CI on acf85102, then close with the commit link)

[loop:torbscript] close: PR #541 landed on main (acf85102). Its tier A, tier B and gates were green on the PR head; the push CI of the landed commit is still pending. next: waiting (main CI on acf85102, then close with the commit link)
Author
Collaborator

[loop:torbscript] close: PR #541 landed on main as acf8510 (acf8510278); main CI on that commit is green (bootstrap, tier A, tier B, gates). Step 2a of #127 is done, the epic continues with its next step. Closing.

[loop:torbscript] close: PR #541 landed on main as acf8510 (https://git.torb.dev/torbscript/language/commit/acf8510278d75b049969072c6926dd4374678086); main CI on that commit is green (bootstrap, tier A, tier B, gates). Step 2a of #127 is done, the epic continues with its next step. Closing.
orion closed this issue 2026-10-28 13:15:25 +00:00
Sign in to join this conversation.
No labels
loop
ready
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
torbscript/language#538
No description provided.