simdref 0.0.9__tar.gz → 0.0.11__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. simdref-0.0.11/PKG-INFO +208 -0
  2. simdref-0.0.11/README.md +174 -0
  3. {simdref-0.0.9 → simdref-0.0.11}/pyproject.toml +1 -1
  4. {simdref-0.0.9 → simdref-0.0.11}/src/simdref/lsp.py +73 -15
  5. simdref-0.0.11/src/simdref.egg-info/PKG-INFO +208 -0
  6. {simdref-0.0.9 → simdref-0.0.11}/tests/test_lsp_stdio.py +49 -0
  7. simdref-0.0.9/PKG-INFO +0 -251
  8. simdref-0.0.9/README.md +0 -217
  9. simdref-0.0.9/src/simdref.egg-info/PKG-INFO +0 -251
  10. {simdref-0.0.9 → simdref-0.0.11}/LICENSE +0 -0
  11. {simdref-0.0.9 → simdref-0.0.11}/setup.cfg +0 -0
  12. {simdref-0.0.9 → simdref-0.0.11}/src/simdref/__init__.py +0 -0
  13. {simdref-0.0.9 → simdref-0.0.11}/src/simdref/__main__.py +0 -0
  14. {simdref-0.0.9 → simdref-0.0.11}/src/simdref/annotate.py +0 -0
  15. {simdref-0.0.9 → simdref-0.0.11}/src/simdref/arm_instructions.py +0 -0
  16. {simdref-0.0.9 → simdref-0.0.11}/src/simdref/cli.py +0 -0
  17. {simdref-0.0.9 → simdref-0.0.11}/src/simdref/display.py +0 -0
  18. {simdref-0.0.9 → simdref-0.0.11}/src/simdref/export.py +0 -0
  19. {simdref-0.0.9 → simdref-0.0.11}/src/simdref/filters.py +0 -0
  20. {simdref-0.0.9 → simdref-0.0.11}/src/simdref/ingest.py +0 -0
  21. {simdref-0.0.9 → simdref-0.0.11}/src/simdref/ingest_catalog.py +0 -0
  22. {simdref-0.0.9 → simdref-0.0.11}/src/simdref/ingest_pdf.py +0 -0
  23. {simdref-0.0.9 → simdref-0.0.11}/src/simdref/ingest_sources.py +0 -0
  24. {simdref-0.0.9 → simdref-0.0.11}/src/simdref/manpages.py +0 -0
  25. {simdref-0.0.9 → simdref-0.0.11}/src/simdref/models.py +0 -0
  26. {simdref-0.0.9 → simdref-0.0.11}/src/simdref/pdfparse/__init__.py +0 -0
  27. {simdref-0.0.9 → simdref-0.0.11}/src/simdref/pdfparse/base.py +0 -0
  28. {simdref-0.0.9 → simdref-0.0.11}/src/simdref/pdfparse/intel.py +0 -0
  29. {simdref-0.0.9 → simdref-0.0.11}/src/simdref/pdfparse/registry.py +0 -0
  30. {simdref-0.0.9 → simdref-0.0.11}/src/simdref/pdfparse/types.py +0 -0
  31. {simdref-0.0.9 → simdref-0.0.11}/src/simdref/pdfrefs.py +0 -0
  32. {simdref-0.0.9 → simdref-0.0.11}/src/simdref/perf.py +0 -0
  33. {simdref-0.0.9 → simdref-0.0.11}/src/simdref/perf_sources/__init__.py +0 -0
  34. {simdref-0.0.9 → simdref-0.0.11}/src/simdref/perf_sources/cores.py +0 -0
  35. {simdref-0.0.9 → simdref-0.0.11}/src/simdref/perf_sources/llvm_mca.py +0 -0
  36. {simdref-0.0.9 → simdref-0.0.11}/src/simdref/perf_sources/llvm_scheduling.py +0 -0
  37. {simdref-0.0.9 → simdref-0.0.11}/src/simdref/perf_sources/merge.py +0 -0
  38. {simdref-0.0.9 → simdref-0.0.11}/src/simdref/queries.py +0 -0
  39. {simdref-0.0.9 → simdref-0.0.11}/src/simdref/riscv.py +0 -0
  40. {simdref-0.0.9 → simdref-0.0.11}/src/simdref/search.py +0 -0
  41. {simdref-0.0.9 → simdref-0.0.11}/src/simdref/storage.py +0 -0
  42. {simdref-0.0.9 → simdref-0.0.11}/src/simdref/tui.py +0 -0
  43. {simdref-0.0.9 → simdref-0.0.11}/src/simdref/ui_labels.py +0 -0
  44. {simdref-0.0.9 → simdref-0.0.11}/src/simdref.egg-info/SOURCES.txt +0 -0
  45. {simdref-0.0.9 → simdref-0.0.11}/src/simdref.egg-info/dependency_links.txt +0 -0
  46. {simdref-0.0.9 → simdref-0.0.11}/src/simdref.egg-info/entry_points.txt +0 -0
  47. {simdref-0.0.9 → simdref-0.0.11}/src/simdref.egg-info/requires.txt +0 -0
  48. {simdref-0.0.9 → simdref-0.0.11}/src/simdref.egg-info/top_level.txt +0 -0
  49. {simdref-0.0.9 → simdref-0.0.11}/tests/test_annotate.py +0 -0
  50. {simdref-0.0.9 → simdref-0.0.11}/tests/test_annotate_positions.py +0 -0
  51. {simdref-0.0.9 → simdref-0.0.11}/tests/test_audit_coverage.py +0 -0
  52. {simdref-0.0.9 → simdref-0.0.11}/tests/test_auto_update_on_version_change.py +0 -0
  53. {simdref-0.0.9 → simdref-0.0.11}/tests/test_cli_bare_query.py +0 -0
  54. {simdref-0.0.9 → simdref-0.0.11}/tests/test_cli_bootstrap_progress.py +0 -0
  55. {simdref-0.0.9 → simdref-0.0.11}/tests/test_cli_help.py +0 -0
  56. {simdref-0.0.9 → simdref-0.0.11}/tests/test_cli_llm.py +0 -0
  57. {simdref-0.0.9 → simdref-0.0.11}/tests/test_coverage_live.py +0 -0
  58. {simdref-0.0.9 → simdref-0.0.11}/tests/test_coverage_parity.py +0 -0
  59. {simdref-0.0.9 → simdref-0.0.11}/tests/test_display.py +0 -0
  60. {simdref-0.0.9 → simdref-0.0.11}/tests/test_export.py +0 -0
  61. {simdref-0.0.9 → simdref-0.0.11}/tests/test_filters.py +0 -0
  62. {simdref-0.0.9 → simdref-0.0.11}/tests/test_ingest_sources.py +0 -0
  63. {simdref-0.0.9 → simdref-0.0.11}/tests/test_intel_operation_and_url.py +0 -0
  64. {simdref-0.0.9 → simdref-0.0.11}/tests/test_issue2_fixes.py +0 -0
  65. {simdref-0.0.9 → simdref-0.0.11}/tests/test_issues_23_24_25.py +0 -0
  66. {simdref-0.0.9 → simdref-0.0.11}/tests/test_lsp_web.py +0 -0
  67. {simdref-0.0.9 → simdref-0.0.11}/tests/test_models.py +0 -0
  68. {simdref-0.0.9 → simdref-0.0.11}/tests/test_pdfparse.py +0 -0
  69. {simdref-0.0.9 → simdref-0.0.11}/tests/test_perf.py +0 -0
  70. {simdref-0.0.9 → simdref-0.0.11}/tests/test_perf_sources.py +0 -0
  71. {simdref-0.0.9 → simdref-0.0.11}/tests/test_presentation.py +0 -0
  72. {simdref-0.0.9 → simdref-0.0.11}/tests/test_preset_persistence.py +0 -0
  73. {simdref-0.0.9 → simdref-0.0.11}/tests/test_riscv_docs_pages.py +0 -0
  74. {simdref-0.0.9 → simdref-0.0.11}/tests/test_search.py +0 -0
  75. {simdref-0.0.9 → simdref-0.0.11}/tests/test_search_pushdown.py +0 -0
  76. {simdref-0.0.9 → simdref-0.0.11}/tests/test_source_kind_filter.py +0 -0
  77. {simdref-0.0.9 → simdref-0.0.11}/tests/test_source_validation.py +0 -0
  78. {simdref-0.0.9 → simdref-0.0.11}/tests/test_storage_payload.py +0 -0
  79. {simdref-0.0.9 → simdref-0.0.11}/tests/test_storage_schema.py +0 -0
  80. {simdref-0.0.9 → simdref-0.0.11}/tests/test_tui.py +0 -0
  81. {simdref-0.0.9 → simdref-0.0.11}/tests/test_ui_labels_parity.py +0 -0
  82. {simdref-0.0.9 → simdref-0.0.11}/tests/test_version_matches_pyproject.py +0 -0
  83. {simdref-0.0.9 → simdref-0.0.11}/tests/test_x86_linking.py +0 -0
@@ -0,0 +1,208 @@
1
+ Metadata-Version: 2.4
2
+ Name: simdref
3
+ Version: 0.0.11
4
+ Summary: Searchable SIMD intrinsic and instruction reference with CLI, manpages, TUI, and LSP.
5
+ Author: Marco
6
+ License: GPL-3.0-or-later
7
+ Classifier: Development Status :: 3 - Alpha
8
+ Classifier: Environment :: Console
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Programming Language :: Python :: 3.14
18
+ Classifier: Topic :: Software Development :: Documentation
19
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
+ Requires-Python: >=3.10
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Requires-Dist: click<9,>=8.5
24
+ Requires-Dist: httpx<1,>=0.28
25
+ Requires-Dist: msgpack<2,>=1.2.1
26
+ Requires-Dist: pdfplumber<1,>=0.11.10
27
+ Requires-Dist: PyMuPDF<2,>=1.28
28
+ Requires-Dist: PyYAML<7,>=6.0.3
29
+ Requires-Dist: rapidfuzz<4,>=3.14
30
+ Requires-Dist: rich<16,>=15
31
+ Requires-Dist: textual<9,>=8.2
32
+ Requires-Dist: typer<1,>=0.27
33
+ Dynamic: license-file
34
+
35
+ # simdref
36
+
37
+ [![CI](https://github.com/simd-labs/simdref/actions/workflows/ci.yml/badge.svg)](https://github.com/simd-labs/simdref/actions/workflows/ci.yml)
38
+ [![TestPyPI](https://img.shields.io/pypi/v/simdref?pypiBaseUrl=https%3A%2F%2Ftest.pypi.org&label=TestPyPI)](https://test.pypi.org/project/simdref/)
39
+ [![Python](https://img.shields.io/pypi/pyversions/simdref?pypiBaseUrl=https%3A%2F%2Ftest.pypi.org)](https://pypi.org/project/simdref/)
40
+
41
+ simdref is a SIMD intrinsic and instruction reference for x86 (Intel +
42
+ uops.info), Arm (ACLE, AARCHMRS), and RISC-V (RVV + unified-db). It runs as
43
+ a CLI, a TUI, an LSP server, and an on-demand manpage renderer.
44
+
45
+ [Web app](https://simdref.diamondinoia.com/) ·
46
+ [TestPyPI](https://test.pypi.org/project/simdref/) ·
47
+ [GitHub](https://github.com/simd-labs/simdref) ·
48
+ [Contributing](CONTRIBUTING.md)
49
+
50
+ <p align="center">
51
+ <img alt="simdref TUI" src="https://raw.githubusercontent.com/simd-labs/simdref/refs/assets/docs/img/tui.svg" width="720">
52
+ </p>
53
+
54
+ ## Install the Claude Code and Codex skill
55
+
56
+ The `asm-analysis` skill lives in
57
+ [simd-labs/simdref-skill](https://github.com/simd-labs/simdref-skill). Follow
58
+ the install steps in that repo.
59
+
60
+ ## Install
61
+
62
+ ```bash
63
+ pip install simdref
64
+ isa update # download the pre-built catalog
65
+ isa doctor # check the install
66
+ isa # open the TUI
67
+ ```
68
+
69
+ The package installs two equivalent executables, `isa` and `simdref`. The
70
+ catalog download does not need `llvm-mca`. Only `isa build` needs
71
+ `llvm-mca` 18+ on `PATH`.
72
+
73
+ Pre-release builds live on TestPyPI:
74
+
75
+ ```bash
76
+ pip install -i https://test.pypi.org/simple/ \
77
+ --extra-index-url https://pypi.org/simple/ simdref
78
+ ```
79
+
80
+ ## Quickstart
81
+
82
+ ```bash
83
+ isa _mm_add_ps # exact intrinsic -> detailed view
84
+ isa VPADDD # exact instruction -> detailed view
85
+ isa _mm_add # fuzzy -> ranked search results
86
+ isa mm add # tokenized query -> intrinsic-biased search
87
+ isa ADD # mnemonic-like -> instruction-biased search
88
+ isa VADDPS 2 # pick variant #2 from the last result list
89
+ isa # open the TUI
90
+ ```
91
+
92
+ ## Interfaces
93
+
94
+ The web app at [simdref.diamondinoia.com](https://simdref.diamondinoia.com/)
95
+ reads the JSON site data this repo exports:
96
+
97
+ ```bash
98
+ isa export --out-dir ./site-data
99
+ ```
100
+
101
+ The LSP server speaks JSON-RPC over stdio:
102
+
103
+ ```bash
104
+ simdref-lsp
105
+ ```
106
+
107
+ Editor clients, one for each editor:
108
+
109
+ - Zed: [zed-simdref](https://github.com/simd-labs/zed-simdref)
110
+ - VS Code: [vscode-simdref](https://github.com/simd-labs/vscode-simdref)
111
+ - JetBrains: [jetbrains-simdref](https://github.com/simd-labs/jetbrains-simdref)
112
+ - Neovim: [nvim-simdref](https://github.com/simd-labs/nvim-simdref)
113
+
114
+ Each client shows a one-line brief at the end of each instruction line and
115
+ the full manpage on hover, from the local catalog.
116
+
117
+ The LLM interface emits JSON and NDJSON with exit codes 0 (match), 1 (bad
118
+ flag), 2 (no match), 3 (ambiguous):
119
+
120
+ ```bash
121
+ isa llm query _mm_add_ps --source-kind measured
122
+ echo -e "_mm_add_ps\nVPADDD" | isa llm batch
123
+ isa llm list --pattern "*gather*" --isa Intel
124
+ ```
125
+
126
+ See [docs/LLM.md](docs/LLM.md) for the payload shape.
127
+
128
+ The annotator turns compiler `.s` output into an annotated `.sa` file.
129
+
130
+ ```bash
131
+ isa annotate hello_simd.s # writes hello_simd.sa
132
+ isa annotate hello_simd.s --arch skylake-x -o - # stdout, skylake-x only
133
+ ```
134
+
135
+ The annotator adds a trailing comment with the summary, latency, and CPI to
136
+ each instruction line. The output stays valid assembly.
137
+
138
+ ## Commands
139
+
140
+ `isa --help` groups commands into Commands and Dev commands.
141
+
142
+ Commands
143
+
144
+ | Command | Description |
145
+ | ----------------------- | ------------------------------------------------------------------------- |
146
+ | `isa` | Open the TUI |
147
+ | `isa <query>` | Open the TUI with the query in a TTY, else print ranked results to stdout |
148
+ | `isa doctor` | Check the install, non-zero exit on failure |
149
+ | `isa update` | Download the pre-built catalog, `--from-release` for the GitHub Release |
150
+ | `isa annotate <file.s>` | Annotate a `.s` file with summaries and latency/CPI, writes `<file>.sa` |
151
+ | `isa man <name>` | Show a manpage, rendered on demand |
152
+ | `isa install-manpages` | Pre-generate man7 pages so plain `man vpaddd` works |
153
+ | `isa llm query <q>` | Strict lookup to JSON, NDJSON, or Markdown |
154
+ | `isa llm batch` | Resolve many queries from stdin in one invocation |
155
+ | `isa llm list` | Emit the FilterSpec or stream matching catalog entries |
156
+ | `isa llm schema` | Print the JSON schema for `llm` payloads |
157
+
158
+ Dev commands
159
+
160
+ | Command | Description |
161
+ | -------------------------------- | ------------------------------------------------------- |
162
+ | `isa build` | Rebuild the catalog from upstream, needs `llvm-mca` 18+ |
163
+ | `isa export` | Export the site-data JSON for the `simdref-web` repo |
164
+ | `isa completion install [SHELL]` | Install shell completion into the user profile |
165
+ | `isa completion show [SHELL]` | Print the completion script |
166
+
167
+ ## Data sources
168
+
169
+ | Source | What | Entries¹ |
170
+ | ----------------------- | ------------------------------------------------------- | ------------------ |
171
+ | Intel Intrinsics Guide | Signatures, descriptions, ISA, categories | 7,381 intrinsics |
172
+ | uops.info | Instructions, operands, latency, throughput, ports | 2,558 instructions |
173
+ | Arm ACLE (NEON, SVE) | Intrinsic signatures and descriptions | 10,791 intrinsics |
174
+ | Arm AARCHMRS (A64) | Base instruction forms and operand tables | live-only² |
175
+ | riscv-rvv-intrinsic-doc | RVV intrinsics with deterministic instruction refs | 74,289 intrinsics |
176
+ | RISC-V unified-db | RVV instruction forms, ISA tags, description, operation | 672 instructions |
177
+
178
+ ¹ Counts from the vendored snapshot. See
179
+ [`docs/coverage/summary.json`](docs/coverage/summary.json) for parity
180
+ against upstream and [`docs/SOURCES.md`](docs/SOURCES.md) for licenses.
181
+
182
+ ² The full AARCHMRS A64 spec needs a live fetch or a tarball under
183
+ `vendor/arm/`.
184
+
185
+ Each perf row carries a `(measured, <core>)` or `(modeled, <core>)` tag.
186
+
187
+ ### Scope
188
+
189
+ - Performance data is x86-only.
190
+ - RISC-V coverage is RVV only, not scalar or privileged ISA.
191
+
192
+ ## Development
193
+
194
+ ```bash
195
+ git clone https://github.com/simd-labs/simdref.git
196
+ cd simdref
197
+ python3 -m venv .venv
198
+ .venv/bin/pip install -e .
199
+ .venv/bin/isa build # needs llvm-mca 18+
200
+ .venv/bin/python -m pytest tests/ -v
201
+ ```
202
+
203
+ See [CONTRIBUTING.md](CONTRIBUTING.md) and
204
+ [ARCHITECTURE.md](ARCHITECTURE.md).
205
+
206
+ ## License
207
+
208
+ [GNU General Public License v3.0](LICENSE).
@@ -0,0 +1,174 @@
1
+ # simdref
2
+
3
+ [![CI](https://github.com/simd-labs/simdref/actions/workflows/ci.yml/badge.svg)](https://github.com/simd-labs/simdref/actions/workflows/ci.yml)
4
+ [![TestPyPI](https://img.shields.io/pypi/v/simdref?pypiBaseUrl=https%3A%2F%2Ftest.pypi.org&label=TestPyPI)](https://test.pypi.org/project/simdref/)
5
+ [![Python](https://img.shields.io/pypi/pyversions/simdref?pypiBaseUrl=https%3A%2F%2Ftest.pypi.org)](https://pypi.org/project/simdref/)
6
+
7
+ simdref is a SIMD intrinsic and instruction reference for x86 (Intel +
8
+ uops.info), Arm (ACLE, AARCHMRS), and RISC-V (RVV + unified-db). It runs as
9
+ a CLI, a TUI, an LSP server, and an on-demand manpage renderer.
10
+
11
+ [Web app](https://simdref.diamondinoia.com/) ·
12
+ [TestPyPI](https://test.pypi.org/project/simdref/) ·
13
+ [GitHub](https://github.com/simd-labs/simdref) ·
14
+ [Contributing](CONTRIBUTING.md)
15
+
16
+ <p align="center">
17
+ <img alt="simdref TUI" src="https://raw.githubusercontent.com/simd-labs/simdref/refs/assets/docs/img/tui.svg" width="720">
18
+ </p>
19
+
20
+ ## Install the Claude Code and Codex skill
21
+
22
+ The `asm-analysis` skill lives in
23
+ [simd-labs/simdref-skill](https://github.com/simd-labs/simdref-skill). Follow
24
+ the install steps in that repo.
25
+
26
+ ## Install
27
+
28
+ ```bash
29
+ pip install simdref
30
+ isa update # download the pre-built catalog
31
+ isa doctor # check the install
32
+ isa # open the TUI
33
+ ```
34
+
35
+ The package installs two equivalent executables, `isa` and `simdref`. The
36
+ catalog download does not need `llvm-mca`. Only `isa build` needs
37
+ `llvm-mca` 18+ on `PATH`.
38
+
39
+ Pre-release builds live on TestPyPI:
40
+
41
+ ```bash
42
+ pip install -i https://test.pypi.org/simple/ \
43
+ --extra-index-url https://pypi.org/simple/ simdref
44
+ ```
45
+
46
+ ## Quickstart
47
+
48
+ ```bash
49
+ isa _mm_add_ps # exact intrinsic -> detailed view
50
+ isa VPADDD # exact instruction -> detailed view
51
+ isa _mm_add # fuzzy -> ranked search results
52
+ isa mm add # tokenized query -> intrinsic-biased search
53
+ isa ADD # mnemonic-like -> instruction-biased search
54
+ isa VADDPS 2 # pick variant #2 from the last result list
55
+ isa # open the TUI
56
+ ```
57
+
58
+ ## Interfaces
59
+
60
+ The web app at [simdref.diamondinoia.com](https://simdref.diamondinoia.com/)
61
+ reads the JSON site data this repo exports:
62
+
63
+ ```bash
64
+ isa export --out-dir ./site-data
65
+ ```
66
+
67
+ The LSP server speaks JSON-RPC over stdio:
68
+
69
+ ```bash
70
+ simdref-lsp
71
+ ```
72
+
73
+ Editor clients, one for each editor:
74
+
75
+ - Zed: [zed-simdref](https://github.com/simd-labs/zed-simdref)
76
+ - VS Code: [vscode-simdref](https://github.com/simd-labs/vscode-simdref)
77
+ - JetBrains: [jetbrains-simdref](https://github.com/simd-labs/jetbrains-simdref)
78
+ - Neovim: [nvim-simdref](https://github.com/simd-labs/nvim-simdref)
79
+
80
+ Each client shows a one-line brief at the end of each instruction line and
81
+ the full manpage on hover, from the local catalog.
82
+
83
+ The LLM interface emits JSON and NDJSON with exit codes 0 (match), 1 (bad
84
+ flag), 2 (no match), 3 (ambiguous):
85
+
86
+ ```bash
87
+ isa llm query _mm_add_ps --source-kind measured
88
+ echo -e "_mm_add_ps\nVPADDD" | isa llm batch
89
+ isa llm list --pattern "*gather*" --isa Intel
90
+ ```
91
+
92
+ See [docs/LLM.md](docs/LLM.md) for the payload shape.
93
+
94
+ The annotator turns compiler `.s` output into an annotated `.sa` file.
95
+
96
+ ```bash
97
+ isa annotate hello_simd.s # writes hello_simd.sa
98
+ isa annotate hello_simd.s --arch skylake-x -o - # stdout, skylake-x only
99
+ ```
100
+
101
+ The annotator adds a trailing comment with the summary, latency, and CPI to
102
+ each instruction line. The output stays valid assembly.
103
+
104
+ ## Commands
105
+
106
+ `isa --help` groups commands into Commands and Dev commands.
107
+
108
+ Commands
109
+
110
+ | Command | Description |
111
+ | ----------------------- | ------------------------------------------------------------------------- |
112
+ | `isa` | Open the TUI |
113
+ | `isa <query>` | Open the TUI with the query in a TTY, else print ranked results to stdout |
114
+ | `isa doctor` | Check the install, non-zero exit on failure |
115
+ | `isa update` | Download the pre-built catalog, `--from-release` for the GitHub Release |
116
+ | `isa annotate <file.s>` | Annotate a `.s` file with summaries and latency/CPI, writes `<file>.sa` |
117
+ | `isa man <name>` | Show a manpage, rendered on demand |
118
+ | `isa install-manpages` | Pre-generate man7 pages so plain `man vpaddd` works |
119
+ | `isa llm query <q>` | Strict lookup to JSON, NDJSON, or Markdown |
120
+ | `isa llm batch` | Resolve many queries from stdin in one invocation |
121
+ | `isa llm list` | Emit the FilterSpec or stream matching catalog entries |
122
+ | `isa llm schema` | Print the JSON schema for `llm` payloads |
123
+
124
+ Dev commands
125
+
126
+ | Command | Description |
127
+ | -------------------------------- | ------------------------------------------------------- |
128
+ | `isa build` | Rebuild the catalog from upstream, needs `llvm-mca` 18+ |
129
+ | `isa export` | Export the site-data JSON for the `simdref-web` repo |
130
+ | `isa completion install [SHELL]` | Install shell completion into the user profile |
131
+ | `isa completion show [SHELL]` | Print the completion script |
132
+
133
+ ## Data sources
134
+
135
+ | Source | What | Entries¹ |
136
+ | ----------------------- | ------------------------------------------------------- | ------------------ |
137
+ | Intel Intrinsics Guide | Signatures, descriptions, ISA, categories | 7,381 intrinsics |
138
+ | uops.info | Instructions, operands, latency, throughput, ports | 2,558 instructions |
139
+ | Arm ACLE (NEON, SVE) | Intrinsic signatures and descriptions | 10,791 intrinsics |
140
+ | Arm AARCHMRS (A64) | Base instruction forms and operand tables | live-only² |
141
+ | riscv-rvv-intrinsic-doc | RVV intrinsics with deterministic instruction refs | 74,289 intrinsics |
142
+ | RISC-V unified-db | RVV instruction forms, ISA tags, description, operation | 672 instructions |
143
+
144
+ ¹ Counts from the vendored snapshot. See
145
+ [`docs/coverage/summary.json`](docs/coverage/summary.json) for parity
146
+ against upstream and [`docs/SOURCES.md`](docs/SOURCES.md) for licenses.
147
+
148
+ ² The full AARCHMRS A64 spec needs a live fetch or a tarball under
149
+ `vendor/arm/`.
150
+
151
+ Each perf row carries a `(measured, <core>)` or `(modeled, <core>)` tag.
152
+
153
+ ### Scope
154
+
155
+ - Performance data is x86-only.
156
+ - RISC-V coverage is RVV only, not scalar or privileged ISA.
157
+
158
+ ## Development
159
+
160
+ ```bash
161
+ git clone https://github.com/simd-labs/simdref.git
162
+ cd simdref
163
+ python3 -m venv .venv
164
+ .venv/bin/pip install -e .
165
+ .venv/bin/isa build # needs llvm-mca 18+
166
+ .venv/bin/python -m pytest tests/ -v
167
+ ```
168
+
169
+ See [CONTRIBUTING.md](CONTRIBUTING.md) and
170
+ [ARCHITECTURE.md](ARCHITECTURE.md).
171
+
172
+ ## License
173
+
174
+ [GNU General Public License v3.0](LICENSE).
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "simdref"
7
- version = "0.0.9"
7
+ version = "0.0.11"
8
8
  description = "Searchable SIMD intrinsic and instruction reference with CLI, manpages, TUI, and LSP."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -83,17 +83,27 @@ def _word_at(text: str, line: int, character: int) -> str | None:
83
83
  if line >= len(lines):
84
84
  return None
85
85
  current = lines[line]
86
+ character = _code_point_index(current, character)
86
87
  for match in WORD_RE.finditer(current):
87
88
  if match.start() <= character <= match.end():
88
89
  return match.group(0)
89
90
  return None
90
91
 
91
92
 
93
+ def _code_point_index(line: str, character: int) -> int:
94
+ # LSP columns count UTF-16 code units; Python indexes code points.
95
+ units, index = 0, 0
96
+ while index < len(line) and units < character:
97
+ units += 2 if ord(line[index]) > 0xFFFF else 1
98
+ index += 1
99
+ return index
100
+
101
+
92
102
  def _line_prefix(text: str, line: int, character: int) -> str:
93
103
  lines = text.splitlines()
94
104
  if line >= len(lines):
95
105
  return ""
96
- current = lines[line][:character]
106
+ current = lines[line][: _code_point_index(lines[line], character)]
97
107
  match = re.search(WORD_RE.pattern + r"$", current)
98
108
  return match.group(0) if match else ""
99
109
 
@@ -216,6 +226,43 @@ def _is_c_doc(language_id: str, uri: str) -> bool:
216
226
  return language_id in ("c", "cpp") or uri.lower().endswith(C_EXTENSIONS)
217
227
 
218
228
 
229
+ def _semicolon_is_comment(language_id: str, uri: str) -> bool:
230
+ # A .s/.S extension means GAS syntax: ";" stays a statement separator there
231
+ # even if the client tags the buffer with an assembly languageId.
232
+ if _is_c_doc(language_id, uri):
233
+ return False
234
+ if uri.lower().endswith(".s"):
235
+ return False
236
+ return language_id in ("asm", "nasm", "masm") or uri.lower().endswith((".asm", ".nasm"))
237
+
238
+
239
+ def _asm_line_at(text: str, language_id: str, uri: str, offset: int) -> str | None:
240
+ """Return the assembler segment that holds the text offset, or None.
241
+
242
+ C/C++ documents hold assembler in string literals in asm(...) calls, so the
243
+ segment comes from _asm_literals. In every other document the whole source
244
+ line is the segment. Hover and inlay hints must call this one function so
245
+ both parse the same text.
246
+ """
247
+ if _is_c_doc(language_id, uri):
248
+ spaced = text.replace("\\t", " ")
249
+ for start, body in _asm_literals(spaced):
250
+ if start <= offset <= start + len(body):
251
+ cut = 0
252
+ for split in ASM_SPLIT_RE.finditer(body):
253
+ if cut <= offset - start < split.start():
254
+ return body[cut : split.start()]
255
+ cut = split.end()
256
+ return body[cut:]
257
+ return None
258
+ lines = text.split("\n")
259
+ for line, source_line in enumerate(lines):
260
+ end = offset - sum(len(item) + 1 for item in lines[:line])
261
+ if 0 <= end <= len(source_line):
262
+ return source_line
263
+ return None
264
+
265
+
219
266
  def _asm_literals(text: str) -> list[tuple[int, str]]:
220
267
  """Return (offset, body) for each string literal inside an asm(...) call in C source."""
221
268
  masked = C_TOKEN_RE.sub(
@@ -230,7 +277,9 @@ def _asm_literals(text: str) -> list[tuple[int, str]]:
230
277
 
231
278
 
232
279
  def _in_asm_string(text: str, line: int, character: int) -> bool:
233
- offset = sum(len(item) + 1 for item in text.split("\n")[:line]) + character
280
+ offset = sum(len(item) + 1 for item in text.split("\n")[:line]) + _code_point_index(
281
+ text.split("\n")[line], character
282
+ )
234
283
  return any(start <= offset <= start + len(body) for start, body in _asm_literals(text))
235
284
 
236
285
 
@@ -303,13 +352,7 @@ def _inlay_hints(conn, text: str, language_id: str, uri: str, start: int, end: i
303
352
  db_path = conn.execute("PRAGMA database_list").fetchone()[2]
304
353
  source_lines = [line.rstrip("\r") for line in text.split("\n")]
305
354
  is_c_doc = _is_c_doc(language_id, uri)
306
- # A .s/.S extension means GAS syntax: ";" stays a statement separator there
307
- # even if the client tags the buffer with an assembly languageId.
308
- semicolon_is_comment = (
309
- not is_c_doc
310
- and not uri.lower().endswith(".s")
311
- and (language_id in ("asm", "nasm", "masm") or uri.lower().endswith((".asm", ".nasm")))
312
- )
355
+ semicolon_is_comment = _semicolon_is_comment(language_id, uri)
313
356
  if is_c_doc:
314
357
  candidates = [
315
358
  (text.count("\n", 0, offset), segment)
@@ -411,12 +454,27 @@ def main() -> int:
411
454
  operand_count = None
412
455
  operand_text = ""
413
456
  if word and allow_instruction:
414
- source_lines = text.split("\n")
415
- source_line = source_lines[line] if line < len(source_lines) else ""
416
- operand_text = source_line
417
- parsed = _mnemonic_from_asm_line(source_line)
418
- if parsed and parsed[0].casefold() == word.casefold():
419
- operand_count = parsed[1]
457
+ offset = sum(len(item) + 1 for item in text.split("\n")[:line]) + _code_point_index(
458
+ text.split("\n")[line], character
459
+ )
460
+ language_id = session.languages.get(uri, "")
461
+ segment = _asm_line_at(text, language_id, uri, offset)
462
+ if segment:
463
+ operand_text = segment
464
+ # The C-escape pair "\t" starts a segment in asm("...\n\t...").
465
+ # Strip the backslash so the mnemonic survives.
466
+ parsed = _mnemonic_from_asm_line(
467
+ segment.lstrip("\\"), _semicolon_is_comment(language_id, uri)
468
+ )
469
+ if parsed:
470
+ if parsed[0].casefold() == word.casefold():
471
+ operand_count = parsed[1]
472
+ elif word.casefold().endswith(parsed[0].casefold()):
473
+ # The raw word can swallow a preceding escape character:
474
+ # on "\tvmulps" _word_at reads "tvmulps", but the parsed
475
+ # segment names the real mnemonic.
476
+ word = parsed[0]
477
+ operand_count = parsed[1]
420
478
  body = (
421
479
  _hover_markdown(
422
480
  conn,