Files
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

202 lines
6.3 KiB
Python

# Copyright (c) 2026 Advanced Micro Devices, Inc.
# SPDX-License-Identifier: MIT
"""Emit C++20 legalization tables from ``LegalizationGenerator`` output.
Generates:
- ``legalization_types.h`` — shared types (``Action``, ``InstructionLegalization``,
``lookup()``).
- One ``legalization_<src>_<dst>.h`` header per ISA pair containing an
``inline constexpr InstructionLegalization[]`` array.
"""
from __future__ import annotations
from pathlib import Path
import shutil
import subprocess
import sys
from amdisa.legalization import LegalizationEntry
_COPYRIGHT = """\
// Copyright (c) 2025-2026 Advanced Micro Devices, Inc.
// SPDX-License-Identifier: MIT
//
// AUTO-GENERATED by the amdisa codegen pipeline. DO NOT EDIT.
"""
def _action_enum(entry: LegalizationEntry) -> str:
return {
'identity': 'Action::Identity',
'substitute': 'Action::Substitute',
'lower': 'Action::Lower',
'expand': 'Action::Expand',
'illegal': 'Action::Illegal',
}[entry.action.kind]
def _pair_name(src: str, dst: str) -> str:
return f'{src}_to_{dst}'
def _clang_format(path: Path) -> None:
"""Format emitted C++ headers when clang-format is available.
The generator emits simple 4-space templates; formatting here keeps the
checked-in generated headers aligned with rocjitsu's 2-space C++ style.
"""
exe = shutil.which('clang-format')
if exe is None:
print(
'warning: clang-format not found; emitted files may need manual '
'formatting',
file=sys.stderr,
)
return
try:
subprocess.run([exe, '-i', str(path)], check=True)
except subprocess.CalledProcessError as exc:
print(f'warning: clang-format failed for {path}: {exc}', file=sys.stderr)
def emit_all(
output_dir: str | Path,
pairs: list[tuple[str, str, list[LegalizationEntry]]],
) -> list[str]:
output_dir = Path(output_dir)
output_dir.mkdir(parents=True, exist_ok=True)
generated: list[str] = []
types_path = output_dir / 'legalization_types.h'
_emit_types(types_path)
_clang_format(types_path)
generated.append(str(types_path))
for src, dst, entries in pairs:
# Duplicate entries for encoding formats with narrow (<9-bit) encoding
# fields. The 9-bit encoding_id (raw[0]>>23) has don't-care low bits
# for these formats. We emit one entry per alias so that binary search
# works without encoding_id normalization.
expanded = []
for e in entries:
enc_id = e.src_encoding_order if e.src_encoding_order >= 0 else 0xFFFF
dont_care = 9 - e.src_encoding_bits
if dont_care > 0 and enc_id < 0xFFFF:
for i in range(1 << dont_care):
alias_id = enc_id | i
expanded.append(
LegalizationEntry(
src_mnemonic=e.src_mnemonic,
src_encoding=e.src_encoding,
src_encoding_order=alias_id,
src_encoding_bits=9,
src_opcode=e.src_opcode,
action=e.action,
)
)
else:
expanded.append(e)
sorted_entries = sorted(
expanded,
key=lambda e: (
e.src_encoding_order if e.src_encoding_order >= 0 else 0xFFFF,
e.src_opcode,
),
)
pair_path = output_dir / f'legalization_{_pair_name(src, dst)}.h'
_emit_pair(pair_path, src, dst, sorted_entries)
_clang_format(pair_path)
generated.append(str(pair_path))
return generated
def _emit_types(path: Path) -> None:
lines = [
_COPYRIGHT,
'',
'#pragma once',
'',
'#include <algorithm>',
'#include <compare>',
'#include <cstdint>',
'#include <span>',
'',
'namespace rocjitsu {',
'',
'enum class Action : uint8_t {',
' Identity = 0,',
' Substitute = 1,',
' Lower = 2,',
' Expand = 3,',
' Illegal = 4,',
'};',
'',
'struct InstructionLegalization {',
' uint16_t src_opcode;',
' uint16_t src_encoding_id;',
' Action action;',
' uint16_t target_opcode;',
'',
' constexpr auto operator<=>(const InstructionLegalization &rhs) const {',
' if (auto cmp = src_encoding_id <=> rhs.src_encoding_id; cmp != 0)',
' return cmp;',
' return src_opcode <=> rhs.src_opcode;',
' }',
' constexpr bool operator==(const InstructionLegalization &rhs) const {',
' return src_encoding_id == rhs.src_encoding_id && src_opcode == rhs.src_opcode;',
' }',
'};',
'',
'inline const InstructionLegalization *lookup(',
' std::span<const InstructionLegalization> table,',
' uint16_t encoding_id, uint16_t opcode) {',
' InstructionLegalization key{.src_opcode = opcode, .src_encoding_id = encoding_id,',
' .action = Action::Illegal, .target_opcode = 0};',
' auto it = std::lower_bound(table.begin(), table.end(), key);',
' if (it != table.end() && *it == key)',
' return &*it;',
' return nullptr;',
'}',
'',
'} // namespace rocjitsu',
'',
]
path.write_text('\n'.join(lines))
def _emit_pair(
path: Path,
src: str,
dst: str,
entries: list[LegalizationEntry],
) -> None:
name = _pair_name(src, dst)
lines = [
_COPYRIGHT,
'',
'#pragma once',
'',
'#include "legalization_types.h"',
'',
'namespace rocjitsu {',
'',
f'inline constexpr InstructionLegalization kLegalization_{name}[] = {{',
]
for e in entries:
tgt = e.action.target_opcode
enc_id = e.src_encoding_order if e.src_encoding_order >= 0 else 0xFFFF
lines.append(
f' {{{e.src_opcode:>5}, {enc_id:>5}, '
f'{_action_enum(e):<20s}, {tgt:>5}}},'
)
lines += ['};', '', '} // namespace rocjitsu', '']
path.write_text('\n'.join(lines))