PageRenderTime 43ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/rpython/jit/backend/detect_cpu.py

https://bitbucket.org/pypy/pypy/
Python | 163 lines | 151 code | 6 blank | 6 comment | 3 complexity | 0adffc942b33f3af59e6e6ee5b097cfa MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. """
  2. Processor auto-detection
  3. """
  4. import sys, os
  5. from rpython.rtyper.tool.rffi_platform import getdefined
  6. from rpython.translator.platform import is_host_build
  7. class ProcessorAutodetectError(Exception):
  8. pass
  9. MODEL_X86 = 'x86'
  10. MODEL_X86_NO_SSE2 = 'x86-without-sse2'
  11. MODEL_X86_64 = 'x86-64'
  12. MODEL_X86_64_SSE4 = 'x86-64-sse4'
  13. MODEL_ARM = 'arm'
  14. MODEL_PPC_64 = 'ppc-64'
  15. MODEL_S390_64 = 's390x'
  16. # don't use '_' in the model strings; they are replaced by '-'
  17. def detect_model_from_c_compiler():
  18. # based on http://sourceforge.net/p/predef/wiki/Architectures/
  19. # and http://msdn.microsoft.com/en-us/library/b0084kay.aspx
  20. mapping = {
  21. MODEL_X86_64: ['__amd64__', '__amd64', '__x86_64__', '__x86_64', '_M_X64', '_M_AMD64'],
  22. MODEL_ARM: ['__arm__', '__thumb__','_M_ARM_EP'],
  23. MODEL_X86: ['i386', '__i386', '__i386__', '__i686__','_M_IX86'],
  24. MODEL_PPC_64: ['__powerpc64__'],
  25. MODEL_S390_64:['__s390x__'],
  26. }
  27. for k, v in mapping.iteritems():
  28. for macro in v:
  29. if not getdefined(macro, ''):
  30. continue
  31. return k
  32. raise ProcessorAutodetectError("Cannot detect processor using compiler macros")
  33. def detect_model_from_host_platform():
  34. mach = None
  35. try:
  36. import platform
  37. mach = platform.machine()
  38. except ImportError:
  39. pass
  40. if not mach:
  41. platform = sys.platform.lower()
  42. if platform.startswith('win'): # assume an Intel Windows
  43. return MODEL_X86
  44. # assume we have 'uname'
  45. mach = os.popen('uname -m', 'r').read().strip()
  46. if not mach:
  47. raise ProcessorAutodetectError("cannot run 'uname -m'")
  48. #
  49. result ={'i386': MODEL_X86,
  50. 'i486': MODEL_X86,
  51. 'i586': MODEL_X86,
  52. 'i686': MODEL_X86,
  53. 'i86pc': MODEL_X86, # Solaris/Intel
  54. 'x86': MODEL_X86, # Apple
  55. 'Power Macintosh': MODEL_PPC_64,
  56. 'ppc64': MODEL_PPC_64,
  57. 'ppc64le': MODEL_PPC_64,
  58. 'x86_64': MODEL_X86,
  59. 'amd64': MODEL_X86, # freebsd
  60. 'AMD64': MODEL_X86, # win64
  61. 'armv8l': MODEL_ARM, # 32-bit ARMv8
  62. 'armv7l': MODEL_ARM,
  63. 'armv6l': MODEL_ARM,
  64. 'arm': MODEL_ARM, # freebsd
  65. 's390x': MODEL_S390_64
  66. }.get(mach)
  67. if result is None:
  68. raise ProcessorAutodetectError("unknown machine name %s" % mach)
  69. #
  70. if result.startswith('x86'):
  71. from rpython.jit.backend.x86 import detect_feature as feature
  72. if sys.maxint == 2**63-1:
  73. result = MODEL_X86_64
  74. # has sse 2 at least
  75. if feature.detect_sse4_1():
  76. result = MODEL_X86_64_SSE4
  77. else:
  78. assert sys.maxint == 2**31-1
  79. if feature.detect_sse2():
  80. result = MODEL_X86
  81. else:
  82. result = MODEL_X86_NO_SSE2
  83. if feature.detect_x32_mode():
  84. raise ProcessorAutodetectError(
  85. 'JITting in x32 mode is not implemented')
  86. #
  87. if result.startswith('arm'):
  88. from rpython.jit.backend.arm.detect import detect_float
  89. if not detect_float():
  90. raise ProcessorAutodetectError(
  91. 'the JIT-compiler requires a vfp unit')
  92. #
  93. return result
  94. def autodetect():
  95. if not is_host_build():
  96. return detect_model_from_c_compiler()
  97. else:
  98. return detect_model_from_host_platform()
  99. def getcpuclassname(backend_name="auto"):
  100. if backend_name == "auto":
  101. backend_name = autodetect()
  102. backend_name = backend_name.replace('_', '-')
  103. if backend_name == MODEL_X86:
  104. return "rpython.jit.backend.x86.runner", "CPU"
  105. elif backend_name == MODEL_X86_NO_SSE2:
  106. return "rpython.jit.backend.x86.runner", "CPU386_NO_SSE2"
  107. elif backend_name == MODEL_X86_64:
  108. return "rpython.jit.backend.x86.runner", "CPU_X86_64"
  109. elif backend_name == MODEL_X86_64_SSE4:
  110. return "rpython.jit.backend.x86.runner", "CPU_X86_64_SSE4"
  111. elif backend_name == MODEL_ARM:
  112. return "rpython.jit.backend.arm.runner", "CPU_ARM"
  113. elif backend_name == MODEL_PPC_64:
  114. return "rpython.jit.backend.ppc.runner", "PPC_CPU"
  115. elif backend_name == MODEL_S390_64:
  116. return "rpython.jit.backend.zarch.runner", "CPU_S390_64"
  117. else:
  118. raise ProcessorAutodetectError(
  119. "we have no JIT backend for this cpu: '%s'" % backend_name)
  120. def getcpuclass(backend_name="auto"):
  121. modname, clsname = getcpuclassname(backend_name)
  122. mod = __import__(modname, {}, {}, clsname)
  123. return getattr(mod, clsname)
  124. def getcpufeatures(backend_name="auto"):
  125. if backend_name == "auto":
  126. backend_name = autodetect()
  127. return {
  128. MODEL_X86: ['floats', 'singlefloats', 'longlong'],
  129. MODEL_X86_NO_SSE2: ['longlong'],
  130. MODEL_X86_64: ['floats', 'singlefloats'],
  131. MODEL_X86_64_SSE4: ['floats', 'singlefloats'],
  132. MODEL_ARM: ['floats', 'singlefloats', 'longlong'],
  133. MODEL_PPC_64: ['floats'],
  134. MODEL_S390_64: ['floats'],
  135. }[backend_name]
  136. if __name__ == '__main__':
  137. if len(sys.argv) > 1:
  138. name = sys.argv[1]
  139. x = name
  140. else:
  141. name = 'auto'
  142. x = autodetect()
  143. x = (x, getcpuclassname(name), getcpufeatures(name))
  144. print 'autodetect: ', x[0]
  145. print 'getcpuclassname:', x[1]
  146. print 'getcpufeatures: ', x[2]