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:
parent
97c0e15e72
commit
83299a20a6
3 changed files with 196 additions and 174 deletions
|
|
@ -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()
|
|
||||||
|
|
||||||
|
|
|
||||||
171
llvm/ee.py
171
llvm/ee.py
|
|
@ -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
189
llvm/target.py
Normal 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()
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue