PageRenderTime 41ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/rpython/translator/goal/translate.py

https://bitbucket.org/pypy/pypy/
Python | 333 lines | 322 code | 4 blank | 7 comment | 9 complexity | fc723bb6647a740dcd8519cee3f55519 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. #! /usr/bin/env pypy
  2. """
  3. Command-line options for translate:
  4. See below
  5. """
  6. import os
  7. import sys
  8. import py
  9. from rpython.config.config import (to_optparse, OptionDescription, BoolOption,
  10. ArbitraryOption, StrOption, IntOption, Config, ChoiceOption, OptHelpFormatter)
  11. from rpython.config.translationoption import (get_combined_translation_config,
  12. set_opt_level, OPT_LEVELS, DEFAULT_OPT_LEVEL, set_platform, CACHE_DIR)
  13. # clean up early rpython/_cache
  14. try:
  15. py.path.local(CACHE_DIR).remove()
  16. except Exception:
  17. pass
  18. GOALS = [
  19. ("annotate", "do type inference", "-a --annotate", ""),
  20. ("rtype", "do rtyping", "-t --rtype", ""),
  21. ("pyjitpl", "JIT generation step", "--pyjitpl", ""),
  22. ("jittest", "JIT test with llgraph backend", "--pyjittest", ""),
  23. ("backendopt", "do backend optimizations", "--backendopt", ""),
  24. ("source", "create source", "-s --source", ""),
  25. ("compile", "compile", "-c --compile", " (default goal)"),
  26. ("llinterpret", "interpret the rtyped flow graphs", "--llinterpret", ""),
  27. ]
  28. def goal_options():
  29. result = []
  30. for name, doc, cmdline, extra in GOALS:
  31. optional = False
  32. if name.startswith('?'):
  33. optional = True
  34. name = name[1:]
  35. yesdoc = doc[0].upper() + doc[1:] + extra
  36. result.append(BoolOption(name, yesdoc, default=False, cmdline=cmdline,
  37. negation=False))
  38. if not optional:
  39. result.append(BoolOption("no_%s" % name, "Don't " + doc, default=False,
  40. cmdline="--no-" + name, negation=False))
  41. return result
  42. translate_optiondescr = OptionDescription("translate", "XXX", [
  43. StrOption("targetspec", "XXX", default='targetpypystandalone',
  44. cmdline=None),
  45. ChoiceOption("opt",
  46. "optimization level", OPT_LEVELS, default=DEFAULT_OPT_LEVEL,
  47. cmdline="--opt -O"),
  48. BoolOption("profile",
  49. "cProfile (to debug the speed of the translation process)",
  50. default=False,
  51. cmdline="--profile"),
  52. BoolOption("pdb",
  53. "Always run pdb even if the translation succeeds",
  54. default=False,
  55. cmdline="--pdb"),
  56. BoolOption("batch", "Don't run interactive helpers", default=False,
  57. cmdline="--batch", negation=False),
  58. IntOption("huge", "Threshold in the number of functions after which "
  59. "a local call graph and not a full one is displayed",
  60. default=100, cmdline="--huge"),
  61. BoolOption("view", "Start the pygame viewer", default=False,
  62. cmdline="--view", negation=False),
  63. BoolOption("help", "show this help message and exit", default=False,
  64. cmdline="-h --help", negation=False),
  65. BoolOption("fullhelp", "show full help message and exit", default=False,
  66. cmdline="--full-help", negation=False),
  67. ArbitraryOption("goals", "XXX",
  68. defaultfactory=list),
  69. # xxx default goals ['annotate', 'rtype', 'backendopt', 'source', 'compile']
  70. ArbitraryOption("skipped_goals", "XXX",
  71. defaultfactory=list),
  72. OptionDescription("goal_options",
  73. "Goals that should be reached during translation",
  74. goal_options()),
  75. ])
  76. import optparse
  77. from rpython.tool.ansi_print import AnsiLogger
  78. log = AnsiLogger("translation")
  79. def load_target(targetspec):
  80. log.info("Translating target as defined by %s" % targetspec)
  81. if not targetspec.endswith('.py'):
  82. targetspec += '.py'
  83. thismod = sys.modules[__name__]
  84. sys.modules['translate'] = thismod
  85. specname = os.path.splitext(os.path.basename(targetspec))[0]
  86. sys.path.insert(0, os.path.dirname(targetspec))
  87. mod = __import__(specname)
  88. if 'target' not in mod.__dict__:
  89. raise Exception("file %r is not a valid targetxxx.py." % (targetspec,))
  90. return mod.__dict__
  91. def parse_options_and_load_target():
  92. opt_parser = optparse.OptionParser(usage="%prog [options] [target] [target-specific-options]",
  93. prog="translate",
  94. formatter=OptHelpFormatter(),
  95. add_help_option=False)
  96. opt_parser.disable_interspersed_args()
  97. config = get_combined_translation_config(translating=True)
  98. to_optparse(config, parser=opt_parser, useoptions=['translation.*'])
  99. translateconfig = Config(translate_optiondescr)
  100. to_optparse(translateconfig, parser=opt_parser)
  101. options, args = opt_parser.parse_args()
  102. # set goals and skipped_goals
  103. reset = False
  104. for name, _, _, _ in GOALS:
  105. if name.startswith('?'):
  106. continue
  107. if getattr(translateconfig.goal_options, name):
  108. if name not in translateconfig.goals:
  109. translateconfig.goals.append(name)
  110. if getattr(translateconfig.goal_options, 'no_' + name):
  111. if name not in translateconfig.skipped_goals:
  112. if not reset:
  113. translateconfig.skipped_goals[:] = []
  114. reset = True
  115. translateconfig.skipped_goals.append(name)
  116. if args:
  117. arg = args[0]
  118. args = args[1:]
  119. if os.path.isfile(arg + '.py'):
  120. assert not os.path.isfile(arg), (
  121. "ambiguous file naming, please rename %s" % arg)
  122. translateconfig.targetspec = arg
  123. elif os.path.isfile(arg) and arg.endswith('.py'):
  124. translateconfig.targetspec = arg[:-3]
  125. else:
  126. log.ERROR("Could not find target %r" % (arg, ))
  127. sys.exit(1)
  128. else:
  129. show_help(translateconfig, opt_parser, None, config)
  130. # print the version of the host
  131. # (if it's PyPy, it includes the hg checksum)
  132. log.info(sys.version)
  133. # apply the platform settings
  134. set_platform(config)
  135. targetspec = translateconfig.targetspec
  136. targetspec_dic = load_target(targetspec)
  137. if args and not targetspec_dic.get('take_options', False):
  138. log.WARNING("target specific arguments supplied but will be ignored: %s" % ' '.join(args))
  139. # give the target the possibility to get its own configuration options
  140. # into the config
  141. if 'get_additional_config_options' in targetspec_dic:
  142. optiondescr = targetspec_dic['get_additional_config_options']()
  143. config = get_combined_translation_config(
  144. optiondescr,
  145. existing_config=config,
  146. translating=True)
  147. # show the target-specific help if --help was given
  148. show_help(translateconfig, opt_parser, targetspec_dic, config)
  149. # apply the optimization level settings
  150. set_opt_level(config, translateconfig.opt)
  151. # let the target modify or prepare itself
  152. # based on the config
  153. if 'handle_config' in targetspec_dic:
  154. targetspec_dic['handle_config'](config, translateconfig)
  155. return targetspec_dic, translateconfig, config, args
  156. def show_help(translateconfig, opt_parser, targetspec_dic, config):
  157. if translateconfig.help:
  158. if targetspec_dic is None:
  159. opt_parser.print_help()
  160. print "\n\nDefault target: %s" % translateconfig.targetspec
  161. print "Run '%s --help %s' for target-specific help" % (
  162. sys.argv[0], translateconfig.targetspec)
  163. elif 'print_help' in targetspec_dic:
  164. print "\n\nTarget specific help for %s:\n\n" % (
  165. translateconfig.targetspec,)
  166. targetspec_dic['print_help'](config)
  167. else:
  168. print "\n\nNo target-specific help available for %s" % (
  169. translateconfig.targetspec,)
  170. print "\n\nFor detailed descriptions of the command line options see"
  171. print "http://pypy.readthedocs.org/en/latest/config/commandline.html"
  172. sys.exit(0)
  173. def log_options(options, header="options in effect"):
  174. # list options (xxx filter, filter for target)
  175. log('%s:' % header)
  176. optnames = options.__dict__.keys()
  177. optnames.sort()
  178. for name in optnames:
  179. optvalue = getattr(options, name)
  180. log('%25s: %s' % (name, optvalue))
  181. def log_config(config, header="config used"):
  182. log('%s:' % header)
  183. log(str(config))
  184. for warning in config.get_warnings():
  185. log.WARNING(warning)
  186. def main():
  187. targetspec_dic, translateconfig, config, args = parse_options_and_load_target()
  188. from rpython.translator import translator
  189. from rpython.translator import driver
  190. from rpython.translator.tool.pdbplus import PdbPlusShow
  191. if translateconfig.view:
  192. translateconfig.pdb = True
  193. if translateconfig.profile:
  194. from cProfile import Profile
  195. prof = Profile()
  196. prof.enable()
  197. else:
  198. prof = None
  199. t = translator.TranslationContext(config=config)
  200. pdb_plus_show = PdbPlusShow(t) # need a translator to support extended commands
  201. def finish_profiling():
  202. if prof:
  203. prof.disable()
  204. statfilename = 'prof.dump'
  205. log.info('Dumping profiler stats to: %s' % statfilename)
  206. prof.dump_stats(statfilename)
  207. def debug(got_error):
  208. tb = None
  209. if got_error:
  210. import traceback
  211. stacktrace_errmsg = ["Error:\n"]
  212. exc, val, tb = sys.exc_info()
  213. stacktrace_errmsg.extend([" %s" % line for line in traceback.format_tb(tb)])
  214. summary_errmsg = traceback.format_exception_only(exc, val)
  215. block = getattr(val, '__annotator_block', None)
  216. if block:
  217. class FileLike:
  218. def write(self, s):
  219. summary_errmsg.append(" %s" % s)
  220. summary_errmsg.append("Processing block:\n")
  221. t.about(block, FileLike())
  222. log.info(''.join(stacktrace_errmsg))
  223. log.ERROR(''.join(summary_errmsg))
  224. else:
  225. log.event('Done.')
  226. if translateconfig.batch:
  227. log.event("batch mode, not calling interactive helpers")
  228. return
  229. log.event("start debugger...")
  230. if translateconfig.view:
  231. try:
  232. t1 = drv.hint_translator
  233. except (NameError, AttributeError):
  234. t1 = t
  235. from rpython.translator.tool import graphpage
  236. page = graphpage.TranslatorPage(t1, translateconfig.huge)
  237. page.display_background()
  238. pdb_plus_show.start(tb)
  239. try:
  240. drv = driver.TranslationDriver.from_targetspec(targetspec_dic, config, args,
  241. empty_translator=t,
  242. disable=translateconfig.skipped_goals,
  243. default_goal='compile')
  244. log_config(translateconfig, "translate.py configuration")
  245. if config.translation.jit:
  246. if (translateconfig.goals != ['annotate'] and
  247. translateconfig.goals != ['rtype']):
  248. drv.set_extra_goals(['pyjitpl'])
  249. # early check:
  250. from rpython.jit.backend.detect_cpu import getcpuclassname
  251. getcpuclassname(config.translation.jit_backend)
  252. log_config(config.translation, "translation configuration")
  253. pdb_plus_show.expose({'drv': drv, 'prof': prof})
  254. if config.translation.output:
  255. drv.exe_name = config.translation.output
  256. elif drv.exe_name is None and '__name__' in targetspec_dic:
  257. drv.exe_name = targetspec_dic['__name__'] + '-%(backend)s'
  258. # Double check to ensure we are not overwriting the current interpreter
  259. goals = translateconfig.goals
  260. if not goals or 'compile' in goals:
  261. try:
  262. this_exe = py.path.local(sys.executable).new(ext='')
  263. exe_name = drv.compute_exe_name()
  264. samefile = this_exe.samefile(exe_name)
  265. assert not samefile, (
  266. 'Output file %s is the currently running '
  267. 'interpreter (please move the executable, and '
  268. 'possibly its associated libpypy-c, somewhere else '
  269. 'before you execute it)' % exe_name)
  270. except EnvironmentError:
  271. pass
  272. try:
  273. drv.proceed(goals)
  274. finally:
  275. drv.timer.pprint()
  276. except SystemExit:
  277. raise
  278. except:
  279. finish_profiling()
  280. debug(True)
  281. raise SystemExit(1)
  282. else:
  283. finish_profiling()
  284. if translateconfig.pdb:
  285. debug(False)
  286. if __name__ == '__main__':
  287. main()