mirror of
https://github.com/python/cpython
synced 2024-10-14 13:18:08 +00:00
GH-111485: Allow arbitrary annotations on instructions and micro-ops. (GH-111697)
This commit is contained in:
parent
13405ecffd
commit
931f4438c9
10
Include/internal/pycore_opcode_metadata.h
generated
10
Include/internal/pycore_opcode_metadata.h
generated
|
@ -1771,6 +1771,7 @@ const struct opcode_macro_expansion _PyOpcode_macro_expansion[OPCODE_MACRO_EXPAN
|
|||
[END_SEND] = { .nuops = 1, .uops = { { END_SEND, 0, 0 } } },
|
||||
[UNARY_NEGATIVE] = { .nuops = 1, .uops = { { UNARY_NEGATIVE, 0, 0 } } },
|
||||
[UNARY_NOT] = { .nuops = 1, .uops = { { UNARY_NOT, 0, 0 } } },
|
||||
[TO_BOOL] = { .nuops = 1, .uops = { { _TO_BOOL, 0, 0 } } },
|
||||
[TO_BOOL_BOOL] = { .nuops = 1, .uops = { { TO_BOOL_BOOL, 0, 0 } } },
|
||||
[TO_BOOL_INT] = { .nuops = 1, .uops = { { TO_BOOL_INT, 0, 0 } } },
|
||||
[TO_BOOL_LIST] = { .nuops = 1, .uops = { { TO_BOOL_LIST, 0, 0 } } },
|
||||
|
@ -1785,6 +1786,7 @@ const struct opcode_macro_expansion _PyOpcode_macro_expansion[OPCODE_MACRO_EXPAN
|
|||
[BINARY_OP_ADD_FLOAT] = { .nuops = 2, .uops = { { _GUARD_BOTH_FLOAT, 0, 0 }, { _BINARY_OP_ADD_FLOAT, 0, 0 } } },
|
||||
[BINARY_OP_SUBTRACT_FLOAT] = { .nuops = 2, .uops = { { _GUARD_BOTH_FLOAT, 0, 0 }, { _BINARY_OP_SUBTRACT_FLOAT, 0, 0 } } },
|
||||
[BINARY_OP_ADD_UNICODE] = { .nuops = 2, .uops = { { _GUARD_BOTH_UNICODE, 0, 0 }, { _BINARY_OP_ADD_UNICODE, 0, 0 } } },
|
||||
[BINARY_SUBSCR] = { .nuops = 1, .uops = { { _BINARY_SUBSCR, 0, 0 } } },
|
||||
[BINARY_SLICE] = { .nuops = 1, .uops = { { BINARY_SLICE, 0, 0 } } },
|
||||
[STORE_SLICE] = { .nuops = 1, .uops = { { STORE_SLICE, 0, 0 } } },
|
||||
[BINARY_SUBSCR_LIST_INT] = { .nuops = 1, .uops = { { BINARY_SUBSCR_LIST_INT, 0, 0 } } },
|
||||
|
@ -1793,6 +1795,7 @@ const struct opcode_macro_expansion _PyOpcode_macro_expansion[OPCODE_MACRO_EXPAN
|
|||
[BINARY_SUBSCR_DICT] = { .nuops = 1, .uops = { { BINARY_SUBSCR_DICT, 0, 0 } } },
|
||||
[LIST_APPEND] = { .nuops = 1, .uops = { { LIST_APPEND, 0, 0 } } },
|
||||
[SET_ADD] = { .nuops = 1, .uops = { { SET_ADD, 0, 0 } } },
|
||||
[STORE_SUBSCR] = { .nuops = 1, .uops = { { _STORE_SUBSCR, 0, 0 } } },
|
||||
[STORE_SUBSCR_LIST_INT] = { .nuops = 1, .uops = { { STORE_SUBSCR_LIST_INT, 0, 0 } } },
|
||||
[STORE_SUBSCR_DICT] = { .nuops = 1, .uops = { { STORE_SUBSCR_DICT, 0, 0 } } },
|
||||
[DELETE_SUBSCR] = { .nuops = 1, .uops = { { DELETE_SUBSCR, 0, 0 } } },
|
||||
|
@ -1808,17 +1811,19 @@ const struct opcode_macro_expansion _PyOpcode_macro_expansion[OPCODE_MACRO_EXPAN
|
|||
[LOAD_BUILD_CLASS] = { .nuops = 1, .uops = { { LOAD_BUILD_CLASS, 0, 0 } } },
|
||||
[STORE_NAME] = { .nuops = 1, .uops = { { STORE_NAME, 0, 0 } } },
|
||||
[DELETE_NAME] = { .nuops = 1, .uops = { { DELETE_NAME, 0, 0 } } },
|
||||
[UNPACK_SEQUENCE] = { .nuops = 2, .uops = { { _SPECIALIZE_UNPACK_SEQUENCE, 1, 0 }, { _UNPACK_SEQUENCE, 0, 0 } } },
|
||||
[UNPACK_SEQUENCE] = { .nuops = 1, .uops = { { _UNPACK_SEQUENCE, 0, 0 } } },
|
||||
[UNPACK_SEQUENCE_TWO_TUPLE] = { .nuops = 1, .uops = { { UNPACK_SEQUENCE_TWO_TUPLE, 0, 0 } } },
|
||||
[UNPACK_SEQUENCE_TUPLE] = { .nuops = 1, .uops = { { UNPACK_SEQUENCE_TUPLE, 0, 0 } } },
|
||||
[UNPACK_SEQUENCE_LIST] = { .nuops = 1, .uops = { { UNPACK_SEQUENCE_LIST, 0, 0 } } },
|
||||
[UNPACK_EX] = { .nuops = 1, .uops = { { UNPACK_EX, 0, 0 } } },
|
||||
[STORE_ATTR] = { .nuops = 1, .uops = { { _STORE_ATTR, 0, 0 } } },
|
||||
[DELETE_ATTR] = { .nuops = 1, .uops = { { DELETE_ATTR, 0, 0 } } },
|
||||
[STORE_GLOBAL] = { .nuops = 1, .uops = { { STORE_GLOBAL, 0, 0 } } },
|
||||
[DELETE_GLOBAL] = { .nuops = 1, .uops = { { DELETE_GLOBAL, 0, 0 } } },
|
||||
[LOAD_LOCALS] = { .nuops = 1, .uops = { { LOAD_LOCALS, 0, 0 } } },
|
||||
[LOAD_FROM_DICT_OR_GLOBALS] = { .nuops = 1, .uops = { { LOAD_FROM_DICT_OR_GLOBALS, 0, 0 } } },
|
||||
[LOAD_NAME] = { .nuops = 1, .uops = { { LOAD_NAME, 0, 0 } } },
|
||||
[LOAD_GLOBAL] = { .nuops = 1, .uops = { { _LOAD_GLOBAL, 0, 0 } } },
|
||||
[LOAD_GLOBAL_MODULE] = { .nuops = 2, .uops = { { _GUARD_GLOBALS_VERSION, 1, 1 }, { _LOAD_GLOBAL_MODULE, 1, 3 } } },
|
||||
[LOAD_GLOBAL_BUILTIN] = { .nuops = 3, .uops = { { _GUARD_GLOBALS_VERSION, 1, 1 }, { _GUARD_BUILTINS_VERSION, 1, 2 }, { _LOAD_GLOBAL_BUILTINS, 1, 3 } } },
|
||||
[DELETE_FAST] = { .nuops = 1, .uops = { { DELETE_FAST, 0, 0 } } },
|
||||
|
@ -1842,6 +1847,7 @@ const struct opcode_macro_expansion _PyOpcode_macro_expansion[OPCODE_MACRO_EXPAN
|
|||
[MAP_ADD] = { .nuops = 1, .uops = { { MAP_ADD, 0, 0 } } },
|
||||
[LOAD_SUPER_ATTR_ATTR] = { .nuops = 1, .uops = { { LOAD_SUPER_ATTR_ATTR, 0, 0 } } },
|
||||
[LOAD_SUPER_ATTR_METHOD] = { .nuops = 1, .uops = { { LOAD_SUPER_ATTR_METHOD, 0, 0 } } },
|
||||
[LOAD_ATTR] = { .nuops = 1, .uops = { { _LOAD_ATTR, 0, 0 } } },
|
||||
[LOAD_ATTR_INSTANCE_VALUE] = { .nuops = 3, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _CHECK_MANAGED_OBJECT_HAS_VALUES, 0, 0 }, { _LOAD_ATTR_INSTANCE_VALUE, 1, 3 } } },
|
||||
[LOAD_ATTR_MODULE] = { .nuops = 2, .uops = { { _CHECK_ATTR_MODULE, 2, 1 }, { _LOAD_ATTR_MODULE, 1, 3 } } },
|
||||
[LOAD_ATTR_WITH_HINT] = { .nuops = 3, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _CHECK_ATTR_WITH_HINT, 0, 0 }, { _LOAD_ATTR_WITH_HINT, 1, 3 } } },
|
||||
|
@ -1849,6 +1855,7 @@ const struct opcode_macro_expansion _PyOpcode_macro_expansion[OPCODE_MACRO_EXPAN
|
|||
[LOAD_ATTR_CLASS] = { .nuops = 2, .uops = { { _CHECK_ATTR_CLASS, 2, 1 }, { _LOAD_ATTR_CLASS, 4, 5 } } },
|
||||
[STORE_ATTR_INSTANCE_VALUE] = { .nuops = 3, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _GUARD_DORV_VALUES, 0, 0 }, { _STORE_ATTR_INSTANCE_VALUE, 1, 3 } } },
|
||||
[STORE_ATTR_SLOT] = { .nuops = 2, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _STORE_ATTR_SLOT, 1, 3 } } },
|
||||
[COMPARE_OP] = { .nuops = 1, .uops = { { _COMPARE_OP, 0, 0 } } },
|
||||
[COMPARE_OP_FLOAT] = { .nuops = 1, .uops = { { COMPARE_OP_FLOAT, 0, 0 } } },
|
||||
[COMPARE_OP_INT] = { .nuops = 1, .uops = { { COMPARE_OP_INT, 0, 0 } } },
|
||||
[COMPARE_OP_STR] = { .nuops = 1, .uops = { { COMPARE_OP_STR, 0, 0 } } },
|
||||
|
@ -1895,6 +1902,7 @@ const struct opcode_macro_expansion _PyOpcode_macro_expansion[OPCODE_MACRO_EXPAN
|
|||
[FORMAT_SIMPLE] = { .nuops = 1, .uops = { { FORMAT_SIMPLE, 0, 0 } } },
|
||||
[FORMAT_WITH_SPEC] = { .nuops = 1, .uops = { { FORMAT_WITH_SPEC, 0, 0 } } },
|
||||
[COPY] = { .nuops = 1, .uops = { { COPY, 0, 0 } } },
|
||||
[BINARY_OP] = { .nuops = 1, .uops = { { _BINARY_OP, 0, 0 } } },
|
||||
[SWAP] = { .nuops = 1, .uops = { { SWAP, 0, 0 } } },
|
||||
};
|
||||
#endif // NEED_OPCODE_METADATA
|
||||
|
|
|
@ -707,6 +707,49 @@ def test_override_op(self):
|
|||
"""
|
||||
self.run_cases_test(input, output)
|
||||
|
||||
def test_annotated_inst(self):
|
||||
input = """
|
||||
guard inst(OP, (--)) {
|
||||
ham();
|
||||
}
|
||||
"""
|
||||
output = """
|
||||
TARGET(OP) {
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(OP);
|
||||
ham();
|
||||
DISPATCH();
|
||||
}
|
||||
"""
|
||||
self.run_cases_test(input, output)
|
||||
|
||||
def test_annotated_op(self):
|
||||
input = """
|
||||
guard op(OP, (--)) {
|
||||
spam();
|
||||
}
|
||||
macro(M) = OP;
|
||||
"""
|
||||
output = """
|
||||
TARGET(M) {
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(M);
|
||||
spam();
|
||||
DISPATCH();
|
||||
}
|
||||
"""
|
||||
self.run_cases_test(input, output)
|
||||
|
||||
input = """
|
||||
guard register specializing op(OP, (--)) {
|
||||
spam();
|
||||
}
|
||||
macro(M) = OP;
|
||||
"""
|
||||
self.run_cases_test(input, output)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
4
Python/abstract_interp_cases.c.h
generated
4
Python/abstract_interp_cases.c.h
generated
|
@ -242,10 +242,6 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _SPECIALIZE_UNPACK_SEQUENCE: {
|
||||
break;
|
||||
}
|
||||
|
||||
case _UNPACK_SEQUENCE: {
|
||||
STACK_SHRINK(1);
|
||||
STACK_GROW(oparg);
|
||||
|
|
|
@ -50,6 +50,11 @@
|
|||
#define family(name, ...) static int family_##name
|
||||
#define pseudo(name) static int pseudo_##name
|
||||
|
||||
/* Annotations */
|
||||
#define guard
|
||||
#define override
|
||||
#define specializing
|
||||
|
||||
// Dummy variables for stack effects.
|
||||
static PyObject *value, *value1, *value2, *left, *right, *res, *sum, *prod, *sub;
|
||||
static PyObject *container, *start, *stop, *v, *lhs, *rhs, *res2;
|
||||
|
@ -312,7 +317,7 @@ dummy_func(
|
|||
TO_BOOL_STR,
|
||||
};
|
||||
|
||||
op(_SPECIALIZE_TO_BOOL, (counter/1, value -- value)) {
|
||||
specializing op(_SPECIALIZE_TO_BOOL, (counter/1, value -- value)) {
|
||||
TIER_ONE_ONLY
|
||||
#if ENABLE_SPECIALIZATION
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(counter)) {
|
||||
|
@ -537,7 +542,7 @@ dummy_func(
|
|||
BINARY_SUBSCR_TUPLE_INT,
|
||||
};
|
||||
|
||||
op(_SPECIALIZE_BINARY_SUBSCR, (counter/1, container, sub -- container, sub)) {
|
||||
specializing op(_SPECIALIZE_BINARY_SUBSCR, (counter/1, container, sub -- container, sub)) {
|
||||
TIER_ONE_ONLY
|
||||
#if ENABLE_SPECIALIZATION
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(counter)) {
|
||||
|
@ -689,7 +694,7 @@ dummy_func(
|
|||
STORE_SUBSCR_LIST_INT,
|
||||
};
|
||||
|
||||
op(_SPECIALIZE_STORE_SUBSCR, (counter/1, container, sub -- container, sub)) {
|
||||
specializing op(_SPECIALIZE_STORE_SUBSCR, (counter/1, container, sub -- container, sub)) {
|
||||
TIER_ONE_ONLY
|
||||
#if ENABLE_SPECIALIZATION
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(counter)) {
|
||||
|
@ -974,7 +979,7 @@ dummy_func(
|
|||
SEND_GEN,
|
||||
};
|
||||
|
||||
op(_SPECIALIZE_SEND, (counter/1, receiver, unused -- receiver, unused)) {
|
||||
specializing op(_SPECIALIZE_SEND, (counter/1, receiver, unused -- receiver, unused)) {
|
||||
TIER_ONE_ONLY
|
||||
#if ENABLE_SPECIALIZATION
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(counter)) {
|
||||
|
@ -1208,7 +1213,7 @@ dummy_func(
|
|||
UNPACK_SEQUENCE_LIST,
|
||||
};
|
||||
|
||||
op(_SPECIALIZE_UNPACK_SEQUENCE, (counter/1, seq -- seq)) {
|
||||
specializing op(_SPECIALIZE_UNPACK_SEQUENCE, (counter/1, seq -- seq)) {
|
||||
#if ENABLE_SPECIALIZATION
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(counter)) {
|
||||
next_instr = this_instr;
|
||||
|
@ -1277,7 +1282,7 @@ dummy_func(
|
|||
STORE_ATTR_WITH_HINT,
|
||||
};
|
||||
|
||||
op(_SPECIALIZE_STORE_ATTR, (counter/1, owner -- owner)) {
|
||||
specializing op(_SPECIALIZE_STORE_ATTR, (counter/1, owner -- owner)) {
|
||||
TIER_ONE_ONLY
|
||||
#if ENABLE_SPECIALIZATION
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(counter)) {
|
||||
|
@ -1404,7 +1409,7 @@ dummy_func(
|
|||
LOAD_GLOBAL_BUILTIN,
|
||||
};
|
||||
|
||||
op(_SPECIALIZE_LOAD_GLOBAL, (counter/1 -- )) {
|
||||
specializing op(_SPECIALIZE_LOAD_GLOBAL, (counter/1 -- )) {
|
||||
TIER_ONE_ONLY
|
||||
#if ENABLE_SPECIALIZATION
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(counter)) {
|
||||
|
@ -1744,7 +1749,7 @@ dummy_func(
|
|||
LOAD_SUPER_ATTR_METHOD,
|
||||
};
|
||||
|
||||
op(_SPECIALIZE_LOAD_SUPER_ATTR, (counter/1, global_super, class, unused -- global_super, class, unused)) {
|
||||
specializing op(_SPECIALIZE_LOAD_SUPER_ATTR, (counter/1, global_super, class, unused -- global_super, class, unused)) {
|
||||
TIER_ONE_ONLY
|
||||
#if ENABLE_SPECIALIZATION
|
||||
int load_method = oparg & 1;
|
||||
|
@ -1860,7 +1865,7 @@ dummy_func(
|
|||
LOAD_ATTR_NONDESCRIPTOR_NO_DICT,
|
||||
};
|
||||
|
||||
op(_SPECIALIZE_LOAD_ATTR, (counter/1, owner -- owner)) {
|
||||
specializing op(_SPECIALIZE_LOAD_ATTR, (counter/1, owner -- owner)) {
|
||||
TIER_ONE_ONLY
|
||||
#if ENABLE_SPECIALIZATION
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(counter)) {
|
||||
|
@ -2182,7 +2187,7 @@ dummy_func(
|
|||
COMPARE_OP_STR,
|
||||
};
|
||||
|
||||
op(_SPECIALIZE_COMPARE_OP, (counter/1, left, right -- left, right)) {
|
||||
specializing op(_SPECIALIZE_COMPARE_OP, (counter/1, left, right -- left, right)) {
|
||||
TIER_ONE_ONLY
|
||||
#if ENABLE_SPECIALIZATION
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(counter)) {
|
||||
|
@ -2506,7 +2511,7 @@ dummy_func(
|
|||
FOR_ITER_GEN,
|
||||
};
|
||||
|
||||
op(_SPECIALIZE_FOR_ITER, (counter/1, iter -- iter)) {
|
||||
specializing op(_SPECIALIZE_FOR_ITER, (counter/1, iter -- iter)) {
|
||||
TIER_ONE_ONLY
|
||||
#if ENABLE_SPECIALIZATION
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(counter)) {
|
||||
|
@ -3000,7 +3005,7 @@ dummy_func(
|
|||
CALL_ALLOC_AND_ENTER_INIT,
|
||||
};
|
||||
|
||||
op(_SPECIALIZE_CALL, (counter/1, callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) {
|
||||
specializing op(_SPECIALIZE_CALL, (counter/1, callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) {
|
||||
TIER_ONE_ONLY
|
||||
#if ENABLE_SPECIALIZATION
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(counter)) {
|
||||
|
@ -3865,7 +3870,7 @@ dummy_func(
|
|||
top = Py_NewRef(bottom);
|
||||
}
|
||||
|
||||
op(_SPECIALIZE_BINARY_OP, (counter/1, lhs, rhs -- lhs, rhs)) {
|
||||
specializing op(_SPECIALIZE_BINARY_OP, (counter/1, lhs, rhs -- lhs, rhs)) {
|
||||
TIER_ONE_ONLY
|
||||
#if ENABLE_SPECIALIZATION
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(counter)) {
|
||||
|
|
18
Python/executor_cases.c.h
generated
18
Python/executor_cases.c.h
generated
|
@ -871,24 +871,6 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _SPECIALIZE_UNPACK_SEQUENCE: {
|
||||
PyObject *seq;
|
||||
seq = stack_pointer[-1];
|
||||
uint16_t counter = (uint16_t)next_uop[-1].operand;
|
||||
#if ENABLE_SPECIALIZATION
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(counter)) {
|
||||
next_instr = this_instr;
|
||||
_Py_Specialize_UnpackSequence(seq, next_instr, oparg);
|
||||
DISPATCH_SAME_OPARG();
|
||||
}
|
||||
STAT_INC(UNPACK_SEQUENCE, deferred);
|
||||
DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache);
|
||||
#endif /* ENABLE_SPECIALIZATION */
|
||||
(void)seq;
|
||||
(void)counter;
|
||||
break;
|
||||
}
|
||||
|
||||
case _UNPACK_SEQUENCE: {
|
||||
PyObject *seq;
|
||||
seq = stack_pointer[-1];
|
||||
|
|
|
@ -139,17 +139,17 @@ def parse_file(self, filename: str, instrs_idx: dict[str, int]) -> None:
|
|||
match thing:
|
||||
case parsing.InstDef(name=name):
|
||||
macro: parsing.Macro | None = None
|
||||
if thing.kind == "inst" and not thing.override:
|
||||
if thing.kind == "inst" and "override" not in thing.annotations:
|
||||
macro = parsing.Macro(name, [parsing.OpName(name)])
|
||||
if name in self.instrs:
|
||||
if not thing.override:
|
||||
if "override" not in thing.annotations:
|
||||
raise psr.make_syntax_error(
|
||||
f"Duplicate definition of '{name}' @ {thing.context} "
|
||||
f"previous definition @ {self.instrs[name].inst.context}",
|
||||
thing_first_token,
|
||||
)
|
||||
self.everything[instrs_idx[name]] = thing
|
||||
if name not in self.instrs and thing.override:
|
||||
if name not in self.instrs and "override" in thing.annotations:
|
||||
raise psr.make_syntax_error(
|
||||
f"Definition of '{name}' @ {thing.context} is supposed to be "
|
||||
"an override but no previous definition exists.",
|
||||
|
|
|
@ -651,7 +651,10 @@ def write_macro_expansions(
|
|||
expansions: list[tuple[str, int, int]] = [] # [(name, size, offset), ...]
|
||||
for part in parts:
|
||||
if isinstance(part, Component):
|
||||
# All component instructions must be viable uops
|
||||
# Skip specializations
|
||||
if "specializing" in part.instr.annotations:
|
||||
continue
|
||||
# All other component instructions must be viable uops
|
||||
if not part.instr.is_viable_uop():
|
||||
# This note just reminds us about macros that cannot
|
||||
# be expanded to Tier 2 uops. It is not an error.
|
||||
|
|
|
@ -46,6 +46,7 @@ class Instruction:
|
|||
# Parts of the underlying instruction definition
|
||||
inst: parsing.InstDef
|
||||
name: str
|
||||
annotations: list[str]
|
||||
block: parsing.Block
|
||||
block_text: list[str] # Block.text, less curlies, less PREDICT() calls
|
||||
block_line: int # First line of block in original code
|
||||
|
@ -70,6 +71,7 @@ class Instruction:
|
|||
def __init__(self, inst: parsing.InstDef):
|
||||
self.inst = inst
|
||||
self.name = inst.name
|
||||
self.annotations = inst.annotations
|
||||
self.block = inst.block
|
||||
self.block_text, self.check_eval_breaker, self.block_line = extract_block_text(
|
||||
self.block
|
||||
|
@ -118,6 +120,8 @@ def is_viable_uop(self) -> bool:
|
|||
|
||||
if self.name == "_EXIT_TRACE":
|
||||
return True # This has 'return frame' but it's okay
|
||||
if self.name == "_SAVE_RETURN_OFFSET":
|
||||
return True # Adjusts next_instr, but only in tier 1 code
|
||||
if self.always_exits:
|
||||
dprint(f"Skipping {self.name} because it always exits: {self.always_exits}")
|
||||
return False
|
||||
|
|
|
@ -80,11 +80,12 @@ def choice(*opts: str) -> str:
|
|||
|
||||
# Macros
|
||||
macro = r"# *(ifdef|ifndef|undef|define|error|endif|if|else|include|#)"
|
||||
MACRO = "MACRO"
|
||||
CMACRO = "CMACRO"
|
||||
|
||||
id_re = r"[a-zA-Z_][0-9a-zA-Z_]*"
|
||||
IDENTIFIER = "IDENTIFIER"
|
||||
|
||||
|
||||
suffix = r"([uU]?[lL]?[lL]?)"
|
||||
octal = r"0[0-7]+" + suffix
|
||||
hex = r"0[xX][0-9a-fA-F]+"
|
||||
|
@ -173,10 +174,6 @@ def choice(*opts: str) -> str:
|
|||
kwds.append(INT)
|
||||
LONG = "LONG"
|
||||
kwds.append(LONG)
|
||||
OVERRIDE = "OVERRIDE"
|
||||
kwds.append(OVERRIDE)
|
||||
REGISTER = "REGISTER"
|
||||
kwds.append(REGISTER)
|
||||
OFFSETOF = "OFFSETOF"
|
||||
kwds.append(OFFSETOF)
|
||||
RESTRICT = "RESTRICT"
|
||||
|
@ -207,8 +204,20 @@ def choice(*opts: str) -> str:
|
|||
kwds.append(VOLATILE)
|
||||
WHILE = "WHILE"
|
||||
kwds.append(WHILE)
|
||||
# An instruction in the DSL
|
||||
INST = "INST"
|
||||
kwds.append(INST)
|
||||
# A micro-op in the DSL
|
||||
OP = "OP"
|
||||
kwds.append(OP)
|
||||
# A macro in the DSL
|
||||
MACRO = "MACRO"
|
||||
kwds.append(MACRO)
|
||||
keywords = {name.lower(): name for name in kwds}
|
||||
|
||||
ANNOTATION = "ANNOTATION"
|
||||
annotations = {"specializing", "guard", "override", "register"}
|
||||
|
||||
__all__ = []
|
||||
__all__.extend(kwds)
|
||||
|
||||
|
@ -270,6 +279,8 @@ def tokenize(src: str, line: int = 1, filename: str | None = None) -> Iterator[T
|
|||
text = m.group(0)
|
||||
if text in keywords:
|
||||
kind = keywords[text]
|
||||
elif text in annotations:
|
||||
kind = ANNOTATION
|
||||
elif letter.match(text):
|
||||
kind = IDENTIFIER
|
||||
elif text == "...":
|
||||
|
@ -289,7 +300,7 @@ def tokenize(src: str, line: int = 1, filename: str | None = None) -> Iterator[T
|
|||
elif text[0] == "'":
|
||||
kind = CHARACTER
|
||||
elif text[0] == "#":
|
||||
kind = MACRO
|
||||
kind = CMACRO
|
||||
elif text[0] == "/" and text[1] in "/*":
|
||||
kind = COMMENT
|
||||
else:
|
||||
|
|
|
@ -105,8 +105,7 @@ class OpName(Node):
|
|||
|
||||
@dataclass
|
||||
class InstHeader(Node):
|
||||
override: bool
|
||||
register: bool
|
||||
annotations : list[str]
|
||||
kind: Literal["inst", "op"]
|
||||
name: str
|
||||
inputs: list[InputEffect]
|
||||
|
@ -115,8 +114,7 @@ class InstHeader(Node):
|
|||
|
||||
@dataclass
|
||||
class InstDef(Node):
|
||||
override: bool
|
||||
register: bool
|
||||
annotations : list[str]
|
||||
kind: Literal["inst", "op"]
|
||||
name: str
|
||||
inputs: list[InputEffect]
|
||||
|
@ -146,14 +144,14 @@ class Pseudo(Node):
|
|||
class Parser(PLexer):
|
||||
@contextual
|
||||
def definition(self) -> InstDef | Macro | Pseudo | Family | None:
|
||||
if inst := self.inst_def():
|
||||
return inst
|
||||
if macro := self.macro_def():
|
||||
return macro
|
||||
if family := self.family_def():
|
||||
return family
|
||||
if pseudo := self.pseudo_def():
|
||||
return pseudo
|
||||
if inst := self.inst_def():
|
||||
return inst
|
||||
return None
|
||||
|
||||
@contextual
|
||||
|
@ -161,8 +159,7 @@ def inst_def(self) -> InstDef | None:
|
|||
if hdr := self.inst_header():
|
||||
if block := self.block():
|
||||
return InstDef(
|
||||
hdr.override,
|
||||
hdr.register,
|
||||
hdr.annotations,
|
||||
hdr.kind,
|
||||
hdr.name,
|
||||
hdr.inputs,
|
||||
|
@ -174,13 +171,15 @@ def inst_def(self) -> InstDef | None:
|
|||
|
||||
@contextual
|
||||
def inst_header(self) -> InstHeader | None:
|
||||
# [override] inst(NAME)
|
||||
# | [override] [register] inst(NAME, (inputs -- outputs))
|
||||
# | [override] [register] op(NAME, (inputs -- outputs))
|
||||
# TODO: Make INST a keyword in the lexer.
|
||||
override = bool(self.expect(lx.OVERRIDE))
|
||||
register = bool(self.expect(lx.REGISTER))
|
||||
if (tkn := self.expect(lx.IDENTIFIER)) and tkn.text in ("inst", "op"):
|
||||
# annotation* inst(NAME, (inputs -- outputs))
|
||||
# | annotation* op(NAME, (inputs -- outputs))
|
||||
annotations = []
|
||||
while anno := self.expect(lx.ANNOTATION):
|
||||
annotations.append(anno.text)
|
||||
tkn = self.expect(lx.INST)
|
||||
if not tkn:
|
||||
tkn = self.expect(lx.OP)
|
||||
if tkn:
|
||||
kind = cast(Literal["inst", "op"], tkn.text)
|
||||
if self.expect(lx.LPAREN) and (tkn := self.expect(lx.IDENTIFIER)):
|
||||
name = tkn.text
|
||||
|
@ -188,7 +187,7 @@ def inst_header(self) -> InstHeader | None:
|
|||
inp, outp = self.io_effect()
|
||||
if self.expect(lx.RPAREN):
|
||||
if (tkn := self.peek()) and tkn.kind == lx.LBRACE:
|
||||
return InstHeader(override, register, kind, name, inp, outp)
|
||||
return InstHeader(annotations, kind, name, inp, outp)
|
||||
return None
|
||||
|
||||
def io_effect(self) -> tuple[list[InputEffect], list[OutputEffect]]:
|
||||
|
@ -312,7 +311,7 @@ def op(self) -> OpName | None:
|
|||
|
||||
@contextual
|
||||
def macro_def(self) -> Macro | None:
|
||||
if (tkn := self.expect(lx.IDENTIFIER)) and tkn.text == "macro":
|
||||
if tkn := self.expect(lx.MACRO):
|
||||
if self.expect(lx.LPAREN):
|
||||
if tkn := self.expect(lx.IDENTIFIER):
|
||||
if self.expect(lx.RPAREN):
|
||||
|
|
Loading…
Reference in a new issue