From 21d9632d6f698e6386c7ff701a0c3ca0261d301f Mon Sep 17 00:00:00 2001 From: ShaharNaveh <50263213+ShaharNaveh@users.noreply.github.com> Date: Tue, 23 Sep 2025 13:16:43 +0200 Subject: [PATCH 01/43] POC: automated instruction gen --- scripts/gen_instructions.py | 100 ++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100755 scripts/gen_instructions.py diff --git a/scripts/gen_instructions.py b/scripts/gen_instructions.py new file mode 100755 index 00000000000..4f361d611d6 --- /dev/null +++ b/scripts/gen_instructions.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python +import pathlib +import sys +import textwrap +import typing + +CPYTHON_PATH = ( + pathlib.Path(__file__).parents[2] / "cpython" # Local filesystem path of cpython +) + +_cases_generator_path = CPYTHON_PATH / "Tools" / "cases_generator" +sys.path.append(str(_cases_generator_path)) + + +import analyzer +from generators_common import DEFAULT_INPUT +from opcode_metadata_generator import cflags, get_format + +ROOT = pathlib.Path(__file__).parents[1] +OUT_PATH = ROOT / "compiler" / "core" / "src" / "instruction.rs" + + +class Instruction(typing.NamedTuple): + cname: str + id: int + fmt: str + flags: frozenset[str] + + @property + def name(self) -> str: + return self.cname.title().replace("_", "") + + def as_member(self) -> str: + out = self.name + match self.fmt: + case "INSTR_FMT_IB": + out += " { index: Arg }" + out += f" = {self.id}" + return out + + @classmethod + def iter_instructions(cls, analysis: analyzer.Analysis): + """ + Adopted from https://github.com/python/cpython/blob/bcee1c322115c581da27600f2ae55e5439c027eb/Tools/cases_generator/opcode_metadata_generator.py#L186-L213 + """ + opmap = analysis.opmap + for inst in sorted(analysis.instructions.values(), key=lambda t: t.name): + name = inst.name + fmt = get_format(inst) + flags = frozenset(cflags(inst.properties).split(" | ")) + + yield cls(cname=name, id=opmap[name], fmt=fmt, flags=flags) + + def __lt__(self, other: typing.Self) -> bool: + return self.id < other.id + + +def gen_by_comment() -> str: + path = pathlib.Path(__file__).absolute().relative_to(ROOT).as_posix() + return textwrap.indent( + f""" +This file is generated by {path} +Do not edit! +""".strip(), + "// ", + ) + + +def main(): + analysis = analyzer.analyze_files([DEFAULT_INPUT]) + + instruction_memebers = textwrap.indent( + ",\n".join( + ins.as_member() for ins in sorted(Instruction.iter_instructions(analysis)) + ), + " " * 4, + ) + + header = "///! Python opcode implementation. Currently aligned with cpython 3.13.7" + + derive = ", ".join(sorted({"Clone", "Copy", "Debug", "PartialEq", "Eq"})) + + out = f""" +{header} + +{gen_by_comment()} + +/// A Single bytecode instruction. +#[derive({derive})] +#[repr(u16)] +pub enum Instruction {{ +{instruction_memebers} +}} + """.strip() + + OUT_PATH.write_text(out) + + +if __name__ == "__main__": + main() From f6ab8d29b95af95e184deb0bef7e7d32a192051f Mon Sep 17 00:00:00 2001 From: ShaharNaveh <50263213+ShaharNaveh@users.noreply.github.com> Date: Tue, 23 Sep 2025 13:17:07 +0200 Subject: [PATCH 02/43] Add generated file --- compiler/core/src/instruction.rs | 221 +++++++++++++++++++++++++++++++ scripts/gen_instructions.py | 2 +- 2 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 compiler/core/src/instruction.rs diff --git a/compiler/core/src/instruction.rs b/compiler/core/src/instruction.rs new file mode 100644 index 00000000000..4923372ef01 --- /dev/null +++ b/compiler/core/src/instruction.rs @@ -0,0 +1,221 @@ +///! Python opcode implementation. Currently aligned with cpython 3.13.7 + +// This file is generated by scripts/gen_instructions.py +// Do not edit! + +/// A Single bytecode instruction. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +#[repr(u16)] +pub enum Instruction { + Cache = 0, + BeforeAsyncWith = 1, + BeforeWith = 2, + BinaryOpInplaceAddUnicode = 3, + BinarySlice = 4, + BinarySubscr = 5, + CheckEgMatch = 6, + CheckExcMatch = 7, + CleanupThrow = 8, + DeleteSubscr = 9, + EndAsyncFor = 10, + EndFor = 11, + EndSend = 12, + ExitInitCheck = 13, + FormatSimple = 14, + FormatWithSpec = 15, + GetAiter = 16, + Reserved = 17, + GetAnext = 18, + GetIter = 19, + GetLen = 20, + GetYieldFromIter = 21, + InterpreterExit = 22, + LoadAssertionError = 23, + LoadBuildClass = 24, + LoadLocals = 25, + MakeFunction = 26, + MatchKeys = 27, + MatchMapping = 28, + MatchSequence = 29, + Nop = 30, + PopExcept = 31, + PopTop = 32, + PushExcInfo = 33, + PushNull = 34, + ReturnGenerator = 35, + ReturnValue = 36, + SetupAnnotations = 37, + StoreSlice = 38, + StoreSubscr = 39, + ToBool = 40, + UnaryInvert = 41, + UnaryNegative = 42, + UnaryNot = 43, + WithExceptStart = 44, + BinaryOp = 45, + BuildConstKeyMap { index: Arg } = 46, + BuildList { index: Arg } = 47, + BuildMap { index: Arg } = 48, + BuildSet { index: Arg } = 49, + BuildSlice { index: Arg } = 50, + BuildString { index: Arg } = 51, + BuildTuple { index: Arg } = 52, + Call = 53, + CallFunctionEx { index: Arg } = 54, + CallIntrinsic1 { index: Arg } = 55, + CallIntrinsic2 { index: Arg } = 56, + CallKw { index: Arg } = 57, + CompareOp = 58, + ContainsOp = 59, + ConvertValue { index: Arg } = 60, + Copy { index: Arg } = 61, + CopyFreeVars { index: Arg } = 62, + DeleteAttr { index: Arg } = 63, + DeleteDeref { index: Arg } = 64, + DeleteFast { index: Arg } = 65, + DeleteGlobal { index: Arg } = 66, + DeleteName { index: Arg } = 67, + DictMerge { index: Arg } = 68, + DictUpdate { index: Arg } = 69, + EnterExecutor { index: Arg } = 70, + ExtendedArg { index: Arg } = 71, + ForIter = 72, + GetAwaitable { index: Arg } = 73, + ImportFrom { index: Arg } = 74, + ImportName { index: Arg } = 75, + IsOp { index: Arg } = 76, + JumpBackward = 77, + JumpBackwardNoInterrupt { index: Arg } = 78, + JumpForward { index: Arg } = 79, + ListAppend { index: Arg } = 80, + ListExtend { index: Arg } = 81, + LoadAttr = 82, + LoadConst { index: Arg } = 83, + LoadDeref { index: Arg } = 84, + LoadFast { index: Arg } = 85, + LoadFastAndClear { index: Arg } = 86, + LoadFastCheck { index: Arg } = 87, + LoadFastLoadFast { index: Arg } = 88, + LoadFromDictOrDeref { index: Arg } = 89, + LoadFromDictOrGlobals { index: Arg } = 90, + LoadGlobal = 91, + LoadName { index: Arg } = 92, + LoadSuperAttr = 93, + MakeCell { index: Arg } = 94, + MapAdd { index: Arg } = 95, + MatchClass { index: Arg } = 96, + PopJumpIfFalse = 97, + PopJumpIfNone = 98, + PopJumpIfNotNone = 99, + PopJumpIfTrue = 100, + RaiseVarargs { index: Arg } = 101, + Reraise { index: Arg } = 102, + ReturnConst { index: Arg } = 103, + Send = 104, + SetAdd { index: Arg } = 105, + SetFunctionAttribute { index: Arg } = 106, + SetUpdate { index: Arg } = 107, + StoreAttr = 108, + StoreDeref { index: Arg } = 109, + StoreFast { index: Arg } = 110, + StoreFastLoadFast { index: Arg } = 111, + StoreFastStoreFast { index: Arg } = 112, + StoreGlobal { index: Arg } = 113, + StoreName { index: Arg } = 114, + Swap { index: Arg } = 115, + UnpackEx { index: Arg } = 116, + UnpackSequence = 117, + YieldValue { index: Arg } = 118, + Resume { index: Arg } = 149, + BinaryOpAddFloat = 150, + BinaryOpAddInt = 151, + BinaryOpAddUnicode = 152, + BinaryOpMultiplyFloat = 153, + BinaryOpMultiplyInt = 154, + BinaryOpSubtractFloat = 155, + BinaryOpSubtractInt = 156, + BinarySubscrDict = 157, + BinarySubscrGetitem = 158, + BinarySubscrListInt = 159, + BinarySubscrStrInt = 160, + BinarySubscrTupleInt = 161, + CallAllocAndEnterInit = 162, + CallBoundMethodExactArgs = 163, + CallBoundMethodGeneral = 164, + CallBuiltinClass = 165, + CallBuiltinFast = 166, + CallBuiltinFastWithKeywords = 167, + CallBuiltinO = 168, + CallIsinstance = 169, + CallLen = 170, + CallListAppend = 171, + CallMethodDescriptorFast = 172, + CallMethodDescriptorFastWithKeywords = 173, + CallMethodDescriptorNoargs = 174, + CallMethodDescriptorO = 175, + CallNonPyGeneral = 176, + CallPyExactArgs = 177, + CallPyGeneral = 178, + CallStr1 = 179, + CallTuple1 = 180, + CallType1 = 181, + CompareOpFloat = 182, + CompareOpInt = 183, + CompareOpStr = 184, + ContainsOpDict = 185, + ContainsOpSet = 186, + ForIterGen = 187, + ForIterList = 188, + ForIterRange = 189, + ForIterTuple = 190, + LoadAttrClass = 191, + LoadAttrGetattributeOverridden = 192, + LoadAttrInstanceValue = 193, + LoadAttrMethodLazyDict = 194, + LoadAttrMethodNoDict = 195, + LoadAttrMethodWithValues = 196, + LoadAttrModule = 197, + LoadAttrNondescriptorNoDict = 198, + LoadAttrNondescriptorWithValues = 199, + LoadAttrProperty = 200, + LoadAttrSlot = 201, + LoadAttrWithHint = 202, + LoadGlobalBuiltin = 203, + LoadGlobalModule = 204, + LoadSuperAttrAttr = 205, + LoadSuperAttrMethod = 206, + ResumeCheck = 207, + SendGen = 208, + StoreAttrInstanceValue = 209, + StoreAttrSlot = 210, + StoreAttrWithHint = 211, + StoreSubscrDict = 212, + StoreSubscrListInt = 213, + ToBoolAlwaysTrue = 214, + ToBoolBool = 215, + ToBoolInt = 216, + ToBoolList = 217, + ToBoolNone = 218, + ToBoolStr = 219, + UnpackSequenceList = 220, + UnpackSequenceTuple = 221, + UnpackSequenceTwoTuple = 222, + InstrumentedResume { index: Arg } = 236, + InstrumentedEndFor = 237, + InstrumentedEndSend = 238, + InstrumentedReturnValue = 239, + InstrumentedReturnConst { index: Arg } = 240, + InstrumentedYieldValue { index: Arg } = 241, + InstrumentedLoadSuperAttr = 242, + InstrumentedForIter = 243, + InstrumentedCall = 244, + InstrumentedCallKw { index: Arg } = 245, + InstrumentedCallFunctionEx = 246, + InstrumentedInstruction = 247, + InstrumentedJumpForward { index: Arg } = 248, + InstrumentedJumpBackward = 249, + InstrumentedPopJumpIfTrue = 250, + InstrumentedPopJumpIfFalse = 251, + InstrumentedPopJumpIfNone = 252, + InstrumentedPopJumpIfNotNone = 253 +} diff --git a/scripts/gen_instructions.py b/scripts/gen_instructions.py index 4f361d611d6..1ba33f72ff2 100755 --- a/scripts/gen_instructions.py +++ b/scripts/gen_instructions.py @@ -93,7 +93,7 @@ def main(): }} """.strip() - OUT_PATH.write_text(out) + OUT_PATH.write_text(out + "\n") if __name__ == "__main__": From b8ebe9b9b429e0aa6d86a1fe1dc1f3d5880bf012 Mon Sep 17 00:00:00 2001 From: ShaharNaveh <50263213+ShaharNaveh@users.noreply.github.com> Date: Tue, 23 Sep 2025 13:21:21 +0200 Subject: [PATCH 03/43] Add note about pseudos opcode --- scripts/gen_instructions.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/gen_instructions.py b/scripts/gen_instructions.py index 1ba33f72ff2..7099f43bfc2 100755 --- a/scripts/gen_instructions.py +++ b/scripts/gen_instructions.py @@ -51,6 +51,8 @@ def iter_instructions(cls, analysis: analyzer.Analysis): yield cls(cname=name, id=opmap[name], fmt=fmt, flags=flags) + # TODO: What about `analysis.pseudos` ? + def __lt__(self, other: typing.Self) -> bool: return self.id < other.id From 8510815bba7e5081f5c0ada5ede68b3e85a96527 Mon Sep 17 00:00:00 2001 From: ShaharNaveh <50263213+ShaharNaveh@users.noreply.github.com> Date: Tue, 23 Sep 2025 17:24:27 +0200 Subject: [PATCH 04/43] Use `properties.oparg` instead --- compiler/core/src/instruction.rs | 342 ++++++++++++++++--------------- scripts/gen_instructions.py | 40 ++-- 2 files changed, 203 insertions(+), 179 deletions(-) diff --git a/compiler/core/src/instruction.rs b/compiler/core/src/instruction.rs index 4923372ef01..f6a18f4b21d 100644 --- a/compiler/core/src/instruction.rs +++ b/compiler/core/src/instruction.rs @@ -7,215 +7,227 @@ #[derive(Clone, Copy, Debug, Eq, PartialEq)] #[repr(u16)] pub enum Instruction { - Cache = 0, BeforeAsyncWith = 1, BeforeWith = 2, + BinaryOp(Arg) = 45, + BinaryOpAddFloat = 150, + BinaryOpAddInt = 151, + BinaryOpAddUnicode = 152, BinaryOpInplaceAddUnicode = 3, + BinaryOpMultiplyFloat = 153, + BinaryOpMultiplyInt = 154, + BinaryOpSubtractFloat = 155, + BinaryOpSubtractInt = 156, BinarySlice = 4, BinarySubscr = 5, + BinarySubscrDict = 157, + BinarySubscrGetitem = 158, + BinarySubscrListInt = 159, + BinarySubscrStrInt = 160, + BinarySubscrTupleInt = 161, + BuildConstKeyMap(Arg) = 46, + BuildList(Arg) = 47, + BuildMap(Arg) = 48, + BuildSet(Arg) = 49, + BuildSlice(Arg) = 50, + BuildString(Arg) = 51, + BuildTuple(Arg) = 52, + Cache = 0, + Call(Arg) = 53, + CallAllocAndEnterInit(Arg) = 162, + CallBoundMethodExactArgs(Arg) = 163, + CallBoundMethodGeneral(Arg) = 164, + CallBuiltinClass(Arg) = 165, + CallBuiltinFast(Arg) = 166, + CallBuiltinFastWithKeywords(Arg) = 167, + CallBuiltinO(Arg) = 168, + CallFunctionEx(Arg) = 54, + CallIntrinsic1(Arg) = 55, + CallIntrinsic2(Arg) = 56, + CallIsinstance(Arg) = 169, + CallKw(Arg) = 57, + CallLen(Arg) = 170, + CallListAppend(Arg) = 171, + CallMethodDescriptorFast(Arg) = 172, + CallMethodDescriptorFastWithKeywords(Arg) = 173, + CallMethodDescriptorNoargs(Arg) = 174, + CallMethodDescriptorO(Arg) = 175, + CallNonPyGeneral(Arg) = 176, + CallPyExactArgs(Arg) = 177, + CallPyGeneral(Arg) = 178, + CallStr1(Arg) = 179, + CallTuple1(Arg) = 180, + CallType1(Arg) = 181, CheckEgMatch = 6, CheckExcMatch = 7, CleanupThrow = 8, + CompareOp(Arg) = 58, + CompareOpFloat(Arg) = 182, + CompareOpInt(Arg) = 183, + CompareOpStr(Arg) = 184, + ContainsOp(Arg) = 59, + ContainsOpDict(Arg) = 185, + ContainsOpSet(Arg) = 186, + ConvertValue(Arg) = 60, + Copy(Arg) = 61, + CopyFreeVars(Arg) = 62, + DeleteAttr(Arg) = 63, + DeleteDeref(Arg) = 64, + DeleteFast(Arg) = 65, + DeleteGlobal(Arg) = 66, + DeleteName(Arg) = 67, DeleteSubscr = 9, + DictMerge(Arg) = 68, + DictUpdate(Arg) = 69, EndAsyncFor = 10, EndFor = 11, EndSend = 12, + EnterExecutor(Arg) = 70, ExitInitCheck = 13, + ExtendedArg(Arg) = 71, FormatSimple = 14, FormatWithSpec = 15, + ForIter(Arg) = 72, + ForIterGen(Arg) = 187, + ForIterList(Arg) = 188, + ForIterRange(Arg) = 189, + ForIterTuple(Arg) = 190, GetAiter = 16, - Reserved = 17, GetAnext = 18, + GetAwaitable(Arg) = 73, GetIter = 19, GetLen = 20, GetYieldFromIter = 21, + ImportFrom(Arg) = 74, + ImportName(Arg) = 75, + InstrumentedCall(Arg) = 244, + InstrumentedCallFunctionEx = 246, + InstrumentedCallKw(Arg) = 245, + InstrumentedEndFor = 237, + InstrumentedEndSend = 238, + InstrumentedForIter(Arg) = 243, + InstrumentedInstruction = 247, + InstrumentedJumpBackward(Arg) = 249, + InstrumentedJumpForward(Arg) = 248, + InstrumentedLoadSuperAttr(Arg) = 242, + InstrumentedPopJumpIfFalse(Arg) = 251, + InstrumentedPopJumpIfNone(Arg) = 252, + InstrumentedPopJumpIfNotNone(Arg) = 253, + InstrumentedPopJumpIfTrue(Arg) = 250, + InstrumentedResume(Arg) = 236, + InstrumentedReturnConst(Arg) = 240, + InstrumentedReturnValue = 239, + InstrumentedYieldValue(Arg) = 241, InterpreterExit = 22, + IsOp(Arg) = 76, + JumpBackward(Arg) = 77, + JumpBackwardNoInterrupt(Arg) = 78, + JumpForward(Arg) = 79, + ListAppend(Arg) = 80, + ListExtend(Arg) = 81, LoadAssertionError = 23, + LoadAttr(Arg) = 82, + LoadAttrClass(Arg) = 191, + LoadAttrGetattributeOverridden(Arg) = 192, + LoadAttrInstanceValue(Arg) = 193, + LoadAttrMethodLazyDict(Arg) = 194, + LoadAttrMethodNoDict(Arg) = 195, + LoadAttrMethodWithValues(Arg) = 196, + LoadAttrModule(Arg) = 197, + LoadAttrNondescriptorNoDict(Arg) = 198, + LoadAttrNondescriptorWithValues(Arg) = 199, + LoadAttrProperty(Arg) = 200, + LoadAttrSlot(Arg) = 201, + LoadAttrWithHint(Arg) = 202, LoadBuildClass = 24, + LoadConst(Arg) = 83, + LoadDeref(Arg) = 84, + LoadFast(Arg) = 85, + LoadFastAndClear(Arg) = 86, + LoadFastCheck(Arg) = 87, + LoadFastLoadFast(Arg) = 88, + LoadFromDictOrDeref(Arg) = 89, + LoadFromDictOrGlobals(Arg) = 90, + LoadGlobal(Arg) = 91, + LoadGlobalBuiltin(Arg) = 203, + LoadGlobalModule(Arg) = 204, LoadLocals = 25, + LoadName(Arg) = 92, + LoadSuperAttr(Arg) = 93, + LoadSuperAttrAttr(Arg) = 205, + LoadSuperAttrMethod(Arg) = 206, + MakeCell(Arg) = 94, MakeFunction = 26, + MapAdd(Arg) = 95, + MatchClass(Arg) = 96, MatchKeys = 27, MatchMapping = 28, MatchSequence = 29, Nop = 30, PopExcept = 31, + PopJumpIfFalse(Arg) = 97, + PopJumpIfNone(Arg) = 98, + PopJumpIfNotNone(Arg) = 99, + PopJumpIfTrue(Arg) = 100, PopTop = 32, PushExcInfo = 33, PushNull = 34, + RaiseVarargs(Arg) = 101, + Reraise(Arg) = 102, + Reserved = 17, + Resume(Arg) = 149, + ResumeCheck = 207, + ReturnConst(Arg) = 103, ReturnGenerator = 35, ReturnValue = 36, + Send(Arg) = 104, + SendGen(Arg) = 208, SetupAnnotations = 37, - StoreSlice = 38, - StoreSubscr = 39, - ToBool = 40, - UnaryInvert = 41, - UnaryNegative = 42, - UnaryNot = 43, - WithExceptStart = 44, - BinaryOp = 45, - BuildConstKeyMap { index: Arg } = 46, - BuildList { index: Arg } = 47, - BuildMap { index: Arg } = 48, - BuildSet { index: Arg } = 49, - BuildSlice { index: Arg } = 50, - BuildString { index: Arg } = 51, - BuildTuple { index: Arg } = 52, - Call = 53, - CallFunctionEx { index: Arg } = 54, - CallIntrinsic1 { index: Arg } = 55, - CallIntrinsic2 { index: Arg } = 56, - CallKw { index: Arg } = 57, - CompareOp = 58, - ContainsOp = 59, - ConvertValue { index: Arg } = 60, - Copy { index: Arg } = 61, - CopyFreeVars { index: Arg } = 62, - DeleteAttr { index: Arg } = 63, - DeleteDeref { index: Arg } = 64, - DeleteFast { index: Arg } = 65, - DeleteGlobal { index: Arg } = 66, - DeleteName { index: Arg } = 67, - DictMerge { index: Arg } = 68, - DictUpdate { index: Arg } = 69, - EnterExecutor { index: Arg } = 70, - ExtendedArg { index: Arg } = 71, - ForIter = 72, - GetAwaitable { index: Arg } = 73, - ImportFrom { index: Arg } = 74, - ImportName { index: Arg } = 75, - IsOp { index: Arg } = 76, - JumpBackward = 77, - JumpBackwardNoInterrupt { index: Arg } = 78, - JumpForward { index: Arg } = 79, - ListAppend { index: Arg } = 80, - ListExtend { index: Arg } = 81, - LoadAttr = 82, - LoadConst { index: Arg } = 83, - LoadDeref { index: Arg } = 84, - LoadFast { index: Arg } = 85, - LoadFastAndClear { index: Arg } = 86, - LoadFastCheck { index: Arg } = 87, - LoadFastLoadFast { index: Arg } = 88, - LoadFromDictOrDeref { index: Arg } = 89, - LoadFromDictOrGlobals { index: Arg } = 90, - LoadGlobal = 91, - LoadName { index: Arg } = 92, - LoadSuperAttr = 93, - MakeCell { index: Arg } = 94, - MapAdd { index: Arg } = 95, - MatchClass { index: Arg } = 96, - PopJumpIfFalse = 97, - PopJumpIfNone = 98, - PopJumpIfNotNone = 99, - PopJumpIfTrue = 100, - RaiseVarargs { index: Arg } = 101, - Reraise { index: Arg } = 102, - ReturnConst { index: Arg } = 103, - Send = 104, - SetAdd { index: Arg } = 105, - SetFunctionAttribute { index: Arg } = 106, - SetUpdate { index: Arg } = 107, - StoreAttr = 108, - StoreDeref { index: Arg } = 109, - StoreFast { index: Arg } = 110, - StoreFastLoadFast { index: Arg } = 111, - StoreFastStoreFast { index: Arg } = 112, - StoreGlobal { index: Arg } = 113, - StoreName { index: Arg } = 114, - Swap { index: Arg } = 115, - UnpackEx { index: Arg } = 116, - UnpackSequence = 117, - YieldValue { index: Arg } = 118, - Resume { index: Arg } = 149, - BinaryOpAddFloat = 150, - BinaryOpAddInt = 151, - BinaryOpAddUnicode = 152, - BinaryOpMultiplyFloat = 153, - BinaryOpMultiplyInt = 154, - BinaryOpSubtractFloat = 155, - BinaryOpSubtractInt = 156, - BinarySubscrDict = 157, - BinarySubscrGetitem = 158, - BinarySubscrListInt = 159, - BinarySubscrStrInt = 160, - BinarySubscrTupleInt = 161, - CallAllocAndEnterInit = 162, - CallBoundMethodExactArgs = 163, - CallBoundMethodGeneral = 164, - CallBuiltinClass = 165, - CallBuiltinFast = 166, - CallBuiltinFastWithKeywords = 167, - CallBuiltinO = 168, - CallIsinstance = 169, - CallLen = 170, - CallListAppend = 171, - CallMethodDescriptorFast = 172, - CallMethodDescriptorFastWithKeywords = 173, - CallMethodDescriptorNoargs = 174, - CallMethodDescriptorO = 175, - CallNonPyGeneral = 176, - CallPyExactArgs = 177, - CallPyGeneral = 178, - CallStr1 = 179, - CallTuple1 = 180, - CallType1 = 181, - CompareOpFloat = 182, - CompareOpInt = 183, - CompareOpStr = 184, - ContainsOpDict = 185, - ContainsOpSet = 186, - ForIterGen = 187, - ForIterList = 188, - ForIterRange = 189, - ForIterTuple = 190, - LoadAttrClass = 191, - LoadAttrGetattributeOverridden = 192, - LoadAttrInstanceValue = 193, - LoadAttrMethodLazyDict = 194, - LoadAttrMethodNoDict = 195, - LoadAttrMethodWithValues = 196, - LoadAttrModule = 197, - LoadAttrNondescriptorNoDict = 198, - LoadAttrNondescriptorWithValues = 199, - LoadAttrProperty = 200, - LoadAttrSlot = 201, - LoadAttrWithHint = 202, - LoadGlobalBuiltin = 203, - LoadGlobalModule = 204, - LoadSuperAttrAttr = 205, - LoadSuperAttrMethod = 206, - ResumeCheck = 207, - SendGen = 208, + SetAdd(Arg) = 105, + SetFunctionAttribute(Arg) = 106, + SetUpdate(Arg) = 107, + StoreAttr(Arg) = 108, StoreAttrInstanceValue = 209, StoreAttrSlot = 210, - StoreAttrWithHint = 211, + StoreAttrWithHint(Arg) = 211, + StoreDeref(Arg) = 109, + StoreFast(Arg) = 110, + StoreFastLoadFast(Arg) = 111, + StoreFastStoreFast(Arg) = 112, + StoreGlobal(Arg) = 113, + StoreName(Arg) = 114, + StoreSlice = 38, + StoreSubscr = 39, StoreSubscrDict = 212, StoreSubscrListInt = 213, + Swap(Arg) = 115, + ToBool = 40, ToBoolAlwaysTrue = 214, ToBoolBool = 215, ToBoolInt = 216, ToBoolList = 217, ToBoolNone = 218, ToBoolStr = 219, - UnpackSequenceList = 220, - UnpackSequenceTuple = 221, - UnpackSequenceTwoTuple = 222, - InstrumentedResume { index: Arg } = 236, - InstrumentedEndFor = 237, - InstrumentedEndSend = 238, - InstrumentedReturnValue = 239, - InstrumentedReturnConst { index: Arg } = 240, - InstrumentedYieldValue { index: Arg } = 241, - InstrumentedLoadSuperAttr = 242, - InstrumentedForIter = 243, - InstrumentedCall = 244, - InstrumentedCallKw { index: Arg } = 245, - InstrumentedCallFunctionEx = 246, - InstrumentedInstruction = 247, - InstrumentedJumpForward { index: Arg } = 248, - InstrumentedJumpBackward = 249, - InstrumentedPopJumpIfTrue = 250, - InstrumentedPopJumpIfFalse = 251, - InstrumentedPopJumpIfNone = 252, - InstrumentedPopJumpIfNotNone = 253 + UnaryInvert = 41, + UnaryNegative = 42, + UnaryNot = 43, + UnpackEx(Arg) = 116, + UnpackSequence(Arg) = 117, + UnpackSequenceList(Arg) = 220, + UnpackSequenceTuple(Arg) = 221, + UnpackSequenceTwoTuple(Arg) = 222, + WithExceptStart = 44, + YieldValue(Arg) = 118, + Jump(Arg) = 256, + JumpNoInterrupt(Arg) = 257, + LoadClosure(Arg) = 258, + LoadMethod(Arg) = 259, + LoadSuperMethod(Arg) = 260, + LoadZeroSuperAttr(Arg) = 261, + LoadZeroSuperMethod(Arg) = 262, + PopBlock = 263, + SetupCleanup = 264, + SetupFinally = 265, + SetupWith = 266, + StoreFastMaybeNull(Arg) = 267 } diff --git a/scripts/gen_instructions.py b/scripts/gen_instructions.py index 7099f43bfc2..526da02eef5 100755 --- a/scripts/gen_instructions.py +++ b/scripts/gen_instructions.py @@ -14,7 +14,7 @@ import analyzer from generators_common import DEFAULT_INPUT -from opcode_metadata_generator import cflags, get_format +from opcode_metadata_generator import cflags ROOT = pathlib.Path(__file__).parents[1] OUT_PATH = ROOT / "compiler" / "core" / "src" / "instruction.rs" @@ -23,8 +23,8 @@ class Instruction(typing.NamedTuple): cname: str id: int - fmt: str flags: frozenset[str] + has_oparg: bool @property def name(self) -> str: @@ -32,29 +32,40 @@ def name(self) -> str: def as_member(self) -> str: out = self.name - match self.fmt: - case "INSTR_FMT_IB": - out += " { index: Arg }" + if self.has_oparg: + out += "(Arg)" out += f" = {self.id}" return out @classmethod def iter_instructions(cls, analysis: analyzer.Analysis): """ - Adopted from https://github.com/python/cpython/blob/bcee1c322115c581da27600f2ae55e5439c027eb/Tools/cases_generator/opcode_metadata_generator.py#L186-L213 + Adapted from https://github.com/python/cpython/blob/bcee1c322115c581da27600f2ae55e5439c027eb/Tools/cases_generator/opcode_metadata_generator.py#L186-L213 """ opmap = analysis.opmap for inst in sorted(analysis.instructions.values(), key=lambda t: t.name): name = inst.name - fmt = get_format(inst) flags = frozenset(cflags(inst.properties).split(" | ")) - yield cls(cname=name, id=opmap[name], fmt=fmt, flags=flags) + yield cls( + cname=name, id=opmap[name], flags=flags, has_oparg=inst.properties.oparg + ) - # TODO: What about `analysis.pseudos` ? + for pseudo in sorted(analysis.pseudos.values(), key=lambda t: t.name): + name = pseudo.name + flags = cflags(pseudo.properties) + for flag in pseudo.flags: + if flags == "0": + flags = f"{flag}_FLAG" + else: + flags += f" | {flag}_FLAG" - def __lt__(self, other: typing.Self) -> bool: - return self.id < other.id + yield cls( + cname=name, + id=opmap[name], + has_oparg=pseudo.properties.oparg, + flags=frozenset(flags.split(" | ")), + ) def gen_by_comment() -> str: @@ -72,9 +83,7 @@ def main(): analysis = analyzer.analyze_files([DEFAULT_INPUT]) instruction_memebers = textwrap.indent( - ",\n".join( - ins.as_member() for ins in sorted(Instruction.iter_instructions(analysis)) - ), + ",\n".join(ins.as_member() for ins in Instruction.iter_instructions(analysis)), " " * 4, ) @@ -92,6 +101,9 @@ def main(): #[repr(u16)] pub enum Instruction {{ {instruction_memebers} +}} + +impl Instruction {{ }} """.strip() From bcea0bf9d7b713f50fe236eb04d10f8cb8e75759 Mon Sep 17 00:00:00 2001 From: ShaharNaveh <50263213+ShaharNaveh@users.noreply.github.com> Date: Thu, 25 Sep 2025 12:04:18 +0200 Subject: [PATCH 05/43] Sort by id. impl TryFrom --- compiler/core/src/instruction.rs | 273 +++++++++++++++++-------------- scripts/gen_instructions.py | 66 +++++--- 2 files changed, 194 insertions(+), 145 deletions(-) diff --git a/compiler/core/src/instruction.rs b/compiler/core/src/instruction.rs index f6a18f4b21d..9743ccba589 100644 --- a/compiler/core/src/instruction.rs +++ b/compiler/core/src/instruction.rs @@ -7,24 +7,52 @@ #[derive(Clone, Copy, Debug, Eq, PartialEq)] #[repr(u16)] pub enum Instruction { + Cache = 0, BeforeAsyncWith = 1, BeforeWith = 2, - BinaryOp(Arg) = 45, - BinaryOpAddFloat = 150, - BinaryOpAddInt = 151, - BinaryOpAddUnicode = 152, BinaryOpInplaceAddUnicode = 3, - BinaryOpMultiplyFloat = 153, - BinaryOpMultiplyInt = 154, - BinaryOpSubtractFloat = 155, - BinaryOpSubtractInt = 156, BinarySlice = 4, BinarySubscr = 5, - BinarySubscrDict = 157, - BinarySubscrGetitem = 158, - BinarySubscrListInt = 159, - BinarySubscrStrInt = 160, - BinarySubscrTupleInt = 161, + CheckEgMatch = 6, + CheckExcMatch = 7, + CleanupThrow = 8, + DeleteSubscr = 9, + EndAsyncFor = 10, + EndFor = 11, + EndSend = 12, + ExitInitCheck = 13, + FormatSimple = 14, + FormatWithSpec = 15, + GetAiter = 16, + Reserved = 17, + GetAnext = 18, + GetIter = 19, + GetLen = 20, + GetYieldFromIter = 21, + InterpreterExit = 22, + LoadAssertionError = 23, + LoadBuildClass = 24, + LoadLocals = 25, + MakeFunction = 26, + MatchKeys = 27, + MatchMapping = 28, + MatchSequence = 29, + Nop = 30, + PopExcept = 31, + PopTop = 32, + PushExcInfo = 33, + PushNull = 34, + ReturnGenerator = 35, + ReturnValue = 36, + SetupAnnotations = 37, + StoreSlice = 38, + StoreSubscr = 39, + ToBool = 40, + UnaryInvert = 41, + UnaryNegative = 42, + UnaryNot = 43, + WithExceptStart = 44, + BinaryOp(Arg) = 45, BuildConstKeyMap(Arg) = 46, BuildList(Arg) = 47, BuildMap(Arg) = 48, @@ -32,42 +60,13 @@ pub enum Instruction { BuildSlice(Arg) = 50, BuildString(Arg) = 51, BuildTuple(Arg) = 52, - Cache = 0, Call(Arg) = 53, - CallAllocAndEnterInit(Arg) = 162, - CallBoundMethodExactArgs(Arg) = 163, - CallBoundMethodGeneral(Arg) = 164, - CallBuiltinClass(Arg) = 165, - CallBuiltinFast(Arg) = 166, - CallBuiltinFastWithKeywords(Arg) = 167, - CallBuiltinO(Arg) = 168, CallFunctionEx(Arg) = 54, CallIntrinsic1(Arg) = 55, CallIntrinsic2(Arg) = 56, - CallIsinstance(Arg) = 169, CallKw(Arg) = 57, - CallLen(Arg) = 170, - CallListAppend(Arg) = 171, - CallMethodDescriptorFast(Arg) = 172, - CallMethodDescriptorFastWithKeywords(Arg) = 173, - CallMethodDescriptorNoargs(Arg) = 174, - CallMethodDescriptorO(Arg) = 175, - CallNonPyGeneral(Arg) = 176, - CallPyExactArgs(Arg) = 177, - CallPyGeneral(Arg) = 178, - CallStr1(Arg) = 179, - CallTuple1(Arg) = 180, - CallType1(Arg) = 181, - CheckEgMatch = 6, - CheckExcMatch = 7, - CleanupThrow = 8, CompareOp(Arg) = 58, - CompareOpFloat(Arg) = 182, - CompareOpInt(Arg) = 183, - CompareOpStr(Arg) = 184, ContainsOp(Arg) = 59, - ContainsOpDict(Arg) = 185, - ContainsOpSet(Arg) = 186, ConvertValue(Arg) = 60, Copy(Arg) = 61, CopyFreeVars(Arg) = 62, @@ -76,70 +75,21 @@ pub enum Instruction { DeleteFast(Arg) = 65, DeleteGlobal(Arg) = 66, DeleteName(Arg) = 67, - DeleteSubscr = 9, DictMerge(Arg) = 68, DictUpdate(Arg) = 69, - EndAsyncFor = 10, - EndFor = 11, - EndSend = 12, EnterExecutor(Arg) = 70, - ExitInitCheck = 13, ExtendedArg(Arg) = 71, - FormatSimple = 14, - FormatWithSpec = 15, ForIter(Arg) = 72, - ForIterGen(Arg) = 187, - ForIterList(Arg) = 188, - ForIterRange(Arg) = 189, - ForIterTuple(Arg) = 190, - GetAiter = 16, - GetAnext = 18, GetAwaitable(Arg) = 73, - GetIter = 19, - GetLen = 20, - GetYieldFromIter = 21, ImportFrom(Arg) = 74, ImportName(Arg) = 75, - InstrumentedCall(Arg) = 244, - InstrumentedCallFunctionEx = 246, - InstrumentedCallKw(Arg) = 245, - InstrumentedEndFor = 237, - InstrumentedEndSend = 238, - InstrumentedForIter(Arg) = 243, - InstrumentedInstruction = 247, - InstrumentedJumpBackward(Arg) = 249, - InstrumentedJumpForward(Arg) = 248, - InstrumentedLoadSuperAttr(Arg) = 242, - InstrumentedPopJumpIfFalse(Arg) = 251, - InstrumentedPopJumpIfNone(Arg) = 252, - InstrumentedPopJumpIfNotNone(Arg) = 253, - InstrumentedPopJumpIfTrue(Arg) = 250, - InstrumentedResume(Arg) = 236, - InstrumentedReturnConst(Arg) = 240, - InstrumentedReturnValue = 239, - InstrumentedYieldValue(Arg) = 241, - InterpreterExit = 22, IsOp(Arg) = 76, JumpBackward(Arg) = 77, JumpBackwardNoInterrupt(Arg) = 78, JumpForward(Arg) = 79, ListAppend(Arg) = 80, ListExtend(Arg) = 81, - LoadAssertionError = 23, LoadAttr(Arg) = 82, - LoadAttrClass(Arg) = 191, - LoadAttrGetattributeOverridden(Arg) = 192, - LoadAttrInstanceValue(Arg) = 193, - LoadAttrMethodLazyDict(Arg) = 194, - LoadAttrMethodNoDict(Arg) = 195, - LoadAttrMethodWithValues(Arg) = 196, - LoadAttrModule(Arg) = 197, - LoadAttrNondescriptorNoDict(Arg) = 198, - LoadAttrNondescriptorWithValues(Arg) = 199, - LoadAttrProperty(Arg) = 200, - LoadAttrSlot(Arg) = 201, - LoadAttrWithHint(Arg) = 202, - LoadBuildClass = 24, LoadConst(Arg) = 83, LoadDeref(Arg) = 84, LoadFast(Arg) = 85, @@ -149,75 +99,125 @@ pub enum Instruction { LoadFromDictOrDeref(Arg) = 89, LoadFromDictOrGlobals(Arg) = 90, LoadGlobal(Arg) = 91, - LoadGlobalBuiltin(Arg) = 203, - LoadGlobalModule(Arg) = 204, - LoadLocals = 25, LoadName(Arg) = 92, LoadSuperAttr(Arg) = 93, - LoadSuperAttrAttr(Arg) = 205, - LoadSuperAttrMethod(Arg) = 206, MakeCell(Arg) = 94, - MakeFunction = 26, MapAdd(Arg) = 95, MatchClass(Arg) = 96, - MatchKeys = 27, - MatchMapping = 28, - MatchSequence = 29, - Nop = 30, - PopExcept = 31, PopJumpIfFalse(Arg) = 97, PopJumpIfNone(Arg) = 98, PopJumpIfNotNone(Arg) = 99, PopJumpIfTrue(Arg) = 100, - PopTop = 32, - PushExcInfo = 33, - PushNull = 34, RaiseVarargs(Arg) = 101, Reraise(Arg) = 102, - Reserved = 17, - Resume(Arg) = 149, - ResumeCheck = 207, ReturnConst(Arg) = 103, - ReturnGenerator = 35, - ReturnValue = 36, Send(Arg) = 104, - SendGen(Arg) = 208, - SetupAnnotations = 37, SetAdd(Arg) = 105, SetFunctionAttribute(Arg) = 106, SetUpdate(Arg) = 107, StoreAttr(Arg) = 108, - StoreAttrInstanceValue = 209, - StoreAttrSlot = 210, - StoreAttrWithHint(Arg) = 211, StoreDeref(Arg) = 109, StoreFast(Arg) = 110, StoreFastLoadFast(Arg) = 111, StoreFastStoreFast(Arg) = 112, StoreGlobal(Arg) = 113, StoreName(Arg) = 114, - StoreSlice = 38, - StoreSubscr = 39, + Swap(Arg) = 115, + UnpackEx(Arg) = 116, + UnpackSequence(Arg) = 117, + YieldValue(Arg) = 118, + Resume(Arg) = 149, + BinaryOpAddFloat = 150, + BinaryOpAddInt = 151, + BinaryOpAddUnicode = 152, + BinaryOpMultiplyFloat = 153, + BinaryOpMultiplyInt = 154, + BinaryOpSubtractFloat = 155, + BinaryOpSubtractInt = 156, + BinarySubscrDict = 157, + BinarySubscrGetitem = 158, + BinarySubscrListInt = 159, + BinarySubscrStrInt = 160, + BinarySubscrTupleInt = 161, + CallAllocAndEnterInit(Arg) = 162, + CallBoundMethodExactArgs(Arg) = 163, + CallBoundMethodGeneral(Arg) = 164, + CallBuiltinClass(Arg) = 165, + CallBuiltinFast(Arg) = 166, + CallBuiltinFastWithKeywords(Arg) = 167, + CallBuiltinO(Arg) = 168, + CallIsinstance(Arg) = 169, + CallLen(Arg) = 170, + CallListAppend(Arg) = 171, + CallMethodDescriptorFast(Arg) = 172, + CallMethodDescriptorFastWithKeywords(Arg) = 173, + CallMethodDescriptorNoargs(Arg) = 174, + CallMethodDescriptorO(Arg) = 175, + CallNonPyGeneral(Arg) = 176, + CallPyExactArgs(Arg) = 177, + CallPyGeneral(Arg) = 178, + CallStr1(Arg) = 179, + CallTuple1(Arg) = 180, + CallType1(Arg) = 181, + CompareOpFloat(Arg) = 182, + CompareOpInt(Arg) = 183, + CompareOpStr(Arg) = 184, + ContainsOpDict(Arg) = 185, + ContainsOpSet(Arg) = 186, + ForIterGen(Arg) = 187, + ForIterList(Arg) = 188, + ForIterRange(Arg) = 189, + ForIterTuple(Arg) = 190, + LoadAttrClass(Arg) = 191, + LoadAttrGetattributeOverridden(Arg) = 192, + LoadAttrInstanceValue(Arg) = 193, + LoadAttrMethodLazyDict(Arg) = 194, + LoadAttrMethodNoDict(Arg) = 195, + LoadAttrMethodWithValues(Arg) = 196, + LoadAttrModule(Arg) = 197, + LoadAttrNondescriptorNoDict(Arg) = 198, + LoadAttrNondescriptorWithValues(Arg) = 199, + LoadAttrProperty(Arg) = 200, + LoadAttrSlot(Arg) = 201, + LoadAttrWithHint(Arg) = 202, + LoadGlobalBuiltin(Arg) = 203, + LoadGlobalModule(Arg) = 204, + LoadSuperAttrAttr(Arg) = 205, + LoadSuperAttrMethod(Arg) = 206, + ResumeCheck = 207, + SendGen(Arg) = 208, + StoreAttrInstanceValue = 209, + StoreAttrSlot = 210, + StoreAttrWithHint(Arg) = 211, StoreSubscrDict = 212, StoreSubscrListInt = 213, - Swap(Arg) = 115, - ToBool = 40, ToBoolAlwaysTrue = 214, ToBoolBool = 215, ToBoolInt = 216, ToBoolList = 217, ToBoolNone = 218, ToBoolStr = 219, - UnaryInvert = 41, - UnaryNegative = 42, - UnaryNot = 43, - UnpackEx(Arg) = 116, - UnpackSequence(Arg) = 117, UnpackSequenceList(Arg) = 220, UnpackSequenceTuple(Arg) = 221, UnpackSequenceTwoTuple(Arg) = 222, - WithExceptStart = 44, - YieldValue(Arg) = 118, + InstrumentedResume(Arg) = 236, + InstrumentedEndFor = 237, + InstrumentedEndSend = 238, + InstrumentedReturnValue = 239, + InstrumentedReturnConst(Arg) = 240, + InstrumentedYieldValue(Arg) = 241, + InstrumentedLoadSuperAttr(Arg) = 242, + InstrumentedForIter(Arg) = 243, + InstrumentedCall(Arg) = 244, + InstrumentedCallKw(Arg) = 245, + InstrumentedCallFunctionEx = 246, + InstrumentedInstruction = 247, + InstrumentedJumpForward(Arg) = 248, + InstrumentedJumpBackward(Arg) = 249, + InstrumentedPopJumpIfTrue(Arg) = 250, + InstrumentedPopJumpIfFalse(Arg) = 251, + InstrumentedPopJumpIfNone(Arg) = 252, + InstrumentedPopJumpIfNotNone(Arg) = 253, Jump(Arg) = 256, JumpNoInterrupt(Arg) = 257, LoadClosure(Arg) = 258, @@ -231,3 +231,24 @@ pub enum Instruction { SetupWith = 266, StoreFastMaybeNull(Arg) = 267 } + +impl Instruction { + /// Creates a new Instruction without validating that the `id` is valid before. + #[must_use] + pub unsafe fn new_unchecked(id: u16) -> Self { + unsafe { std::mem::transmute::(id) } + } +} + +impl TryFrom for Instruction { + type Error = crate::marshal::MarshalError; + + fn try_from(id: u16) -> Result { + if matches!(id, 0..=118 | 149..=222 | 236..=253 | 256..=267) { + // SAFETY: we just validated that we have a valid opcode id. + Ok(unsafe { Self::new_unchecked(id) }) + } else { + Err(Self::Error::InvalidBytecode) + } + } +} diff --git a/scripts/gen_instructions.py b/scripts/gen_instructions.py index 526da02eef5..634043a97c6 100755 --- a/scripts/gen_instructions.py +++ b/scripts/gen_instructions.py @@ -67,43 +67,71 @@ def iter_instructions(cls, analysis: analyzer.Analysis): flags=frozenset(flags.split(" | ")), ) + def __lt__(self, other) -> bool: + return self.id < other.id -def gen_by_comment() -> str: - path = pathlib.Path(__file__).absolute().relative_to(ROOT).as_posix() - return textwrap.indent( - f""" -This file is generated by {path} -Do not edit! -""".strip(), - "// ", + +def group_nums(nums: list[int]): + nums = sorted(nums) + start = prev = nums[0] + + for n in nums[1:] + [None]: + if n is None or n != prev + 1: + yield range(start, prev + 1) + start = n + prev = n + + +def gen_valid_ranges(ids: list[int]) -> str: + return " | ".join( + " | ".join(r) if len(r) < 3 else f"{r.start}..={r.stop - 1}" + for r in group_nums(ids) ) def main(): + INDENT = " " * 4 analysis = analyzer.analyze_files([DEFAULT_INPUT]) + instructions = frozenset(Instruction.iter_instructions(analysis)) - instruction_memebers = textwrap.indent( - ",\n".join(ins.as_member() for ins in Instruction.iter_instructions(analysis)), - " " * 4, + members = textwrap.indent( + ",\n".join(ins.as_member() for ins in sorted(instructions)), INDENT ) + valid_ranges = gen_valid_ranges([ins.id for ins in instructions]) - header = "///! Python opcode implementation. Currently aligned with cpython 3.13.7" - - derive = ", ".join(sorted({"Clone", "Copy", "Debug", "PartialEq", "Eq"})) - + script_path = pathlib.Path(__file__).absolute().relative_to(ROOT).as_posix() out = f""" -{header} +///! Python opcode implementation. Currently aligned with cpython 3.13.7 -{gen_by_comment()} +// This file is generated by {script_path} +// Do not edit! /// A Single bytecode instruction. -#[derive({derive})] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] #[repr(u16)] pub enum Instruction {{ -{instruction_memebers} +{members} }} impl Instruction {{ + /// Creates a new Instruction without validating that the `id` is valid before. + #[must_use] + pub unsafe fn new_unchecked(id: u16) -> Self {{ + unsafe {{ std::mem::transmute::(id) }} + }} +}} + +impl TryFrom for Instruction {{ + type Error = crate::marshal::MarshalError; + + fn try_from(id: u16) -> Result {{ + if matches!(id, {valid_ranges}) {{ + // SAFETY: we just validated that we have a valid opcode id. + Ok(unsafe {{ Self::new_unchecked(id) }}) + }} else {{ + Err(Self::Error::InvalidBytecode) + }} + }} }} """.strip() From c7ffa2a0a2e478fd5c29f2655166f864d5323431 Mon Sep 17 00:00:00 2001 From: ShaharNaveh <50263213+ShaharNaveh@users.noreply.github.com> Date: Thu, 25 Sep 2025 18:09:49 +0200 Subject: [PATCH 06/43] Have `is_valid` as a seperate method --- compiler/core/src/instruction.rs | 14 ++++++++++---- scripts/gen_instructions.py | 14 ++++++++++---- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/compiler/core/src/instruction.rs b/compiler/core/src/instruction.rs index 9743ccba589..a27b5d114a8 100644 --- a/compiler/core/src/instruction.rs +++ b/compiler/core/src/instruction.rs @@ -235,18 +235,24 @@ pub enum Instruction { impl Instruction { /// Creates a new Instruction without validating that the `id` is valid before. #[must_use] - pub unsafe fn new_unchecked(id: u16) -> Self { + pub unsafe const fn new_unchecked(id: u16) -> Self { + // SAFETY: Caller responsebility. unsafe { std::mem::transmute::(id) } } + + /// Whether the given ID matches one of the opcode IDs. + #[must_use] + pub const fn is_valid(id: u16) -> bool { + matches!(id, 0..=118 | 149..=222 | 236..=253 | 256..=267) + } } impl TryFrom for Instruction { type Error = crate::marshal::MarshalError; fn try_from(id: u16) -> Result { - if matches!(id, 0..=118 | 149..=222 | 236..=253 | 256..=267) { - // SAFETY: we just validated that we have a valid opcode id. - Ok(unsafe { Self::new_unchecked(id) }) + if Self::is_valid(id) { + Ok(Self::new_unchecked(id)) } else { Err(Self::Error::InvalidBytecode) } diff --git a/scripts/gen_instructions.py b/scripts/gen_instructions.py index 634043a97c6..fc7b1b0c1d8 100755 --- a/scripts/gen_instructions.py +++ b/scripts/gen_instructions.py @@ -116,18 +116,24 @@ def main(): impl Instruction {{ /// Creates a new Instruction without validating that the `id` is valid before. #[must_use] - pub unsafe fn new_unchecked(id: u16) -> Self {{ + pub unsafe const fn new_unchecked(id: u16) -> Self {{ + // SAFETY: Caller responsebility. unsafe {{ std::mem::transmute::(id) }} }} + + /// Whether the given ID matches one of the opcode IDs. + #[must_use] + pub const fn is_valid(id: u16) -> bool {{ + matches!(id, {valid_ranges}) + }} }} impl TryFrom for Instruction {{ type Error = crate::marshal::MarshalError; fn try_from(id: u16) -> Result {{ - if matches!(id, {valid_ranges}) {{ - // SAFETY: we just validated that we have a valid opcode id. - Ok(unsafe {{ Self::new_unchecked(id) }}) + if Self::is_valid(id) {{ + Ok(Self::new_unchecked(id)) }} else {{ Err(Self::Error::InvalidBytecode) }} From f1948c6de35974e8981cbe52ec2bc4232997fe46 Mon Sep 17 00:00:00 2001 From: ShaharNaveh <50263213+ShaharNaveh@users.noreply.github.com> Date: Thu, 25 Sep 2025 18:53:03 +0200 Subject: [PATCH 07/43] Include in tree --- compiler/core/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/core/src/lib.rs b/compiler/core/src/lib.rs index 0ce4a9defb1..b61d509f931 100644 --- a/compiler/core/src/lib.rs +++ b/compiler/core/src/lib.rs @@ -4,6 +4,7 @@ pub mod bytecode; pub mod frozen; pub mod marshal; +pub mod instruction; mod mode; pub use mode::Mode; From 84c7f451621f944f863ec7ad3d6b105f18481036 Mon Sep 17 00:00:00 2001 From: ShaharNaveh <50263213+ShaharNaveh@users.noreply.github.com> Date: Thu, 25 Sep 2025 18:55:58 +0200 Subject: [PATCH 08/43] Impl `has_X` methods --- compiler/core/src/instruction.rs | 273 ++++++++++++++++++++++++++++++- compiler/core/src/lib.rs | 2 +- scripts/gen_instructions.py | 49 +++++- 3 files changed, 317 insertions(+), 7 deletions(-) diff --git a/compiler/core/src/instruction.rs b/compiler/core/src/instruction.rs index a27b5d114a8..6e71f722e10 100644 --- a/compiler/core/src/instruction.rs +++ b/compiler/core/src/instruction.rs @@ -229,13 +229,13 @@ pub enum Instruction { SetupCleanup = 264, SetupFinally = 265, SetupWith = 266, - StoreFastMaybeNull(Arg) = 267 + StoreFastMaybeNull(Arg) = 267, } impl Instruction { /// Creates a new Instruction without validating that the `id` is valid before. #[must_use] - pub unsafe const fn new_unchecked(id: u16) -> Self { + pub const unsafe fn new_unchecked(id: u16) -> Self { // SAFETY: Caller responsebility. unsafe { std::mem::transmute::(id) } } @@ -245,6 +245,275 @@ impl Instruction { pub const fn is_valid(id: u16) -> bool { matches!(id, 0..=118 | 149..=222 | 236..=253 | 256..=267) } + + /// Whether opcode had 'HAS_ARG_FLAG' set. + #[must_use] + pub const fn has_arg(&self) -> bool { + matches!( + self, + BinaryOp(_) + | BuildConstKeyMap(_) + | BuildList(_) + | BuildMap(_) + | BuildSet(_) + | BuildSlice(_) + | BuildString(_) + | BuildTuple(_) + | Call(_) + | CallFunctionEx(_) + | CallIntrinsic1(_) + | CallIntrinsic2(_) + | CallKw(_) + | CompareOp(_) + | ContainsOp(_) + | ConvertValue(_) + | Copy(_) + | CopyFreeVars(_) + | DeleteAttr(_) + | DeleteDeref(_) + | DeleteFast(_) + | DeleteGlobal(_) + | DeleteName(_) + | DictMerge(_) + | DictUpdate(_) + | EnterExecutor(_) + | ExtendedArg(_) + | ForIter(_) + | GetAwaitable(_) + | ImportFrom(_) + | ImportName(_) + | IsOp(_) + | JumpBackward(_) + | JumpBackwardNoInterrupt(_) + | JumpForward(_) + | ListAppend(_) + | ListExtend(_) + | LoadAttr(_) + | LoadConst(_) + | LoadDeref(_) + | LoadFast(_) + | LoadFastAndClear(_) + | LoadFastCheck(_) + | LoadFastLoadFast(_) + | LoadFromDictOrDeref(_) + | LoadFromDictOrGlobals(_) + | LoadGlobal(_) + | LoadName(_) + | LoadSuperAttr(_) + | MakeCell(_) + | MapAdd(_) + | MatchClass(_) + | PopJumpIfFalse(_) + | PopJumpIfNone(_) + | PopJumpIfNotNone(_) + | PopJumpIfTrue(_) + | RaiseVarargs(_) + | Reraise(_) + | ReturnConst(_) + | Send(_) + | SetAdd(_) + | SetFunctionAttribute(_) + | SetUpdate(_) + | StoreAttr(_) + | StoreDeref(_) + | StoreFast(_) + | StoreFastLoadFast(_) + | StoreFastStoreFast(_) + | StoreGlobal(_) + | StoreName(_) + | Swap(_) + | UnpackEx(_) + | UnpackSequence(_) + | YieldValue(_) + | Resume(_) + | CallAllocAndEnterInit(_) + | CallBoundMethodExactArgs(_) + | CallBoundMethodGeneral(_) + | CallBuiltinClass(_) + | CallBuiltinFast(_) + | CallBuiltinFastWithKeywords(_) + | CallBuiltinO(_) + | CallIsinstance(_) + | CallLen(_) + | CallListAppend(_) + | CallMethodDescriptorFast(_) + | CallMethodDescriptorFastWithKeywords(_) + | CallMethodDescriptorNoargs(_) + | CallMethodDescriptorO(_) + | CallNonPyGeneral(_) + | CallPyExactArgs(_) + | CallPyGeneral(_) + | CallStr1(_) + | CallTuple1(_) + | CallType1(_) + | CompareOpFloat(_) + | CompareOpInt(_) + | CompareOpStr(_) + | ContainsOpDict(_) + | ContainsOpSet(_) + | ForIterGen(_) + | ForIterList(_) + | ForIterRange(_) + | ForIterTuple(_) + | LoadAttrClass(_) + | LoadAttrGetattributeOverridden(_) + | LoadAttrInstanceValue(_) + | LoadAttrMethodLazyDict(_) + | LoadAttrMethodNoDict(_) + | LoadAttrMethodWithValues(_) + | LoadAttrModule(_) + | LoadAttrNondescriptorNoDict(_) + | LoadAttrNondescriptorWithValues(_) + | LoadAttrProperty(_) + | LoadAttrSlot(_) + | LoadAttrWithHint(_) + | LoadGlobalBuiltin(_) + | LoadGlobalModule(_) + | LoadSuperAttrAttr(_) + | LoadSuperAttrMethod(_) + | SendGen(_) + | StoreAttrWithHint(_) + | UnpackSequenceList(_) + | UnpackSequenceTuple(_) + | UnpackSequenceTwoTuple(_) + | InstrumentedResume(_) + | InstrumentedReturnConst(_) + | InstrumentedYieldValue(_) + | InstrumentedLoadSuperAttr(_) + | InstrumentedForIter(_) + | InstrumentedCall(_) + | InstrumentedCallKw(_) + | InstrumentedJumpForward(_) + | InstrumentedJumpBackward(_) + | InstrumentedPopJumpIfTrue(_) + | InstrumentedPopJumpIfFalse(_) + | InstrumentedPopJumpIfNone(_) + | InstrumentedPopJumpIfNotNone(_) + | Jump(_) + | JumpNoInterrupt(_) + | LoadClosure(_) + | LoadMethod(_) + | LoadSuperMethod(_) + | LoadZeroSuperAttr(_) + | LoadZeroSuperMethod(_) + | SetupCleanup + | SetupFinally + | SetupWith + | StoreFastMaybeNull(_) + ) + } + + /// Whether opcode had 'HAS_CONST_FLAG' set. + #[must_use] + pub const fn has_const(&self) -> bool { + matches!( + self, + LoadConst(_) | ReturnConst(_) | InstrumentedReturnConst(_) + ) + } + + /// Whether opcode had 'HAS_NAME_FLAG' set. + #[must_use] + pub const fn has_name(&self) -> bool { + matches!( + self, + DeleteAttr(_) + | DeleteGlobal(_) + | DeleteName(_) + | ImportFrom(_) + | ImportName(_) + | LoadAttr(_) + | LoadFromDictOrGlobals(_) + | LoadGlobal(_) + | LoadName(_) + | LoadSuperAttr(_) + | StoreAttr(_) + | StoreGlobal(_) + | StoreName(_) + | LoadAttrGetattributeOverridden(_) + | LoadAttrWithHint(_) + | LoadSuperAttrAttr(_) + | LoadSuperAttrMethod(_) + | StoreAttrWithHint(_) + | LoadMethod(_) + | LoadSuperMethod(_) + | LoadZeroSuperAttr(_) + | LoadZeroSuperMethod(_) + ) + } + + /// Whether opcode had 'HAS_JUMP_FLAG' set. + #[must_use] + pub const fn has_jump(&self) -> bool { + matches!( + self, + ForIter(_) + | JumpBackward(_) + | JumpBackwardNoInterrupt(_) + | JumpForward(_) + | PopJumpIfFalse(_) + | PopJumpIfNone(_) + | PopJumpIfNotNone(_) + | PopJumpIfTrue(_) + | Send(_) + | ForIterList(_) + | ForIterRange(_) + | ForIterTuple(_) + | Jump(_) + | JumpNoInterrupt(_) + ) + } + + /// Whether opcode had 'HAS_FREE_FLAG' set. + #[must_use] + pub const fn has_free(&self) -> bool { + matches!( + self, + DeleteDeref(_) | LoadDeref(_) | LoadFromDictOrDeref(_) | MakeCell(_) | StoreDeref(_) + ) + } + + /// Whether opcode had 'HAS_LOCAL_FLAG' set. + #[must_use] + pub const fn has_local(&self) -> bool { + matches!( + self, + BinaryOpInplaceAddUnicode + | DeleteFast(_) + | LoadFast(_) + | LoadFastAndClear(_) + | LoadFastCheck(_) + | LoadFastLoadFast(_) + | StoreFast(_) + | StoreFastLoadFast(_) + | StoreFastStoreFast(_) + | LoadClosure(_) + | StoreFastMaybeNull(_) + ) + } + + /// Whether opcode had 'HAS_PURE_FLAG' set. + #[must_use] + pub const fn has_exc(&self) -> bool { + matches!( + self, + EndFor + | EndSend + | Nop + | PopTop + | PushNull + | UnaryNot + | Copy(_) + | LoadConst(_) + | LoadFast(_) + | Swap(_) + | LoadClosure(_) + | PopBlock + | SetupCleanup + | SetupFinally + | SetupWith + ) + } } impl TryFrom for Instruction { diff --git a/compiler/core/src/lib.rs b/compiler/core/src/lib.rs index b61d509f931..0c7802f1c84 100644 --- a/compiler/core/src/lib.rs +++ b/compiler/core/src/lib.rs @@ -3,8 +3,8 @@ pub mod bytecode; pub mod frozen; -pub mod marshal; pub mod instruction; +pub mod marshal; mod mode; pub use mode::Mode; diff --git a/scripts/gen_instructions.py b/scripts/gen_instructions.py index fc7b1b0c1d8..33946687692 100755 --- a/scripts/gen_instructions.py +++ b/scripts/gen_instructions.py @@ -1,9 +1,13 @@ #!/usr/bin/env python import pathlib +import subprocess # for `cargo fmt` import sys import textwrap import typing +if typing.TYPE_CHECKING: + from collections.abc import Iterator + CPYTHON_PATH = ( pathlib.Path(__file__).parents[2] / "cpython" # Local filesystem path of cpython ) @@ -37,8 +41,14 @@ def as_member(self) -> str: out += f" = {self.id}" return out + def as_matched(self) -> str: + out = self.name + if self.has_oparg: + out += "(_)" + return out + @classmethod - def iter_instructions(cls, analysis: analyzer.Analysis): + def iter_instructions(cls, analysis: analyzer.Analysis) -> "Iterator[typing.Self]": """ Adapted from https://github.com/python/cpython/blob/bcee1c322115c581da27600f2ae55e5439c027eb/Tools/cases_generator/opcode_metadata_generator.py#L186-L213 """ @@ -71,7 +81,7 @@ def __lt__(self, other) -> bool: return self.id < other.id -def group_nums(nums: list[int]): +def group_nums(nums: list[int]) -> "Iterator[range]": nums = sorted(nums) start = prev = nums[0] @@ -89,17 +99,42 @@ def gen_valid_ranges(ids: list[int]) -> str: ) +def gen_has_attr_fn( + instructions: frozenset[Instruction], + *, + attrs: tuple[str, ...] = ("arg", "const", "name", "jump", "free", "local", "exc"), +) -> "Iterator[str]": + for attr in attrs: + flag_name = "pure" if attr == "exc" else attr + flag = f"has_{flag_name}_flag".upper() + matches = " | ".join( + ins.as_matched() for ins in sorted(instructions) if flag in ins.flags + ) + yield f""" +/// Whether opcode had '{flag}' set. +#[must_use] +pub const fn has_{attr}(&self) -> bool {{ + matches!(self, {matches}) +}} +""".strip() + + def main(): INDENT = " " * 4 + script_path = pathlib.Path(__file__).absolute().relative_to(ROOT).as_posix() + analysis = analyzer.analyze_files([DEFAULT_INPUT]) instructions = frozenset(Instruction.iter_instructions(analysis)) + has_attr_methods = textwrap.indent( + "\n\n".join(gen_has_attr_fn(instructions)), INDENT + ) + members = textwrap.indent( ",\n".join(ins.as_member() for ins in sorted(instructions)), INDENT ) valid_ranges = gen_valid_ranges([ins.id for ins in instructions]) - script_path = pathlib.Path(__file__).absolute().relative_to(ROOT).as_posix() out = f""" ///! Python opcode implementation. Currently aligned with cpython 3.13.7 @@ -116,7 +151,7 @@ def main(): impl Instruction {{ /// Creates a new Instruction without validating that the `id` is valid before. #[must_use] - pub unsafe const fn new_unchecked(id: u16) -> Self {{ + pub const unsafe fn new_unchecked(id: u16) -> Self {{ // SAFETY: Caller responsebility. unsafe {{ std::mem::transmute::(id) }} }} @@ -126,6 +161,8 @@ def main(): pub const fn is_valid(id: u16) -> bool {{ matches!(id, {valid_ranges}) }} + +{has_attr_methods} }} impl TryFrom for Instruction {{ @@ -143,6 +180,10 @@ def main(): OUT_PATH.write_text(out + "\n") + print("DONE") + print("Running `cargo fmt`") + subprocess.run(["cargo", "fmt"], cwd=ROOT) + if __name__ == "__main__": main() From 9adf90881860513d47d000afef058b533a77c410 Mon Sep 17 00:00:00 2001 From: ShaharNaveh <50263213+ShaharNaveh@users.noreply.github.com> Date: Thu, 25 Sep 2025 19:02:21 +0200 Subject: [PATCH 09/43] is_pseudo --- Cargo.lock | 95 +++++++------------------------- compiler/core/src/instruction.rs | 20 +++++++ scripts/gen_instructions.py | 19 ++++++- 3 files changed, 57 insertions(+), 77 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 88146885d85..1bd7b0e577d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -400,20 +400,6 @@ dependencies = [ "static_assertions", ] -[[package]] -name = "compact_str" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb1325a1cece981e8a296ab8f0f9b63ae357bd0784a9faaf548cc7b480707a" -dependencies = [ - "castaway", - "cfg-if", - "itoa", - "rustversion", - "ryu", - "static_assertions", -] - [[package]] name = "console" version = "0.15.11" @@ -2156,34 +2142,16 @@ source = "git+https://github.com/astral-sh/ruff.git?tag=0.11.0#2cd25ef6410fb5fca dependencies = [ "aho-corasick", "bitflags 2.9.4", - "compact_str 0.8.1", + "compact_str", "is-macro", "itertools 0.14.0", "memchr", - "ruff_python_trivia 0.0.0 (git+https://github.com/astral-sh/ruff.git?tag=0.11.0)", - "ruff_source_file 0.0.0 (git+https://github.com/astral-sh/ruff.git?tag=0.11.0)", - "ruff_text_size 0.0.0 (git+https://github.com/astral-sh/ruff.git?tag=0.11.0)", + "ruff_python_trivia", + "ruff_source_file", + "ruff_text_size", "rustc-hash", ] -[[package]] -name = "ruff_python_ast" -version = "0.0.0" -source = "git+https://github.com/astral-sh/ruff.git?tag=0.13.1#706be0a6e7e09936511198f2ff8982915520d138" -dependencies = [ - "aho-corasick", - "bitflags 2.9.4", - "compact_str 0.9.0", - "is-macro", - "itertools 0.14.0", - "memchr", - "ruff_python_trivia 0.0.0 (git+https://github.com/astral-sh/ruff.git?tag=0.13.1)", - "ruff_source_file 0.0.0 (git+https://github.com/astral-sh/ruff.git?tag=0.13.1)", - "ruff_text_size 0.0.0 (git+https://github.com/astral-sh/ruff.git?tag=0.13.1)", - "rustc-hash", - "thiserror 2.0.16", -] - [[package]] name = "ruff_python_parser" version = "0.0.0" @@ -2191,11 +2159,11 @@ source = "git+https://github.com/astral-sh/ruff.git?tag=0.11.0#2cd25ef6410fb5fca dependencies = [ "bitflags 2.9.4", "bstr", - "compact_str 0.8.1", + "compact_str", "memchr", - "ruff_python_ast 0.0.0 (git+https://github.com/astral-sh/ruff.git?tag=0.11.0)", - "ruff_python_trivia 0.0.0 (git+https://github.com/astral-sh/ruff.git?tag=0.11.0)", - "ruff_text_size 0.0.0 (git+https://github.com/astral-sh/ruff.git?tag=0.11.0)", + "ruff_python_ast", + "ruff_python_trivia", + "ruff_text_size", "rustc-hash", "static_assertions", "unicode-ident", @@ -2209,19 +2177,8 @@ version = "0.0.0" source = "git+https://github.com/astral-sh/ruff.git?tag=0.11.0#2cd25ef6410fb5fca96af1578728a3d828d2d53a" dependencies = [ "itertools 0.14.0", - "ruff_source_file 0.0.0 (git+https://github.com/astral-sh/ruff.git?tag=0.11.0)", - "ruff_text_size 0.0.0 (git+https://github.com/astral-sh/ruff.git?tag=0.11.0)", - "unicode-ident", -] - -[[package]] -name = "ruff_python_trivia" -version = "0.0.0" -source = "git+https://github.com/astral-sh/ruff.git?tag=0.13.1#706be0a6e7e09936511198f2ff8982915520d138" -dependencies = [ - "itertools 0.14.0", - "ruff_source_file 0.0.0 (git+https://github.com/astral-sh/ruff.git?tag=0.13.1)", - "ruff_text_size 0.0.0 (git+https://github.com/astral-sh/ruff.git?tag=0.13.1)", + "ruff_source_file", + "ruff_text_size", "unicode-ident", ] @@ -2231,16 +2188,7 @@ version = "0.0.0" source = "git+https://github.com/astral-sh/ruff.git?tag=0.11.0#2cd25ef6410fb5fca96af1578728a3d828d2d53a" dependencies = [ "memchr", - "ruff_text_size 0.0.0 (git+https://github.com/astral-sh/ruff.git?tag=0.11.0)", -] - -[[package]] -name = "ruff_source_file" -version = "0.0.0" -source = "git+https://github.com/astral-sh/ruff.git?tag=0.13.1#706be0a6e7e09936511198f2ff8982915520d138" -dependencies = [ - "memchr", - "ruff_text_size 0.0.0 (git+https://github.com/astral-sh/ruff.git?tag=0.13.1)", + "ruff_text_size", ] [[package]] @@ -2248,11 +2196,6 @@ name = "ruff_text_size" version = "0.0.0" source = "git+https://github.com/astral-sh/ruff.git?tag=0.11.0#2cd25ef6410fb5fca96af1578728a3d828d2d53a" -[[package]] -name = "ruff_text_size" -version = "0.0.0" -source = "git+https://github.com/astral-sh/ruff.git?tag=0.13.1#706be0a6e7e09936511198f2ff8982915520d138" - [[package]] name = "rustc-hash" version = "2.1.1" @@ -2309,9 +2252,9 @@ dependencies = [ "memchr", "num-complex", "num-traits", - "ruff_python_ast 0.0.0 (git+https://github.com/astral-sh/ruff.git?tag=0.13.1)", + "ruff_python_ast", "ruff_python_parser", - "ruff_text_size 0.0.0 (git+https://github.com/astral-sh/ruff.git?tag=0.11.0)", + "ruff_text_size", "rustpython-compiler-core", "rustpython-literal", "rustpython-wtf8", @@ -2350,10 +2293,10 @@ dependencies = [ name = "rustpython-compiler" version = "0.4.0" dependencies = [ - "ruff_python_ast 0.0.0 (git+https://github.com/astral-sh/ruff.git?tag=0.13.1)", + "ruff_python_ast", "ruff_python_parser", - "ruff_source_file 0.0.0 (git+https://github.com/astral-sh/ruff.git?tag=0.11.0)", - "ruff_text_size 0.0.0 (git+https://github.com/astral-sh/ruff.git?tag=0.11.0)", + "ruff_source_file", + "ruff_text_size", "rustpython-codegen", "rustpython-compiler-core", "thiserror 2.0.16", @@ -2368,7 +2311,7 @@ dependencies = [ "lz4_flex", "malachite-bigint", "num-complex", - "ruff_source_file 0.0.0 (git+https://github.com/astral-sh/ruff.git?tag=0.11.0)", + "ruff_source_file", "rustpython-wtf8", ] @@ -2570,9 +2513,9 @@ dependencies = [ "parking_lot", "paste", "result-like", - "ruff_python_ast 0.0.0 (git+https://github.com/astral-sh/ruff.git?tag=0.13.1)", + "ruff_python_ast", "ruff_python_parser", - "ruff_text_size 0.0.0 (git+https://github.com/astral-sh/ruff.git?tag=0.11.0)", + "ruff_text_size", "rustix", "rustpython-codegen", "rustpython-common", diff --git a/compiler/core/src/instruction.rs b/compiler/core/src/instruction.rs index 6e71f722e10..43cb7cdd177 100644 --- a/compiler/core/src/instruction.rs +++ b/compiler/core/src/instruction.rs @@ -514,6 +514,26 @@ impl Instruction { | SetupWith ) } + + /// Whether opcode is pseudo. + #[must_use] + pub const fn is_pseudo(&self) -> bool { + matches!( + self, + Jump(_) + | JumpNoInterrupt(_) + | LoadClosure(_) + | LoadMethod(_) + | LoadSuperMethod(_) + | LoadZeroSuperAttr(_) + | LoadZeroSuperMethod(_) + | PopBlock + | SetupCleanup + | SetupFinally + | SetupWith + | StoreFastMaybeNull(_) + ) + } } impl TryFrom for Instruction { diff --git a/scripts/gen_instructions.py b/scripts/gen_instructions.py index 33946687692..892d5984a53 100755 --- a/scripts/gen_instructions.py +++ b/scripts/gen_instructions.py @@ -29,6 +29,7 @@ class Instruction(typing.NamedTuple): id: int flags: frozenset[str] has_oparg: bool + is_pseudo: bool = False @property def name(self) -> str: @@ -75,6 +76,7 @@ def iter_instructions(cls, analysis: analyzer.Analysis) -> "Iterator[typing.Self id=opmap[name], has_oparg=pseudo.properties.oparg, flags=frozenset(flags.split(" | ")), + is_pseudo=True, ) def __lt__(self, other) -> bool: @@ -99,6 +101,19 @@ def gen_valid_ranges(ids: list[int]) -> str: ) +def build_is_pseudo_fn(instructions: frozenset[Instruction]): + matches = " | ".join( + ins.as_matched() for ins in sorted(instructions) if ins.is_pseudo + ) + return f""" +/// Whether opcode is pseudo. +#[must_use] +pub const fn is_pseudo(&self) -> bool {{ + matches!(self, {matches}) +}} +""".strip() + + def gen_has_attr_fn( instructions: frozenset[Instruction], *, @@ -129,7 +144,7 @@ def main(): has_attr_methods = textwrap.indent( "\n\n".join(gen_has_attr_fn(instructions)), INDENT ) - + is_pseudo_fn = textwrap.indent(build_is_pseudo_fn(instructions), INDENT) members = textwrap.indent( ",\n".join(ins.as_member() for ins in sorted(instructions)), INDENT ) @@ -163,6 +178,8 @@ def main(): }} {has_attr_methods} + +{is_pseudo_fn} }} impl TryFrom for Instruction {{ From 99ed360c282d203649e0249587d1d88dc7f1a7b5 Mon Sep 17 00:00:00 2001 From: ShaharNaveh <50263213+ShaharNaveh@users.noreply.github.com> Date: Thu, 25 Sep 2025 20:34:27 +0200 Subject: [PATCH 10/43] Set `Self::` --- compiler/core/src/instruction.rs | 454 ++++++++++++++++--------------- scripts/gen_instructions.py | 2 +- 2 files changed, 230 insertions(+), 226 deletions(-) diff --git a/compiler/core/src/instruction.rs b/compiler/core/src/instruction.rs index 43cb7cdd177..c749f3c995e 100644 --- a/compiler/core/src/instruction.rs +++ b/compiler/core/src/instruction.rs @@ -251,155 +251,155 @@ impl Instruction { pub const fn has_arg(&self) -> bool { matches!( self, - BinaryOp(_) - | BuildConstKeyMap(_) - | BuildList(_) - | BuildMap(_) - | BuildSet(_) - | BuildSlice(_) - | BuildString(_) - | BuildTuple(_) - | Call(_) - | CallFunctionEx(_) - | CallIntrinsic1(_) - | CallIntrinsic2(_) - | CallKw(_) - | CompareOp(_) - | ContainsOp(_) - | ConvertValue(_) - | Copy(_) - | CopyFreeVars(_) - | DeleteAttr(_) - | DeleteDeref(_) - | DeleteFast(_) - | DeleteGlobal(_) - | DeleteName(_) - | DictMerge(_) - | DictUpdate(_) - | EnterExecutor(_) - | ExtendedArg(_) - | ForIter(_) - | GetAwaitable(_) - | ImportFrom(_) - | ImportName(_) - | IsOp(_) - | JumpBackward(_) - | JumpBackwardNoInterrupt(_) - | JumpForward(_) - | ListAppend(_) - | ListExtend(_) - | LoadAttr(_) - | LoadConst(_) - | LoadDeref(_) - | LoadFast(_) - | LoadFastAndClear(_) - | LoadFastCheck(_) - | LoadFastLoadFast(_) - | LoadFromDictOrDeref(_) - | LoadFromDictOrGlobals(_) - | LoadGlobal(_) - | LoadName(_) - | LoadSuperAttr(_) - | MakeCell(_) - | MapAdd(_) - | MatchClass(_) - | PopJumpIfFalse(_) - | PopJumpIfNone(_) - | PopJumpIfNotNone(_) - | PopJumpIfTrue(_) - | RaiseVarargs(_) - | Reraise(_) - | ReturnConst(_) - | Send(_) - | SetAdd(_) - | SetFunctionAttribute(_) - | SetUpdate(_) - | StoreAttr(_) - | StoreDeref(_) - | StoreFast(_) - | StoreFastLoadFast(_) - | StoreFastStoreFast(_) - | StoreGlobal(_) - | StoreName(_) - | Swap(_) - | UnpackEx(_) - | UnpackSequence(_) - | YieldValue(_) - | Resume(_) - | CallAllocAndEnterInit(_) - | CallBoundMethodExactArgs(_) - | CallBoundMethodGeneral(_) - | CallBuiltinClass(_) - | CallBuiltinFast(_) - | CallBuiltinFastWithKeywords(_) - | CallBuiltinO(_) - | CallIsinstance(_) - | CallLen(_) - | CallListAppend(_) - | CallMethodDescriptorFast(_) - | CallMethodDescriptorFastWithKeywords(_) - | CallMethodDescriptorNoargs(_) - | CallMethodDescriptorO(_) - | CallNonPyGeneral(_) - | CallPyExactArgs(_) - | CallPyGeneral(_) - | CallStr1(_) - | CallTuple1(_) - | CallType1(_) - | CompareOpFloat(_) - | CompareOpInt(_) - | CompareOpStr(_) - | ContainsOpDict(_) - | ContainsOpSet(_) - | ForIterGen(_) - | ForIterList(_) - | ForIterRange(_) - | ForIterTuple(_) - | LoadAttrClass(_) - | LoadAttrGetattributeOverridden(_) - | LoadAttrInstanceValue(_) - | LoadAttrMethodLazyDict(_) - | LoadAttrMethodNoDict(_) - | LoadAttrMethodWithValues(_) - | LoadAttrModule(_) - | LoadAttrNondescriptorNoDict(_) - | LoadAttrNondescriptorWithValues(_) - | LoadAttrProperty(_) - | LoadAttrSlot(_) - | LoadAttrWithHint(_) - | LoadGlobalBuiltin(_) - | LoadGlobalModule(_) - | LoadSuperAttrAttr(_) - | LoadSuperAttrMethod(_) - | SendGen(_) - | StoreAttrWithHint(_) - | UnpackSequenceList(_) - | UnpackSequenceTuple(_) - | UnpackSequenceTwoTuple(_) - | InstrumentedResume(_) - | InstrumentedReturnConst(_) - | InstrumentedYieldValue(_) - | InstrumentedLoadSuperAttr(_) - | InstrumentedForIter(_) - | InstrumentedCall(_) - | InstrumentedCallKw(_) - | InstrumentedJumpForward(_) - | InstrumentedJumpBackward(_) - | InstrumentedPopJumpIfTrue(_) - | InstrumentedPopJumpIfFalse(_) - | InstrumentedPopJumpIfNone(_) - | InstrumentedPopJumpIfNotNone(_) - | Jump(_) - | JumpNoInterrupt(_) - | LoadClosure(_) - | LoadMethod(_) - | LoadSuperMethod(_) - | LoadZeroSuperAttr(_) - | LoadZeroSuperMethod(_) - | SetupCleanup - | SetupFinally - | SetupWith - | StoreFastMaybeNull(_) + Self::BinaryOp(_) + | Self::BuildConstKeyMap(_) + | Self::BuildList(_) + | Self::BuildMap(_) + | Self::BuildSet(_) + | Self::BuildSlice(_) + | Self::BuildString(_) + | Self::BuildTuple(_) + | Self::Call(_) + | Self::CallFunctionEx(_) + | Self::CallIntrinsic1(_) + | Self::CallIntrinsic2(_) + | Self::CallKw(_) + | Self::CompareOp(_) + | Self::ContainsOp(_) + | Self::ConvertValue(_) + | Self::Copy(_) + | Self::CopyFreeVars(_) + | Self::DeleteAttr(_) + | Self::DeleteDeref(_) + | Self::DeleteFast(_) + | Self::DeleteGlobal(_) + | Self::DeleteName(_) + | Self::DictMerge(_) + | Self::DictUpdate(_) + | Self::EnterExecutor(_) + | Self::ExtendedArg(_) + | Self::ForIter(_) + | Self::GetAwaitable(_) + | Self::ImportFrom(_) + | Self::ImportName(_) + | Self::IsOp(_) + | Self::JumpBackward(_) + | Self::JumpBackwardNoInterrupt(_) + | Self::JumpForward(_) + | Self::ListAppend(_) + | Self::ListExtend(_) + | Self::LoadAttr(_) + | Self::LoadConst(_) + | Self::LoadDeref(_) + | Self::LoadFast(_) + | Self::LoadFastAndClear(_) + | Self::LoadFastCheck(_) + | Self::LoadFastLoadFast(_) + | Self::LoadFromDictOrDeref(_) + | Self::LoadFromDictOrGlobals(_) + | Self::LoadGlobal(_) + | Self::LoadName(_) + | Self::LoadSuperAttr(_) + | Self::MakeCell(_) + | Self::MapAdd(_) + | Self::MatchClass(_) + | Self::PopJumpIfFalse(_) + | Self::PopJumpIfNone(_) + | Self::PopJumpIfNotNone(_) + | Self::PopJumpIfTrue(_) + | Self::RaiseVarargs(_) + | Self::Reraise(_) + | Self::ReturnConst(_) + | Self::Send(_) + | Self::SetAdd(_) + | Self::SetFunctionAttribute(_) + | Self::SetUpdate(_) + | Self::StoreAttr(_) + | Self::StoreDeref(_) + | Self::StoreFast(_) + | Self::StoreFastLoadFast(_) + | Self::StoreFastStoreFast(_) + | Self::StoreGlobal(_) + | Self::StoreName(_) + | Self::Swap(_) + | Self::UnpackEx(_) + | Self::UnpackSequence(_) + | Self::YieldValue(_) + | Self::Resume(_) + | Self::CallAllocAndEnterInit(_) + | Self::CallBoundMethodExactArgs(_) + | Self::CallBoundMethodGeneral(_) + | Self::CallBuiltinClass(_) + | Self::CallBuiltinFast(_) + | Self::CallBuiltinFastWithKeywords(_) + | Self::CallBuiltinO(_) + | Self::CallIsinstance(_) + | Self::CallLen(_) + | Self::CallListAppend(_) + | Self::CallMethodDescriptorFast(_) + | Self::CallMethodDescriptorFastWithKeywords(_) + | Self::CallMethodDescriptorNoargs(_) + | Self::CallMethodDescriptorO(_) + | Self::CallNonPyGeneral(_) + | Self::CallPyExactArgs(_) + | Self::CallPyGeneral(_) + | Self::CallStr1(_) + | Self::CallTuple1(_) + | Self::CallType1(_) + | Self::CompareOpFloat(_) + | Self::CompareOpInt(_) + | Self::CompareOpStr(_) + | Self::ContainsOpDict(_) + | Self::ContainsOpSet(_) + | Self::ForIterGen(_) + | Self::ForIterList(_) + | Self::ForIterRange(_) + | Self::ForIterTuple(_) + | Self::LoadAttrClass(_) + | Self::LoadAttrGetattributeOverridden(_) + | Self::LoadAttrInstanceValue(_) + | Self::LoadAttrMethodLazyDict(_) + | Self::LoadAttrMethodNoDict(_) + | Self::LoadAttrMethodWithValues(_) + | Self::LoadAttrModule(_) + | Self::LoadAttrNondescriptorNoDict(_) + | Self::LoadAttrNondescriptorWithValues(_) + | Self::LoadAttrProperty(_) + | Self::LoadAttrSlot(_) + | Self::LoadAttrWithHint(_) + | Self::LoadGlobalBuiltin(_) + | Self::LoadGlobalModule(_) + | Self::LoadSuperAttrAttr(_) + | Self::LoadSuperAttrMethod(_) + | Self::SendGen(_) + | Self::StoreAttrWithHint(_) + | Self::UnpackSequenceList(_) + | Self::UnpackSequenceTuple(_) + | Self::UnpackSequenceTwoTuple(_) + | Self::InstrumentedResume(_) + | Self::InstrumentedReturnConst(_) + | Self::InstrumentedYieldValue(_) + | Self::InstrumentedLoadSuperAttr(_) + | Self::InstrumentedForIter(_) + | Self::InstrumentedCall(_) + | Self::InstrumentedCallKw(_) + | Self::InstrumentedJumpForward(_) + | Self::InstrumentedJumpBackward(_) + | Self::InstrumentedPopJumpIfTrue(_) + | Self::InstrumentedPopJumpIfFalse(_) + | Self::InstrumentedPopJumpIfNone(_) + | Self::InstrumentedPopJumpIfNotNone(_) + | Self::Jump(_) + | Self::JumpNoInterrupt(_) + | Self::LoadClosure(_) + | Self::LoadMethod(_) + | Self::LoadSuperMethod(_) + | Self::LoadZeroSuperAttr(_) + | Self::LoadZeroSuperMethod(_) + | Self::SetupCleanup + | Self::SetupFinally + | Self::SetupWith + | Self::StoreFastMaybeNull(_) ) } @@ -408,7 +408,7 @@ impl Instruction { pub const fn has_const(&self) -> bool { matches!( self, - LoadConst(_) | ReturnConst(_) | InstrumentedReturnConst(_) + Self::LoadConst(_) | Self::ReturnConst(_) | Self::InstrumentedReturnConst(_) ) } @@ -417,28 +417,28 @@ impl Instruction { pub const fn has_name(&self) -> bool { matches!( self, - DeleteAttr(_) - | DeleteGlobal(_) - | DeleteName(_) - | ImportFrom(_) - | ImportName(_) - | LoadAttr(_) - | LoadFromDictOrGlobals(_) - | LoadGlobal(_) - | LoadName(_) - | LoadSuperAttr(_) - | StoreAttr(_) - | StoreGlobal(_) - | StoreName(_) - | LoadAttrGetattributeOverridden(_) - | LoadAttrWithHint(_) - | LoadSuperAttrAttr(_) - | LoadSuperAttrMethod(_) - | StoreAttrWithHint(_) - | LoadMethod(_) - | LoadSuperMethod(_) - | LoadZeroSuperAttr(_) - | LoadZeroSuperMethod(_) + Self::DeleteAttr(_) + | Self::DeleteGlobal(_) + | Self::DeleteName(_) + | Self::ImportFrom(_) + | Self::ImportName(_) + | Self::LoadAttr(_) + | Self::LoadFromDictOrGlobals(_) + | Self::LoadGlobal(_) + | Self::LoadName(_) + | Self::LoadSuperAttr(_) + | Self::StoreAttr(_) + | Self::StoreGlobal(_) + | Self::StoreName(_) + | Self::LoadAttrGetattributeOverridden(_) + | Self::LoadAttrWithHint(_) + | Self::LoadSuperAttrAttr(_) + | Self::LoadSuperAttrMethod(_) + | Self::StoreAttrWithHint(_) + | Self::LoadMethod(_) + | Self::LoadSuperMethod(_) + | Self::LoadZeroSuperAttr(_) + | Self::LoadZeroSuperMethod(_) ) } @@ -447,20 +447,20 @@ impl Instruction { pub const fn has_jump(&self) -> bool { matches!( self, - ForIter(_) - | JumpBackward(_) - | JumpBackwardNoInterrupt(_) - | JumpForward(_) - | PopJumpIfFalse(_) - | PopJumpIfNone(_) - | PopJumpIfNotNone(_) - | PopJumpIfTrue(_) - | Send(_) - | ForIterList(_) - | ForIterRange(_) - | ForIterTuple(_) - | Jump(_) - | JumpNoInterrupt(_) + Self::ForIter(_) + | Self::JumpBackward(_) + | Self::JumpBackwardNoInterrupt(_) + | Self::JumpForward(_) + | Self::PopJumpIfFalse(_) + | Self::PopJumpIfNone(_) + | Self::PopJumpIfNotNone(_) + | Self::PopJumpIfTrue(_) + | Self::Send(_) + | Self::ForIterList(_) + | Self::ForIterRange(_) + | Self::ForIterTuple(_) + | Self::Jump(_) + | Self::JumpNoInterrupt(_) ) } @@ -469,7 +469,11 @@ impl Instruction { pub const fn has_free(&self) -> bool { matches!( self, - DeleteDeref(_) | LoadDeref(_) | LoadFromDictOrDeref(_) | MakeCell(_) | StoreDeref(_) + Self::DeleteDeref(_) + | Self::LoadDeref(_) + | Self::LoadFromDictOrDeref(_) + | Self::MakeCell(_) + | Self::StoreDeref(_) ) } @@ -478,17 +482,17 @@ impl Instruction { pub const fn has_local(&self) -> bool { matches!( self, - BinaryOpInplaceAddUnicode - | DeleteFast(_) - | LoadFast(_) - | LoadFastAndClear(_) - | LoadFastCheck(_) - | LoadFastLoadFast(_) - | StoreFast(_) - | StoreFastLoadFast(_) - | StoreFastStoreFast(_) - | LoadClosure(_) - | StoreFastMaybeNull(_) + Self::BinaryOpInplaceAddUnicode + | Self::DeleteFast(_) + | Self::LoadFast(_) + | Self::LoadFastAndClear(_) + | Self::LoadFastCheck(_) + | Self::LoadFastLoadFast(_) + | Self::StoreFast(_) + | Self::StoreFastLoadFast(_) + | Self::StoreFastStoreFast(_) + | Self::LoadClosure(_) + | Self::StoreFastMaybeNull(_) ) } @@ -497,21 +501,21 @@ impl Instruction { pub const fn has_exc(&self) -> bool { matches!( self, - EndFor - | EndSend - | Nop - | PopTop - | PushNull - | UnaryNot - | Copy(_) - | LoadConst(_) - | LoadFast(_) - | Swap(_) - | LoadClosure(_) - | PopBlock - | SetupCleanup - | SetupFinally - | SetupWith + Self::EndFor + | Self::EndSend + | Self::Nop + | Self::PopTop + | Self::PushNull + | Self::UnaryNot + | Self::Copy(_) + | Self::LoadConst(_) + | Self::LoadFast(_) + | Self::Swap(_) + | Self::LoadClosure(_) + | Self::PopBlock + | Self::SetupCleanup + | Self::SetupFinally + | Self::SetupWith ) } @@ -520,18 +524,18 @@ impl Instruction { pub const fn is_pseudo(&self) -> bool { matches!( self, - Jump(_) - | JumpNoInterrupt(_) - | LoadClosure(_) - | LoadMethod(_) - | LoadSuperMethod(_) - | LoadZeroSuperAttr(_) - | LoadZeroSuperMethod(_) - | PopBlock - | SetupCleanup - | SetupFinally - | SetupWith - | StoreFastMaybeNull(_) + Self::Jump(_) + | Self::JumpNoInterrupt(_) + | Self::LoadClosure(_) + | Self::LoadMethod(_) + | Self::LoadSuperMethod(_) + | Self::LoadZeroSuperAttr(_) + | Self::LoadZeroSuperMethod(_) + | Self::PopBlock + | Self::SetupCleanup + | Self::SetupFinally + | Self::SetupWith + | Self::StoreFastMaybeNull(_) ) } } diff --git a/scripts/gen_instructions.py b/scripts/gen_instructions.py index 892d5984a53..b846953700a 100755 --- a/scripts/gen_instructions.py +++ b/scripts/gen_instructions.py @@ -46,7 +46,7 @@ def as_matched(self) -> str: out = self.name if self.has_oparg: out += "(_)" - return out + return f"Self::{out}" @classmethod def iter_instructions(cls, analysis: analyzer.Analysis) -> "Iterator[typing.Self]": From 56c0dc87cadb85ad3c5ca5d8d2c0c4b45a82cbd0 Mon Sep 17 00:00:00 2001 From: ShaharNaveh <50263213+ShaharNaveh@users.noreply.github.com> Date: Fri, 26 Sep 2025 10:47:36 +0200 Subject: [PATCH 11/43] refactor --- compiler/core/src/instruction.rs | 56 ++++---- scripts/gen_instructions.py | 225 ++++++++++++++++++------------- 2 files changed, 156 insertions(+), 125 deletions(-) diff --git a/compiler/core/src/instruction.rs b/compiler/core/src/instruction.rs index c749f3c995e..283dda9e6f2 100644 --- a/compiler/core/src/instruction.rs +++ b/compiler/core/src/instruction.rs @@ -236,7 +236,7 @@ impl Instruction { /// Creates a new Instruction without validating that the `id` is valid before. #[must_use] pub const unsafe fn new_unchecked(id: u16) -> Self { - // SAFETY: Caller responsebility. + // SAFETY: Caller responsibility. unsafe { std::mem::transmute::(id) } } @@ -246,7 +246,27 @@ impl Instruction { matches!(id, 0..=118 | 149..=222 | 236..=253 | 256..=267) } - /// Whether opcode had 'HAS_ARG_FLAG' set. + /// Whether opcode is pseudo. + #[must_use] + pub const fn is_pseudo(&self) -> bool { + matches!( + self, + Self::Jump(_) + | Self::JumpNoInterrupt(_) + | Self::LoadClosure(_) + | Self::LoadMethod(_) + | Self::LoadSuperMethod(_) + | Self::LoadZeroSuperAttr(_) + | Self::LoadZeroSuperMethod(_) + | Self::PopBlock + | Self::SetupCleanup + | Self::SetupFinally + | Self::SetupWith + | Self::StoreFastMaybeNull(_) + ) + } + + /// Whether opcode have 'HAS_ARG_FLAG' set. #[must_use] pub const fn has_arg(&self) -> bool { matches!( @@ -403,7 +423,7 @@ impl Instruction { ) } - /// Whether opcode had 'HAS_CONST_FLAG' set. + /// Whether opcode have 'HAS_CONST_FLAG' set. #[must_use] pub const fn has_const(&self) -> bool { matches!( @@ -412,7 +432,7 @@ impl Instruction { ) } - /// Whether opcode had 'HAS_NAME_FLAG' set. + /// Whether opcode have 'HAS_NAME_FLAG' set. #[must_use] pub const fn has_name(&self) -> bool { matches!( @@ -442,7 +462,7 @@ impl Instruction { ) } - /// Whether opcode had 'HAS_JUMP_FLAG' set. + /// Whether opcode have 'HAS_JUMP_FLAG' set. #[must_use] pub const fn has_jump(&self) -> bool { matches!( @@ -464,7 +484,7 @@ impl Instruction { ) } - /// Whether opcode had 'HAS_FREE_FLAG' set. + /// Whether opcode have 'HAS_FREE_FLAG' set. #[must_use] pub const fn has_free(&self) -> bool { matches!( @@ -477,7 +497,7 @@ impl Instruction { ) } - /// Whether opcode had 'HAS_LOCAL_FLAG' set. + /// Whether opcode have 'HAS_LOCAL_FLAG' set. #[must_use] pub const fn has_local(&self) -> bool { matches!( @@ -496,7 +516,7 @@ impl Instruction { ) } - /// Whether opcode had 'HAS_PURE_FLAG' set. + /// Whether opcode have 'HAS_PURE_FLAG' set. #[must_use] pub const fn has_exc(&self) -> bool { matches!( @@ -518,26 +538,6 @@ impl Instruction { | Self::SetupWith ) } - - /// Whether opcode is pseudo. - #[must_use] - pub const fn is_pseudo(&self) -> bool { - matches!( - self, - Self::Jump(_) - | Self::JumpNoInterrupt(_) - | Self::LoadClosure(_) - | Self::LoadMethod(_) - | Self::LoadSuperMethod(_) - | Self::LoadZeroSuperAttr(_) - | Self::LoadZeroSuperMethod(_) - | Self::PopBlock - | Self::SetupCleanup - | Self::SetupFinally - | Self::SetupWith - | Self::StoreFastMaybeNull(_) - ) - } } impl TryFrom for Instruction { diff --git a/scripts/gen_instructions.py b/scripts/gen_instructions.py index b846953700a..0f574b31361 100755 --- a/scripts/gen_instructions.py +++ b/scripts/gen_instructions.py @@ -2,7 +2,6 @@ import pathlib import subprocess # for `cargo fmt` import sys -import textwrap import typing if typing.TYPE_CHECKING: @@ -17,6 +16,7 @@ import analyzer +import stack from generators_common import DEFAULT_INPUT from opcode_metadata_generator import cflags @@ -24,21 +24,39 @@ OUT_PATH = ROOT / "compiler" / "core" / "src" / "instruction.rs" -class Instruction(typing.NamedTuple): - cname: str - id: int - flags: frozenset[str] - has_oparg: bool - is_pseudo: bool = False +class Instruction: + def __init__( + self, ins: analyzer.Instruction, val: int, is_pseudo: bool = False + ) -> None: + self.id = val + self.is_pseudo = is_pseudo + self._inner = ins @property def name(self) -> str: - return self.cname.title().replace("_", "") + return self._inner.name.title().replace("_", "") - def as_member(self) -> str: + @property + def has_oparg(self) -> bool: + return self._inner.properties.oparg + + @property + def flags(self) -> frozenset[str]: + if not self.is_pseudo: + return frozenset(cflags(self._inner.properties).split(" | ")) + + flags = cflags(self._inner.properties) + for flag in self._inner.flags: + if flags == "0": + flags = f"{flag}_FLAG" + else: + flags += f" | {flag}_FLAG" + return frozenset(flags.split(" | ")) + + def as_enum_member(self) -> str: out = self.name if self.has_oparg: - out += "(Arg)" + out += "(Arg)" # TODO: What should that be? out += f" = {self.id}" return out @@ -48,64 +66,55 @@ def as_matched(self) -> str: out += "(_)" return f"Self::{out}" - @classmethod - def iter_instructions(cls, analysis: analyzer.Analysis) -> "Iterator[typing.Self]": - """ - Adapted from https://github.com/python/cpython/blob/bcee1c322115c581da27600f2ae55e5439c027eb/Tools/cases_generator/opcode_metadata_generator.py#L186-L213 - """ - opmap = analysis.opmap - for inst in sorted(analysis.instructions.values(), key=lambda t: t.name): - name = inst.name - flags = frozenset(cflags(inst.properties).split(" | ")) - - yield cls( - cname=name, id=opmap[name], flags=flags, has_oparg=inst.properties.oparg - ) - - for pseudo in sorted(analysis.pseudos.values(), key=lambda t: t.name): - name = pseudo.name - flags = cflags(pseudo.properties) - for flag in pseudo.flags: - if flags == "0": - flags = f"{flag}_FLAG" - else: - flags += f" | {flag}_FLAG" - - yield cls( - cname=name, - id=opmap[name], - has_oparg=pseudo.properties.oparg, - flags=frozenset(flags.split(" | ")), - is_pseudo=True, - ) - def __lt__(self, other) -> bool: return self.id < other.id -def group_nums(nums: list[int]) -> "Iterator[range]": - nums = sorted(nums) - start = prev = nums[0] +class Instructions: + def __init__(self, analysis: analyzer.Analysis) -> None: + inner = [] + for ins in analysis.instructions.values(): + inner.append(Instruction(ins, analysis.opmap[ins.name], is_pseudo=False)) + + for pseudo in analysis.pseudos.values(): + inner.append( + Instruction(pseudo, analysis.opmap[pseudo.name], is_pseudo=True) + ) + self._inner = tuple(sorted(inner)) + + def __iter__(self) -> "Iterator[analyzer.Instruction]": + yield from self._inner - for n in nums[1:] + [None]: - if n is None or n != prev + 1: - yield range(start, prev + 1) - start = n - prev = n + def _valid_ranges(self) -> "Iterator[range]": + ids = [ins.id for ins in self] + # Group consecutive numbers into ranges. + start = prev = ids[0] + for n in ids[1:] + [None]: + if n is None or n != prev + 1: + yield range(start, prev + 1) + start = n + prev = n -def gen_valid_ranges(ids: list[int]) -> str: - return " | ".join( - " | ".join(r) if len(r) < 3 else f"{r.start}..={r.stop - 1}" - for r in group_nums(ids) - ) + def generate_enum_members(self) -> str: + return ",".join(ins.as_enum_member() for ins in self) + def generate_is_valid(self) -> str: + valid_ranges = " | ".join( + " | ".join(r) if len(r) < 3 else f"{r.start}..={r.stop - 1}" + for r in self._valid_ranges() + ) + return f""" +/// Whether the given ID matches one of the opcode IDs. +#[must_use] +pub const fn is_valid(id: u16) -> bool {{ + matches!(id, {valid_ranges}) +}} +""".strip() -def build_is_pseudo_fn(instructions: frozenset[Instruction]): - matches = " | ".join( - ins.as_matched() for ins in sorted(instructions) if ins.is_pseudo - ) - return f""" + def generate_is_pseudo(self) -> str: + matches = " | ".join(ins.as_matched() for ins in self if ins.is_pseudo) + return f""" /// Whether opcode is pseudo. #[must_use] pub const fn is_pseudo(&self) -> bool {{ @@ -113,42 +122,56 @@ def build_is_pseudo_fn(instructions: frozenset[Instruction]): }} """.strip() - -def gen_has_attr_fn( - instructions: frozenset[Instruction], - *, - attrs: tuple[str, ...] = ("arg", "const", "name", "jump", "free", "local", "exc"), -) -> "Iterator[str]": - for attr in attrs: - flag_name = "pure" if attr == "exc" else attr - flag = f"has_{flag_name}_flag".upper() - matches = " | ".join( - ins.as_matched() for ins in sorted(instructions) if flag in ins.flags - ) - yield f""" -/// Whether opcode had '{flag}' set. + def _generate_has_attr(self, attr: str, *, flag_override: str | None = None) -> str: + flag = flag_override if flag_override else f"has_{attr}_flag".upper() + matches = " | ".join(ins.as_matched() for ins in self if flag in ins.flags) + return f""" +/// Whether opcode have '{flag}' set. #[must_use] pub const fn has_{attr}(&self) -> bool {{ matches!(self, {matches}) }} """.strip() + def generate_has_arg(self) -> str: + return self._generate_has_attr("arg") -def main(): - INDENT = " " * 4 - script_path = pathlib.Path(__file__).absolute().relative_to(ROOT).as_posix() + def generate_has_const(self) -> str: + return self._generate_has_attr("const") + + def generate_has_name(self) -> str: + return self._generate_has_attr("name") + + def generate_has_jump(self) -> str: + return self._generate_has_attr("jump") + def generate_has_free(self) -> str: + return self._generate_has_attr("free") + + def generate_has_local(self) -> str: + return self._generate_has_attr("local") + + def generate_has_exc(self) -> str: + return self._generate_has_attr("exc", flag_override="HAS_PURE_FLAG") + + +def main(): analysis = analyzer.analyze_files([DEFAULT_INPUT]) - instructions = frozenset(Instruction.iter_instructions(analysis)) + instructions = Instructions(analysis) - has_attr_methods = textwrap.indent( - "\n\n".join(gen_has_attr_fn(instructions)), INDENT - ) - is_pseudo_fn = textwrap.indent(build_is_pseudo_fn(instructions), INDENT) - members = textwrap.indent( - ",\n".join(ins.as_member() for ins in sorted(instructions)), INDENT - ) - valid_ranges = gen_valid_ranges([ins.id for ins in instructions]) + enum_members = instructions.generate_enum_members() + + is_valid = instructions.generate_is_valid() + is_pseudo = instructions.generate_is_pseudo() + has_arg = instructions.generate_has_arg() + has_const = instructions.generate_has_const() + has_name = instructions.generate_has_name() + has_jump = instructions.generate_has_jump() + has_free = instructions.generate_has_free() + has_local = instructions.generate_has_local() + has_exc = instructions.generate_has_exc() + + script_path = pathlib.Path(__file__).absolute().relative_to(ROOT).as_posix() out = f""" ///! Python opcode implementation. Currently aligned with cpython 3.13.7 @@ -160,26 +183,34 @@ def main(): #[derive(Clone, Copy, Debug, Eq, PartialEq)] #[repr(u16)] pub enum Instruction {{ -{members} +{enum_members} }} impl Instruction {{ /// Creates a new Instruction without validating that the `id` is valid before. #[must_use] pub const unsafe fn new_unchecked(id: u16) -> Self {{ - // SAFETY: Caller responsebility. + // SAFETY: Caller responsibility. unsafe {{ std::mem::transmute::(id) }} }} - /// Whether the given ID matches one of the opcode IDs. - #[must_use] - pub const fn is_valid(id: u16) -> bool {{ - matches!(id, {valid_ranges}) - }} +{is_valid} -{has_attr_methods} +{is_pseudo} -{is_pseudo_fn} +{has_arg} + +{has_const} + +{has_name} + +{has_jump} + +{has_free} + +{has_local} + +{has_exc} }} impl TryFrom for Instruction {{ @@ -193,11 +224,11 @@ def main(): }} }} }} - """.strip() - - OUT_PATH.write_text(out + "\n") +""".strip() + OUT_PATH.write_text(out) print("DONE") + print("Running `cargo fmt`") subprocess.run(["cargo", "fmt"], cwd=ROOT) From 3fdc47965da716527785cb6d227aeee5482fbd68 Mon Sep 17 00:00:00 2001 From: ShaharNaveh <50263213+ShaharNaveh@users.noreply.github.com> Date: Fri, 26 Sep 2025 12:36:57 +0200 Subject: [PATCH 12/43] impl num_{pushed,popped} --- compiler/core/src/instruction.rs | 436 +++++++++++++++++++++++++++++++ scripts/gen_instructions.py | 74 +++++- 2 files changed, 507 insertions(+), 3 deletions(-) diff --git a/compiler/core/src/instruction.rs b/compiler/core/src/instruction.rs index 283dda9e6f2..0193d30ea5e 100644 --- a/compiler/core/src/instruction.rs +++ b/compiler/core/src/instruction.rs @@ -538,6 +538,442 @@ impl Instruction { | Self::SetupWith ) } + + /// How many items should be popped from the stack. + const fn num_popped(&self) { + match &self { + Self::Cache => 0, + Self::BeforeAsyncWith => 1, + Self::BeforeWith => 1, + Self::BinaryOpInplaceAddUnicode => 2, + Self::BinarySlice => 3, + Self::BinarySubscr => 2, + Self::CheckEgMatch => 2, + Self::CheckExcMatch => 2, + Self::CleanupThrow => 3, + Self::DeleteSubscr => 2, + Self::EndAsyncFor => 2, + Self::EndFor => 1, + Self::EndSend => 2, + Self::ExitInitCheck => 1, + Self::FormatSimple => 1, + Self::FormatWithSpec => 2, + Self::GetAiter => 1, + Self::Reserved => 0, + Self::GetAnext => 1, + Self::GetIter => 1, + Self::GetLen => 1, + Self::GetYieldFromIter => 1, + Self::InterpreterExit => 1, + Self::LoadAssertionError => 0, + Self::LoadBuildClass => 0, + Self::LoadLocals => 0, + Self::MakeFunction => 1, + Self::MatchKeys => 2, + Self::MatchMapping => 1, + Self::MatchSequence => 1, + Self::Nop => 0, + Self::PopExcept => 1, + Self::PopTop => 1, + Self::PushExcInfo => 1, + Self::PushNull => 0, + Self::ReturnGenerator => 0, + Self::ReturnValue => 1, + Self::SetupAnnotations => 0, + Self::StoreSlice => 4, + Self::StoreSubscr => 3, + Self::ToBool => 1, + Self::UnaryInvert => 1, + Self::UnaryNegative => 1, + Self::UnaryNot => 1, + Self::WithExceptStart => 4, + Self::BinaryOp(_) => 2, + Self::BuildConstKeyMap(oparg) => 1 + oparg, + Self::BuildList(oparg) => oparg, + Self::BuildMap(oparg) => oparg * 2, + Self::BuildSet(oparg) => oparg, + Self::BuildSlice(oparg) => 2 + (if (oparg == 3) { 1 } else { 0 }), + Self::BuildString(oparg) => oparg, + Self::BuildTuple(oparg) => oparg, + Self::Call(oparg) => 2 + oparg, + Self::CallFunctionEx(oparg) => 3 + (oparg & 1), + Self::CallIntrinsic1(_) => 1, + Self::CallIntrinsic2(_) => 2, + Self::CallKw(oparg) => 3 + oparg, + Self::CompareOp(_) => 2, + Self::ContainsOp(_) => 2, + Self::ConvertValue(_) => 1, + Self::Copy(oparg) => 1 + (oparg - 1), + Self::CopyFreeVars(_) => 0, + Self::DeleteAttr(_) => 1, + Self::DeleteDeref(_) => 0, + Self::DeleteFast(_) => 0, + Self::DeleteGlobal(_) => 0, + Self::DeleteName(_) => 0, + Self::DictMerge(oparg) => 5 + (oparg - 1), + Self::DictUpdate(oparg) => 2 + (oparg - 1), + Self::EnterExecutor(_) => 0, + Self::ExtendedArg(_) => 0, + Self::ForIter(_) => 1, + Self::GetAwaitable(_) => 1, + Self::ImportFrom(_) => 1, + Self::ImportName(_) => 2, + Self::IsOp(_) => 2, + Self::JumpBackward(_) => 0, + Self::JumpBackwardNoInterrupt(_) => 0, + Self::JumpForward(_) => 0, + Self::ListAppend(oparg) => 2 + (oparg - 1), + Self::ListExtend(oparg) => 2 + (oparg - 1), + Self::LoadAttr(_) => 1, + Self::LoadConst(_) => 0, + Self::LoadDeref(_) => 0, + Self::LoadFast(_) => 0, + Self::LoadFastAndClear(_) => 0, + Self::LoadFastCheck(_) => 0, + Self::LoadFastLoadFast(_) => 0, + Self::LoadFromDictOrDeref(_) => 1, + Self::LoadFromDictOrGlobals(_) => 1, + Self::LoadGlobal(_) => 0, + Self::LoadName(_) => 0, + Self::LoadSuperAttr(_) => 3, + Self::MakeCell(_) => 0, + Self::MapAdd(oparg) => 3 + (oparg - 1), + Self::MatchClass(_) => 3, + Self::PopJumpIfFalse(_) => 1, + Self::PopJumpIfNone(_) => 1, + Self::PopJumpIfNotNone(_) => 1, + Self::PopJumpIfTrue(_) => 1, + Self::RaiseVarargs(oparg) => oparg, + Self::Reraise(oparg) => 1 + oparg, + Self::ReturnConst(_) => 0, + Self::Send(_) => 2, + Self::SetAdd(oparg) => 2 + (oparg - 1), + Self::SetFunctionAttribute(_) => 2, + Self::SetUpdate(oparg) => 2 + (oparg - 1), + Self::StoreAttr(_) => 2, + Self::StoreDeref(_) => 1, + Self::StoreFast(_) => 1, + Self::StoreFastLoadFast(_) => 1, + Self::StoreFastStoreFast(_) => 2, + Self::StoreGlobal(_) => 1, + Self::StoreName(_) => 1, + Self::Swap(oparg) => 2 + (oparg - 2), + Self::UnpackEx(_) => 1, + Self::UnpackSequence(_) => 1, + Self::YieldValue(_) => 1, + Self::Resume(_) => 0, + Self::BinaryOpAddFloat => 2, + Self::BinaryOpAddInt => 2, + Self::BinaryOpAddUnicode => 2, + Self::BinaryOpMultiplyFloat => 2, + Self::BinaryOpMultiplyInt => 2, + Self::BinaryOpSubtractFloat => 2, + Self::BinaryOpSubtractInt => 2, + Self::BinarySubscrDict => 2, + Self::BinarySubscrGetitem => 2, + Self::BinarySubscrListInt => 2, + Self::BinarySubscrStrInt => 2, + Self::BinarySubscrTupleInt => 2, + Self::CallAllocAndEnterInit(oparg) => 2 + oparg, + Self::CallBoundMethodExactArgs(oparg) => 2 + oparg, + Self::CallBoundMethodGeneral(oparg) => 2 + oparg, + Self::CallBuiltinClass(oparg) => 2 + oparg, + Self::CallBuiltinFast(oparg) => 2 + oparg, + Self::CallBuiltinFastWithKeywords(oparg) => 2 + oparg, + Self::CallBuiltinO(oparg) => 2 + oparg, + Self::CallIsinstance(oparg) => 2 + oparg, + Self::CallLen(oparg) => 2 + oparg, + Self::CallListAppend(_) => 3, + Self::CallMethodDescriptorFast(oparg) => 2 + oparg, + Self::CallMethodDescriptorFastWithKeywords(oparg) => 2 + oparg, + Self::CallMethodDescriptorNoargs(oparg) => 2 + oparg, + Self::CallMethodDescriptorO(oparg) => 2 + oparg, + Self::CallNonPyGeneral(oparg) => 2 + oparg, + Self::CallPyExactArgs(oparg) => 2 + oparg, + Self::CallPyGeneral(oparg) => 2 + oparg, + Self::CallStr1(_) => 3, + Self::CallTuple1(_) => 3, + Self::CallType1(_) => 3, + Self::CompareOpFloat(_) => 2, + Self::CompareOpInt(_) => 2, + Self::CompareOpStr(_) => 2, + Self::ContainsOpDict(_) => 2, + Self::ContainsOpSet(_) => 2, + Self::ForIterGen(_) => 1, + Self::ForIterList(_) => 1, + Self::ForIterRange(_) => 1, + Self::ForIterTuple(_) => 1, + Self::LoadAttrClass(_) => 1, + Self::LoadAttrGetattributeOverridden(_) => 1, + Self::LoadAttrInstanceValue(_) => 1, + Self::LoadAttrMethodLazyDict(_) => 1, + Self::LoadAttrMethodNoDict(_) => 1, + Self::LoadAttrMethodWithValues(_) => 1, + Self::LoadAttrModule(_) => 1, + Self::LoadAttrNondescriptorNoDict(_) => 1, + Self::LoadAttrNondescriptorWithValues(_) => 1, + Self::LoadAttrProperty(_) => 1, + Self::LoadAttrSlot(_) => 1, + Self::LoadAttrWithHint(_) => 1, + Self::LoadGlobalBuiltin(_) => 0, + Self::LoadGlobalModule(_) => 0, + Self::LoadSuperAttrAttr(_) => 3, + Self::LoadSuperAttrMethod(_) => 3, + Self::ResumeCheck => 0, + Self::SendGen(_) => 2, + Self::StoreAttrInstanceValue => 2, + Self::StoreAttrSlot => 2, + Self::StoreAttrWithHint(_) => 2, + Self::StoreSubscrDict => 3, + Self::StoreSubscrListInt => 3, + Self::ToBoolAlwaysTrue => 1, + Self::ToBoolBool => 1, + Self::ToBoolInt => 1, + Self::ToBoolList => 1, + Self::ToBoolNone => 1, + Self::ToBoolStr => 1, + Self::UnpackSequenceList(_) => 1, + Self::UnpackSequenceTuple(_) => 1, + Self::UnpackSequenceTwoTuple(_) => 1, + Self::InstrumentedResume(_) => 0, + Self::InstrumentedEndFor => 2, + Self::InstrumentedEndSend => 2, + Self::InstrumentedReturnValue => 1, + Self::InstrumentedReturnConst(_) => 0, + Self::InstrumentedYieldValue(_) => 1, + Self::InstrumentedLoadSuperAttr(_) => 3, + Self::InstrumentedForIter(_) => 0, + Self::InstrumentedCall(_) => 0, + Self::InstrumentedCallKw(_) => 0, + Self::InstrumentedCallFunctionEx => 0, + Self::InstrumentedInstruction => 0, + Self::InstrumentedJumpForward(_) => 0, + Self::InstrumentedJumpBackward(_) => 0, + Self::InstrumentedPopJumpIfTrue(_) => 0, + Self::InstrumentedPopJumpIfFalse(_) => 0, + Self::InstrumentedPopJumpIfNone(_) => 0, + Self::InstrumentedPopJumpIfNotNone(_) => 0, + _ => panic!("Pseudo opcodes are not allowed!"), + } + } + + /// How many items should be pushed on the stack. + const fn num_pushed(&self) { + match &self { + Self::Cache => 0, + Self::BeforeAsyncWith => 2, + Self::BeforeWith => 2, + Self::BinaryOpInplaceAddUnicode => 0, + Self::BinarySlice => 1, + Self::BinarySubscr => 1, + Self::CheckEgMatch => 2, + Self::CheckExcMatch => 2, + Self::CleanupThrow => 2, + Self::DeleteSubscr => 0, + Self::EndAsyncFor => 0, + Self::EndFor => 0, + Self::EndSend => 1, + Self::ExitInitCheck => 0, + Self::FormatSimple => 1, + Self::FormatWithSpec => 1, + Self::GetAiter => 1, + Self::Reserved => 0, + Self::GetAnext => 2, + Self::GetIter => 1, + Self::GetLen => 2, + Self::GetYieldFromIter => 1, + Self::InterpreterExit => 0, + Self::LoadAssertionError => 1, + Self::LoadBuildClass => 1, + Self::LoadLocals => 1, + Self::MakeFunction => 1, + Self::MatchKeys => 3, + Self::MatchMapping => 2, + Self::MatchSequence => 2, + Self::Nop => 0, + Self::PopExcept => 0, + Self::PopTop => 0, + Self::PushExcInfo => 2, + Self::PushNull => 1, + Self::ReturnGenerator => 1, + Self::ReturnValue => 0, + Self::SetupAnnotations => 0, + Self::StoreSlice => 0, + Self::StoreSubscr => 0, + Self::ToBool => 1, + Self::UnaryInvert => 1, + Self::UnaryNegative => 1, + Self::UnaryNot => 1, + Self::WithExceptStart => 5, + Self::BinaryOp(_) => 1, + Self::BuildConstKeyMap(_) => 1, + Self::BuildList(_) => 1, + Self::BuildMap(_) => 1, + Self::BuildSet(_) => 1, + Self::BuildSlice(_) => 1, + Self::BuildString(_) => 1, + Self::BuildTuple(_) => 1, + Self::Call(_) => 1, + Self::CallFunctionEx(_) => 1, + Self::CallIntrinsic1(_) => 1, + Self::CallIntrinsic2(_) => 1, + Self::CallKw(_) => 1, + Self::CompareOp(_) => 1, + Self::ContainsOp(_) => 1, + Self::ConvertValue(_) => 1, + Self::Copy(oparg) => 2 + (oparg - 1), + Self::CopyFreeVars(_) => 0, + Self::DeleteAttr(_) => 0, + Self::DeleteDeref(_) => 0, + Self::DeleteFast(_) => 0, + Self::DeleteGlobal(_) => 0, + Self::DeleteName(_) => 0, + Self::DictMerge(oparg) => 4 + (oparg - 1), + Self::DictUpdate(oparg) => 1 + (oparg - 1), + Self::EnterExecutor(_) => 0, + Self::ExtendedArg(_) => 0, + Self::ForIter(_) => 2, + Self::GetAwaitable(_) => 1, + Self::ImportFrom(_) => 2, + Self::ImportName(_) => 1, + Self::IsOp(_) => 1, + Self::JumpBackward(_) => 0, + Self::JumpBackwardNoInterrupt(_) => 0, + Self::JumpForward(_) => 0, + Self::ListAppend(oparg) => 1 + (oparg - 1), + Self::ListExtend(oparg) => 1 + (oparg - 1), + Self::LoadAttr(oparg) => 1 + (oparg & 1), + Self::LoadConst(_) => 1, + Self::LoadDeref(_) => 1, + Self::LoadFast(_) => 1, + Self::LoadFastAndClear(_) => 1, + Self::LoadFastCheck(_) => 1, + Self::LoadFastLoadFast(_) => 2, + Self::LoadFromDictOrDeref(_) => 1, + Self::LoadFromDictOrGlobals(_) => 1, + Self::LoadGlobal(oparg) => 1 + (oparg & 1), + Self::LoadName(_) => 1, + Self::LoadSuperAttr(oparg) => 1 + (oparg & 1), + Self::MakeCell(_) => 0, + Self::MapAdd(oparg) => 1 + (oparg - 1), + Self::MatchClass(_) => 1, + Self::PopJumpIfFalse(_) => 0, + Self::PopJumpIfNone(_) => 0, + Self::PopJumpIfNotNone(_) => 0, + Self::PopJumpIfTrue(_) => 0, + Self::RaiseVarargs(_) => 0, + Self::Reraise(oparg) => oparg, + Self::ReturnConst(_) => 0, + Self::Send(_) => 2, + Self::SetAdd(oparg) => 1 + (oparg - 1), + Self::SetFunctionAttribute(_) => 1, + Self::SetUpdate(oparg) => 1 + (oparg - 1), + Self::StoreAttr(_) => 0, + Self::StoreDeref(_) => 0, + Self::StoreFast(_) => 0, + Self::StoreFastLoadFast(_) => 1, + Self::StoreFastStoreFast(_) => 0, + Self::StoreGlobal(_) => 0, + Self::StoreName(_) => 0, + Self::Swap(oparg) => 2 + (oparg - 2), + Self::UnpackEx(oparg) => 1 + (oparg >> 8) + (oparg & 0xFF), + Self::UnpackSequence(oparg) => oparg, + Self::YieldValue(_) => 1, + Self::Resume(_) => 0, + Self::BinaryOpAddFloat => 1, + Self::BinaryOpAddInt => 1, + Self::BinaryOpAddUnicode => 1, + Self::BinaryOpMultiplyFloat => 1, + Self::BinaryOpMultiplyInt => 1, + Self::BinaryOpSubtractFloat => 1, + Self::BinaryOpSubtractInt => 1, + Self::BinarySubscrDict => 1, + Self::BinarySubscrGetitem => 1, + Self::BinarySubscrListInt => 1, + Self::BinarySubscrStrInt => 1, + Self::BinarySubscrTupleInt => 1, + Self::CallAllocAndEnterInit(_) => 1, + Self::CallBoundMethodExactArgs(_) => 0, + Self::CallBoundMethodGeneral(_) => 0, + Self::CallBuiltinClass(_) => 1, + Self::CallBuiltinFast(_) => 1, + Self::CallBuiltinFastWithKeywords(_) => 1, + Self::CallBuiltinO(_) => 1, + Self::CallIsinstance(_) => 1, + Self::CallLen(_) => 1, + Self::CallListAppend(_) => 1, + Self::CallMethodDescriptorFast(_) => 1, + Self::CallMethodDescriptorFastWithKeywords(_) => 1, + Self::CallMethodDescriptorNoargs(_) => 1, + Self::CallMethodDescriptorO(_) => 1, + Self::CallNonPyGeneral(_) => 1, + Self::CallPyExactArgs(_) => 0, + Self::CallPyGeneral(_) => 0, + Self::CallStr1(_) => 1, + Self::CallTuple1(_) => 1, + Self::CallType1(_) => 1, + Self::CompareOpFloat(_) => 1, + Self::CompareOpInt(_) => 1, + Self::CompareOpStr(_) => 1, + Self::ContainsOpDict(_) => 1, + Self::ContainsOpSet(_) => 1, + Self::ForIterGen(_) => 1, + Self::ForIterList(_) => 2, + Self::ForIterRange(_) => 2, + Self::ForIterTuple(_) => 2, + Self::LoadAttrClass(oparg) => 1 + (oparg & 1), + Self::LoadAttrGetattributeOverridden(_) => 1, + Self::LoadAttrInstanceValue(oparg) => 1 + (oparg & 1), + Self::LoadAttrMethodLazyDict(_) => 2, + Self::LoadAttrMethodNoDict(_) => 2, + Self::LoadAttrMethodWithValues(_) => 2, + Self::LoadAttrModule(oparg) => 1 + (oparg & 1), + Self::LoadAttrNondescriptorNoDict(_) => 1, + Self::LoadAttrNondescriptorWithValues(_) => 1, + Self::LoadAttrProperty(_) => 1, + Self::LoadAttrSlot(oparg) => 1 + (oparg & 1), + Self::LoadAttrWithHint(oparg) => 1 + (oparg & 1), + Self::LoadGlobalBuiltin(oparg) => 1 + (oparg & 1), + Self::LoadGlobalModule(oparg) => 1 + (oparg & 1), + Self::LoadSuperAttrAttr(_) => 1, + Self::LoadSuperAttrMethod(_) => 2, + Self::ResumeCheck => 0, + Self::SendGen(_) => 2, + Self::StoreAttrInstanceValue => 0, + Self::StoreAttrSlot => 0, + Self::StoreAttrWithHint(_) => 0, + Self::StoreSubscrDict => 0, + Self::StoreSubscrListInt => 0, + Self::ToBoolAlwaysTrue => 1, + Self::ToBoolBool => 1, + Self::ToBoolInt => 1, + Self::ToBoolList => 1, + Self::ToBoolNone => 1, + Self::ToBoolStr => 1, + Self::UnpackSequenceList(oparg) => oparg, + Self::UnpackSequenceTuple(oparg) => oparg, + Self::UnpackSequenceTwoTuple(_) => 2, + Self::InstrumentedResume(_) => 0, + Self::InstrumentedEndFor => 1, + Self::InstrumentedEndSend => 1, + Self::InstrumentedReturnValue => 0, + Self::InstrumentedReturnConst(_) => 0, + Self::InstrumentedYieldValue(_) => 1, + Self::InstrumentedLoadSuperAttr(oparg) => 1 + (oparg & 1), + Self::InstrumentedForIter(_) => 0, + Self::InstrumentedCall(_) => 0, + Self::InstrumentedCallKw(_) => 0, + Self::InstrumentedCallFunctionEx => 0, + Self::InstrumentedInstruction => 0, + Self::InstrumentedJumpForward(_) => 0, + Self::InstrumentedJumpBackward(_) => 0, + Self::InstrumentedPopJumpIfTrue(_) => 0, + Self::InstrumentedPopJumpIfFalse(_) => 0, + Self::InstrumentedPopJumpIfNone(_) => 0, + Self::InstrumentedPopJumpIfNotNone(_) => 0, + _ => panic!("Pseudo opcodes are not allowed!"), + } + } } impl TryFrom for Instruction { diff --git a/scripts/gen_instructions.py b/scripts/gen_instructions.py index 0f574b31361..955498b0d30 100755 --- a/scripts/gen_instructions.py +++ b/scripts/gen_instructions.py @@ -16,14 +16,35 @@ import analyzer -import stack from generators_common import DEFAULT_INPUT from opcode_metadata_generator import cflags +from stack import StackOffset, get_stack_effect ROOT = pathlib.Path(__file__).parents[1] OUT_PATH = ROOT / "compiler" / "core" / "src" / "instruction.rs" +def _var_size(var): + """ + Adapted from https://github.com/python/cpython/blob/bcee1c322115c581da27600f2ae55e5439c027eb/Tools/cases_generator/stack.py#L24-L36 + """ + if var.condition: + if var.condition == "0": + return "0" + elif var.condition == "1": + return var.size + elif var.condition == "oparg & 1" and var.size == "1": + return f"({var.condition})" + else: + return f"(if ({var.condition}) {{ {var.size} }} else {{ 0 }})" + else: + return var.size + + +StackOffset.pop = lambda self, item: self.popped.append(_var_size(item)) +StackOffset.push = lambda self, item: self.pushed.append(_var_size(item)) + + class Instruction: def __init__( self, ins: analyzer.Instruction, val: int, is_pseudo: bool = False @@ -60,10 +81,10 @@ def as_enum_member(self) -> str: out += f" = {self.id}" return out - def as_matched(self) -> str: + def as_matched(self, arg: str = "_") -> str: out = self.name if self.has_oparg: - out += "(_)" + out += f"({arg})" return f"Self::{out}" def __lt__(self, other) -> bool: @@ -154,6 +175,45 @@ def generate_has_local(self) -> str: def generate_has_exc(self) -> str: return self._generate_has_attr("exc", flag_override="HAS_PURE_FLAG") + def _generate_stack_effect(self, direction: str) -> str: + """ + Adapted from https://github.com/python/cpython/blob/bcee1c322115c581da27600f2ae55e5439c027eb/Tools/cases_generator/stack.py#L89-L111 + """ + lines = [] + for ins in self: + if ins.is_pseudo: + continue + + stack = get_stack_effect(ins._inner) + if direction == "popped": + val = -stack.base_offset + elif direction == "pushed": + val = stack.top_offset - stack.base_offset + + expr = val.to_c() + + matched = ins.as_matched("oparg" if "oparg" in expr else "_") + line = f"{matched} => {expr}" + lines.append(line) + + conds = ",\n".join(lines) + doc = "from" if direction == "popped" else "on" + return f""" +/// How many items should be {direction} {doc} the stack. +const fn num_{direction}(&self) {{ + match &self {{ + {conds}, + _ => panic!("Pseudo opcodes are not allowed!") + }} +}} +""" + + def generate_num_popped(self) -> str: + return self._generate_stack_effect("popped") + + def generate_num_pushed(self) -> str: + return self._generate_stack_effect("pushed") + def main(): analysis = analyzer.analyze_files([DEFAULT_INPUT]) @@ -163,6 +223,7 @@ def main(): is_valid = instructions.generate_is_valid() is_pseudo = instructions.generate_is_pseudo() + has_arg = instructions.generate_has_arg() has_const = instructions.generate_has_const() has_name = instructions.generate_has_name() @@ -171,6 +232,9 @@ def main(): has_local = instructions.generate_has_local() has_exc = instructions.generate_has_exc() + num_popped = instructions.generate_num_popped() + num_pushed = instructions.generate_num_pushed() + script_path = pathlib.Path(__file__).absolute().relative_to(ROOT).as_posix() out = f""" @@ -211,6 +275,10 @@ def main(): {has_local} {has_exc} + +{num_popped} + +{num_pushed} }} impl TryFrom for Instruction {{ From 5cf18883b017ed2e4e2cce42f4c594837a04d034 Mon Sep 17 00:00:00 2001 From: ShaharNaveh <50263213+ShaharNaveh@users.noreply.github.com> Date: Fri, 26 Sep 2025 12:58:11 +0200 Subject: [PATCH 13/43] Resolve some errors --- compiler/core/src/bytecode.rs | 2 +- compiler/core/src/instruction.rs | 424 +++++++++++++++---------------- scripts/gen_instructions.py | 12 +- 3 files changed, 220 insertions(+), 218 deletions(-) diff --git a/compiler/core/src/bytecode.rs b/compiler/core/src/bytecode.rs index 1088dd98487..ed25442f2df 100644 --- a/compiler/core/src/bytecode.rs +++ b/compiler/core/src/bytecode.rs @@ -264,7 +264,7 @@ impl fmt::Debug for OpArgByte { } /// a full 32-bit op_arg, including any possible ExtendedArg extension -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, Eq, PartialEq)] #[repr(transparent)] pub struct OpArg(pub u32); diff --git a/compiler/core/src/instruction.rs b/compiler/core/src/instruction.rs index 0193d30ea5e..0a5ea7a3d3f 100644 --- a/compiler/core/src/instruction.rs +++ b/compiler/core/src/instruction.rs @@ -1,7 +1,7 @@ ///! Python opcode implementation. Currently aligned with cpython 3.13.7 - // This file is generated by scripts/gen_instructions.py // Do not edit! +use crate::bytecode::OpArg; /// A Single bytecode instruction. #[derive(Clone, Copy, Debug, Eq, PartialEq)] @@ -52,81 +52,81 @@ pub enum Instruction { UnaryNegative = 42, UnaryNot = 43, WithExceptStart = 44, - BinaryOp(Arg) = 45, - BuildConstKeyMap(Arg) = 46, - BuildList(Arg) = 47, - BuildMap(Arg) = 48, - BuildSet(Arg) = 49, - BuildSlice(Arg) = 50, - BuildString(Arg) = 51, - BuildTuple(Arg) = 52, - Call(Arg) = 53, - CallFunctionEx(Arg) = 54, - CallIntrinsic1(Arg) = 55, - CallIntrinsic2(Arg) = 56, - CallKw(Arg) = 57, - CompareOp(Arg) = 58, - ContainsOp(Arg) = 59, - ConvertValue(Arg) = 60, - Copy(Arg) = 61, - CopyFreeVars(Arg) = 62, - DeleteAttr(Arg) = 63, - DeleteDeref(Arg) = 64, - DeleteFast(Arg) = 65, - DeleteGlobal(Arg) = 66, - DeleteName(Arg) = 67, - DictMerge(Arg) = 68, - DictUpdate(Arg) = 69, - EnterExecutor(Arg) = 70, - ExtendedArg(Arg) = 71, - ForIter(Arg) = 72, - GetAwaitable(Arg) = 73, - ImportFrom(Arg) = 74, - ImportName(Arg) = 75, - IsOp(Arg) = 76, - JumpBackward(Arg) = 77, - JumpBackwardNoInterrupt(Arg) = 78, - JumpForward(Arg) = 79, - ListAppend(Arg) = 80, - ListExtend(Arg) = 81, - LoadAttr(Arg) = 82, - LoadConst(Arg) = 83, - LoadDeref(Arg) = 84, - LoadFast(Arg) = 85, - LoadFastAndClear(Arg) = 86, - LoadFastCheck(Arg) = 87, - LoadFastLoadFast(Arg) = 88, - LoadFromDictOrDeref(Arg) = 89, - LoadFromDictOrGlobals(Arg) = 90, - LoadGlobal(Arg) = 91, - LoadName(Arg) = 92, - LoadSuperAttr(Arg) = 93, - MakeCell(Arg) = 94, - MapAdd(Arg) = 95, - MatchClass(Arg) = 96, - PopJumpIfFalse(Arg) = 97, - PopJumpIfNone(Arg) = 98, - PopJumpIfNotNone(Arg) = 99, - PopJumpIfTrue(Arg) = 100, - RaiseVarargs(Arg) = 101, - Reraise(Arg) = 102, - ReturnConst(Arg) = 103, - Send(Arg) = 104, - SetAdd(Arg) = 105, - SetFunctionAttribute(Arg) = 106, - SetUpdate(Arg) = 107, - StoreAttr(Arg) = 108, - StoreDeref(Arg) = 109, - StoreFast(Arg) = 110, - StoreFastLoadFast(Arg) = 111, - StoreFastStoreFast(Arg) = 112, - StoreGlobal(Arg) = 113, - StoreName(Arg) = 114, - Swap(Arg) = 115, - UnpackEx(Arg) = 116, - UnpackSequence(Arg) = 117, - YieldValue(Arg) = 118, - Resume(Arg) = 149, + BinaryOp(OpArg) = 45, + BuildConstKeyMap(OpArg) = 46, + BuildList(OpArg) = 47, + BuildMap(OpArg) = 48, + BuildSet(OpArg) = 49, + BuildSlice(OpArg) = 50, + BuildString(OpArg) = 51, + BuildTuple(OpArg) = 52, + Call(OpArg) = 53, + CallFunctionEx(OpArg) = 54, + CallIntrinsic1(OpArg) = 55, + CallIntrinsic2(OpArg) = 56, + CallKw(OpArg) = 57, + CompareOp(OpArg) = 58, + ContainsOp(OpArg) = 59, + ConvertValue(OpArg) = 60, + Copy(OpArg) = 61, + CopyFreeVars(OpArg) = 62, + DeleteAttr(OpArg) = 63, + DeleteDeref(OpArg) = 64, + DeleteFast(OpArg) = 65, + DeleteGlobal(OpArg) = 66, + DeleteName(OpArg) = 67, + DictMerge(OpArg) = 68, + DictUpdate(OpArg) = 69, + EnterExecutor(OpArg) = 70, + ExtendedArg(OpArg) = 71, + ForIter(OpArg) = 72, + GetAwaitable(OpArg) = 73, + ImportFrom(OpArg) = 74, + ImportName(OpArg) = 75, + IsOp(OpArg) = 76, + JumpBackward(OpArg) = 77, + JumpBackwardNoInterrupt(OpArg) = 78, + JumpForward(OpArg) = 79, + ListAppend(OpArg) = 80, + ListExtend(OpArg) = 81, + LoadAttr(OpArg) = 82, + LoadConst(OpArg) = 83, + LoadDeref(OpArg) = 84, + LoadFast(OpArg) = 85, + LoadFastAndClear(OpArg) = 86, + LoadFastCheck(OpArg) = 87, + LoadFastLoadFast(OpArg) = 88, + LoadFromDictOrDeref(OpArg) = 89, + LoadFromDictOrGlobals(OpArg) = 90, + LoadGlobal(OpArg) = 91, + LoadName(OpArg) = 92, + LoadSuperAttr(OpArg) = 93, + MakeCell(OpArg) = 94, + MapAdd(OpArg) = 95, + MatchClass(OpArg) = 96, + PopJumpIfFalse(OpArg) = 97, + PopJumpIfNone(OpArg) = 98, + PopJumpIfNotNone(OpArg) = 99, + PopJumpIfTrue(OpArg) = 100, + RaiseVarargs(OpArg) = 101, + Reraise(OpArg) = 102, + ReturnConst(OpArg) = 103, + Send(OpArg) = 104, + SetAdd(OpArg) = 105, + SetFunctionAttribute(OpArg) = 106, + SetUpdate(OpArg) = 107, + StoreAttr(OpArg) = 108, + StoreDeref(OpArg) = 109, + StoreFast(OpArg) = 110, + StoreFastLoadFast(OpArg) = 111, + StoreFastStoreFast(OpArg) = 112, + StoreGlobal(OpArg) = 113, + StoreName(OpArg) = 114, + Swap(OpArg) = 115, + UnpackEx(OpArg) = 116, + UnpackSequence(OpArg) = 117, + YieldValue(OpArg) = 118, + Resume(OpArg) = 149, BinaryOpAddFloat = 150, BinaryOpAddInt = 151, BinaryOpAddUnicode = 152, @@ -139,56 +139,56 @@ pub enum Instruction { BinarySubscrListInt = 159, BinarySubscrStrInt = 160, BinarySubscrTupleInt = 161, - CallAllocAndEnterInit(Arg) = 162, - CallBoundMethodExactArgs(Arg) = 163, - CallBoundMethodGeneral(Arg) = 164, - CallBuiltinClass(Arg) = 165, - CallBuiltinFast(Arg) = 166, - CallBuiltinFastWithKeywords(Arg) = 167, - CallBuiltinO(Arg) = 168, - CallIsinstance(Arg) = 169, - CallLen(Arg) = 170, - CallListAppend(Arg) = 171, - CallMethodDescriptorFast(Arg) = 172, - CallMethodDescriptorFastWithKeywords(Arg) = 173, - CallMethodDescriptorNoargs(Arg) = 174, - CallMethodDescriptorO(Arg) = 175, - CallNonPyGeneral(Arg) = 176, - CallPyExactArgs(Arg) = 177, - CallPyGeneral(Arg) = 178, - CallStr1(Arg) = 179, - CallTuple1(Arg) = 180, - CallType1(Arg) = 181, - CompareOpFloat(Arg) = 182, - CompareOpInt(Arg) = 183, - CompareOpStr(Arg) = 184, - ContainsOpDict(Arg) = 185, - ContainsOpSet(Arg) = 186, - ForIterGen(Arg) = 187, - ForIterList(Arg) = 188, - ForIterRange(Arg) = 189, - ForIterTuple(Arg) = 190, - LoadAttrClass(Arg) = 191, - LoadAttrGetattributeOverridden(Arg) = 192, - LoadAttrInstanceValue(Arg) = 193, - LoadAttrMethodLazyDict(Arg) = 194, - LoadAttrMethodNoDict(Arg) = 195, - LoadAttrMethodWithValues(Arg) = 196, - LoadAttrModule(Arg) = 197, - LoadAttrNondescriptorNoDict(Arg) = 198, - LoadAttrNondescriptorWithValues(Arg) = 199, - LoadAttrProperty(Arg) = 200, - LoadAttrSlot(Arg) = 201, - LoadAttrWithHint(Arg) = 202, - LoadGlobalBuiltin(Arg) = 203, - LoadGlobalModule(Arg) = 204, - LoadSuperAttrAttr(Arg) = 205, - LoadSuperAttrMethod(Arg) = 206, + CallAllocAndEnterInit(OpArg) = 162, + CallBoundMethodExactArgs(OpArg) = 163, + CallBoundMethodGeneral(OpArg) = 164, + CallBuiltinClass(OpArg) = 165, + CallBuiltinFast(OpArg) = 166, + CallBuiltinFastWithKeywords(OpArg) = 167, + CallBuiltinO(OpArg) = 168, + CallIsinstance(OpArg) = 169, + CallLen(OpArg) = 170, + CallListAppend(OpArg) = 171, + CallMethodDescriptorFast(OpArg) = 172, + CallMethodDescriptorFastWithKeywords(OpArg) = 173, + CallMethodDescriptorNoargs(OpArg) = 174, + CallMethodDescriptorO(OpArg) = 175, + CallNonPyGeneral(OpArg) = 176, + CallPyExactArgs(OpArg) = 177, + CallPyGeneral(OpArg) = 178, + CallStr1(OpArg) = 179, + CallTuple1(OpArg) = 180, + CallType1(OpArg) = 181, + CompareOpFloat(OpArg) = 182, + CompareOpInt(OpArg) = 183, + CompareOpStr(OpArg) = 184, + ContainsOpDict(OpArg) = 185, + ContainsOpSet(OpArg) = 186, + ForIterGen(OpArg) = 187, + ForIterList(OpArg) = 188, + ForIterRange(OpArg) = 189, + ForIterTuple(OpArg) = 190, + LoadAttrClass(OpArg) = 191, + LoadAttrGetattributeOverridden(OpArg) = 192, + LoadAttrInstanceValue(OpArg) = 193, + LoadAttrMethodLazyDict(OpArg) = 194, + LoadAttrMethodNoDict(OpArg) = 195, + LoadAttrMethodWithValues(OpArg) = 196, + LoadAttrModule(OpArg) = 197, + LoadAttrNondescriptorNoDict(OpArg) = 198, + LoadAttrNondescriptorWithValues(OpArg) = 199, + LoadAttrProperty(OpArg) = 200, + LoadAttrSlot(OpArg) = 201, + LoadAttrWithHint(OpArg) = 202, + LoadGlobalBuiltin(OpArg) = 203, + LoadGlobalModule(OpArg) = 204, + LoadSuperAttrAttr(OpArg) = 205, + LoadSuperAttrMethod(OpArg) = 206, ResumeCheck = 207, - SendGen(Arg) = 208, + SendGen(OpArg) = 208, StoreAttrInstanceValue = 209, StoreAttrSlot = 210, - StoreAttrWithHint(Arg) = 211, + StoreAttrWithHint(OpArg) = 211, StoreSubscrDict = 212, StoreSubscrListInt = 213, ToBoolAlwaysTrue = 214, @@ -197,39 +197,39 @@ pub enum Instruction { ToBoolList = 217, ToBoolNone = 218, ToBoolStr = 219, - UnpackSequenceList(Arg) = 220, - UnpackSequenceTuple(Arg) = 221, - UnpackSequenceTwoTuple(Arg) = 222, - InstrumentedResume(Arg) = 236, + UnpackSequenceList(OpArg) = 220, + UnpackSequenceTuple(OpArg) = 221, + UnpackSequenceTwoTuple(OpArg) = 222, + InstrumentedResume(OpArg) = 236, InstrumentedEndFor = 237, InstrumentedEndSend = 238, InstrumentedReturnValue = 239, - InstrumentedReturnConst(Arg) = 240, - InstrumentedYieldValue(Arg) = 241, - InstrumentedLoadSuperAttr(Arg) = 242, - InstrumentedForIter(Arg) = 243, - InstrumentedCall(Arg) = 244, - InstrumentedCallKw(Arg) = 245, + InstrumentedReturnConst(OpArg) = 240, + InstrumentedYieldValue(OpArg) = 241, + InstrumentedLoadSuperAttr(OpArg) = 242, + InstrumentedForIter(OpArg) = 243, + InstrumentedCall(OpArg) = 244, + InstrumentedCallKw(OpArg) = 245, InstrumentedCallFunctionEx = 246, InstrumentedInstruction = 247, - InstrumentedJumpForward(Arg) = 248, - InstrumentedJumpBackward(Arg) = 249, - InstrumentedPopJumpIfTrue(Arg) = 250, - InstrumentedPopJumpIfFalse(Arg) = 251, - InstrumentedPopJumpIfNone(Arg) = 252, - InstrumentedPopJumpIfNotNone(Arg) = 253, - Jump(Arg) = 256, - JumpNoInterrupt(Arg) = 257, - LoadClosure(Arg) = 258, - LoadMethod(Arg) = 259, - LoadSuperMethod(Arg) = 260, - LoadZeroSuperAttr(Arg) = 261, - LoadZeroSuperMethod(Arg) = 262, + InstrumentedJumpForward(OpArg) = 248, + InstrumentedJumpBackward(OpArg) = 249, + InstrumentedPopJumpIfTrue(OpArg) = 250, + InstrumentedPopJumpIfFalse(OpArg) = 251, + InstrumentedPopJumpIfNone(OpArg) = 252, + InstrumentedPopJumpIfNotNone(OpArg) = 253, + Jump(OpArg) = 256, + JumpNoInterrupt(OpArg) = 257, + LoadClosure(OpArg) = 258, + LoadMethod(OpArg) = 259, + LoadSuperMethod(OpArg) = 260, + LoadZeroSuperAttr(OpArg) = 261, + LoadZeroSuperMethod(OpArg) = 262, PopBlock = 263, SetupCleanup = 264, SetupFinally = 265, SetupWith = 266, - StoreFastMaybeNull(Arg) = 267, + StoreFastMaybeNull(OpArg) = 267, } impl Instruction { @@ -540,7 +540,7 @@ impl Instruction { } /// How many items should be popped from the stack. - const fn num_popped(&self) { + const fn num_popped(&self) -> u32 { match &self { Self::Cache => 0, Self::BeforeAsyncWith => 1, @@ -588,30 +588,30 @@ impl Instruction { Self::UnaryNot => 1, Self::WithExceptStart => 4, Self::BinaryOp(_) => 2, - Self::BuildConstKeyMap(oparg) => 1 + oparg, - Self::BuildList(oparg) => oparg, - Self::BuildMap(oparg) => oparg * 2, - Self::BuildSet(oparg) => oparg, - Self::BuildSlice(oparg) => 2 + (if (oparg == 3) { 1 } else { 0 }), - Self::BuildString(oparg) => oparg, - Self::BuildTuple(oparg) => oparg, - Self::Call(oparg) => 2 + oparg, - Self::CallFunctionEx(oparg) => 3 + (oparg & 1), + Self::BuildConstKeyMap(oparg) => 1 + oparg.0, + Self::BuildList(oparg) => oparg.0, + Self::BuildMap(oparg) => oparg.0 * 2, + Self::BuildSet(oparg) => oparg.0, + Self::BuildSlice(oparg) => 2 + (if oparg.0 == 3 { 1 } else { 0 }), + Self::BuildString(oparg) => oparg.0, + Self::BuildTuple(oparg) => oparg.0, + Self::Call(oparg) => 2 + oparg.0, + Self::CallFunctionEx(oparg) => 3 + (oparg.0 & 1), Self::CallIntrinsic1(_) => 1, Self::CallIntrinsic2(_) => 2, - Self::CallKw(oparg) => 3 + oparg, + Self::CallKw(oparg) => 3 + oparg.0, Self::CompareOp(_) => 2, Self::ContainsOp(_) => 2, Self::ConvertValue(_) => 1, - Self::Copy(oparg) => 1 + (oparg - 1), + Self::Copy(oparg) => 1 + (oparg.0 - 1), Self::CopyFreeVars(_) => 0, Self::DeleteAttr(_) => 1, Self::DeleteDeref(_) => 0, Self::DeleteFast(_) => 0, Self::DeleteGlobal(_) => 0, Self::DeleteName(_) => 0, - Self::DictMerge(oparg) => 5 + (oparg - 1), - Self::DictUpdate(oparg) => 2 + (oparg - 1), + Self::DictMerge(oparg) => 5 + (oparg.0 - 1), + Self::DictUpdate(oparg) => 2 + (oparg.0 - 1), Self::EnterExecutor(_) => 0, Self::ExtendedArg(_) => 0, Self::ForIter(_) => 1, @@ -622,8 +622,8 @@ impl Instruction { Self::JumpBackward(_) => 0, Self::JumpBackwardNoInterrupt(_) => 0, Self::JumpForward(_) => 0, - Self::ListAppend(oparg) => 2 + (oparg - 1), - Self::ListExtend(oparg) => 2 + (oparg - 1), + Self::ListAppend(oparg) => 2 + (oparg.0 - 1), + Self::ListExtend(oparg) => 2 + (oparg.0 - 1), Self::LoadAttr(_) => 1, Self::LoadConst(_) => 0, Self::LoadDeref(_) => 0, @@ -637,19 +637,19 @@ impl Instruction { Self::LoadName(_) => 0, Self::LoadSuperAttr(_) => 3, Self::MakeCell(_) => 0, - Self::MapAdd(oparg) => 3 + (oparg - 1), + Self::MapAdd(oparg) => 3 + (oparg.0 - 1), Self::MatchClass(_) => 3, Self::PopJumpIfFalse(_) => 1, Self::PopJumpIfNone(_) => 1, Self::PopJumpIfNotNone(_) => 1, Self::PopJumpIfTrue(_) => 1, - Self::RaiseVarargs(oparg) => oparg, - Self::Reraise(oparg) => 1 + oparg, + Self::RaiseVarargs(oparg) => oparg.0, + Self::Reraise(oparg) => 1 + oparg.0, Self::ReturnConst(_) => 0, Self::Send(_) => 2, - Self::SetAdd(oparg) => 2 + (oparg - 1), + Self::SetAdd(oparg) => 2 + (oparg.0 - 1), Self::SetFunctionAttribute(_) => 2, - Self::SetUpdate(oparg) => 2 + (oparg - 1), + Self::SetUpdate(oparg) => 2 + (oparg.0 - 1), Self::StoreAttr(_) => 2, Self::StoreDeref(_) => 1, Self::StoreFast(_) => 1, @@ -657,7 +657,7 @@ impl Instruction { Self::StoreFastStoreFast(_) => 2, Self::StoreGlobal(_) => 1, Self::StoreName(_) => 1, - Self::Swap(oparg) => 2 + (oparg - 2), + Self::Swap(oparg) => 2 + (oparg.0 - 2), Self::UnpackEx(_) => 1, Self::UnpackSequence(_) => 1, Self::YieldValue(_) => 1, @@ -674,23 +674,23 @@ impl Instruction { Self::BinarySubscrListInt => 2, Self::BinarySubscrStrInt => 2, Self::BinarySubscrTupleInt => 2, - Self::CallAllocAndEnterInit(oparg) => 2 + oparg, - Self::CallBoundMethodExactArgs(oparg) => 2 + oparg, - Self::CallBoundMethodGeneral(oparg) => 2 + oparg, - Self::CallBuiltinClass(oparg) => 2 + oparg, - Self::CallBuiltinFast(oparg) => 2 + oparg, - Self::CallBuiltinFastWithKeywords(oparg) => 2 + oparg, - Self::CallBuiltinO(oparg) => 2 + oparg, - Self::CallIsinstance(oparg) => 2 + oparg, - Self::CallLen(oparg) => 2 + oparg, + Self::CallAllocAndEnterInit(oparg) => 2 + oparg.0, + Self::CallBoundMethodExactArgs(oparg) => 2 + oparg.0, + Self::CallBoundMethodGeneral(oparg) => 2 + oparg.0, + Self::CallBuiltinClass(oparg) => 2 + oparg.0, + Self::CallBuiltinFast(oparg) => 2 + oparg.0, + Self::CallBuiltinFastWithKeywords(oparg) => 2 + oparg.0, + Self::CallBuiltinO(oparg) => 2 + oparg.0, + Self::CallIsinstance(oparg) => 2 + oparg.0, + Self::CallLen(oparg) => 2 + oparg.0, Self::CallListAppend(_) => 3, - Self::CallMethodDescriptorFast(oparg) => 2 + oparg, - Self::CallMethodDescriptorFastWithKeywords(oparg) => 2 + oparg, - Self::CallMethodDescriptorNoargs(oparg) => 2 + oparg, - Self::CallMethodDescriptorO(oparg) => 2 + oparg, - Self::CallNonPyGeneral(oparg) => 2 + oparg, - Self::CallPyExactArgs(oparg) => 2 + oparg, - Self::CallPyGeneral(oparg) => 2 + oparg, + Self::CallMethodDescriptorFast(oparg) => 2 + oparg.0, + Self::CallMethodDescriptorFastWithKeywords(oparg) => 2 + oparg.0, + Self::CallMethodDescriptorNoargs(oparg) => 2 + oparg.0, + Self::CallMethodDescriptorO(oparg) => 2 + oparg.0, + Self::CallNonPyGeneral(oparg) => 2 + oparg.0, + Self::CallPyExactArgs(oparg) => 2 + oparg.0, + Self::CallPyGeneral(oparg) => 2 + oparg.0, Self::CallStr1(_) => 3, Self::CallTuple1(_) => 3, Self::CallType1(_) => 3, @@ -758,7 +758,7 @@ impl Instruction { } /// How many items should be pushed on the stack. - const fn num_pushed(&self) { + const fn num_pushed(&self) -> u32 { match &self { Self::Cache => 0, Self::BeforeAsyncWith => 2, @@ -821,15 +821,15 @@ impl Instruction { Self::CompareOp(_) => 1, Self::ContainsOp(_) => 1, Self::ConvertValue(_) => 1, - Self::Copy(oparg) => 2 + (oparg - 1), + Self::Copy(oparg) => 2 + (oparg.0 - 1), Self::CopyFreeVars(_) => 0, Self::DeleteAttr(_) => 0, Self::DeleteDeref(_) => 0, Self::DeleteFast(_) => 0, Self::DeleteGlobal(_) => 0, Self::DeleteName(_) => 0, - Self::DictMerge(oparg) => 4 + (oparg - 1), - Self::DictUpdate(oparg) => 1 + (oparg - 1), + Self::DictMerge(oparg) => 4 + (oparg.0 - 1), + Self::DictUpdate(oparg) => 1 + (oparg.0 - 1), Self::EnterExecutor(_) => 0, Self::ExtendedArg(_) => 0, Self::ForIter(_) => 2, @@ -840,9 +840,9 @@ impl Instruction { Self::JumpBackward(_) => 0, Self::JumpBackwardNoInterrupt(_) => 0, Self::JumpForward(_) => 0, - Self::ListAppend(oparg) => 1 + (oparg - 1), - Self::ListExtend(oparg) => 1 + (oparg - 1), - Self::LoadAttr(oparg) => 1 + (oparg & 1), + Self::ListAppend(oparg) => 1 + (oparg.0 - 1), + Self::ListExtend(oparg) => 1 + (oparg.0 - 1), + Self::LoadAttr(oparg) => 1 + (oparg.0 & 1), Self::LoadConst(_) => 1, Self::LoadDeref(_) => 1, Self::LoadFast(_) => 1, @@ -851,23 +851,23 @@ impl Instruction { Self::LoadFastLoadFast(_) => 2, Self::LoadFromDictOrDeref(_) => 1, Self::LoadFromDictOrGlobals(_) => 1, - Self::LoadGlobal(oparg) => 1 + (oparg & 1), + Self::LoadGlobal(oparg) => 1 + (oparg.0 & 1), Self::LoadName(_) => 1, - Self::LoadSuperAttr(oparg) => 1 + (oparg & 1), + Self::LoadSuperAttr(oparg) => 1 + (oparg.0 & 1), Self::MakeCell(_) => 0, - Self::MapAdd(oparg) => 1 + (oparg - 1), + Self::MapAdd(oparg) => 1 + (oparg.0 - 1), Self::MatchClass(_) => 1, Self::PopJumpIfFalse(_) => 0, Self::PopJumpIfNone(_) => 0, Self::PopJumpIfNotNone(_) => 0, Self::PopJumpIfTrue(_) => 0, Self::RaiseVarargs(_) => 0, - Self::Reraise(oparg) => oparg, + Self::Reraise(oparg) => oparg.0, Self::ReturnConst(_) => 0, Self::Send(_) => 2, - Self::SetAdd(oparg) => 1 + (oparg - 1), + Self::SetAdd(oparg) => 1 + (oparg.0 - 1), Self::SetFunctionAttribute(_) => 1, - Self::SetUpdate(oparg) => 1 + (oparg - 1), + Self::SetUpdate(oparg) => 1 + (oparg.0 - 1), Self::StoreAttr(_) => 0, Self::StoreDeref(_) => 0, Self::StoreFast(_) => 0, @@ -875,9 +875,9 @@ impl Instruction { Self::StoreFastStoreFast(_) => 0, Self::StoreGlobal(_) => 0, Self::StoreName(_) => 0, - Self::Swap(oparg) => 2 + (oparg - 2), - Self::UnpackEx(oparg) => 1 + (oparg >> 8) + (oparg & 0xFF), - Self::UnpackSequence(oparg) => oparg, + Self::Swap(oparg) => 2 + (oparg.0 - 2), + Self::UnpackEx(oparg) => 1 + (oparg.0 >> 8) + (oparg.0 & 0xFF), + Self::UnpackSequence(oparg) => oparg.0, Self::YieldValue(_) => 1, Self::Resume(_) => 0, Self::BinaryOpAddFloat => 1, @@ -921,20 +921,20 @@ impl Instruction { Self::ForIterList(_) => 2, Self::ForIterRange(_) => 2, Self::ForIterTuple(_) => 2, - Self::LoadAttrClass(oparg) => 1 + (oparg & 1), + Self::LoadAttrClass(oparg) => 1 + (oparg.0 & 1), Self::LoadAttrGetattributeOverridden(_) => 1, - Self::LoadAttrInstanceValue(oparg) => 1 + (oparg & 1), + Self::LoadAttrInstanceValue(oparg) => 1 + (oparg.0 & 1), Self::LoadAttrMethodLazyDict(_) => 2, Self::LoadAttrMethodNoDict(_) => 2, Self::LoadAttrMethodWithValues(_) => 2, - Self::LoadAttrModule(oparg) => 1 + (oparg & 1), + Self::LoadAttrModule(oparg) => 1 + (oparg.0 & 1), Self::LoadAttrNondescriptorNoDict(_) => 1, Self::LoadAttrNondescriptorWithValues(_) => 1, Self::LoadAttrProperty(_) => 1, - Self::LoadAttrSlot(oparg) => 1 + (oparg & 1), - Self::LoadAttrWithHint(oparg) => 1 + (oparg & 1), - Self::LoadGlobalBuiltin(oparg) => 1 + (oparg & 1), - Self::LoadGlobalModule(oparg) => 1 + (oparg & 1), + Self::LoadAttrSlot(oparg) => 1 + (oparg.0 & 1), + Self::LoadAttrWithHint(oparg) => 1 + (oparg.0 & 1), + Self::LoadGlobalBuiltin(oparg) => 1 + (oparg.0 & 1), + Self::LoadGlobalModule(oparg) => 1 + (oparg.0 & 1), Self::LoadSuperAttrAttr(_) => 1, Self::LoadSuperAttrMethod(_) => 2, Self::ResumeCheck => 0, @@ -950,8 +950,8 @@ impl Instruction { Self::ToBoolList => 1, Self::ToBoolNone => 1, Self::ToBoolStr => 1, - Self::UnpackSequenceList(oparg) => oparg, - Self::UnpackSequenceTuple(oparg) => oparg, + Self::UnpackSequenceList(oparg) => oparg.0, + Self::UnpackSequenceTuple(oparg) => oparg.0, Self::UnpackSequenceTwoTuple(_) => 2, Self::InstrumentedResume(_) => 0, Self::InstrumentedEndFor => 1, @@ -959,7 +959,7 @@ impl Instruction { Self::InstrumentedReturnValue => 0, Self::InstrumentedReturnConst(_) => 0, Self::InstrumentedYieldValue(_) => 1, - Self::InstrumentedLoadSuperAttr(oparg) => 1 + (oparg & 1), + Self::InstrumentedLoadSuperAttr(oparg) => 1 + (oparg.0 & 1), Self::InstrumentedForIter(_) => 0, Self::InstrumentedCall(_) => 0, Self::InstrumentedCallKw(_) => 0, @@ -981,7 +981,7 @@ impl TryFrom for Instruction { fn try_from(id: u16) -> Result { if Self::is_valid(id) { - Ok(Self::new_unchecked(id)) + Ok(unsafe { Self::new_unchecked(id) }) } else { Err(Self::Error::InvalidBytecode) } diff --git a/scripts/gen_instructions.py b/scripts/gen_instructions.py index 955498b0d30..c1dbfd37e66 100755 --- a/scripts/gen_instructions.py +++ b/scripts/gen_instructions.py @@ -36,7 +36,7 @@ def _var_size(var): elif var.condition == "oparg & 1" and var.size == "1": return f"({var.condition})" else: - return f"(if ({var.condition}) {{ {var.size} }} else {{ 0 }})" + return f"(if {var.condition} {{ {var.size} }} else {{ 0 }})" else: return var.size @@ -77,7 +77,7 @@ def flags(self) -> frozenset[str]: def as_enum_member(self) -> str: out = self.name if self.has_oparg: - out += "(Arg)" # TODO: What should that be? + out += "(OpArg)" # TODO: What should that be? out += f" = {self.id}" return out @@ -190,7 +190,7 @@ def _generate_stack_effect(self, direction: str) -> str: elif direction == "pushed": val = stack.top_offset - stack.base_offset - expr = val.to_c() + expr = val.to_c().replace("oparg", "oparg.0") matched = ins.as_matched("oparg" if "oparg" in expr else "_") line = f"{matched} => {expr}" @@ -200,7 +200,7 @@ def _generate_stack_effect(self, direction: str) -> str: doc = "from" if direction == "popped" else "on" return f""" /// How many items should be {direction} {doc} the stack. -const fn num_{direction}(&self) {{ +const fn num_{direction}(&self) -> u32 {{ match &self {{ {conds}, _ => panic!("Pseudo opcodes are not allowed!") @@ -243,6 +243,8 @@ def main(): // This file is generated by {script_path} // Do not edit! +use crate::bytecode::{{OpArg}}; + /// A Single bytecode instruction. #[derive(Clone, Copy, Debug, Eq, PartialEq)] #[repr(u16)] @@ -286,7 +288,7 @@ def main(): fn try_from(id: u16) -> Result {{ if Self::is_valid(id) {{ - Ok(Self::new_unchecked(id)) + Ok(unsafe {{ Self::new_unchecked(id) }}) }} else {{ Err(Self::Error::InvalidBytecode) }} From eaee21e98b51676b74b9256d6428241405ecbdb8 Mon Sep 17 00:00:00 2001 From: ShaharNaveh <50263213+ShaharNaveh@users.noreply.github.com> Date: Fri, 26 Sep 2025 13:10:45 +0200 Subject: [PATCH 14/43] Sort like cpython does it --- compiler/core/src/instruction.rs | 928 +++++++++++++++---------------- scripts/gen_instructions.py | 4 +- 2 files changed, 466 insertions(+), 466 deletions(-) diff --git a/compiler/core/src/instruction.rs b/compiler/core/src/instruction.rs index 0a5ea7a3d3f..90e906a344f 100644 --- a/compiler/core/src/instruction.rs +++ b/compiler/core/src/instruction.rs @@ -7,52 +7,24 @@ use crate::bytecode::OpArg; #[derive(Clone, Copy, Debug, Eq, PartialEq)] #[repr(u16)] pub enum Instruction { - Cache = 0, BeforeAsyncWith = 1, BeforeWith = 2, + BinaryOp(OpArg) = 45, + BinaryOpAddFloat = 150, + BinaryOpAddInt = 151, + BinaryOpAddUnicode = 152, BinaryOpInplaceAddUnicode = 3, + BinaryOpMultiplyFloat = 153, + BinaryOpMultiplyInt = 154, + BinaryOpSubtractFloat = 155, + BinaryOpSubtractInt = 156, BinarySlice = 4, BinarySubscr = 5, - CheckEgMatch = 6, - CheckExcMatch = 7, - CleanupThrow = 8, - DeleteSubscr = 9, - EndAsyncFor = 10, - EndFor = 11, - EndSend = 12, - ExitInitCheck = 13, - FormatSimple = 14, - FormatWithSpec = 15, - GetAiter = 16, - Reserved = 17, - GetAnext = 18, - GetIter = 19, - GetLen = 20, - GetYieldFromIter = 21, - InterpreterExit = 22, - LoadAssertionError = 23, - LoadBuildClass = 24, - LoadLocals = 25, - MakeFunction = 26, - MatchKeys = 27, - MatchMapping = 28, - MatchSequence = 29, - Nop = 30, - PopExcept = 31, - PopTop = 32, - PushExcInfo = 33, - PushNull = 34, - ReturnGenerator = 35, - ReturnValue = 36, - SetupAnnotations = 37, - StoreSlice = 38, - StoreSubscr = 39, - ToBool = 40, - UnaryInvert = 41, - UnaryNegative = 42, - UnaryNot = 43, - WithExceptStart = 44, - BinaryOp(OpArg) = 45, + BinarySubscrDict = 157, + BinarySubscrGetitem = 158, + BinarySubscrListInt = 159, + BinarySubscrStrInt = 160, + BinarySubscrTupleInt = 161, BuildConstKeyMap(OpArg) = 46, BuildList(OpArg) = 47, BuildMap(OpArg) = 48, @@ -60,13 +32,42 @@ pub enum Instruction { BuildSlice(OpArg) = 50, BuildString(OpArg) = 51, BuildTuple(OpArg) = 52, + Cache = 0, Call(OpArg) = 53, + CallAllocAndEnterInit(OpArg) = 162, + CallBoundMethodExactArgs(OpArg) = 163, + CallBoundMethodGeneral(OpArg) = 164, + CallBuiltinClass(OpArg) = 165, + CallBuiltinFast(OpArg) = 166, + CallBuiltinFastWithKeywords(OpArg) = 167, + CallBuiltinO(OpArg) = 168, CallFunctionEx(OpArg) = 54, CallIntrinsic1(OpArg) = 55, CallIntrinsic2(OpArg) = 56, + CallIsinstance(OpArg) = 169, CallKw(OpArg) = 57, + CallLen(OpArg) = 170, + CallListAppend(OpArg) = 171, + CallMethodDescriptorFast(OpArg) = 172, + CallMethodDescriptorFastWithKeywords(OpArg) = 173, + CallMethodDescriptorNoargs(OpArg) = 174, + CallMethodDescriptorO(OpArg) = 175, + CallNonPyGeneral(OpArg) = 176, + CallPyExactArgs(OpArg) = 177, + CallPyGeneral(OpArg) = 178, + CallStr1(OpArg) = 179, + CallTuple1(OpArg) = 180, + CallType1(OpArg) = 181, + CheckEgMatch = 6, + CheckExcMatch = 7, + CleanupThrow = 8, CompareOp(OpArg) = 58, + CompareOpFloat(OpArg) = 182, + CompareOpInt(OpArg) = 183, + CompareOpStr(OpArg) = 184, ContainsOp(OpArg) = 59, + ContainsOpDict(OpArg) = 185, + ContainsOpSet(OpArg) = 186, ConvertValue(OpArg) = 60, Copy(OpArg) = 61, CopyFreeVars(OpArg) = 62, @@ -75,21 +76,70 @@ pub enum Instruction { DeleteFast(OpArg) = 65, DeleteGlobal(OpArg) = 66, DeleteName(OpArg) = 67, + DeleteSubscr = 9, DictMerge(OpArg) = 68, DictUpdate(OpArg) = 69, + EndAsyncFor = 10, + EndFor = 11, + EndSend = 12, EnterExecutor(OpArg) = 70, + ExitInitCheck = 13, ExtendedArg(OpArg) = 71, ForIter(OpArg) = 72, + ForIterGen(OpArg) = 187, + ForIterList(OpArg) = 188, + ForIterRange(OpArg) = 189, + ForIterTuple(OpArg) = 190, + FormatSimple = 14, + FormatWithSpec = 15, + GetAiter = 16, + GetAnext = 18, GetAwaitable(OpArg) = 73, + GetIter = 19, + GetLen = 20, + GetYieldFromIter = 21, ImportFrom(OpArg) = 74, ImportName(OpArg) = 75, + InstrumentedCall(OpArg) = 244, + InstrumentedCallFunctionEx = 246, + InstrumentedCallKw(OpArg) = 245, + InstrumentedEndFor = 237, + InstrumentedEndSend = 238, + InstrumentedForIter(OpArg) = 243, + InstrumentedInstruction = 247, + InstrumentedJumpBackward(OpArg) = 249, + InstrumentedJumpForward(OpArg) = 248, + InstrumentedLoadSuperAttr(OpArg) = 242, + InstrumentedPopJumpIfFalse(OpArg) = 251, + InstrumentedPopJumpIfNone(OpArg) = 252, + InstrumentedPopJumpIfNotNone(OpArg) = 253, + InstrumentedPopJumpIfTrue(OpArg) = 250, + InstrumentedResume(OpArg) = 236, + InstrumentedReturnConst(OpArg) = 240, + InstrumentedReturnValue = 239, + InstrumentedYieldValue(OpArg) = 241, + InterpreterExit = 22, IsOp(OpArg) = 76, JumpBackward(OpArg) = 77, JumpBackwardNoInterrupt(OpArg) = 78, JumpForward(OpArg) = 79, ListAppend(OpArg) = 80, ListExtend(OpArg) = 81, + LoadAssertionError = 23, LoadAttr(OpArg) = 82, + LoadAttrClass(OpArg) = 191, + LoadAttrGetattributeOverridden(OpArg) = 192, + LoadAttrInstanceValue(OpArg) = 193, + LoadAttrMethodLazyDict(OpArg) = 194, + LoadAttrMethodNoDict(OpArg) = 195, + LoadAttrMethodWithValues(OpArg) = 196, + LoadAttrModule(OpArg) = 197, + LoadAttrNondescriptorNoDict(OpArg) = 198, + LoadAttrNondescriptorWithValues(OpArg) = 199, + LoadAttrProperty(OpArg) = 200, + LoadAttrSlot(OpArg) = 201, + LoadAttrWithHint(OpArg) = 202, + LoadBuildClass = 24, LoadConst(OpArg) = 83, LoadDeref(OpArg) = 84, LoadFast(OpArg) = 85, @@ -99,125 +149,75 @@ pub enum Instruction { LoadFromDictOrDeref(OpArg) = 89, LoadFromDictOrGlobals(OpArg) = 90, LoadGlobal(OpArg) = 91, + LoadGlobalBuiltin(OpArg) = 203, + LoadGlobalModule(OpArg) = 204, + LoadLocals = 25, LoadName(OpArg) = 92, LoadSuperAttr(OpArg) = 93, + LoadSuperAttrAttr(OpArg) = 205, + LoadSuperAttrMethod(OpArg) = 206, MakeCell(OpArg) = 94, + MakeFunction = 26, MapAdd(OpArg) = 95, MatchClass(OpArg) = 96, + MatchKeys = 27, + MatchMapping = 28, + MatchSequence = 29, + Nop = 30, + PopExcept = 31, PopJumpIfFalse(OpArg) = 97, PopJumpIfNone(OpArg) = 98, PopJumpIfNotNone(OpArg) = 99, PopJumpIfTrue(OpArg) = 100, + PopTop = 32, + PushExcInfo = 33, + PushNull = 34, RaiseVarargs(OpArg) = 101, Reraise(OpArg) = 102, + Reserved = 17, + Resume(OpArg) = 149, + ResumeCheck = 207, ReturnConst(OpArg) = 103, + ReturnGenerator = 35, + ReturnValue = 36, Send(OpArg) = 104, + SendGen(OpArg) = 208, SetAdd(OpArg) = 105, SetFunctionAttribute(OpArg) = 106, SetUpdate(OpArg) = 107, + SetupAnnotations = 37, StoreAttr(OpArg) = 108, + StoreAttrInstanceValue = 209, + StoreAttrSlot = 210, + StoreAttrWithHint(OpArg) = 211, StoreDeref(OpArg) = 109, StoreFast(OpArg) = 110, StoreFastLoadFast(OpArg) = 111, StoreFastStoreFast(OpArg) = 112, StoreGlobal(OpArg) = 113, StoreName(OpArg) = 114, - Swap(OpArg) = 115, - UnpackEx(OpArg) = 116, - UnpackSequence(OpArg) = 117, - YieldValue(OpArg) = 118, - Resume(OpArg) = 149, - BinaryOpAddFloat = 150, - BinaryOpAddInt = 151, - BinaryOpAddUnicode = 152, - BinaryOpMultiplyFloat = 153, - BinaryOpMultiplyInt = 154, - BinaryOpSubtractFloat = 155, - BinaryOpSubtractInt = 156, - BinarySubscrDict = 157, - BinarySubscrGetitem = 158, - BinarySubscrListInt = 159, - BinarySubscrStrInt = 160, - BinarySubscrTupleInt = 161, - CallAllocAndEnterInit(OpArg) = 162, - CallBoundMethodExactArgs(OpArg) = 163, - CallBoundMethodGeneral(OpArg) = 164, - CallBuiltinClass(OpArg) = 165, - CallBuiltinFast(OpArg) = 166, - CallBuiltinFastWithKeywords(OpArg) = 167, - CallBuiltinO(OpArg) = 168, - CallIsinstance(OpArg) = 169, - CallLen(OpArg) = 170, - CallListAppend(OpArg) = 171, - CallMethodDescriptorFast(OpArg) = 172, - CallMethodDescriptorFastWithKeywords(OpArg) = 173, - CallMethodDescriptorNoargs(OpArg) = 174, - CallMethodDescriptorO(OpArg) = 175, - CallNonPyGeneral(OpArg) = 176, - CallPyExactArgs(OpArg) = 177, - CallPyGeneral(OpArg) = 178, - CallStr1(OpArg) = 179, - CallTuple1(OpArg) = 180, - CallType1(OpArg) = 181, - CompareOpFloat(OpArg) = 182, - CompareOpInt(OpArg) = 183, - CompareOpStr(OpArg) = 184, - ContainsOpDict(OpArg) = 185, - ContainsOpSet(OpArg) = 186, - ForIterGen(OpArg) = 187, - ForIterList(OpArg) = 188, - ForIterRange(OpArg) = 189, - ForIterTuple(OpArg) = 190, - LoadAttrClass(OpArg) = 191, - LoadAttrGetattributeOverridden(OpArg) = 192, - LoadAttrInstanceValue(OpArg) = 193, - LoadAttrMethodLazyDict(OpArg) = 194, - LoadAttrMethodNoDict(OpArg) = 195, - LoadAttrMethodWithValues(OpArg) = 196, - LoadAttrModule(OpArg) = 197, - LoadAttrNondescriptorNoDict(OpArg) = 198, - LoadAttrNondescriptorWithValues(OpArg) = 199, - LoadAttrProperty(OpArg) = 200, - LoadAttrSlot(OpArg) = 201, - LoadAttrWithHint(OpArg) = 202, - LoadGlobalBuiltin(OpArg) = 203, - LoadGlobalModule(OpArg) = 204, - LoadSuperAttrAttr(OpArg) = 205, - LoadSuperAttrMethod(OpArg) = 206, - ResumeCheck = 207, - SendGen(OpArg) = 208, - StoreAttrInstanceValue = 209, - StoreAttrSlot = 210, - StoreAttrWithHint(OpArg) = 211, + StoreSlice = 38, + StoreSubscr = 39, StoreSubscrDict = 212, StoreSubscrListInt = 213, + Swap(OpArg) = 115, + ToBool = 40, ToBoolAlwaysTrue = 214, ToBoolBool = 215, ToBoolInt = 216, ToBoolList = 217, ToBoolNone = 218, ToBoolStr = 219, + UnaryInvert = 41, + UnaryNegative = 42, + UnaryNot = 43, + UnpackEx(OpArg) = 116, + UnpackSequence(OpArg) = 117, UnpackSequenceList(OpArg) = 220, UnpackSequenceTuple(OpArg) = 221, UnpackSequenceTwoTuple(OpArg) = 222, - InstrumentedResume(OpArg) = 236, - InstrumentedEndFor = 237, - InstrumentedEndSend = 238, - InstrumentedReturnValue = 239, - InstrumentedReturnConst(OpArg) = 240, - InstrumentedYieldValue(OpArg) = 241, - InstrumentedLoadSuperAttr(OpArg) = 242, - InstrumentedForIter(OpArg) = 243, - InstrumentedCall(OpArg) = 244, - InstrumentedCallKw(OpArg) = 245, - InstrumentedCallFunctionEx = 246, - InstrumentedInstruction = 247, - InstrumentedJumpForward(OpArg) = 248, - InstrumentedJumpBackward(OpArg) = 249, - InstrumentedPopJumpIfTrue(OpArg) = 250, - InstrumentedPopJumpIfFalse(OpArg) = 251, - InstrumentedPopJumpIfNone(OpArg) = 252, - InstrumentedPopJumpIfNotNone(OpArg) = 253, + WithExceptStart = 44, + YieldValue(OpArg) = 118, Jump(OpArg) = 256, JumpNoInterrupt(OpArg) = 257, LoadClosure(OpArg) = 258, @@ -280,12 +280,37 @@ impl Instruction { | Self::BuildString(_) | Self::BuildTuple(_) | Self::Call(_) - | Self::CallFunctionEx(_) - | Self::CallIntrinsic1(_) - | Self::CallIntrinsic2(_) - | Self::CallKw(_) + | Self::CallAllocAndEnterInit(_) + | Self::CallBoundMethodExactArgs(_) + | Self::CallBoundMethodGeneral(_) + | Self::CallBuiltinClass(_) + | Self::CallBuiltinFast(_) + | Self::CallBuiltinFastWithKeywords(_) + | Self::CallBuiltinO(_) + | Self::CallFunctionEx(_) + | Self::CallIntrinsic1(_) + | Self::CallIntrinsic2(_) + | Self::CallIsinstance(_) + | Self::CallKw(_) + | Self::CallLen(_) + | Self::CallListAppend(_) + | Self::CallMethodDescriptorFast(_) + | Self::CallMethodDescriptorFastWithKeywords(_) + | Self::CallMethodDescriptorNoargs(_) + | Self::CallMethodDescriptorO(_) + | Self::CallNonPyGeneral(_) + | Self::CallPyExactArgs(_) + | Self::CallPyGeneral(_) + | Self::CallStr1(_) + | Self::CallTuple1(_) + | Self::CallType1(_) | Self::CompareOp(_) + | Self::CompareOpFloat(_) + | Self::CompareOpInt(_) + | Self::CompareOpStr(_) | Self::ContainsOp(_) + | Self::ContainsOpDict(_) + | Self::ContainsOpSet(_) | Self::ConvertValue(_) | Self::Copy(_) | Self::CopyFreeVars(_) @@ -299,9 +324,26 @@ impl Instruction { | Self::EnterExecutor(_) | Self::ExtendedArg(_) | Self::ForIter(_) + | Self::ForIterGen(_) + | Self::ForIterList(_) + | Self::ForIterRange(_) + | Self::ForIterTuple(_) | Self::GetAwaitable(_) | Self::ImportFrom(_) | Self::ImportName(_) + | Self::InstrumentedCall(_) + | Self::InstrumentedCallKw(_) + | Self::InstrumentedForIter(_) + | Self::InstrumentedJumpBackward(_) + | Self::InstrumentedJumpForward(_) + | Self::InstrumentedLoadSuperAttr(_) + | Self::InstrumentedPopJumpIfFalse(_) + | Self::InstrumentedPopJumpIfNone(_) + | Self::InstrumentedPopJumpIfNotNone(_) + | Self::InstrumentedPopJumpIfTrue(_) + | Self::InstrumentedResume(_) + | Self::InstrumentedReturnConst(_) + | Self::InstrumentedYieldValue(_) | Self::IsOp(_) | Self::JumpBackward(_) | Self::JumpBackwardNoInterrupt(_) @@ -309,6 +351,18 @@ impl Instruction { | Self::ListAppend(_) | Self::ListExtend(_) | Self::LoadAttr(_) + | Self::LoadAttrClass(_) + | Self::LoadAttrGetattributeOverridden(_) + | Self::LoadAttrInstanceValue(_) + | Self::LoadAttrMethodLazyDict(_) + | Self::LoadAttrMethodNoDict(_) + | Self::LoadAttrMethodWithValues(_) + | Self::LoadAttrModule(_) + | Self::LoadAttrNondescriptorNoDict(_) + | Self::LoadAttrNondescriptorWithValues(_) + | Self::LoadAttrProperty(_) + | Self::LoadAttrSlot(_) + | Self::LoadAttrWithHint(_) | Self::LoadConst(_) | Self::LoadDeref(_) | Self::LoadFast(_) @@ -318,8 +372,12 @@ impl Instruction { | Self::LoadFromDictOrDeref(_) | Self::LoadFromDictOrGlobals(_) | Self::LoadGlobal(_) + | Self::LoadGlobalBuiltin(_) + | Self::LoadGlobalModule(_) | Self::LoadName(_) | Self::LoadSuperAttr(_) + | Self::LoadSuperAttrAttr(_) + | Self::LoadSuperAttrMethod(_) | Self::MakeCell(_) | Self::MapAdd(_) | Self::MatchClass(_) @@ -329,12 +387,15 @@ impl Instruction { | Self::PopJumpIfTrue(_) | Self::RaiseVarargs(_) | Self::Reraise(_) + | Self::Resume(_) | Self::ReturnConst(_) | Self::Send(_) + | Self::SendGen(_) | Self::SetAdd(_) | Self::SetFunctionAttribute(_) | Self::SetUpdate(_) | Self::StoreAttr(_) + | Self::StoreAttrWithHint(_) | Self::StoreDeref(_) | Self::StoreFast(_) | Self::StoreFastLoadFast(_) @@ -344,71 +405,10 @@ impl Instruction { | Self::Swap(_) | Self::UnpackEx(_) | Self::UnpackSequence(_) - | Self::YieldValue(_) - | Self::Resume(_) - | Self::CallAllocAndEnterInit(_) - | Self::CallBoundMethodExactArgs(_) - | Self::CallBoundMethodGeneral(_) - | Self::CallBuiltinClass(_) - | Self::CallBuiltinFast(_) - | Self::CallBuiltinFastWithKeywords(_) - | Self::CallBuiltinO(_) - | Self::CallIsinstance(_) - | Self::CallLen(_) - | Self::CallListAppend(_) - | Self::CallMethodDescriptorFast(_) - | Self::CallMethodDescriptorFastWithKeywords(_) - | Self::CallMethodDescriptorNoargs(_) - | Self::CallMethodDescriptorO(_) - | Self::CallNonPyGeneral(_) - | Self::CallPyExactArgs(_) - | Self::CallPyGeneral(_) - | Self::CallStr1(_) - | Self::CallTuple1(_) - | Self::CallType1(_) - | Self::CompareOpFloat(_) - | Self::CompareOpInt(_) - | Self::CompareOpStr(_) - | Self::ContainsOpDict(_) - | Self::ContainsOpSet(_) - | Self::ForIterGen(_) - | Self::ForIterList(_) - | Self::ForIterRange(_) - | Self::ForIterTuple(_) - | Self::LoadAttrClass(_) - | Self::LoadAttrGetattributeOverridden(_) - | Self::LoadAttrInstanceValue(_) - | Self::LoadAttrMethodLazyDict(_) - | Self::LoadAttrMethodNoDict(_) - | Self::LoadAttrMethodWithValues(_) - | Self::LoadAttrModule(_) - | Self::LoadAttrNondescriptorNoDict(_) - | Self::LoadAttrNondescriptorWithValues(_) - | Self::LoadAttrProperty(_) - | Self::LoadAttrSlot(_) - | Self::LoadAttrWithHint(_) - | Self::LoadGlobalBuiltin(_) - | Self::LoadGlobalModule(_) - | Self::LoadSuperAttrAttr(_) - | Self::LoadSuperAttrMethod(_) - | Self::SendGen(_) - | Self::StoreAttrWithHint(_) | Self::UnpackSequenceList(_) | Self::UnpackSequenceTuple(_) | Self::UnpackSequenceTwoTuple(_) - | Self::InstrumentedResume(_) - | Self::InstrumentedReturnConst(_) - | Self::InstrumentedYieldValue(_) - | Self::InstrumentedLoadSuperAttr(_) - | Self::InstrumentedForIter(_) - | Self::InstrumentedCall(_) - | Self::InstrumentedCallKw(_) - | Self::InstrumentedJumpForward(_) - | Self::InstrumentedJumpBackward(_) - | Self::InstrumentedPopJumpIfTrue(_) - | Self::InstrumentedPopJumpIfFalse(_) - | Self::InstrumentedPopJumpIfNone(_) - | Self::InstrumentedPopJumpIfNotNone(_) + | Self::YieldValue(_) | Self::Jump(_) | Self::JumpNoInterrupt(_) | Self::LoadClosure(_) @@ -428,7 +428,7 @@ impl Instruction { pub const fn has_const(&self) -> bool { matches!( self, - Self::LoadConst(_) | Self::ReturnConst(_) | Self::InstrumentedReturnConst(_) + Self::InstrumentedReturnConst(_) | Self::LoadConst(_) | Self::ReturnConst(_) ) } @@ -443,18 +443,18 @@ impl Instruction { | Self::ImportFrom(_) | Self::ImportName(_) | Self::LoadAttr(_) + | Self::LoadAttrGetattributeOverridden(_) + | Self::LoadAttrWithHint(_) | Self::LoadFromDictOrGlobals(_) | Self::LoadGlobal(_) | Self::LoadName(_) | Self::LoadSuperAttr(_) - | Self::StoreAttr(_) - | Self::StoreGlobal(_) - | Self::StoreName(_) - | Self::LoadAttrGetattributeOverridden(_) - | Self::LoadAttrWithHint(_) | Self::LoadSuperAttrAttr(_) | Self::LoadSuperAttrMethod(_) + | Self::StoreAttr(_) | Self::StoreAttrWithHint(_) + | Self::StoreGlobal(_) + | Self::StoreName(_) | Self::LoadMethod(_) | Self::LoadSuperMethod(_) | Self::LoadZeroSuperAttr(_) @@ -468,6 +468,9 @@ impl Instruction { matches!( self, Self::ForIter(_) + | Self::ForIterList(_) + | Self::ForIterRange(_) + | Self::ForIterTuple(_) | Self::JumpBackward(_) | Self::JumpBackwardNoInterrupt(_) | Self::JumpForward(_) @@ -476,9 +479,6 @@ impl Instruction { | Self::PopJumpIfNotNone(_) | Self::PopJumpIfTrue(_) | Self::Send(_) - | Self::ForIterList(_) - | Self::ForIterRange(_) - | Self::ForIterTuple(_) | Self::Jump(_) | Self::JumpNoInterrupt(_) ) @@ -521,16 +521,16 @@ impl Instruction { pub const fn has_exc(&self) -> bool { matches!( self, - Self::EndFor + Self::Copy(_) + | Self::EndFor | Self::EndSend + | Self::LoadConst(_) + | Self::LoadFast(_) | Self::Nop | Self::PopTop | Self::PushNull - | Self::UnaryNot - | Self::Copy(_) - | Self::LoadConst(_) - | Self::LoadFast(_) | Self::Swap(_) + | Self::UnaryNot | Self::LoadClosure(_) | Self::PopBlock | Self::SetupCleanup @@ -542,52 +542,24 @@ impl Instruction { /// How many items should be popped from the stack. const fn num_popped(&self) -> u32 { match &self { - Self::Cache => 0, Self::BeforeAsyncWith => 1, Self::BeforeWith => 1, + Self::BinaryOp(_) => 2, + Self::BinaryOpAddFloat => 2, + Self::BinaryOpAddInt => 2, + Self::BinaryOpAddUnicode => 2, Self::BinaryOpInplaceAddUnicode => 2, + Self::BinaryOpMultiplyFloat => 2, + Self::BinaryOpMultiplyInt => 2, + Self::BinaryOpSubtractFloat => 2, + Self::BinaryOpSubtractInt => 2, Self::BinarySlice => 3, Self::BinarySubscr => 2, - Self::CheckEgMatch => 2, - Self::CheckExcMatch => 2, - Self::CleanupThrow => 3, - Self::DeleteSubscr => 2, - Self::EndAsyncFor => 2, - Self::EndFor => 1, - Self::EndSend => 2, - Self::ExitInitCheck => 1, - Self::FormatSimple => 1, - Self::FormatWithSpec => 2, - Self::GetAiter => 1, - Self::Reserved => 0, - Self::GetAnext => 1, - Self::GetIter => 1, - Self::GetLen => 1, - Self::GetYieldFromIter => 1, - Self::InterpreterExit => 1, - Self::LoadAssertionError => 0, - Self::LoadBuildClass => 0, - Self::LoadLocals => 0, - Self::MakeFunction => 1, - Self::MatchKeys => 2, - Self::MatchMapping => 1, - Self::MatchSequence => 1, - Self::Nop => 0, - Self::PopExcept => 1, - Self::PopTop => 1, - Self::PushExcInfo => 1, - Self::PushNull => 0, - Self::ReturnGenerator => 0, - Self::ReturnValue => 1, - Self::SetupAnnotations => 0, - Self::StoreSlice => 4, - Self::StoreSubscr => 3, - Self::ToBool => 1, - Self::UnaryInvert => 1, - Self::UnaryNegative => 1, - Self::UnaryNot => 1, - Self::WithExceptStart => 4, - Self::BinaryOp(_) => 2, + Self::BinarySubscrDict => 2, + Self::BinarySubscrGetitem => 2, + Self::BinarySubscrListInt => 2, + Self::BinarySubscrStrInt => 2, + Self::BinarySubscrTupleInt => 2, Self::BuildConstKeyMap(oparg) => 1 + oparg.0, Self::BuildList(oparg) => oparg.0, Self::BuildMap(oparg) => oparg.0 * 2, @@ -595,13 +567,42 @@ impl Instruction { Self::BuildSlice(oparg) => 2 + (if oparg.0 == 3 { 1 } else { 0 }), Self::BuildString(oparg) => oparg.0, Self::BuildTuple(oparg) => oparg.0, + Self::Cache => 0, Self::Call(oparg) => 2 + oparg.0, + Self::CallAllocAndEnterInit(oparg) => 2 + oparg.0, + Self::CallBoundMethodExactArgs(oparg) => 2 + oparg.0, + Self::CallBoundMethodGeneral(oparg) => 2 + oparg.0, + Self::CallBuiltinClass(oparg) => 2 + oparg.0, + Self::CallBuiltinFast(oparg) => 2 + oparg.0, + Self::CallBuiltinFastWithKeywords(oparg) => 2 + oparg.0, + Self::CallBuiltinO(oparg) => 2 + oparg.0, Self::CallFunctionEx(oparg) => 3 + (oparg.0 & 1), Self::CallIntrinsic1(_) => 1, Self::CallIntrinsic2(_) => 2, + Self::CallIsinstance(oparg) => 2 + oparg.0, Self::CallKw(oparg) => 3 + oparg.0, + Self::CallLen(oparg) => 2 + oparg.0, + Self::CallListAppend(_) => 3, + Self::CallMethodDescriptorFast(oparg) => 2 + oparg.0, + Self::CallMethodDescriptorFastWithKeywords(oparg) => 2 + oparg.0, + Self::CallMethodDescriptorNoargs(oparg) => 2 + oparg.0, + Self::CallMethodDescriptorO(oparg) => 2 + oparg.0, + Self::CallNonPyGeneral(oparg) => 2 + oparg.0, + Self::CallPyExactArgs(oparg) => 2 + oparg.0, + Self::CallPyGeneral(oparg) => 2 + oparg.0, + Self::CallStr1(_) => 3, + Self::CallTuple1(_) => 3, + Self::CallType1(_) => 3, + Self::CheckEgMatch => 2, + Self::CheckExcMatch => 2, + Self::CleanupThrow => 3, Self::CompareOp(_) => 2, + Self::CompareOpFloat(_) => 2, + Self::CompareOpInt(_) => 2, + Self::CompareOpStr(_) => 2, Self::ContainsOp(_) => 2, + Self::ContainsOpDict(_) => 2, + Self::ContainsOpSet(_) => 2, Self::ConvertValue(_) => 1, Self::Copy(oparg) => 1 + (oparg.0 - 1), Self::CopyFreeVars(_) => 0, @@ -610,21 +611,70 @@ impl Instruction { Self::DeleteFast(_) => 0, Self::DeleteGlobal(_) => 0, Self::DeleteName(_) => 0, + Self::DeleteSubscr => 2, Self::DictMerge(oparg) => 5 + (oparg.0 - 1), Self::DictUpdate(oparg) => 2 + (oparg.0 - 1), + Self::EndAsyncFor => 2, + Self::EndFor => 1, + Self::EndSend => 2, Self::EnterExecutor(_) => 0, + Self::ExitInitCheck => 1, Self::ExtendedArg(_) => 0, Self::ForIter(_) => 1, + Self::ForIterGen(_) => 1, + Self::ForIterList(_) => 1, + Self::ForIterRange(_) => 1, + Self::ForIterTuple(_) => 1, + Self::FormatSimple => 1, + Self::FormatWithSpec => 2, + Self::GetAiter => 1, + Self::GetAnext => 1, Self::GetAwaitable(_) => 1, + Self::GetIter => 1, + Self::GetLen => 1, + Self::GetYieldFromIter => 1, Self::ImportFrom(_) => 1, Self::ImportName(_) => 2, - Self::IsOp(_) => 2, - Self::JumpBackward(_) => 0, - Self::JumpBackwardNoInterrupt(_) => 0, - Self::JumpForward(_) => 0, - Self::ListAppend(oparg) => 2 + (oparg.0 - 1), - Self::ListExtend(oparg) => 2 + (oparg.0 - 1), + Self::InstrumentedCall(_) => 0, + Self::InstrumentedCallFunctionEx => 0, + Self::InstrumentedCallKw(_) => 0, + Self::InstrumentedEndFor => 2, + Self::InstrumentedEndSend => 2, + Self::InstrumentedForIter(_) => 0, + Self::InstrumentedInstruction => 0, + Self::InstrumentedJumpBackward(_) => 0, + Self::InstrumentedJumpForward(_) => 0, + Self::InstrumentedLoadSuperAttr(_) => 3, + Self::InstrumentedPopJumpIfFalse(_) => 0, + Self::InstrumentedPopJumpIfNone(_) => 0, + Self::InstrumentedPopJumpIfNotNone(_) => 0, + Self::InstrumentedPopJumpIfTrue(_) => 0, + Self::InstrumentedResume(_) => 0, + Self::InstrumentedReturnConst(_) => 0, + Self::InstrumentedReturnValue => 1, + Self::InstrumentedYieldValue(_) => 1, + Self::InterpreterExit => 1, + Self::IsOp(_) => 2, + Self::JumpBackward(_) => 0, + Self::JumpBackwardNoInterrupt(_) => 0, + Self::JumpForward(_) => 0, + Self::ListAppend(oparg) => 2 + (oparg.0 - 1), + Self::ListExtend(oparg) => 2 + (oparg.0 - 1), + Self::LoadAssertionError => 0, Self::LoadAttr(_) => 1, + Self::LoadAttrClass(_) => 1, + Self::LoadAttrGetattributeOverridden(_) => 1, + Self::LoadAttrInstanceValue(_) => 1, + Self::LoadAttrMethodLazyDict(_) => 1, + Self::LoadAttrMethodNoDict(_) => 1, + Self::LoadAttrMethodWithValues(_) => 1, + Self::LoadAttrModule(_) => 1, + Self::LoadAttrNondescriptorNoDict(_) => 1, + Self::LoadAttrNondescriptorWithValues(_) => 1, + Self::LoadAttrProperty(_) => 1, + Self::LoadAttrSlot(_) => 1, + Self::LoadAttrWithHint(_) => 1, + Self::LoadBuildClass => 0, Self::LoadConst(_) => 0, Self::LoadDeref(_) => 0, Self::LoadFast(_) => 0, @@ -634,125 +684,75 @@ impl Instruction { Self::LoadFromDictOrDeref(_) => 1, Self::LoadFromDictOrGlobals(_) => 1, Self::LoadGlobal(_) => 0, + Self::LoadGlobalBuiltin(_) => 0, + Self::LoadGlobalModule(_) => 0, + Self::LoadLocals => 0, Self::LoadName(_) => 0, Self::LoadSuperAttr(_) => 3, + Self::LoadSuperAttrAttr(_) => 3, + Self::LoadSuperAttrMethod(_) => 3, Self::MakeCell(_) => 0, + Self::MakeFunction => 1, Self::MapAdd(oparg) => 3 + (oparg.0 - 1), Self::MatchClass(_) => 3, + Self::MatchKeys => 2, + Self::MatchMapping => 1, + Self::MatchSequence => 1, + Self::Nop => 0, + Self::PopExcept => 1, Self::PopJumpIfFalse(_) => 1, Self::PopJumpIfNone(_) => 1, Self::PopJumpIfNotNone(_) => 1, Self::PopJumpIfTrue(_) => 1, + Self::PopTop => 1, + Self::PushExcInfo => 1, + Self::PushNull => 0, Self::RaiseVarargs(oparg) => oparg.0, Self::Reraise(oparg) => 1 + oparg.0, + Self::Reserved => 0, + Self::Resume(_) => 0, + Self::ResumeCheck => 0, Self::ReturnConst(_) => 0, + Self::ReturnGenerator => 0, + Self::ReturnValue => 1, Self::Send(_) => 2, + Self::SendGen(_) => 2, Self::SetAdd(oparg) => 2 + (oparg.0 - 1), Self::SetFunctionAttribute(_) => 2, Self::SetUpdate(oparg) => 2 + (oparg.0 - 1), + Self::SetupAnnotations => 0, Self::StoreAttr(_) => 2, + Self::StoreAttrInstanceValue => 2, + Self::StoreAttrSlot => 2, + Self::StoreAttrWithHint(_) => 2, Self::StoreDeref(_) => 1, Self::StoreFast(_) => 1, Self::StoreFastLoadFast(_) => 1, Self::StoreFastStoreFast(_) => 2, Self::StoreGlobal(_) => 1, Self::StoreName(_) => 1, - Self::Swap(oparg) => 2 + (oparg.0 - 2), - Self::UnpackEx(_) => 1, - Self::UnpackSequence(_) => 1, - Self::YieldValue(_) => 1, - Self::Resume(_) => 0, - Self::BinaryOpAddFloat => 2, - Self::BinaryOpAddInt => 2, - Self::BinaryOpAddUnicode => 2, - Self::BinaryOpMultiplyFloat => 2, - Self::BinaryOpMultiplyInt => 2, - Self::BinaryOpSubtractFloat => 2, - Self::BinaryOpSubtractInt => 2, - Self::BinarySubscrDict => 2, - Self::BinarySubscrGetitem => 2, - Self::BinarySubscrListInt => 2, - Self::BinarySubscrStrInt => 2, - Self::BinarySubscrTupleInt => 2, - Self::CallAllocAndEnterInit(oparg) => 2 + oparg.0, - Self::CallBoundMethodExactArgs(oparg) => 2 + oparg.0, - Self::CallBoundMethodGeneral(oparg) => 2 + oparg.0, - Self::CallBuiltinClass(oparg) => 2 + oparg.0, - Self::CallBuiltinFast(oparg) => 2 + oparg.0, - Self::CallBuiltinFastWithKeywords(oparg) => 2 + oparg.0, - Self::CallBuiltinO(oparg) => 2 + oparg.0, - Self::CallIsinstance(oparg) => 2 + oparg.0, - Self::CallLen(oparg) => 2 + oparg.0, - Self::CallListAppend(_) => 3, - Self::CallMethodDescriptorFast(oparg) => 2 + oparg.0, - Self::CallMethodDescriptorFastWithKeywords(oparg) => 2 + oparg.0, - Self::CallMethodDescriptorNoargs(oparg) => 2 + oparg.0, - Self::CallMethodDescriptorO(oparg) => 2 + oparg.0, - Self::CallNonPyGeneral(oparg) => 2 + oparg.0, - Self::CallPyExactArgs(oparg) => 2 + oparg.0, - Self::CallPyGeneral(oparg) => 2 + oparg.0, - Self::CallStr1(_) => 3, - Self::CallTuple1(_) => 3, - Self::CallType1(_) => 3, - Self::CompareOpFloat(_) => 2, - Self::CompareOpInt(_) => 2, - Self::CompareOpStr(_) => 2, - Self::ContainsOpDict(_) => 2, - Self::ContainsOpSet(_) => 2, - Self::ForIterGen(_) => 1, - Self::ForIterList(_) => 1, - Self::ForIterRange(_) => 1, - Self::ForIterTuple(_) => 1, - Self::LoadAttrClass(_) => 1, - Self::LoadAttrGetattributeOverridden(_) => 1, - Self::LoadAttrInstanceValue(_) => 1, - Self::LoadAttrMethodLazyDict(_) => 1, - Self::LoadAttrMethodNoDict(_) => 1, - Self::LoadAttrMethodWithValues(_) => 1, - Self::LoadAttrModule(_) => 1, - Self::LoadAttrNondescriptorNoDict(_) => 1, - Self::LoadAttrNondescriptorWithValues(_) => 1, - Self::LoadAttrProperty(_) => 1, - Self::LoadAttrSlot(_) => 1, - Self::LoadAttrWithHint(_) => 1, - Self::LoadGlobalBuiltin(_) => 0, - Self::LoadGlobalModule(_) => 0, - Self::LoadSuperAttrAttr(_) => 3, - Self::LoadSuperAttrMethod(_) => 3, - Self::ResumeCheck => 0, - Self::SendGen(_) => 2, - Self::StoreAttrInstanceValue => 2, - Self::StoreAttrSlot => 2, - Self::StoreAttrWithHint(_) => 2, + Self::StoreSlice => 4, + Self::StoreSubscr => 3, Self::StoreSubscrDict => 3, Self::StoreSubscrListInt => 3, + Self::Swap(oparg) => 2 + (oparg.0 - 2), + Self::ToBool => 1, Self::ToBoolAlwaysTrue => 1, Self::ToBoolBool => 1, Self::ToBoolInt => 1, Self::ToBoolList => 1, Self::ToBoolNone => 1, Self::ToBoolStr => 1, + Self::UnaryInvert => 1, + Self::UnaryNegative => 1, + Self::UnaryNot => 1, + Self::UnpackEx(_) => 1, + Self::UnpackSequence(_) => 1, Self::UnpackSequenceList(_) => 1, Self::UnpackSequenceTuple(_) => 1, Self::UnpackSequenceTwoTuple(_) => 1, - Self::InstrumentedResume(_) => 0, - Self::InstrumentedEndFor => 2, - Self::InstrumentedEndSend => 2, - Self::InstrumentedReturnValue => 1, - Self::InstrumentedReturnConst(_) => 0, - Self::InstrumentedYieldValue(_) => 1, - Self::InstrumentedLoadSuperAttr(_) => 3, - Self::InstrumentedForIter(_) => 0, - Self::InstrumentedCall(_) => 0, - Self::InstrumentedCallKw(_) => 0, - Self::InstrumentedCallFunctionEx => 0, - Self::InstrumentedInstruction => 0, - Self::InstrumentedJumpForward(_) => 0, - Self::InstrumentedJumpBackward(_) => 0, - Self::InstrumentedPopJumpIfTrue(_) => 0, - Self::InstrumentedPopJumpIfFalse(_) => 0, - Self::InstrumentedPopJumpIfNone(_) => 0, - Self::InstrumentedPopJumpIfNotNone(_) => 0, + Self::WithExceptStart => 4, + Self::YieldValue(_) => 1, _ => panic!("Pseudo opcodes are not allowed!"), } } @@ -760,52 +760,24 @@ impl Instruction { /// How many items should be pushed on the stack. const fn num_pushed(&self) -> u32 { match &self { - Self::Cache => 0, Self::BeforeAsyncWith => 2, Self::BeforeWith => 2, + Self::BinaryOp(_) => 1, + Self::BinaryOpAddFloat => 1, + Self::BinaryOpAddInt => 1, + Self::BinaryOpAddUnicode => 1, Self::BinaryOpInplaceAddUnicode => 0, + Self::BinaryOpMultiplyFloat => 1, + Self::BinaryOpMultiplyInt => 1, + Self::BinaryOpSubtractFloat => 1, + Self::BinaryOpSubtractInt => 1, Self::BinarySlice => 1, Self::BinarySubscr => 1, - Self::CheckEgMatch => 2, - Self::CheckExcMatch => 2, - Self::CleanupThrow => 2, - Self::DeleteSubscr => 0, - Self::EndAsyncFor => 0, - Self::EndFor => 0, - Self::EndSend => 1, - Self::ExitInitCheck => 0, - Self::FormatSimple => 1, - Self::FormatWithSpec => 1, - Self::GetAiter => 1, - Self::Reserved => 0, - Self::GetAnext => 2, - Self::GetIter => 1, - Self::GetLen => 2, - Self::GetYieldFromIter => 1, - Self::InterpreterExit => 0, - Self::LoadAssertionError => 1, - Self::LoadBuildClass => 1, - Self::LoadLocals => 1, - Self::MakeFunction => 1, - Self::MatchKeys => 3, - Self::MatchMapping => 2, - Self::MatchSequence => 2, - Self::Nop => 0, - Self::PopExcept => 0, - Self::PopTop => 0, - Self::PushExcInfo => 2, - Self::PushNull => 1, - Self::ReturnGenerator => 1, - Self::ReturnValue => 0, - Self::SetupAnnotations => 0, - Self::StoreSlice => 0, - Self::StoreSubscr => 0, - Self::ToBool => 1, - Self::UnaryInvert => 1, - Self::UnaryNegative => 1, - Self::UnaryNot => 1, - Self::WithExceptStart => 5, - Self::BinaryOp(_) => 1, + Self::BinarySubscrDict => 1, + Self::BinarySubscrGetitem => 1, + Self::BinarySubscrListInt => 1, + Self::BinarySubscrStrInt => 1, + Self::BinarySubscrTupleInt => 1, Self::BuildConstKeyMap(_) => 1, Self::BuildList(_) => 1, Self::BuildMap(_) => 1, @@ -813,13 +785,42 @@ impl Instruction { Self::BuildSlice(_) => 1, Self::BuildString(_) => 1, Self::BuildTuple(_) => 1, + Self::Cache => 0, Self::Call(_) => 1, + Self::CallAllocAndEnterInit(_) => 1, + Self::CallBoundMethodExactArgs(_) => 0, + Self::CallBoundMethodGeneral(_) => 0, + Self::CallBuiltinClass(_) => 1, + Self::CallBuiltinFast(_) => 1, + Self::CallBuiltinFastWithKeywords(_) => 1, + Self::CallBuiltinO(_) => 1, Self::CallFunctionEx(_) => 1, Self::CallIntrinsic1(_) => 1, Self::CallIntrinsic2(_) => 1, + Self::CallIsinstance(_) => 1, Self::CallKw(_) => 1, + Self::CallLen(_) => 1, + Self::CallListAppend(_) => 1, + Self::CallMethodDescriptorFast(_) => 1, + Self::CallMethodDescriptorFastWithKeywords(_) => 1, + Self::CallMethodDescriptorNoargs(_) => 1, + Self::CallMethodDescriptorO(_) => 1, + Self::CallNonPyGeneral(_) => 1, + Self::CallPyExactArgs(_) => 0, + Self::CallPyGeneral(_) => 0, + Self::CallStr1(_) => 1, + Self::CallTuple1(_) => 1, + Self::CallType1(_) => 1, + Self::CheckEgMatch => 2, + Self::CheckExcMatch => 2, + Self::CleanupThrow => 2, Self::CompareOp(_) => 1, + Self::CompareOpFloat(_) => 1, + Self::CompareOpInt(_) => 1, + Self::CompareOpStr(_) => 1, Self::ContainsOp(_) => 1, + Self::ContainsOpDict(_) => 1, + Self::ContainsOpSet(_) => 1, Self::ConvertValue(_) => 1, Self::Copy(oparg) => 2 + (oparg.0 - 1), Self::CopyFreeVars(_) => 0, @@ -828,21 +829,70 @@ impl Instruction { Self::DeleteFast(_) => 0, Self::DeleteGlobal(_) => 0, Self::DeleteName(_) => 0, + Self::DeleteSubscr => 0, Self::DictMerge(oparg) => 4 + (oparg.0 - 1), Self::DictUpdate(oparg) => 1 + (oparg.0 - 1), + Self::EndAsyncFor => 0, + Self::EndFor => 0, + Self::EndSend => 1, Self::EnterExecutor(_) => 0, + Self::ExitInitCheck => 0, Self::ExtendedArg(_) => 0, Self::ForIter(_) => 2, + Self::ForIterGen(_) => 1, + Self::ForIterList(_) => 2, + Self::ForIterRange(_) => 2, + Self::ForIterTuple(_) => 2, + Self::FormatSimple => 1, + Self::FormatWithSpec => 1, + Self::GetAiter => 1, + Self::GetAnext => 2, Self::GetAwaitable(_) => 1, + Self::GetIter => 1, + Self::GetLen => 2, + Self::GetYieldFromIter => 1, Self::ImportFrom(_) => 2, Self::ImportName(_) => 1, + Self::InstrumentedCall(_) => 0, + Self::InstrumentedCallFunctionEx => 0, + Self::InstrumentedCallKw(_) => 0, + Self::InstrumentedEndFor => 1, + Self::InstrumentedEndSend => 1, + Self::InstrumentedForIter(_) => 0, + Self::InstrumentedInstruction => 0, + Self::InstrumentedJumpBackward(_) => 0, + Self::InstrumentedJumpForward(_) => 0, + Self::InstrumentedLoadSuperAttr(oparg) => 1 + (oparg.0 & 1), + Self::InstrumentedPopJumpIfFalse(_) => 0, + Self::InstrumentedPopJumpIfNone(_) => 0, + Self::InstrumentedPopJumpIfNotNone(_) => 0, + Self::InstrumentedPopJumpIfTrue(_) => 0, + Self::InstrumentedResume(_) => 0, + Self::InstrumentedReturnConst(_) => 0, + Self::InstrumentedReturnValue => 0, + Self::InstrumentedYieldValue(_) => 1, + Self::InterpreterExit => 0, Self::IsOp(_) => 1, Self::JumpBackward(_) => 0, Self::JumpBackwardNoInterrupt(_) => 0, Self::JumpForward(_) => 0, Self::ListAppend(oparg) => 1 + (oparg.0 - 1), Self::ListExtend(oparg) => 1 + (oparg.0 - 1), + Self::LoadAssertionError => 1, Self::LoadAttr(oparg) => 1 + (oparg.0 & 1), + Self::LoadAttrClass(oparg) => 1 + (oparg.0 & 1), + Self::LoadAttrGetattributeOverridden(_) => 1, + Self::LoadAttrInstanceValue(oparg) => 1 + (oparg.0 & 1), + Self::LoadAttrMethodLazyDict(_) => 2, + Self::LoadAttrMethodNoDict(_) => 2, + Self::LoadAttrMethodWithValues(_) => 2, + Self::LoadAttrModule(oparg) => 1 + (oparg.0 & 1), + Self::LoadAttrNondescriptorNoDict(_) => 1, + Self::LoadAttrNondescriptorWithValues(_) => 1, + Self::LoadAttrProperty(_) => 1, + Self::LoadAttrSlot(oparg) => 1 + (oparg.0 & 1), + Self::LoadAttrWithHint(oparg) => 1 + (oparg.0 & 1), + Self::LoadBuildClass => 1, Self::LoadConst(_) => 1, Self::LoadDeref(_) => 1, Self::LoadFast(_) => 1, @@ -852,125 +902,75 @@ impl Instruction { Self::LoadFromDictOrDeref(_) => 1, Self::LoadFromDictOrGlobals(_) => 1, Self::LoadGlobal(oparg) => 1 + (oparg.0 & 1), + Self::LoadGlobalBuiltin(oparg) => 1 + (oparg.0 & 1), + Self::LoadGlobalModule(oparg) => 1 + (oparg.0 & 1), + Self::LoadLocals => 1, Self::LoadName(_) => 1, Self::LoadSuperAttr(oparg) => 1 + (oparg.0 & 1), + Self::LoadSuperAttrAttr(_) => 1, + Self::LoadSuperAttrMethod(_) => 2, Self::MakeCell(_) => 0, + Self::MakeFunction => 1, Self::MapAdd(oparg) => 1 + (oparg.0 - 1), Self::MatchClass(_) => 1, + Self::MatchKeys => 3, + Self::MatchMapping => 2, + Self::MatchSequence => 2, + Self::Nop => 0, + Self::PopExcept => 0, Self::PopJumpIfFalse(_) => 0, Self::PopJumpIfNone(_) => 0, Self::PopJumpIfNotNone(_) => 0, Self::PopJumpIfTrue(_) => 0, + Self::PopTop => 0, + Self::PushExcInfo => 2, + Self::PushNull => 1, Self::RaiseVarargs(_) => 0, Self::Reraise(oparg) => oparg.0, + Self::Reserved => 0, + Self::Resume(_) => 0, + Self::ResumeCheck => 0, Self::ReturnConst(_) => 0, + Self::ReturnGenerator => 1, + Self::ReturnValue => 0, Self::Send(_) => 2, + Self::SendGen(_) => 2, Self::SetAdd(oparg) => 1 + (oparg.0 - 1), Self::SetFunctionAttribute(_) => 1, Self::SetUpdate(oparg) => 1 + (oparg.0 - 1), + Self::SetupAnnotations => 0, Self::StoreAttr(_) => 0, + Self::StoreAttrInstanceValue => 0, + Self::StoreAttrSlot => 0, + Self::StoreAttrWithHint(_) => 0, Self::StoreDeref(_) => 0, Self::StoreFast(_) => 0, Self::StoreFastLoadFast(_) => 1, Self::StoreFastStoreFast(_) => 0, Self::StoreGlobal(_) => 0, Self::StoreName(_) => 0, - Self::Swap(oparg) => 2 + (oparg.0 - 2), - Self::UnpackEx(oparg) => 1 + (oparg.0 >> 8) + (oparg.0 & 0xFF), - Self::UnpackSequence(oparg) => oparg.0, - Self::YieldValue(_) => 1, - Self::Resume(_) => 0, - Self::BinaryOpAddFloat => 1, - Self::BinaryOpAddInt => 1, - Self::BinaryOpAddUnicode => 1, - Self::BinaryOpMultiplyFloat => 1, - Self::BinaryOpMultiplyInt => 1, - Self::BinaryOpSubtractFloat => 1, - Self::BinaryOpSubtractInt => 1, - Self::BinarySubscrDict => 1, - Self::BinarySubscrGetitem => 1, - Self::BinarySubscrListInt => 1, - Self::BinarySubscrStrInt => 1, - Self::BinarySubscrTupleInt => 1, - Self::CallAllocAndEnterInit(_) => 1, - Self::CallBoundMethodExactArgs(_) => 0, - Self::CallBoundMethodGeneral(_) => 0, - Self::CallBuiltinClass(_) => 1, - Self::CallBuiltinFast(_) => 1, - Self::CallBuiltinFastWithKeywords(_) => 1, - Self::CallBuiltinO(_) => 1, - Self::CallIsinstance(_) => 1, - Self::CallLen(_) => 1, - Self::CallListAppend(_) => 1, - Self::CallMethodDescriptorFast(_) => 1, - Self::CallMethodDescriptorFastWithKeywords(_) => 1, - Self::CallMethodDescriptorNoargs(_) => 1, - Self::CallMethodDescriptorO(_) => 1, - Self::CallNonPyGeneral(_) => 1, - Self::CallPyExactArgs(_) => 0, - Self::CallPyGeneral(_) => 0, - Self::CallStr1(_) => 1, - Self::CallTuple1(_) => 1, - Self::CallType1(_) => 1, - Self::CompareOpFloat(_) => 1, - Self::CompareOpInt(_) => 1, - Self::CompareOpStr(_) => 1, - Self::ContainsOpDict(_) => 1, - Self::ContainsOpSet(_) => 1, - Self::ForIterGen(_) => 1, - Self::ForIterList(_) => 2, - Self::ForIterRange(_) => 2, - Self::ForIterTuple(_) => 2, - Self::LoadAttrClass(oparg) => 1 + (oparg.0 & 1), - Self::LoadAttrGetattributeOverridden(_) => 1, - Self::LoadAttrInstanceValue(oparg) => 1 + (oparg.0 & 1), - Self::LoadAttrMethodLazyDict(_) => 2, - Self::LoadAttrMethodNoDict(_) => 2, - Self::LoadAttrMethodWithValues(_) => 2, - Self::LoadAttrModule(oparg) => 1 + (oparg.0 & 1), - Self::LoadAttrNondescriptorNoDict(_) => 1, - Self::LoadAttrNondescriptorWithValues(_) => 1, - Self::LoadAttrProperty(_) => 1, - Self::LoadAttrSlot(oparg) => 1 + (oparg.0 & 1), - Self::LoadAttrWithHint(oparg) => 1 + (oparg.0 & 1), - Self::LoadGlobalBuiltin(oparg) => 1 + (oparg.0 & 1), - Self::LoadGlobalModule(oparg) => 1 + (oparg.0 & 1), - Self::LoadSuperAttrAttr(_) => 1, - Self::LoadSuperAttrMethod(_) => 2, - Self::ResumeCheck => 0, - Self::SendGen(_) => 2, - Self::StoreAttrInstanceValue => 0, - Self::StoreAttrSlot => 0, - Self::StoreAttrWithHint(_) => 0, + Self::StoreSlice => 0, + Self::StoreSubscr => 0, Self::StoreSubscrDict => 0, Self::StoreSubscrListInt => 0, + Self::Swap(oparg) => 2 + (oparg.0 - 2), + Self::ToBool => 1, Self::ToBoolAlwaysTrue => 1, Self::ToBoolBool => 1, Self::ToBoolInt => 1, Self::ToBoolList => 1, Self::ToBoolNone => 1, Self::ToBoolStr => 1, + Self::UnaryInvert => 1, + Self::UnaryNegative => 1, + Self::UnaryNot => 1, + Self::UnpackEx(oparg) => 1 + (oparg.0 >> 8) + (oparg.0 & 0xFF), + Self::UnpackSequence(oparg) => oparg.0, Self::UnpackSequenceList(oparg) => oparg.0, Self::UnpackSequenceTuple(oparg) => oparg.0, Self::UnpackSequenceTwoTuple(_) => 2, - Self::InstrumentedResume(_) => 0, - Self::InstrumentedEndFor => 1, - Self::InstrumentedEndSend => 1, - Self::InstrumentedReturnValue => 0, - Self::InstrumentedReturnConst(_) => 0, - Self::InstrumentedYieldValue(_) => 1, - Self::InstrumentedLoadSuperAttr(oparg) => 1 + (oparg.0 & 1), - Self::InstrumentedForIter(_) => 0, - Self::InstrumentedCall(_) => 0, - Self::InstrumentedCallKw(_) => 0, - Self::InstrumentedCallFunctionEx => 0, - Self::InstrumentedInstruction => 0, - Self::InstrumentedJumpForward(_) => 0, - Self::InstrumentedJumpBackward(_) => 0, - Self::InstrumentedPopJumpIfTrue(_) => 0, - Self::InstrumentedPopJumpIfFalse(_) => 0, - Self::InstrumentedPopJumpIfNone(_) => 0, - Self::InstrumentedPopJumpIfNotNone(_) => 0, + Self::WithExceptStart => 5, + Self::YieldValue(_) => 1, _ => panic!("Pseudo opcodes are not allowed!"), } } diff --git a/scripts/gen_instructions.py b/scripts/gen_instructions.py index c1dbfd37e66..22cbce38802 100755 --- a/scripts/gen_instructions.py +++ b/scripts/gen_instructions.py @@ -88,7 +88,7 @@ def as_matched(self, arg: str = "_") -> str: return f"Self::{out}" def __lt__(self, other) -> bool: - return self.id < other.id + return (self.is_pseudo, self.name) < (other.is_pseudo, other.name) class Instructions: @@ -107,7 +107,7 @@ def __iter__(self) -> "Iterator[analyzer.Instruction]": yield from self._inner def _valid_ranges(self) -> "Iterator[range]": - ids = [ins.id for ins in self] + ids = sorted(ins.id for ins in self) # Group consecutive numbers into ranges. start = prev = ids[0] From acd74c73315345c89790b480377795a6579339bd Mon Sep 17 00:00:00 2001 From: ShaharNaveh <50263213+ShaharNaveh@users.noreply.github.com> Date: Fri, 26 Sep 2025 17:17:47 +0200 Subject: [PATCH 15/43] Make more things compile --- compiler/core/src/bytecode.rs | 676 +------------------------------ compiler/core/src/instruction.rs | 435 ++++++++++---------- compiler/core/src/marshal.rs | 4 +- scripts/gen_instructions.py | 23 +- 4 files changed, 260 insertions(+), 878 deletions(-) diff --git a/compiler/core/src/bytecode.rs b/compiler/core/src/bytecode.rs index ed25442f2df..a86aeb6ec76 100644 --- a/compiler/core/src/bytecode.rs +++ b/compiler/core/src/bytecode.rs @@ -9,6 +9,8 @@ use num_complex::Complex64; use rustpython_wtf8::{Wtf8, Wtf8Buf}; use std::{collections::BTreeSet, fmt, hash, marker::PhantomData, mem}; +pub use crate::instruction::{Instruction, NameIdx}; + #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] #[repr(i8)] #[allow(clippy::cast_possible_wrap)] @@ -131,7 +133,7 @@ impl Constant for ConstantData { } /// A Constant Bag -pub trait ConstantBag: Sized + Copy { +pub trait ConstantBag: Sized + std::marker::Copy { type Constant: Constant; fn make_constant(&self, constant: BorrowedConstant<'_, C>) -> Self::Constant; @@ -310,7 +312,7 @@ impl OpArgState { #[inline(always)] pub fn get(&mut self, ins: CodeUnit) -> (Instruction, OpArg) { let arg = self.extend(ins.arg); - if ins.op != Instruction::ExtendedArg { + if !matches!(ins.op, Instruction::ExtendedArg(_)) { self.reset(); } (ins.op, arg) @@ -328,7 +330,7 @@ impl OpArgState { } } -pub trait OpArgType: Copy { +pub trait OpArgType: std::marker::Copy { fn from_op_arg(x: u32) -> Option; fn to_op_arg(self) -> u32; @@ -534,292 +536,6 @@ op_arg_enum!( } ); -pub type NameIdx = u32; - -/// A Single bytecode instruction. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -#[repr(u8)] -pub enum Instruction { - Nop, - /// Importing by name - ImportName { - idx: Arg, - }, - /// Importing without name - ImportNameless, - /// from ... import ... - ImportFrom { - idx: Arg, - }, - LoadFast(Arg), - LoadNameAny(Arg), - LoadGlobal(Arg), - LoadDeref(Arg), - LoadClassDeref(Arg), - StoreFast(Arg), - StoreLocal(Arg), - StoreGlobal(Arg), - StoreDeref(Arg), - DeleteFast(Arg), - DeleteLocal(Arg), - DeleteGlobal(Arg), - DeleteDeref(Arg), - LoadClosure(Arg), - Subscript, - StoreSubscript, - DeleteSubscript, - StoreAttr { - idx: Arg, - }, - DeleteAttr { - idx: Arg, - }, - LoadConst { - /// index into constants vec - idx: Arg, - }, - UnaryOperation { - op: Arg, - }, - BinaryOperation { - op: Arg, - }, - BinaryOperationInplace { - op: Arg, - }, - BinarySubscript, - LoadAttr { - idx: Arg, - }, - TestOperation { - op: Arg, - }, - CompareOperation { - op: Arg, - }, - CopyItem { - index: Arg, - }, - Pop, - Swap { - index: Arg, - }, - ToBool, - Rotate2, - Rotate3, - Duplicate, - Duplicate2, - GetIter, - GetLen, - CallIntrinsic1 { - func: Arg, - }, - CallIntrinsic2 { - func: Arg, - }, - Continue { - target: Arg