Files
jak-project/third-party/capstone/suite/auto-sync/src/autosync/Helper.py
T
Tyler Wilding bfc4c18ada goalc: replicate tests for the majority of ARM64 non-simd cases (#4377)
- Adds `capstone` as a disassembling library that could eventually
replace Zydis (for now left that alone)
- Replicates all of the existing x86 tests to ARM64, fixed a bunch of
underlying issues along the way
- There are a very small handful of tests remaining that need to be
enabled / fixed
2026-08-16 15:34:37 -04:00

171 lines
5.1 KiB
Python
Vendored
Generated

# Copyright © 2022 Rot127 <unisono@quyllur.org>
# SPDX-License-Identifier: BSD-3
import hashlib
import logging as log
import shutil
import subprocess
import sys
from pathlib import Path
import termcolor
from tree_sitter import Node
from autosync.PathVarHandler import PathVarHandler
def convert_loglevel(level: str) -> int:
if level == "debug":
return log.DEBUG
elif level == "info":
return log.INFO
elif level == "warning":
return log.WARNING
elif level == "error":
return log.ERROR
elif level == "fatal":
return log.FATAL
elif level == "critical":
return log.CRITICAL
raise ValueError(f'Unknown loglevel "{level}"')
def find_id_by_type(node: Node, node_types: [str], type_must_match: bool) -> bytes:
"""
Recursively searches for a node sequence with given node types.
A valid sequence is a path from node_n to node_{(n + |node_types|-1)} where
forall i in {0, ..., |node_types|-1}: type(node_{(n + i)}) = node_types_i.
If a node sequence is found, this functions returns the text associated with the
last node in the sequence.
:param node: Current node.
:param node_types: List of node types.
:param type_must_match: If true, it is mandatory for the current node that its type matches node_types[0]
:return: The nodes text of the last node in a valid sequence of and empty string of no such sequence exists.
"""
if len(node_types) == 0:
# No ids left to compare to: Nothing found
return b""
# Set true if:
# current node type matches.
# OR
# parent dictates that node type match
type_must_match = node.type == node_types[0] or type_must_match
if type_must_match and node.type != node_types[0]:
# This child has no matching type. Return.
return b""
if len(node_types) == 1 and type_must_match:
if node.type == node_types[0]:
# Found it
return node.text
else:
# Not found. Return to parent
return b""
# If this nodes type matches the first in the list
# we remove this one from the list.
# Otherwise, give the whole list to the child (since our type does not matter).
children_id_types = node_types[1:] if type_must_match else node_types
# Check if any child has a matching type.
for child in node.named_children:
res = find_id_by_type(child, children_id_types, type_must_match)
if res:
# A path from this node matches the id_types!
return res
# None of our children matched the type list.
return b""
def print_prominent_warning(msg: str, wait_for_user: bool = True) -> None:
print("\n" + separator_line_1("yellow"))
print(termcolor.colored("WARNING", "yellow", attrs=["bold"]) + "\n")
print(msg)
print(separator_line_1("yellow"))
if wait_for_user:
input("Press enter to continue...\n")
def term_width() -> int:
return shutil.get_terminal_size()[0]
def print_prominent_info(msg: str, wait_for_user: bool = True) -> None:
print("\n" + separator_line_1("blue"))
print(msg)
print(separator_line_1("blue"))
if wait_for_user:
input("Press enter to continue...\n")
def bold(msg: str, color: str = None) -> str:
if color:
return termcolor.colored(msg, attrs=["bold"], color=color)
return termcolor.colored(msg, attrs=["bold"])
def colored(msg: str, color: str) -> str:
return termcolor.colored(msg, color=color)
def separator_line_1(color: str = None) -> str:
return f"{bold(f'' * int(term_width() / 2), color)}\n"
def separator_line_2(color: str = None) -> str:
return f"{bold(f'' * int(term_width() / 2), color)}\n"
def get_sha256(data: bytes) -> str:
h = hashlib.sha256()
h.update(data)
return h.hexdigest()
def get_header() -> str:
return (
"/* Capstone Disassembly Engine, http://www.capstone-engine.org */\n"
"/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2022, */\n"
"/* Rot127 <unisono@quyllur.org> 2022-2023 */\n"
"/* Automatically translated source file from LLVM. */\n\n"
"/* LLVM-commit: <commit> */\n"
"/* LLVM-tag: <tag> */\n\n"
"/* Only small edits allowed. */\n"
"/* For multiple similar edits, please create a Patch for the translator. */\n\n"
"/* Capstone's C++ file translator: */\n"
"/* https://github.com/capstone-engine/capstone/tree/next/suite/auto-sync */\n\n"
)
def run_clang_format(out_paths: list[Path]):
for out_file in out_paths:
log.info(f"Format {out_file}")
subprocess.run(
[
"clang-format",
f"-style=file:{get_path('{CS_CLANG_FORMAT_FILE}')}",
"-i",
out_file,
]
)
def get_path(config_path: str) -> Path:
return PathVarHandler().complete_path(config_path)
def test_only_overwrite_path_var(var_name: str, new_path: Path):
"""Don't use outside of testing."""
return PathVarHandler().test_only_overwrite_var(var_name, new_path)
def fail_exit(msg: str) -> None:
"""Logs a fatal message and exits with error code 1."""
log.fatal(msg)
exit(1)