mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-02 19:39:49 +09:00
247 lines
8.3 KiB
Python
247 lines
8.3 KiB
Python
"""Generate _opcode_metadata.py for RustPython bytecode.
|
|
|
|
This file generates opcode metadata that is compatible with CPython 3.13.
|
|
RustPython's Instruction enum is now ordered to match CPython opcode numbers exactly.
|
|
"""
|
|
|
|
import re
|
|
|
|
# Read the bytecode.rs file to get instruction names
|
|
with open("crates/compiler-core/src/bytecode.rs", "r") as f:
|
|
content = f.read()
|
|
|
|
# Find the Instruction enum
|
|
match = re.search(r"pub enum Instruction \{(.+?)\n\}", content, re.DOTALL)
|
|
if not match:
|
|
raise ValueError("Could not find Instruction enum")
|
|
|
|
enum_body = match.group(1)
|
|
|
|
# Extract variant names
|
|
variants = []
|
|
for line in enum_body.split("\n"):
|
|
if line.strip().startswith("///") or line.strip().startswith("//"):
|
|
continue
|
|
m = re.match(r"^\s+([A-Z][a-zA-Z0-9]*)", line)
|
|
if m:
|
|
variants.append(m.group(1))
|
|
|
|
print(f"Found {len(variants)} instruction variants")
|
|
|
|
# Map RustPython variant names to CPython-compatible names
|
|
# The opcode number is the index in the Instruction enum
|
|
name_mapping = {
|
|
# Dummy/placeholder instructions
|
|
"Cache": "CACHE",
|
|
"Reserved3": "RESERVED",
|
|
"Reserved17": "RESERVED",
|
|
"Reserved141": "RESERVED",
|
|
"Reserved142": "RESERVED",
|
|
"Reserved143": "RESERVED",
|
|
"Reserved144": "RESERVED",
|
|
"Reserved145": "RESERVED",
|
|
"Reserved146": "RESERVED",
|
|
"Reserved147": "RESERVED",
|
|
"Reserved148": "RESERVED",
|
|
"BinarySlice": "BINARY_SLICE",
|
|
"EndFor": "END_FOR",
|
|
"ExitInitCheck": "EXIT_INIT_CHECK",
|
|
"GetYieldFromIter": "GET_YIELD_FROM_ITER",
|
|
"InterpreterExit": "INTERPRETER_EXIT",
|
|
"LoadAssertionError": "LOAD_ASSERTION_ERROR",
|
|
"LoadLocals": "LOAD_LOCALS",
|
|
"PushNull": "PUSH_NULL",
|
|
"ReturnGenerator": "RETURN_GENERATOR",
|
|
"StoreSlice": "STORE_SLICE",
|
|
"UnaryInvert": "UNARY_INVERT",
|
|
"UnaryNegative": "UNARY_NEGATIVE",
|
|
"UnaryNot": "UNARY_NOT",
|
|
"BuildConstKeyMap": "BUILD_CONST_KEY_MAP",
|
|
"CopyFreeVars": "COPY_FREE_VARS",
|
|
"DictMerge": "DICT_MERGE",
|
|
"EnterExecutor": "ENTER_EXECUTOR",
|
|
"JumpBackward": "JUMP_BACKWARD",
|
|
"JumpBackwardNoInterrupt": "JUMP_BACKWARD_NO_INTERRUPT",
|
|
"JumpForward": "JUMP_FORWARD",
|
|
"ListExtend": "LIST_EXTEND",
|
|
"LoadFastCheck": "LOAD_FAST_CHECK",
|
|
"LoadFastLoadFast": "LOAD_FAST_LOAD_FAST",
|
|
"LoadFromDictOrDeref": "LOAD_FROM_DICT_OR_DEREF",
|
|
"LoadFromDictOrGlobals": "LOAD_FROM_DICT_OR_GLOBALS",
|
|
"LoadSuperAttr": "LOAD_SUPER_ATTR",
|
|
"MakeCell": "MAKE_CELL",
|
|
"PopJumpIfNone": "POP_JUMP_IF_NONE",
|
|
"PopJumpIfNotNone": "POP_JUMP_IF_NOT_NONE",
|
|
"SetUpdate": "SET_UPDATE",
|
|
"StoreFastStoreFast": "STORE_FAST_STORE_FAST",
|
|
# Real instructions
|
|
"BeforeAsyncWith": "BEFORE_ASYNC_WITH",
|
|
"BeforeWith": "BEFORE_WITH",
|
|
"BinaryOp": "BINARY_OP",
|
|
"BinarySubscript": "BINARY_SUBSCR",
|
|
"Break": "BREAK",
|
|
"BuildList": "BUILD_LIST",
|
|
"BuildListFromTuples": "BUILD_LIST_UNPACK",
|
|
"BuildMap": "BUILD_MAP",
|
|
"BuildMapForCall": "BUILD_MAP_FOR_CALL",
|
|
"BuildSet": "BUILD_SET",
|
|
"BuildSetFromTuples": "BUILD_SET_UNPACK",
|
|
"BuildSlice": "BUILD_SLICE",
|
|
"BuildString": "BUILD_STRING",
|
|
"BuildTuple": "BUILD_TUPLE",
|
|
"BuildTupleFromIter": "BUILD_TUPLE_ITER",
|
|
"BuildTupleFromTuples": "BUILD_TUPLE_UNPACK",
|
|
"CallFunctionEx": "CALL_FUNCTION_EX",
|
|
"CallFunctionKeyword": "CALL_KW",
|
|
"CallFunctionPositional": "CALL",
|
|
"CallIntrinsic1": "CALL_INTRINSIC_1",
|
|
"CallIntrinsic2": "CALL_INTRINSIC_2",
|
|
"CallMethodEx": "CALL_METHOD_EX",
|
|
"CallMethodKeyword": "CALL_METHOD_KW",
|
|
"CallMethodPositional": "CALL_METHOD",
|
|
"CheckEgMatch": "CHECK_EG_MATCH",
|
|
"CheckExcMatch": "CHECK_EXC_MATCH",
|
|
"CleanupThrow": "CLEANUP_THROW",
|
|
"CompareOperation": "COMPARE_OP",
|
|
"ContainsOp": "CONTAINS_OP",
|
|
"Continue": "CONTINUE",
|
|
"ConvertValue": "CONVERT_VALUE",
|
|
"CopyItem": "COPY",
|
|
"DeleteAttr": "DELETE_ATTR",
|
|
"DeleteDeref": "DELETE_DEREF",
|
|
"DeleteFast": "DELETE_FAST",
|
|
"DeleteGlobal": "DELETE_GLOBAL",
|
|
"DeleteLocal": "DELETE_NAME",
|
|
"DeleteSubscript": "DELETE_SUBSCR",
|
|
"DictUpdate": "DICT_UPDATE",
|
|
"EndAsyncFor": "END_ASYNC_FOR",
|
|
"EndSend": "END_SEND",
|
|
"ExtendedArg": "EXTENDED_ARG",
|
|
"ForIter": "FOR_ITER",
|
|
"FormatSimple": "FORMAT_SIMPLE",
|
|
"FormatWithSpec": "FORMAT_WITH_SPEC",
|
|
"GetAIter": "GET_AITER",
|
|
"GetANext": "GET_ANEXT",
|
|
"GetAwaitable": "GET_AWAITABLE",
|
|
"GetIter": "GET_ITER",
|
|
"GetLen": "GET_LEN",
|
|
"ImportFrom": "IMPORT_FROM",
|
|
"ImportName": "IMPORT_NAME",
|
|
"IsOp": "IS_OP",
|
|
"Jump": "JUMP",
|
|
"JumpIfFalseOrPop": "JUMP_IF_FALSE_OR_POP",
|
|
"JumpIfNotExcMatch": "JUMP_IF_NOT_EXC_MATCH",
|
|
"JumpIfTrueOrPop": "JUMP_IF_TRUE_OR_POP",
|
|
"ListAppend": "LIST_APPEND",
|
|
"LoadAttr": "LOAD_ATTR",
|
|
"LoadBuildClass": "LOAD_BUILD_CLASS",
|
|
"LoadClassDeref": "LOAD_CLASSDEREF",
|
|
"LoadClosure": "LOAD_CLOSURE",
|
|
"LoadConst": "LOAD_CONST",
|
|
"LoadDeref": "LOAD_DEREF",
|
|
"LoadFast": "LOAD_FAST",
|
|
"LoadFastAndClear": "LOAD_FAST_AND_CLEAR",
|
|
"LoadGlobal": "LOAD_GLOBAL",
|
|
"LoadMethod": "LOAD_METHOD",
|
|
"LoadNameAny": "LOAD_NAME",
|
|
"MakeFunction": "MAKE_FUNCTION",
|
|
"MapAdd": "MAP_ADD",
|
|
"MatchClass": "MATCH_CLASS",
|
|
"MatchKeys": "MATCH_KEYS",
|
|
"MatchMapping": "MATCH_MAPPING",
|
|
"MatchSequence": "MATCH_SEQUENCE",
|
|
"Nop": "NOP",
|
|
"PopBlock": "POP_BLOCK",
|
|
"PopException": "POP_EXCEPT",
|
|
"PopJumpIfFalse": "POP_JUMP_IF_FALSE",
|
|
"PopJumpIfTrue": "POP_JUMP_IF_TRUE",
|
|
"PopTop": "POP_TOP",
|
|
"PushExcInfo": "PUSH_EXC_INFO",
|
|
"Raise": "RAISE_VARARGS",
|
|
"Reraise": "RERAISE",
|
|
"Resume": "RESUME",
|
|
"ReturnConst": "RETURN_CONST",
|
|
"ReturnValue": "RETURN_VALUE",
|
|
"Reverse": "REVERSE",
|
|
"Send": "SEND",
|
|
"SetAdd": "SET_ADD",
|
|
"SetExcInfo": "SET_EXC_INFO",
|
|
"SetFunctionAttribute": "SET_FUNCTION_ATTRIBUTE",
|
|
"SetupAnnotation": "SETUP_ANNOTATIONS",
|
|
"StoreAttr": "STORE_ATTR",
|
|
"StoreDeref": "STORE_DEREF",
|
|
"StoreFast": "STORE_FAST",
|
|
"StoreFastLoadFast": "STORE_FAST_LOAD_FAST",
|
|
"StoreGlobal": "STORE_GLOBAL",
|
|
"StoreLocal": "STORE_NAME",
|
|
"StoreSubscript": "STORE_SUBSCR",
|
|
"Subscript": "SUBSCRIPT",
|
|
"Swap": "SWAP",
|
|
"ToBool": "TO_BOOL",
|
|
"UnaryOperation": "UNARY_OP",
|
|
"UnpackEx": "UNPACK_EX",
|
|
"UnpackSequence": "UNPACK_SEQUENCE",
|
|
"WithExceptStart": "WITH_EXCEPT_START",
|
|
"YieldValue": "YIELD_VALUE",
|
|
}
|
|
|
|
# Build opmap with RustPython instruction indices
|
|
opmap = {}
|
|
rust_to_cpython_name = {}
|
|
for i, variant in enumerate(variants):
|
|
cpython_name = name_mapping.get(variant, variant.upper())
|
|
# Skip adding duplicates (RESERVED appears multiple times)
|
|
if cpython_name == "RESERVED":
|
|
# Use unique names for reserved slots
|
|
cpython_name = f"RESERVED_{i}"
|
|
if cpython_name not in opmap:
|
|
opmap[cpython_name] = i
|
|
rust_to_cpython_name[variant] = cpython_name
|
|
|
|
|
|
# Find specific instruction indices for categorization
|
|
def find_opcode(cpython_name):
|
|
return opmap.get(cpython_name, -1)
|
|
|
|
|
|
# Generate the output file
|
|
output = """# This file is generated by scripts/generate_opcode_metadata.py
|
|
# for RustPython bytecode format (CPython 3.13 compatible opcode numbers).
|
|
# Do not edit!
|
|
|
|
_specializations = {}
|
|
|
|
_specialized_opmap = {}
|
|
|
|
opmap = {
|
|
"""
|
|
|
|
for name, num in sorted(opmap.items(), key=lambda x: x[1]):
|
|
output += f" '{name}': {num},\n"
|
|
|
|
output += """}
|
|
|
|
# CPython 3.13 compatible: opcodes < 44 have no argument
|
|
HAVE_ARGUMENT = 44
|
|
MIN_INSTRUMENTED_OPCODE = 236
|
|
"""
|
|
|
|
with open("Lib/_opcode_metadata.py", "w") as f:
|
|
f.write(output)
|
|
|
|
print("Generated Lib/_opcode_metadata.py")
|
|
print("\nKey opcode indices (matching CPython 3.13):")
|
|
print(f" CACHE = {find_opcode('CACHE')} (expected: 0)")
|
|
print(f" BEFORE_ASYNC_WITH = {find_opcode('BEFORE_ASYNC_WITH')} (expected: 1)")
|
|
print(f" BINARY_SUBSCR = {find_opcode('BINARY_SUBSCR')} (expected: 5)")
|
|
print(
|
|
f" WITH_EXCEPT_START = {find_opcode('WITH_EXCEPT_START')} (expected: 44, HAVE_ARGUMENT)"
|
|
)
|
|
print(f" BINARY_OP = {find_opcode('BINARY_OP')} (expected: 45)")
|
|
print(f" LOAD_CONST = {find_opcode('LOAD_CONST')} (expected: 83)")
|
|
print(f" LOAD_FAST = {find_opcode('LOAD_FAST')} (expected: 85)")
|
|
print(f" LOAD_GLOBAL = {find_opcode('LOAD_GLOBAL')} (expected: 91)")
|
|
print(f" STORE_FAST = {find_opcode('STORE_FAST')} (expected: 110)")
|
|
print(f" YIELD_VALUE = {find_opcode('YIELD_VALUE')} (expected: 118)")
|
|
print(f" RESUME = {find_opcode('RESUME')} (expected: 149)")
|