tritonparse 0.3.1.dev20251027071529__tar.gz → 0.3.1.dev20251029071541__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.

Potentially problematic release.


This version of tritonparse might be problematic. Click here for more details.

Files changed (120) hide show
  1. {tritonparse-0.3.1.dev20251027071529/tritonparse.egg-info → tritonparse-0.3.1.dev20251029071541}/PKG-INFO +2 -2
  2. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/README.md +1 -1
  3. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tests/test_tritonparse.py +64 -0
  4. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse/cli.py +9 -1
  5. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse/ir_analysis.py +7 -4
  6. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse/ir_parser.py +93 -2
  7. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse/reproducer/cli.py +5 -0
  8. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse/reproducer/ingestion/ndjson.py +2 -2
  9. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse/reproducer/orchestrator.py +3 -3
  10. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse/reproducer/placeholder_replacer.py +35 -17
  11. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse/reproducer/templates/example.py +5 -1
  12. tritonparse-0.3.1.dev20251029071541/tritonparse/reproducer/templates/tritonbench.py +103 -0
  13. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse/reproducer/utils.py +7 -2
  14. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse/trace_processor.py +34 -3
  15. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541/tritonparse.egg-info}/PKG-INFO +2 -2
  16. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse.egg-info/SOURCES.txt +3 -0
  17. tritonparse-0.3.1.dev20251029071541/website/index.html +24 -0
  18. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/src/App.tsx +28 -2
  19. tritonparse-0.3.1.dev20251029071541/website/src/components/CodeViewer.css +43 -0
  20. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/src/components/CodeViewer.tsx +65 -3
  21. tritonparse-0.3.1.dev20251029071541/website/src/pages/IRAnalysis.tsx +98 -0
  22. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/src/utils/dataLoader.ts +22 -0
  23. tritonparse-0.3.1.dev20251027071529/website/index.html +0 -14
  24. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/.ci/README.md +0 -0
  25. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/.ci/install-project.sh +0 -0
  26. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/.ci/install-triton.sh +0 -0
  27. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/.ci/run-tests.sh +0 -0
  28. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/.ci/setup.sh +0 -0
  29. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/.github/PAGES_SETUP.md +0 -0
  30. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/.github/workflows/deploy-pages-standalone.yml +0 -0
  31. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/.github/workflows/deploy-pages.yml +0 -0
  32. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/.github/workflows/nightly-pypi.yml +0 -0
  33. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/.github/workflows/test.yml +0 -0
  34. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/.gitignore +0 -0
  35. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/CHANGELOG.md +0 -0
  36. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/CODE_OF_CONDUCT.md +0 -0
  37. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/CONTRIBUTING.md +0 -0
  38. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/LICENSE +0 -0
  39. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/Makefile +0 -0
  40. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/__init__.py +0 -0
  41. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/pyproject.toml +0 -0
  42. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/run.py +0 -0
  43. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/setup.cfg +0 -0
  44. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tests/README.md +0 -0
  45. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tests/__init__.py +0 -0
  46. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tests/example_output/logs/dedicated_log_triton_trace_findhao_.ndjson +0 -0
  47. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tests/example_output/parsed_output/dedicated_log_triton_trace_findhao__mapped.ndjson.gz +0 -0
  48. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tests/example_output/parsed_output/f0_fc0_a0_cai-.ndjson.gz +0 -0
  49. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tests/example_output/parsed_output/log_file_list.json +0 -0
  50. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tests/example_output/parsed_output_complex/dedicated_log_triton_trace_findhao__mapped.ndjson.gz +0 -0
  51. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tests/example_output/parsed_output_complex/log_file_list.json +0 -0
  52. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tests/test_add.py +0 -0
  53. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse/__init__.py +0 -0
  54. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse/__main__.py +0 -0
  55. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse/common.py +0 -0
  56. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse/context_manager.py +0 -0
  57. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse/event_diff.py +0 -0
  58. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse/extract_source_mappings.py +0 -0
  59. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse/mapper.py +0 -0
  60. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse/reproducer/__init__.py +0 -0
  61. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse/reproducer/function_extractor.py +0 -0
  62. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse/reproducer/templates/__init__.py +0 -0
  63. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse/reproducer/templates/loader.py +0 -0
  64. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse/reproducer/types.py +0 -0
  65. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse/shared_vars.py +0 -0
  66. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse/source_type.py +0 -0
  67. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse/sourcemap_utils.py +0 -0
  68. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse/structured_logging.py +0 -0
  69. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse/tools/__init__.py +0 -0
  70. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse/tools/decompress_bin_ndjson.py +0 -0
  71. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse/tools/disasm.py +0 -0
  72. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse/tools/format_fix.py +0 -0
  73. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse/tools/load_tensor.py +0 -0
  74. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse/tools/prettify_ndjson.py +0 -0
  75. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse/tools/readme.md +0 -0
  76. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse/tp_logger.py +0 -0
  77. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse/utils.py +0 -0
  78. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse.egg-info/dependency_links.txt +0 -0
  79. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse.egg-info/entry_points.txt +0 -0
  80. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse.egg-info/requires.txt +0 -0
  81. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/tritonparse.egg-info/top_level.txt +0 -0
  82. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/eslint.config.js +0 -0
  83. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/package-lock.json +0 -0
  84. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/package.json +0 -0
  85. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/public/dedicated_log_triton_trace_findhao__mapped.ndjson.gz +0 -0
  86. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/public/f0_fc0_a0_cai-.ndjson +0 -0
  87. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/public/favicon.ico +0 -0
  88. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/public/logo.svg +0 -0
  89. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/scripts/inline-html.js +0 -0
  90. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/scripts/update_deps.sh +0 -0
  91. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/src/App.css +0 -0
  92. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/src/assets/react.svg +0 -0
  93. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/src/components/ArgumentViewer.tsx +0 -0
  94. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/src/components/Callstack.tsx +0 -0
  95. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/src/components/CodeComparisonView.tsx +0 -0
  96. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/src/components/CompilationInfo.tsx +0 -0
  97. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/src/components/CopyCodeButton.tsx +0 -0
  98. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/src/components/DataSourceSelector.tsx +0 -0
  99. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/src/components/DiffComparisonView.tsx +0 -0
  100. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/src/components/DiffViewer.tsx +0 -0
  101. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/src/components/ExternalLink.tsx +0 -0
  102. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/src/components/SingleCodeViewer.tsx +0 -0
  103. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/src/components/StackDiffViewer.tsx +0 -0
  104. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/src/components/ToggleSwitch.tsx +0 -0
  105. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/src/components/TritonIRs.tsx +0 -0
  106. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/src/components/WelcomeScreen.tsx +0 -0
  107. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/src/context/FileDiffSession.tsx +0 -0
  108. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/src/index.css +0 -0
  109. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/src/main.tsx +0 -0
  110. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/src/pages/CodeView.tsx +0 -0
  111. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/src/pages/FileDiffView.tsx +0 -0
  112. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/src/pages/KernelOverview.tsx +0 -0
  113. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/src/utils/fbDetection.ts +0 -0
  114. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/src/utils/safeImport.ts +0 -0
  115. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/src/utils/tensor.ts +0 -0
  116. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/src/vite-env.d.ts +0 -0
  117. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/tsconfig.app.json +0 -0
  118. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/tsconfig.json +0 -0
  119. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/tsconfig.node.json +0 -0
  120. {tritonparse-0.3.1.dev20251027071529 → tritonparse-0.3.1.dev20251029071541}/website/vite.config.ts +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tritonparse
3
- Version: 0.3.1.dev20251027071529
3
+ Version: 0.3.1.dev20251029071541
4
4
  Summary: TritonParse: A Compiler Tracer, Visualizer, and mini-Reproducer Generator for Triton Kernels
5
5
  Author-email: Yueming Hao <yhao@meta.com>
6
6
  License-Expression: BSD-3-Clause
@@ -134,7 +134,7 @@ from tritonparse.reproducer.orchestrator import reproduce
134
134
 
135
135
  result = reproduce(
136
136
  input_path="./parsed_output/trace.ndjson.gz",
137
- line_index=1, # Which launch event (1-based)
137
+ line_index=0, # 0-based index (first event is 0)
138
138
  out_dir="repro_output"
139
139
  )
140
140
  ```
@@ -116,7 +116,7 @@ from tritonparse.reproducer.orchestrator import reproduce
116
116
 
117
117
  result = reproduce(
118
118
  input_path="./parsed_output/trace.ndjson.gz",
119
- line_index=1, # Which launch event (1-based)
119
+ line_index=0, # 0-based index (first event is 0)
120
120
  out_dir="repro_output"
121
121
  )
122
122
  ```
@@ -187,6 +187,70 @@ class TestTritonparseCPU(unittest.TestCase):
187
187
 
188
188
  assert convert(nested_structure) == expected_nested
189
189
 
190
+ def test_loc_alias_parsing(self):
191
+ """Test parsing of location aliases in TTIR/TTGIR"""
192
+ from tritonparse.ir_parser import extract_loc_definitions
193
+
194
+ # Test case 1: Bare #loc reference (no number)
195
+ ir_with_bare_loc = """
196
+ module {
197
+ #loc = loc("/tmp/test.py":10:5)
198
+ #loc13 = loc("x_ptr"(#loc))
199
+ func @kernel(%arg0: !tt.ptr<f32> loc(#loc13)) {
200
+ return loc(#loc)
201
+ }
202
+ }
203
+ """
204
+ locs = extract_loc_definitions(ir_with_bare_loc)
205
+ # Main #loc should be stored with "" key
206
+ assert "" in locs, "Main #loc not found"
207
+ assert locs[""]["file"] == "/tmp/test.py"
208
+ assert locs[""]["line"] == 10
209
+ # Alias #loc13 should resolve to same location
210
+ assert "13" in locs, "#loc13 not found"
211
+ assert locs["13"]["file"] == "/tmp/test.py"
212
+ assert locs["13"]["line"] == 10
213
+ assert locs["13"]["alias_name"] == "x_ptr"
214
+ assert locs["13"]["alias_of"] == ""
215
+
216
+ # Test case 2: Named alias with numbered reference
217
+ ir_with_numbered_alias = """
218
+ #loc = loc("/tmp/test.py":5:0)
219
+ #loc2 = loc("/tmp/test.py":20:28)
220
+ #loc16 = loc("pid"(#loc2))
221
+ %0 = tt.get_program_id x : i32 loc(#loc16)
222
+ """
223
+ locs = extract_loc_definitions(ir_with_numbered_alias)
224
+ assert "2" in locs
225
+ assert locs["2"]["line"] == 20
226
+ assert "16" in locs
227
+ assert locs["16"]["file"] == "/tmp/test.py"
228
+ assert locs["16"]["line"] == 20
229
+ assert locs["16"]["alias_name"] == "pid"
230
+ assert locs["16"]["alias_of"] == "2"
231
+
232
+ # Test case 3: Simple alias (no name)
233
+ ir_with_simple_alias = """
234
+ #loc = loc("/tmp/test.py":1:1)
235
+ #loc1 = loc("/tmp/test.py":15:10)
236
+ #loc20 = loc(#loc1)
237
+ %1 = arith.constant 0 : i32 loc(#loc20)
238
+ """
239
+ locs = extract_loc_definitions(ir_with_simple_alias)
240
+ assert "1" in locs
241
+ assert "20" in locs
242
+ assert locs["20"]["file"] == "/tmp/test.py"
243
+ assert locs["20"]["line"] == 15
244
+ assert locs["20"]["alias_of"] == "1"
245
+ assert "alias_name" not in locs["20"]
246
+
247
+ # Test case 4: Definition line tracking
248
+ assert "def_line" in locs[""]
249
+ assert "def_line" in locs["1"]
250
+ assert "def_line" in locs["20"]
251
+
252
+ print("✓ All loc alias parsing tests passed")
253
+
190
254
 
191
255
  class TestTritonparseCUDA(unittest.TestCase):
192
256
  """CUDA tests (require GPU)"""
@@ -68,12 +68,20 @@ def main():
68
68
  }
69
69
  unified_parse(**parse_args)
70
70
  elif args.func == "reproduce":
71
+ replacer = None
72
+ if args.use_fbcode:
73
+ from tritonparse.fb.reproducer.replacer import FBCodePlaceholderReplacer
74
+
75
+ replacer = FBCodePlaceholderReplacer()
76
+ print(f"Using FBCode placeholder replacer for template: {args.template}")
77
+
71
78
  reproduce(
72
79
  input_path=args.input,
73
- line_index=args.line,
80
+ line_index=args.line - 1, # Convert 1-based line number to 0-based index
74
81
  out_dir=args.out_dir,
75
82
  template=args.template,
76
83
  kernel_import=args.kernel_import,
84
+ replacer=replacer,
77
85
  )
78
86
  else:
79
87
  raise RuntimeError(f"Unknown command: {args.func}")
@@ -42,7 +42,7 @@ def process_amd_gcn_bufferops(
42
42
  ) -> dict[str, int]:
43
43
  ir_content = load_ir_contents(key, file_content, file_path)
44
44
  # TODO: Add atomics
45
- io_keys = ["global_load_", "global_store_", "buffer_load_", "buffer_store_"]
45
+ io_keys = ["global_load", "global_store", "buffer_load", "buffer_store"]
46
46
  return process_amd_bufferop(ir_content, io_keys)
47
47
 
48
48
 
@@ -66,9 +66,12 @@ def _generate_ir_analysis(entry: str):
66
66
  gcn_bufferops_info = process_amd_gcn_bufferops(
67
67
  amdgcn_key, file_content, file_path
68
68
  )
69
+ io_counts = {}
69
70
  # NDJSON format requires a newline at the end of each line
70
71
  if ttgir_bufferops_info:
71
- ir_analysis["amd_ttgir_bufferops_count"] = ttgir_bufferops_info
72
+ io_counts["amd_ttgir_bufferops_count"] = ttgir_bufferops_info
72
73
  if gcn_bufferops_info:
73
- ir_analysis["amd_gcn_bufferops_count"] = gcn_bufferops_info
74
- return {"ir_analysis": ir_analysis}
74
+ io_counts["amd_gcn_bufferops_count"] = gcn_bufferops_info
75
+ if io_counts:
76
+ ir_analysis["io_counts"] = io_counts
77
+ return ir_analysis
@@ -10,7 +10,8 @@ logger = logging.getLogger("SourceMapping")
10
10
 
11
11
  # the definition of the #loc directive. they are in the bottom of the IR files
12
12
  # Example:#loc2 = loc("/tmp/torchinductor_yhao/yp/abcdef.py":20:28)
13
- LOC_PATTERN = re.compile(r'#loc(\d*) = loc\("([^"]+)":(\d+):(\d+)\)')
13
+ # Note: This should only match numbered locs like #loc1, #loc2, not bare #loc
14
+ LOC_PATTERN = re.compile(r'#loc(\d+) = loc\("([^"]+)":(\d+):(\d+)\)')
14
15
 
15
16
  # the reference to the #loc directive. they are in the end of lines of the IR files
16
17
  # Example: loc(#loc2)
@@ -33,6 +34,17 @@ AMDGCN_LOC_PATTERN = re.compile(
33
34
  )
34
35
 
35
36
 
37
+ # alias loc definitions in TTGIR/TTIR
38
+ # Example: #loc16 = loc("pid"(#loc2))
39
+ # Example: #loc13 = loc("x_ptr"(#loc)) - bare #loc without number
40
+ ALIAS_WITH_NAME_PATTERN = re.compile(
41
+ r'#loc(\d+)\s*=\s*loc\("([^"]+)"\s*\(\s*#loc(\d*)\s*\)\s*\)'
42
+ )
43
+
44
+ # Example: #loc20 = loc(#loc16)
45
+ ALIAS_SIMPLE_PATTERN = re.compile(r"#loc(\d+)\s*=\s*loc\(\s*#loc(\d*)\s*\)")
46
+
47
+
36
48
  def extract_loc_definitions(ir_content: str) -> Dict[str, Dict[str, Any]]:
37
49
  """
38
50
  Extracts location definitions from the given IR content.
@@ -50,9 +62,10 @@ def extract_loc_definitions(ir_content: str) -> Dict[str, Dict[str, Any]]:
50
62
  """
51
63
  locations = {}
52
64
  # The first #loc directive is a special case. It locates at the top of the IR files
65
+ # Store it with empty string "" as key to avoid conflict with #loc1
53
66
  main_match = re.search(r'#loc = loc\("([^"]+)":(\d+):(\d+)\)', ir_content)
54
67
  if main_match:
55
- locations["1"] = {
68
+ locations[""] = {
56
69
  "file": main_match.group(1),
57
70
  "line": int(main_match.group(2)),
58
71
  "column": int(main_match.group(3)),
@@ -61,6 +74,84 @@ def extract_loc_definitions(ir_content: str) -> Dict[str, Dict[str, Any]]:
61
74
  for loc_id, filename, line, col in LOC_PATTERN.findall(ir_content):
62
75
  key = loc_id
63
76
  locations[key] = {"file": filename, "line": int(line), "column": int(col)}
77
+
78
+ # Handle alias-style loc definitions that reference another #loc
79
+ # Build alias map first: alias_id -> target_id
80
+ alias_map: Dict[str, str] = {}
81
+ for m in ALIAS_WITH_NAME_PATTERN.finditer(ir_content):
82
+ alias_id, _name, target_id = m.groups()
83
+ # Empty target_id means bare #loc, map to "" (main loc key)
84
+ alias_map[alias_id] = target_id or ""
85
+ for m in ALIAS_SIMPLE_PATTERN.finditer(ir_content):
86
+ alias_id, target_id = m.groups()
87
+ # Empty target_id means bare #loc, map to "" (main loc key)
88
+ alias_map[alias_id] = target_id or ""
89
+
90
+ # Build definition line map and alias name map by scanning lines
91
+ def_line_map: Dict[str, int] = {}
92
+ alias_name_map: Dict[str, str] = {}
93
+ main_loc_line: int = 0
94
+ for i, line in enumerate(ir_content.split("\n"), start=1):
95
+ if m := ALIAS_WITH_NAME_PATTERN.search(line):
96
+ alias_id, name, target_id = m.groups()
97
+ def_line_map[alias_id] = i
98
+ alias_name_map[alias_id] = name
99
+ # ensure alias map is populated even if only found in line scan
100
+ # Empty target_id means bare #loc, map to "" (main loc key)
101
+ alias_map.setdefault(alias_id, target_id or "")
102
+ elif m := ALIAS_SIMPLE_PATTERN.search(line):
103
+ alias_id, target_id = m.groups()
104
+ def_line_map[alias_id] = i
105
+ # Empty target_id means bare #loc, map to "" (main loc key)
106
+ alias_map.setdefault(alias_id, target_id or "")
107
+ if m2 := LOC_PATTERN.search(line):
108
+ base_id, _fn, _ln, _col = m2.groups()
109
+ def_line_map[base_id] = i
110
+ if re.search(r'#loc\s*=\s*loc\("[^"]+":\d+:\d+\)', line):
111
+ # main #loc = loc("file":line:col) without id
112
+ main_loc_line = main_loc_line or i
113
+
114
+ # Resolve aliases to base locations (file/line/column)
115
+ resolving_stack = set()
116
+
117
+ def resolve_alias(current_id: str) -> Dict[str, Any]:
118
+ # Already a concrete location
119
+ if current_id in locations:
120
+ return locations[current_id]
121
+ # Detect cycles
122
+ if current_id in resolving_stack:
123
+ return {}
124
+ resolving_stack.add(current_id)
125
+ parent_id = alias_map.get(current_id)
126
+ result: Dict[str, Any] = {}
127
+ if parent_id is not None:
128
+ base = resolve_alias(parent_id)
129
+ if base:
130
+ # copy to avoid sharing the same dict by reference
131
+ result = {
132
+ "file": base.get("file"),
133
+ "line": base.get("line"),
134
+ "column": base.get("column"),
135
+ }
136
+ locations[current_id] = result
137
+ resolving_stack.remove(current_id)
138
+ return result
139
+
140
+ # Resolve aliases and attach alias metadata
141
+ for alias_id, target_id in alias_map.items():
142
+ if alias_id not in locations:
143
+ resolve_alias(alias_id)
144
+ if alias_id in locations:
145
+ locations[alias_id]["alias_of"] = target_id
146
+ if alias_id in alias_name_map:
147
+ locations[alias_id]["alias_name"] = alias_name_map[alias_id]
148
+
149
+ # Attach definition line metadata
150
+ for k, v in def_line_map.items():
151
+ if k in locations:
152
+ locations[k]["def_line"] = v
153
+ if main_loc_line and "" in locations:
154
+ locations[""]["def_line"] = main_loc_line
64
155
  return locations
65
156
 
66
157
 
@@ -46,3 +46,8 @@ def _add_reproducer_args(parser: argparse.ArgumentParser) -> None:
46
46
  "Defaults to 'default'."
47
47
  ),
48
48
  )
49
+ parser.add_argument(
50
+ "--use-fbcode",
51
+ action="store_true",
52
+ help=("Use fbcode to setup repro environment."),
53
+ )
@@ -40,7 +40,7 @@ def get_launch_and_compilation_events(
40
40
 
41
41
  Args:
42
42
  events: List of parsed event dictionaries.
43
- line_index: Index of the launch event to process.
43
+ line_index: 0-based index of the launch event to process.
44
44
 
45
45
  Returns:
46
46
  Tuple of (launch_event, compilation_event).
@@ -179,7 +179,7 @@ def build_context_bundle(
179
179
 
180
180
  Args:
181
181
  events: List of parsed event dictionaries.
182
- line_index: Index of the launch event to process.
182
+ line_index: 0-based index of the launch event to process.
183
183
 
184
184
  Returns:
185
185
  ContextBundle containing all information needed to reproduce the kernel launch.
@@ -23,13 +23,13 @@ def reproduce(
23
23
  template: str,
24
24
  replacer: Optional[PlaceholderReplacer] = None,
25
25
  kernel_import: KernelImportMode = KernelImportMode.DEFAULT,
26
- ) -> dict[str, Path]:
26
+ ) -> dict[str, str]:
27
27
  """
28
28
  Generate a reproducer script from NDJSON trace file.
29
29
 
30
30
  Args:
31
31
  input_path: Path to the NDJSON trace file.
32
- line_index: Line index of the launch event to reproduce.
32
+ line_index: 0-based index of the launch event to reproduce in the events list.
33
33
  out_dir: Output directory for reproducer files.
34
34
  template: Template name to use for the reproducer.
35
35
  replacer: Optional custom PlaceholderReplacer instance. If None, uses DefaultPlaceholderReplacer.
@@ -45,7 +45,7 @@ def reproduce(
45
45
  f"Built context bundle for kernel: {context_bundle.kernel_info.function_name}"
46
46
  )
47
47
  out_py_path, temp_json_path = determine_output_paths(
48
- out_dir, context_bundle.kernel_info.function_name
48
+ out_dir, context_bundle.kernel_info.function_name, template
49
49
  )
50
50
  save_prettified_json(context_bundle.raw_launch_event, temp_json_path)
51
51
 
@@ -76,21 +76,39 @@ class DefaultPlaceholderReplacer(PlaceholderReplacer):
76
76
  - # {{KERNEL_INVOCATION_PLACEHOLDER}}: Replaced with kernel invocation code
77
77
  """
78
78
 
79
+ KERNEL_NAME_PLACEHOLDER = "{{KERNEL_NAME_PLACEHOLDER}}"
80
+ JSON_FILE_NAME_PLACEHOLDER = "{{JSON_FILE_NAME_PLACEHOLDER}}"
81
+ IR_OVERRIDE_SETUP_PLACEHOLDER = "# {{IR_OVERRIDE_SETUP_PLACEHOLDER}}"
82
+ KERNEL_SYSPATH_PLACEHOLDER = "# {{KERNEL_SYSPATH_PLACEHOLDER}}"
83
+ KERNEL_IMPORT_PLACEHOLDER = "# {{KERNEL_IMPORT_PLACEHOLDER}}"
84
+ UTILITY_FUNCTIONS_PLACEHOLDER = "# {{UTILITY_FUNCTIONS_PLACEHOLDER}}"
85
+ KERNEL_INVOCATION_PLACEHOLDER = "# {{KERNEL_INVOCATION_PLACEHOLDER}}"
86
+
79
87
  def __init__(self):
80
88
  super().__init__()
81
89
  # Register all default handlers
82
- self.register("{{JSON_FILE_NAME_PLACEHOLDER}}", self._replace_json_filename)
90
+ self.register(self.JSON_FILE_NAME_PLACEHOLDER, self._replace_json_filename)
83
91
  self.register(
84
- "# {{IR_OVERRIDE_SETUP_PLACEHOLDER}}", self._replace_ir_override_setup
92
+ self.IR_OVERRIDE_SETUP_PLACEHOLDER, self._replace_ir_override_setup
85
93
  )
86
- self.register("# {{KERNEL_SYSPATH_PLACEHOLDER}}", self._replace_kernel_syspath)
87
- self.register("# {{KERNEL_IMPORT_PLACEHOLDER}}", self._replace_kernel_import)
94
+ self.register(self.KERNEL_SYSPATH_PLACEHOLDER, self._replace_kernel_syspath)
95
+ self.register(self.KERNEL_IMPORT_PLACEHOLDER, self._replace_kernel_import)
88
96
  self.register(
89
- "# {{UTILITY_FUNCTIONS_PLACEHOLDER}}", self._replace_utility_functions
97
+ self.UTILITY_FUNCTIONS_PLACEHOLDER, self._replace_utility_functions
90
98
  )
91
99
  self.register(
92
- "# {{KERNEL_INVOCATION_PLACEHOLDER}}", self._replace_kernel_invocation
100
+ self.KERNEL_INVOCATION_PLACEHOLDER, self._replace_kernel_invocation
93
101
  )
102
+ self.register(self.KERNEL_NAME_PLACEHOLDER, self._replace_kernel_name)
103
+
104
+ def _replace_kernel_name(
105
+ self, code: str, context_bundle: ContextBundle, **kwargs
106
+ ) -> str:
107
+ """Replace the kernel name placeholder."""
108
+ kernel_name = context_bundle.kernel_info.function_name
109
+ if not kernel_name:
110
+ raise ValueError("Kernel function name is not available")
111
+ return code.replace(self.KERNEL_NAME_PLACEHOLDER, kernel_name)
94
112
 
95
113
  def _replace_json_filename(
96
114
  self, code: str, context_bundle: ContextBundle, **kwargs
@@ -99,7 +117,7 @@ class DefaultPlaceholderReplacer(PlaceholderReplacer):
99
117
  temp_json_path = kwargs.get("temp_json_path")
100
118
  if temp_json_path is None:
101
119
  raise ValueError("temp_json_path is required for JSON filename replacement")
102
- return code.replace("{{JSON_FILE_NAME_PLACEHOLDER}}", temp_json_path.name)
120
+ return code.replace(self.JSON_FILE_NAME_PLACEHOLDER, temp_json_path.name)
103
121
 
104
122
  def _replace_ir_override_setup(
105
123
  self, code: str, context_bundle: ContextBundle, **kwargs
@@ -108,7 +126,7 @@ class DefaultPlaceholderReplacer(PlaceholderReplacer):
108
126
  kernel_import = kwargs.get("kernel_import", KernelImportMode.DEFAULT)
109
127
 
110
128
  if kernel_import != KernelImportMode.OVERRIDE_TTIR:
111
- return code.replace("# {{IR_OVERRIDE_SETUP_PLACEHOLDER}}", "")
129
+ return code.replace(self.IR_OVERRIDE_SETUP_PLACEHOLDER, "")
112
130
 
113
131
  comp_json_filename = kwargs.get("comp_json_filename")
114
132
  if not comp_json_filename:
@@ -158,7 +176,7 @@ _original_autotune = triton.autotune
158
176
  triton.autotune = _patched_autotune
159
177
  '''
160
178
 
161
- return code.replace("# {{IR_OVERRIDE_SETUP_PLACEHOLDER}}", setup_code)
179
+ return code.replace(self.IR_OVERRIDE_SETUP_PLACEHOLDER, setup_code)
162
180
 
163
181
  def _replace_kernel_syspath(
164
182
  self, code: str, context_bundle: ContextBundle, **kwargs
@@ -168,15 +186,15 @@ triton.autotune = _patched_autotune
168
186
 
169
187
  if kernel_import == KernelImportMode.DEFAULT:
170
188
  sys_stmt, _ = _generate_import_statements(context_bundle.kernel_info)
171
- return code.replace("# {{KERNEL_SYSPATH_PLACEHOLDER}}", sys_stmt)
189
+ return code.replace(self.KERNEL_SYSPATH_PLACEHOLDER, sys_stmt)
172
190
  elif kernel_import == KernelImportMode.COPY:
173
191
  comment = (
174
192
  "# Kernel sys.path setup skipped - kernel source code embedded below"
175
193
  )
176
- return code.replace("# {{KERNEL_SYSPATH_PLACEHOLDER}}", comment)
194
+ return code.replace(self.KERNEL_SYSPATH_PLACEHOLDER, comment)
177
195
  elif kernel_import == KernelImportMode.OVERRIDE_TTIR:
178
196
  comment = "# Kernel sys.path setup skipped - using IR override mode"
179
- return code.replace("# {{KERNEL_SYSPATH_PLACEHOLDER}}", comment)
197
+ return code.replace(self.KERNEL_SYSPATH_PLACEHOLDER, comment)
180
198
  else:
181
199
  raise ValueError(f"Unknown kernel_import mode: {kernel_import}")
182
200
 
@@ -190,7 +208,7 @@ triton.autotune = _patched_autotune
190
208
  _, import_statement = _generate_import_statements(
191
209
  context_bundle.kernel_info
192
210
  )
193
- return code.replace("# {{KERNEL_IMPORT_PLACEHOLDER}}", import_statement)
211
+ return code.replace(self.KERNEL_IMPORT_PLACEHOLDER, import_statement)
194
212
  elif kernel_import == KernelImportMode.COPY:
195
213
  source_code = context_bundle.kernel_info.source_code
196
214
  func_name = context_bundle.kernel_info.function_name
@@ -216,10 +234,10 @@ triton.autotune = _patched_autotune
216
234
  embedded_code += "\n" + source_code
217
235
  embedded_code += f"\n\n# Use kernel function directly\nimported_kernel_function = {func_name}"
218
236
 
219
- return code.replace("# {{KERNEL_IMPORT_PLACEHOLDER}}", embedded_code)
237
+ return code.replace(self.KERNEL_IMPORT_PLACEHOLDER, embedded_code)
220
238
  elif kernel_import == KernelImportMode.OVERRIDE_TTIR:
221
239
  comment = "# Kernel import skipped - using IR override mode with TTIR"
222
- return code.replace("# {{KERNEL_IMPORT_PLACEHOLDER}}", comment)
240
+ return code.replace(self.KERNEL_IMPORT_PLACEHOLDER, comment)
223
241
  else:
224
242
  raise ValueError(f"Unknown kernel_import mode: {kernel_import}")
225
243
 
@@ -228,7 +246,7 @@ triton.autotune = _patched_autotune
228
246
  ) -> str:
229
247
  """Replace the utility functions placeholder with extracted functions."""
230
248
  utility_code = extract_utility_functions()
231
- return code.replace("# {{UTILITY_FUNCTIONS_PLACEHOLDER}}", utility_code)
249
+ return code.replace(self.UTILITY_FUNCTIONS_PLACEHOLDER, utility_code)
232
250
 
233
251
  def _replace_kernel_invocation(
234
252
  self, code: str, context_bundle: ContextBundle, **kwargs
@@ -237,4 +255,4 @@ triton.autotune = _patched_autotune
237
255
  source_code = context_bundle.kernel_info.source_code
238
256
  pos_args, kw_args = _parse_kernel_signature(source_code)
239
257
  invocation_snippet = _generate_invocation_snippet(pos_args, kw_args)
240
- return code.replace("# {{KERNEL_INVOCATION_PLACEHOLDER}}", invocation_snippet)
258
+ return code.replace(self.KERNEL_INVOCATION_PLACEHOLDER, invocation_snippet)
@@ -14,7 +14,7 @@ import torch
14
14
  # {{UTILITY_FUNCTIONS_PLACEHOLDER}}
15
15
 
16
16
 
17
- if __name__ == "__main__":
17
+ def launch_kernel():
18
18
  script_dir = Path(__file__).resolve().parent # noqa: F821
19
19
  json_file = script_dir / "{{JSON_FILE_NAME_PLACEHOLDER}}"
20
20
  grid, args_dict = create_args_from_json_file(str(json_file)) # noqa: F821
@@ -28,3 +28,7 @@ if __name__ == "__main__":
28
28
 
29
29
  torch.cuda.synchronize()
30
30
  print("Kernel execution finished.")
31
+
32
+
33
+ if __name__ == "__main__":
34
+ launch_kernel()
@@ -0,0 +1,103 @@
1
+ # (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
2
+
3
+ from pathlib import Path
4
+ from typing import Any, Callable, Dict, Optional, Tuple
5
+
6
+ import torch
7
+ from tritonbench.utils.triton_op import (
8
+ BenchmarkOperator,
9
+ register_benchmark,
10
+ REGISTERED_X_VALS,
11
+ )
12
+
13
+
14
+ imported_kernel_function: Optional[Callable[[Tuple[int], Dict[str, Any]], None]] = None
15
+
16
+ # {{IR_OVERRIDE_SETUP_PLACEHOLDER}}
17
+
18
+ # {{KERNEL_SYSPATH_PLACEHOLDER}}
19
+
20
+ # {{KERNEL_IMPORT_PLACEHOLDER}}
21
+
22
+ # {{UTILITY_FUNCTIONS_PLACEHOLDER}}
23
+
24
+ assert imported_kernel_function is not None, "imported_kernel_function is missing"
25
+
26
+ KERNEL_NAME = "{{KERNEL_NAME_PLACEHOLDER}}"
27
+ REPRO_CONTEXT_FILE_NAME = "{{JSON_FILE_NAME_PLACEHOLDER}}"
28
+
29
+
30
+ def _get_launch_kernel_args() -> Tuple[Tuple[int], Dict[str, Any]]:
31
+ script_dir = Path(__file__).resolve().parent # noqa: F821
32
+ json_file = script_dir / REPRO_CONTEXT_FILE_NAME
33
+
34
+ grid, args_dict = create_args_from_json_file(json_file) # noqa: F821, F841
35
+
36
+ print("Recorded kernel arguments dictionary:")
37
+ for name, arg in args_dict.items():
38
+ if isinstance(arg, torch.Tensor):
39
+ print(
40
+ f" {name}: Tensor: {arg.shape} {arg.dtype} stride: {arg.stride()}, is_contiguous: {arg.is_contiguous()}"
41
+ )
42
+ else:
43
+ print(f" {name}: {arg}")
44
+ print(f"Grid: {grid}")
45
+
46
+ return tuple(grid), args_dict
47
+
48
+
49
+ grid, args_dict = _get_launch_kernel_args()
50
+
51
+
52
+ def _launch_kernel(grid: tuple[int], args_dict: dict[str, Any]):
53
+ try:
54
+ assert grid is not None
55
+ assert args_dict is not None
56
+
57
+ # {{KERNEL_INVOCATION_PLACEHOLDER}}
58
+
59
+ except Exception as e:
60
+ print(f"Error: {e}")
61
+ print("Failed to launch kernel!")
62
+
63
+
64
+ # HACK: @register_x_val doesn't allow us to pass `operator_name`` as a parameter
65
+ tensor_args = {k: v for k, v in args_dict.items() if isinstance(v, torch.Tensor)}
66
+ x_vals_label = ", ".join(tensor_args.keys())
67
+ REGISTERED_X_VALS[KERNEL_NAME] = x_vals_label
68
+
69
+
70
+ class Operator(BenchmarkOperator):
71
+ @register_benchmark(operator_name=KERNEL_NAME)
72
+ def run_kernel(self, grid, args_dict):
73
+ return lambda: _launch_kernel(grid, args_dict)
74
+
75
+ def get_input_iter(self):
76
+ yield {"grid": grid, "args_dict": args_dict}
77
+
78
+ def get_x_val(self, example_inputs):
79
+ tensors_shapes = [
80
+ tuple(v.shape)
81
+ for v in example_inputs["args_dict"].values()
82
+ if isinstance(v, torch.Tensor)
83
+ ]
84
+ return tuple(tensors_shapes)
85
+
86
+
87
+ if __name__ == "__main__":
88
+ print("do_benchmark...")
89
+
90
+ args = [
91
+ "--benchmark-name",
92
+ KERNEL_NAME,
93
+ ]
94
+
95
+ from tritonbench.utils.parser import get_parser
96
+
97
+ parser = get_parser(args)
98
+ tb_args, extra_args = parser.parse_known_args(args)
99
+ bench = Operator(tb_args, extra_args)
100
+ bench.run()
101
+
102
+ print(bench.output)
103
+ print("Benchmark completed successfully!")
@@ -327,7 +327,7 @@ def _create_arg_from_info(arg_info):
327
327
  return None
328
328
 
329
329
 
330
- def determine_output_paths(out_dir: str, kernel_name: str):
330
+ def determine_output_paths(out_dir: str, kernel_name: str, template: str):
331
331
  """
332
332
  Determine output file paths for reproducer script and context data.
333
333
 
@@ -342,7 +342,12 @@ def determine_output_paths(out_dir: str, kernel_name: str):
342
342
  output_directory = Path(out_dir) / kernel_name
343
343
  output_directory.mkdir(parents=True, exist_ok=True)
344
344
 
345
- out_py_path = output_directory / f"repro_{timestamp}.py"
345
+ filename_parts = ["repro"]
346
+ if template != "example":
347
+ filename_parts.append(template.replace(".", "_"))
348
+ filename_parts.append(timestamp)
349
+ filename = "_".join(filename_parts) + ".py"
350
+ out_py_path = output_directory / filename
346
351
  temp_json_path = output_directory / f"repro_context_{timestamp}.json"
347
352
 
348
353
  return out_py_path, temp_json_path
@@ -71,12 +71,38 @@ def generate_source_mappings(
71
71
  }
72
72
  elif loc_id in loc_defs:
73
73
  info = loc_defs[loc_id]
74
- mappings[str(ln)] = {
74
+ entry = {
75
75
  "file": info["file"],
76
76
  "line": info["line"],
77
77
  "column": info["column"],
78
78
  f"{ir_type}_line": ln,
79
79
  }
80
+ # Propagate alias metadata if present
81
+ if "alias_name" in info:
82
+ entry["alias_name"] = info["alias_name"]
83
+ if "alias_of" in info:
84
+ entry["loc_id"] = loc_id
85
+ mappings[str(ln)] = entry
86
+
87
+ # Add separate entries for loc definition lines
88
+ for loc_id, info in loc_defs.items():
89
+ if "def_line" not in info:
90
+ continue
91
+ def_ln = info["def_line"]
92
+ # Only create mapping if this line doesn't already have one
93
+ if str(def_ln) not in mappings:
94
+ entry = {
95
+ "file": info["file"],
96
+ "line": info["line"],
97
+ "column": info["column"],
98
+ f"{ir_type}_line": def_ln,
99
+ "kind": "loc_def",
100
+ }
101
+ if "alias_name" in info:
102
+ entry["alias_name"] = info["alias_name"]
103
+ if "alias_of" in info:
104
+ entry["loc_id"] = loc_id
105
+ mappings[str(def_ln)] = entry
80
106
 
81
107
  return mappings
82
108
 
@@ -301,8 +327,13 @@ def parse_single_file(
301
327
  )
302
328
 
303
329
  if compilation_event:
304
- ir_analysis_event = _generate_ir_analysis(compilation_event)
305
- if ir_analysis_event:
330
+ ir_analysis = _generate_ir_analysis(compilation_event)
331
+ if ir_analysis:
332
+ ir_analysis_event = {
333
+ "event_type": "ir_analysis",
334
+ "hash": _kernel_hash,
335
+ "ir_analysis": ir_analysis,
336
+ }
306
337
  all_output_lines[output_file].append(
307
338
  json.dumps(ir_analysis_event, separators=(",", ":")) + "\n"
308
339
  )