refactor TargetMachine into a new target module

TargetMachine is generally useful outside of the execution engine
context so i think it makes sense to move it into its own module.
This commit is contained in:
anthony cantor 2013-08-17 00:41:42 -06:00 • committed by Siu Kwan Lam
commit 83299a20a6
3 changed files with 196 additions and 174 deletions

View file

@ -4,7 +4,6 @@ del get_versions
from llvmpy import extra from llvmpy import extra
from llvmpy import api
version = extra.get_llvm_version() version = extra.get_llvm_version()
del extra del extra
@ -44,12 +43,3 @@ def test(verbosity=1):
return len(result.failures) + len(result.errors) return len(result.failures) + len(result.errors)
def initialize_all_target_components():
api.llvm.InitializeAllTargets()
api.llvm.InitializeAllTargetInfos()
api.llvm.InitializeAllTargetMCs()
api.llvm.InitializeAllAsmPrinters()
api.llvm.InitializeAllDisassemblers()
api.llvm.InitializeAllAsmParsers()

View file

@ -31,33 +31,20 @@
"Execution Engine and related classes." "Execution Engine and related classes."
import sys import sys
from io import BytesIO
import contextlib
import llvm import llvm
from llvm import core from llvm import core
from llvm.passes import TargetData, TargetTransformInfo from llvm.passes import TargetData, TargetTransformInfo
from llvmpy import api, extra from llvmpy import api, extra
#===----------------------------------------------------------------------=== #===----------------------------------------------------------------------===
# Enumerations # import items which were moved to target module
#===----------------------------------------------------------------------=== #===----------------------------------------------------------------------===
from llvm.target import initialize_target, \
BO_BIG_ENDIAN = 0 print_registered_targets, \
BO_LITTLE_ENDIAN = 1 get_host_cpu_name, \
get_default_triple, \
# CodeModel TargetMachine
CM_DEFAULT = api.llvm.CodeModel.Model.Default
CM_JITDEFAULT = api.llvm.CodeModel.Model.JITDefault
CM_SMALL = api.llvm.CodeModel.Model.Small
CM_KERNEL = api.llvm.CodeModel.Model.Kernel
CM_MEDIUM = api.llvm.CodeModel.Model.Medium
CM_LARGE = api.llvm.CodeModel.Model.Large
# Reloc
RELOC_DEFAULT = api.llvm.Reloc.Model.Default
RELOC_STATIC = api.llvm.Reloc.Model.Static
RELOC_PIC = api.llvm.Reloc.Model.PIC_
RELOC_DYNAMIC_NO_PIC = api.llvm.Reloc.Model.DynamicNoPIC
#===----------------------------------------------------------------------=== #===----------------------------------------------------------------------===
# Generic value # Generic value
@ -239,150 +226,6 @@ class ExecutionEngine(llvm.Wrapper):
ptr = self._ptr.getDataLayout() ptr = self._ptr.getDataLayout()
return TargetData(ptr) return TargetData(ptr)
#===----------------------------------------------------------------------===
# Target machine
#===----------------------------------------------------------------------===
def initialize_target(target, noraise=False):
"""Initialize target by name.
It is safe to initialize the same target multiple times.
"""
prefix = 'LLVMInitialize'
postfixes = ['Target', 'TargetInfo', 'TargetMC', 'AsmPrinter', 'AsmParser']
try:
for postfix in postfixes:
getattr(api, '%s%s%s' % (prefix, target, postfix))()
except AttributeError:
if noraise:
return False
else:
raise
else:
return True
def print_registered_targets():
'''
Note: print directly to stdout
'''
api.llvm.TargetRegistry.printRegisteredTargetsForVersion()
def get_host_cpu_name():
'''return the string name of the host CPU
'''
return api.llvm.sys.getHostCPUName()
def get_default_triple():
'''return the target triple of the host in str-rep
'''
return api.llvm.sys.getDefaultTargetTriple()
class TargetMachine(llvm.Wrapper):
@staticmethod
def new(triple='', cpu='', features='', opt=2, cm=CM_DEFAULT,
reloc=RELOC_DEFAULT):
if not triple:
triple = get_default_triple()
if not cpu:
cpu = get_host_cpu_name()
with contextlib.closing(BytesIO()) as error:
target = api.llvm.TargetRegistry.lookupTarget(triple, error)
if not target:
raise llvm.LLVMException(error.getvalue())
if not target.hasTargetMachine():
raise llvm.LLVMException(target, "No target machine.")
target_options = api.llvm.TargetOptions.new()
tm = target.createTargetMachine(triple, cpu, features,
target_options,
reloc, cm, opt)
if not tm:
raise llvm.LLVMException("Cannot create target machine")
return TargetMachine(tm)
@staticmethod
def lookup(arch, cpu='', features='', opt=2, cm=CM_DEFAULT,
reloc=RELOC_DEFAULT):
'''create a targetmachine given an architecture name
For a list of architectures,
use: `llc -help`
For a list of available CPUs,
use: `llvm-as < /dev/null | llc -march=xyz -mcpu=help`
For a list of available attributes (features),
use: `llvm-as < /dev/null | llc -march=xyz -mattr=help`
'''
triple = api.llvm.Triple.new()
with contextlib.closing(BytesIO()) as error:
target = api.llvm.TargetRegistry.lookupTarget(arch, triple, error)
if not target:
raise llvm.LLVMException(error.getvalue())
if not target.hasTargetMachine():
raise llvm.LLVMException(target, "No target machine.")
target_options = api.llvm.TargetOptions.new()
tm = target.createTargetMachine(str(triple), cpu, features,
target_options,
reloc, cm, opt)
if not tm:
raise llvm.LLVMException("Cannot create target machine")
return TargetMachine(tm)
def _emit_file(self, module, cgft):
pm = api.llvm.PassManager.new()
os = extra.make_raw_ostream_for_printing()
pm.add(api.llvm.DataLayout.new(str(self.target_data)))
failed = self._ptr.addPassesToEmitFile(pm, os, cgft)
pm.run(module)
CGFT = api.llvm.TargetMachine.CodeGenFileType
if cgft == CGFT.CGFT_ObjectFile:
return os.bytes()
else:
return os.str()
def emit_assembly(self, module):
'''returns byte string of the module as assembly code of the target machine
'''
CGFT = api.llvm.TargetMachine.CodeGenFileType
return self._emit_file(module._ptr, CGFT.CGFT_AssemblyFile)
def emit_object(self, module):
'''returns byte string of the module as native code of the target machine
'''
CGFT = api.llvm.TargetMachine.CodeGenFileType
return self._emit_file(module._ptr, CGFT.CGFT_ObjectFile)
@property
def target_data(self):
'''get target data of this machine
'''
return TargetData(self._ptr.getDataLayout())
@property
def target_name(self):
return self._ptr.getTarget().getName()
@property
def target_short_description(self):
return self._ptr.getTarget().getShortDescription()
@property
def triple(self):
return self._ptr.getTargetTriple()
@property
def cpu(self):
return self._ptr.getTargetCPU()
@property
def feature_string(self):
return self._ptr.getTargetFeatureString()
#===----------------------------------------------------------------------=== #===----------------------------------------------------------------------===
# Dynamic Library # Dynamic Library

189
llvm/target.py Normal file
View file

@ -0,0 +1,189 @@
import llvm
from llvmpy import api, extra
from io import BytesIO
import contextlib
from llvm.passes import TargetData
#===----------------------------------------------------------------------===
# Enumerations
#===----------------------------------------------------------------------===
BO_BIG_ENDIAN = 0
BO_LITTLE_ENDIAN = 1
# CodeModel
CM_DEFAULT = api.llvm.CodeModel.Model.Default
CM_JITDEFAULT = api.llvm.CodeModel.Model.JITDefault
CM_SMALL = api.llvm.CodeModel.Model.Small
CM_KERNEL = api.llvm.CodeModel.Model.Kernel
CM_MEDIUM = api.llvm.CodeModel.Model.Medium
CM_LARGE = api.llvm.CodeModel.Model.Large
# Reloc
RELOC_DEFAULT = api.llvm.Reloc.Model.Default
RELOC_STATIC = api.llvm.Reloc.Model.Static
RELOC_PIC = api.llvm.Reloc.Model.PIC_
RELOC_DYNAMIC_NO_PIC = api.llvm.Reloc.Model.DynamicNoPIC
def initialize_all():
api.llvm.InitializeAllTargets()
api.llvm.InitializeAllTargetInfos()
api.llvm.InitializeAllTargetMCs()
api.llvm.InitializeAllAsmPrinters()
api.llvm.InitializeAllDisassemblers()
api.llvm.InitializeAllAsmParsers()
def initialize_target(target, noraise=False):
"""Initialize target by name.
It is safe to initialize the same target multiple times.
"""
prefix = 'LLVMInitialize'
postfixes = ['Target', 'TargetInfo', 'TargetMC', 'AsmPrinter', 'AsmParser']
try:
for postfix in postfixes:
getattr(api, '%s%s%s' % (prefix, target, postfix))()
except AttributeError:
if noraise:
return False
else:
raise
else:
return True
def print_registered_targets():
'''
Note: print directly to stdout
'''
api.llvm.TargetRegistry.printRegisteredTargetsForVersion()
def get_host_cpu_name():
'''return the string name of the host CPU
'''
return api.llvm.sys.getHostCPUName()
def get_default_triple():
'''return the target triple of the host in str-rep
'''
return api.llvm.sys.getDefaultTargetTriple()
class TargetMachine(llvm.Wrapper):
@staticmethod
def new(triple='', cpu='', features='', opt=2, cm=CM_DEFAULT,
reloc=RELOC_DEFAULT):
if not triple:
triple = get_default_triple()
if not cpu:
cpu = get_host_cpu_name()
with contextlib.closing(BytesIO()) as error:
target = api.llvm.TargetRegistry.lookupTarget(triple, error)
if not target:
raise llvm.LLVMException(error.getvalue())
if not target.hasTargetMachine():
raise llvm.LLVMException(target, "No target machine.")
target_options = api.llvm.TargetOptions.new()
tm = target.createTargetMachine(triple, cpu, features,
target_options,
reloc, cm, opt)
if not tm:
raise llvm.LLVMException("Cannot create target machine")
return TargetMachine(tm)
@staticmethod
def lookup(arch, cpu='', features='', opt=2, cm=CM_DEFAULT,
reloc=RELOC_DEFAULT):
'''create a targetmachine given an architecture name
For a list of architectures,
use: `llc -help`
For a list of available CPUs,
use: `llvm-as < /dev/null | llc -march=xyz -mcpu=help`
For a list of available attributes (features),
use: `llvm-as < /dev/null | llc -march=xyz -mattr=help`
'''
triple = api.llvm.Triple.new()
with contextlib.closing(BytesIO()) as error:
target = api.llvm.TargetRegistry.lookupTarget(arch, triple, error)
if not target:
raise llvm.LLVMException(error.getvalue())
if not target.hasTargetMachine():
raise llvm.LLVMException(target, "No target machine.")
target_options = api.llvm.TargetOptions.new()
tm = target.createTargetMachine(str(triple), cpu, features,
target_options,
reloc, cm, opt)
if not tm:
raise llvm.LLVMException("Cannot create target machine")
return TargetMachine(tm)
@staticmethod
def x86():
return TargetMachine.lookup('x86')
@staticmethod
def x86_64():
return TargetMachine.lookup('x86-64')
@staticmethod
def arm():
return TargetMachine.lookup('arm')
@staticmethod
def thumb():
return TargetMachine.lookup('thumb')
def _emit_file(self, module, cgft):
pm = api.llvm.PassManager.new()
os = extra.make_raw_ostream_for_printing()
pm.add(api.llvm.DataLayout.new(str(self.target_data)))
failed = self._ptr.addPassesToEmitFile(pm, os, cgft)
pm.run(module)
CGFT = api.llvm.TargetMachine.CodeGenFileType
if cgft == CGFT.CGFT_ObjectFile:
return os.bytes()
else:
return os.str()
def emit_assembly(self, module):
'''returns byte string of the module as assembly code of the target machine
'''
CGFT = api.llvm.TargetMachine.CodeGenFileType
return self._emit_file(module._ptr, CGFT.CGFT_AssemblyFile)
def emit_object(self, module):
'''returns byte string of the module as native code of the target machine
'''
CGFT = api.llvm.TargetMachine.CodeGenFileType
return self._emit_file(module._ptr, CGFT.CGFT_ObjectFile)
@property
def target_data(self):
'''get target data of this machine
'''
return TargetData(self._ptr.getDataLayout())
@property
def target_name(self):
return self._ptr.getTarget().getName()
@property
def target_short_description(self):
return self._ptr.getTarget().getShortDescription()
@property
def triple(self):
return self._ptr.getTargetTriple()
@property
def cpu(self):
return self._ptr.getTargetCPU()
@property
def feature_string(self):
return self._ptr.getTargetFeatureString()