1  #! /usr/bin/env python
       2  """Generate C code for the jump table of the threaded code interpreter
       3  (for compilers supporting computed gotos or "labels-as-values", such as gcc).
       4  """
       5  
       6  import os
       7  import sys
       8  
       9  
      10  # 2023-04-27(warsaw): Pre-Python 3.12, this would catch ImportErrors and try to
      11  # import imp, and then use imp.load_module().  The imp module was removed in
      12  # Python 3.12 (and long deprecated before that), and it's unclear under what
      13  # conditions this import will now fail, so the fallback was simply removed.
      14  from importlib.machinery import SourceFileLoader
      15  
      16  def find_module(modname):
      17      """Finds and returns a module in the local dist/checkout.
      18      """
      19      modpath = os.path.join(
      20          os.path.dirname(os.path.dirname(__file__)), "Lib", modname + ".py")
      21      return SourceFileLoader(modname, modpath).load_module()
      22  
      23  
      24  def write_contents(f):
      25      """Write C code contents to the target file object.
      26      """
      27      opcode = find_module('opcode')
      28      targets = ['_unknown_opcode'] * 256
      29      for opname, op in opcode.opmap.items():
      30          if not opcode.is_pseudo(op):
      31              targets[op] = "TARGET_%s" % opname
      32      next_op = 1
      33      for opname in opcode._specialized_instructions:
      34          while targets[next_op] != '_unknown_opcode':
      35              next_op += 1
      36          targets[next_op] = "TARGET_%s" % opname
      37      f.write("static void *opcode_targets[256] = {\n")
      38      f.write(",\n".join(["    &&%s" % s for s in targets]))
      39      f.write("\n};\n")
      40  
      41  
      42  def main():
      43      if len(sys.argv) >= 3:
      44          sys.exit("Too many arguments")
      45      if len(sys.argv) == 2:
      46          target = sys.argv[1]
      47      else:
      48          target = "Python/opcode_targets.h"
      49      with open(target, "w") as f:
      50          write_contents(f)
      51      print("Jump table written into %s" % target)
      52  
      53  
      54  if __name__ == "__main__":
      55      main()