Source

hotpy_2 / HotPy / trace_opcode_header_gen.py

Full commit

import opcode, sys, re

small_ops = [ 'make_frame', 'leave_frame', 'as_tuple', 'reraise',
              'stop_iteration_or_reraise',  'sub_type', 'kw_dict_merge',
              'make_generator', 'enter_frame', 'new_function', 'new_closure',
              'trace_end', 'get_global_and_builtins', 'save_exc_state', 'swap_exc_state',
              'restore_clear_exc_state', 'setup_except_handler', 'clear_frame',
              'get_globals_from_function' ]

with_arg_ops = [ 'binary_op', 'ensure_type_tos', 'ensure_type_nos', 'jump_back',
                 'fast_frame', 'set_lasti', 'trace_load_constant', 'pick',
                 'setup_for_iter', 'load_and_clear_register',
                 'call_object', 'pop_exit_if_true', 'exit', 'poly_exit',
                 'pop_exit_if_false', 'exit_if_different', 'load_register',
                 'store_register', 'call_cfunc_0', 'call_cfunc_1',
                 'call_cfunc_2', 'call_cmeth_0', 'call_cmeth_1',
                 'call_cmeth_2', 'no_keywords', 'no_args', 'one_arg',
                 'two_args', 'three_args', 'call_wrapper_unary',
                 'call_wrapper_next', 'call_wrapper_binary',
                 'call_wrapper_trinary_proc', 'exit_if_not_bool_or_int',
                 'value_from_object_dict_or_exit', 'gen_check_or_exit',
                 'exit_if_value_in_object_dict', 'load_slot', 'store_slot',
                 'load_slot_ex', 'store_member',
                 'call_wrapper_binary_null_proc',
                 'value_from_object_dict_and_jump',
                 'load_from_global_and_builtins',
                 'store_to_globals', 'one_plus_args',
                 'materialise_frame', 'set_in_object_dict_const',
                 'trace_descriptor_get', 'trace_descriptor_set' ]

register_ops = [ 'new_frame', 'push_register_to_stack', 'move',
                 'pop_stack_to_register', 'tuple_set_item', 'list_set_item',
                 'const_to_register', 'exit_if_false', 'exit_if_true',
                 'ensure_type', 'ensure_value', 'ensure_slot',
                 'value_from_object_dict_or_exit_const', 'setup_block',
                 'poly_type_exit', 'two_move', 'copy_move', 'fast_load_global',
                 'binary_op_kv', 'binary_op_vk', 'load_member' ]

names =  [ '' ] * 256
op_used = [ False ] * 256
last_used_op = 0 # Don't use 0
opcode_list = [ '/* Opcode %d unused */' % n for n in range(256)]
for op, code in opcode.opmap.items():
    if op.startswith("BINARY_") or op.startswith("INPLACE_"):
        names[code] = '%s' % op
    else:
        opcode_list[code] = '/* Non-trace opcode %s = %d */' % (op, code)
        op_used[code] = True
        names[code] = '%s' % op

def add_op(name, op):
    op_used[op] = True
    opcode_list[op] = "#define %s %d" %(name.upper(), op)
    if names[op]:
        names[op] += ' or ' + name.upper()
    else:
        names[op] = name.upper()

def add_extra_op(name):
    global last_used_op
    last_used_op += 1
    while op_used[last_used_op]:
        last_used_op += 1
    add_op(name, last_used_op)

for op in small_ops:
    add_extra_op(op)

assert last_used_op < opcode.HAVE_ARGUMENT
last_used_op = opcode.HAVE_ARGUMENT

for op in with_arg_ops:
    add_extra_op(op)

for op in register_ops:
    add_extra_op(op)

for line in opcode_list:
    print (line)

print()
print('#ifdef WITH_INSTRUCTION_NAMES')
print('char * _HotPy_Instruction_Names[] = {')
for op, name in enumerate(names):
    if name:
        print ('"%s",' % name)
    else:
        print ('"%s",' % op)
print('};\n')
print('#else')
print('extern char *_HotPy_Instruction_Names[];')
print('#endif\n')
print('#define USED_OPCODES %d' % (last_used_op +1 ))
print()