Merge branch 'master' of github.com:llvmpy/llvmpy

This commit is contained in:
Maggie Mari 2012-08-15 17:28:34 -05:00
commit 0b63bd7a9f
10 changed files with 465 additions and 34 deletions

View file

@ -200,8 +200,11 @@ _wLLVMGetNativeCodeFromModule(PyObject * self, PyObject * args)
m = (LLVMModuleRef) PyCapsule_GetPointer(arg_m, NULL);
if ( !(bytes = LLVMGetNativeCodeFromModule(m, arg_use_asm, &len)) )
Py_RETURN_NONE;
std::string error;
bytes = LLVMGetNativeCodeFromModule(m, arg_use_asm, &len, error);
if ( !error.empty() ){
PyErr_SetString(PyExc_RuntimeError, error.c_str());
}
ret = PyBytes_FromStringAndSize((char *)bytes, (Py_ssize_t)len);
delete [] bytes;
@ -888,16 +891,15 @@ _wrap_obj2none(LLVMDisposePassManager, LLVMPassManagerRef)
_wrap_none2str(LLVMDumpPasses)
_wrap_objstr2obj(LLVMAddPassByName, LLVMPassManagerRef, int)
static PyObject *
_wLLVMInitializePasses(PyObject * self, PyObject * args)
{
if (!PyArg_ParseTuple(args, ""))
return NULL;
LLVMInitializePasses();
Py_RETURN_NONE;
}
_wrap_none2none(LLVMInitializePasses)
_wrap_none2obj(LLVMInitializeNativeTarget, int)
_wrap_none2obj(LLVMInitializeNativeTargetAsmPrinter, int)
_wrap_none2none(LLVMInitializePTXTarget)
_wrap_none2none(LLVMInitializePTXTargetInfo)
_wrap_none2none( LLVMInitializePTXTargetMC )
_wrap_none2none(LLVMInitializePTXAsmPrinter)
/*===----------------------------------------------------------------------===*/
@ -993,6 +995,77 @@ _wrap_pass( UnifyFunctionExitNodes )
_wrap_pass( Internalize2 )
*/
/*===----------------------------------------------------------------------===*/
/* Target Machine */
/*===----------------------------------------------------------------------===*/
_wrap_obj2obj(LLVMTargetMachineFromEngineBuilder, LLVMEngineBuilderRef,
LLVMTargetMachineRef)
_wrap_obj2none(LLVMDisposeTargetMachine, LLVMTargetMachineRef)
static PyObject *
_wLLVMTargetMachineLookup(PyObject * self, PyObject * args)
{
const char *arch;
const char *cpu;
const char *features;
int opt;
if (!PyArg_ParseTuple(args, "sssi", &arch, &cpu, &features, &opt))
return NULL;
std::string error;
LLVMTargetMachineRef tm = LLVMTargetMachineLookup(arch, cpu, features, opt,
error);
if(!error.empty()){
PyErr_SetString(PyExc_RuntimeError, error.c_str());
return NULL;
}
return ctor_LLVMTargetMachineRef(tm);
}
static PyObject *
_wLLVMTargetMachineEmitFile(PyObject * self, PyObject * args)
{
PyObject * ret;
unsigned len;
unsigned char * bytes;
LLVMTargetMachineRef tm;
LLVMModuleRef m;
PyObject *arg_tm, *arg_m;
int arg_use_asm;
if (!PyArg_ParseTuple(args, "OOi", &arg_tm, &arg_m, &arg_use_asm))
return NULL;
tm = (LLVMTargetMachineRef) PyCapsule_GetPointer(arg_tm, NULL);
m = (LLVMModuleRef) PyCapsule_GetPointer(arg_m, NULL);
std::string error;
bytes = LLVMTargetMachineEmitFile(tm, m, arg_use_asm, &len, error);
if ( !error.empty() ){
PyErr_SetString(PyExc_RuntimeError, error.c_str());
return NULL;
}
ret = PyBytes_FromStringAndSize((char *)bytes, (Py_ssize_t)len);
delete [] bytes;
return ret;
}
_wrap_obj2obj(LLVMTargetMachineGetTargetData, LLVMTargetMachineRef,
LLVMTargetDataRef)
_wrap_obj2str(LLVMTargetMachineGetTargetName, LLVMTargetMachineRef)
_wrap_obj2str(LLVMTargetMachineGetTargetShortDescription, LLVMTargetMachineRef)
_wrap_obj2str(LLVMTargetMachineGetTriple, LLVMTargetMachineRef)
_wrap_obj2str(LLVMTargetMachineGetCPU, LLVMTargetMachineRef)
_wrap_obj2str(LLVMTargetMachineGetFS, LLVMTargetMachineRef)
_wrap_none2none(LLVMPrintRegisteredTargetsForVersion)
/*===----------------------------------------------------------------------===*/
/* Target Data */
/*===----------------------------------------------------------------------===*/
@ -1744,7 +1817,13 @@ static PyMethodDef core_methods[] = {
_method( LLVMDumpPasses )
_method( LLVMAddPassByName )
_method( LLVMInitializePasses )
_method( LLVMInitializeNativeTarget )
_method( LLVMInitializeNativeTargetAsmPrinter )
_method( LLVMInitializePTXTarget )
_method( LLVMInitializePTXTargetInfo )
_method( LLVMInitializePTXTargetMC )
_method( LLVMInitializePTXAsmPrinter )
/* Passes */
@ -1835,6 +1914,19 @@ static PyMethodDef core_methods[] = {
_pass( Internalize2 )
*/
/* Target Machine */
_method( LLVMTargetMachineFromEngineBuilder )
_method( LLVMDisposeTargetMachine )
_method( LLVMTargetMachineLookup )
_method( LLVMTargetMachineEmitFile )
_method( LLVMTargetMachineGetTargetData )
_method( LLVMTargetMachineGetTargetName )
_method( LLVMTargetMachineGetTargetShortDescription )
_method( LLVMTargetMachineGetTriple )
_method( LLVMTargetMachineGetCPU )
_method( LLVMTargetMachineGetFS )
_method( LLVMPrintRegisteredTargetsForVersion )
/* Target Data */
_method( LLVMCreateTargetData )
_method( LLVMDisposeTargetData )

View file

@ -2143,5 +2143,13 @@ def inline_function(call):
#===----------------------------------------------------------------------===
if _core.LLVMInitializeNativeTarget():
raise llvm.LLVMException("No native target!?")
if _core.LLVMInitializeNativeTargetAsmPrinter():
# should this be an optional feature?
# should user trigger the initialization?
raise llvm.LLVMException("No native asm printer!?")
if True: # use PTX
_core.LLVMInitializePTXTarget()
_core.LLVMInitializePTXTargetInfo()
_core.LLVMInitializePTXTargetMC()
_core.LLVMInitializePTXAsmPrinter()

View file

@ -231,6 +231,12 @@ class EngineBuilder(object):
raise llvm.LLVMException(ret)
return ExecutionEngine(ret, self._module)
def select_target(self):
'''get the corresponding target machine
'''
ptr = _core.LLVMTargetMachineFromEngineBuilder(self.ptr)
return TargetMachine(ptr)
#===----------------------------------------------------------------------===
# Execution engine
#===----------------------------------------------------------------------===
@ -293,3 +299,74 @@ class ExecutionEngine(object):
td._own(self)
return td
#===----------------------------------------------------------------------===
# Target machine
#===----------------------------------------------------------------------===
def print_registered_targets():
'''
Note: print directly to stdout
'''
_core.LLVMPrintRegisteredTargetsForVersion()
class TargetMachine(object):
@staticmethod
def lookup(arch, cpu='', features='', opt=2):
'''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`
'''
ptr = _core.LLVMTargetMachineLookup(arch, cpu, features, opt)
return TargetMachine(ptr)
def __init__(self, ptr):
self.ptr = ptr
def __del__(self):
_core.LLVMDisposeTargetMachine(self.ptr)
def emit_assembly(self, module):
'''returns byte string of the module as assembly code of the target machine
'''
return _core.LLVMTargetMachineEmitFile(self.ptr, module.ptr, True)
def emit_object(self, module):
'''returns byte string of the module as assembly code of the target machine
'''
return _core.LLVMTargetMachineEmitFile(self.ptr, module.ptr, False)
@property
def target_data(self):
'''get target data of this machine
'''
ptr = _core.LLVMTargetMachineGetTargetData(self.ptr)
return TargetData(ptr)
@property
def target_name(self):
return _core.LLVMTargetMachineGetTargetName(self.ptr)
@property
def target_short_description(self):
return _core.LLVMTargetMachineGetTargetShortDescription(self.ptr)
@property
def triple(self):
return _core.LLVMTargetMachineGetTriple(self.ptr)
@property
def cpu(self):
return _core.LLVMTargetMachineGetCPU(self.ptr)
@property
def feature_string(self):
return _core.LLVMTargetMachineGetFS(self.ptr)

View file

@ -54,6 +54,7 @@
#include "llvm/Support/CallSite.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/IntrinsicInst.h"
@ -84,6 +85,7 @@
namespace llvm{
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(EngineBuilder, LLVMEngineBuilderRef)
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
}
/*
* For use in LLVMDumpPasses to dump passes.
@ -113,15 +115,96 @@ char *do_print(W obj)
return strdup(buf.str().c_str());
}
unsigned char* LLVMGetNativeCodeFromModule(LLVMModuleRef module, int assembly,
unsigned * lenp)
namespace {
using namespace llvm;
const CodeGenOpt::Level OptLevelMap[] = {
CodeGenOpt::None,
CodeGenOpt::Less,
CodeGenOpt::Default,
CodeGenOpt::Aggressive,
};
} // end anony namespace
int LLVMInitializeNativeTargetAsmPrinter()
{
return llvm::InitializeNativeTargetAsmPrinter();
}
LLVMTargetMachineRef LLVMTargetMachineLookup(const char *arch, const char *cpu,
const char *features, int opt,
std::string &error)
{
using namespace llvm;
Triple TheTriple;
// begin borrow from LLVM 3.2 code
// because we don't have 3 argument version of lookup() in 3.1
const Target * TheTarget = NULL;
const std::string ArchName(arch);
for (TargetRegistry::iterator it = TargetRegistry::begin(),
ie = TargetRegistry::end(); it != ie; ++it) {
if (ArchName == it->getName()) {
TheTarget = &*it;
break;
}
}
if (!TheTarget) {
error = "Unknown arch";
return NULL;
}
Triple::ArchType Type = Triple::getArchTypeForLLVMName(ArchName);
if (Type != Triple::UnknownArch){
TheTriple.setArch(Type);
}
// end borrow from LLVM 3.2 code
if (!TheTarget->hasTargetMachine()){
error = "No target machine for the arch";
return NULL;
}
TargetOptions no_target_options;
TargetMachine * tm = TheTarget->createTargetMachine(
TheTriple.str(), cpu, features,
no_target_options,
Reloc::Default, CodeModel::Default,
OptLevelMap[opt]);
if (!tm){
error = "Cannot create target machine";
return NULL;
}
return wrap(tm);
}
LLVMTargetMachineRef LLVMTargetMachineFromEngineBuilder(LLVMEngineBuilderRef eb)
{
using namespace llvm;
TargetMachine * tm = unwrap(eb)->selectTarget();
return wrap(tm);
}
void LLVMDisposeTargetMachine(LLVMTargetMachineRef tm){
delete llvm::unwrap(tm);
}
unsigned char* LLVMTargetMachineEmitFile(LLVMTargetMachineRef tmref,
LLVMModuleRef modref,
int assembly, unsigned * lenp,
std::string &error)
{
using namespace llvm;
assert(lenp);
InitializeNativeTargetAsmPrinter();
Module *modulep = unwrap(module);
Module *modulep = unwrap(modref);
assert(modulep);
// get objectcode into a string
@ -130,17 +213,15 @@ unsigned char* LLVMGetNativeCodeFromModule(LLVMModuleRef module, int assembly,
formatted_raw_ostream fso(buf);
TargetMachine * tm = EngineBuilder(modulep).selectTarget();
TargetMachine * tm = unwrap(tmref);
PassManager pm;
if (!tm->getTargetData()){
printf("No target data in target machine");
error = "No target data in target machine";
return NULL;
}
//printf("%s\n", modulep->getDataLayout().c_str());
pm.add(new TargetData(*tm->getTargetData()));
bool failed;
@ -151,8 +232,7 @@ unsigned char* LLVMGetNativeCodeFromModule(LLVMModuleRef module, int assembly,
}
if ( failed ) {
printf("No support\n");
printf("%s\n", tm->getTargetData()->getStringRepresentation().c_str());
error = "No support for emit file";
return NULL;
}
@ -168,6 +248,7 @@ unsigned char* LLVMGetNativeCodeFromModule(LLVMModuleRef module, int assembly,
size_t bclen = bc.size();
unsigned char *bytes = new unsigned char[bclen];
if (!bytes){
error = "Out of memory";
return NULL;
}
memcpy(bytes, bc.data(), bclen);
@ -177,6 +258,57 @@ unsigned char* LLVMGetNativeCodeFromModule(LLVMModuleRef module, int assembly,
return bytes;
}
const char* LLVMTargetMachineGetTargetName(LLVMTargetMachineRef tm)
{
return strdup(llvm::unwrap(tm)->getTarget().getName());
}
const char* LLVMTargetMachineGetTargetShortDescription(LLVMTargetMachineRef tm)
{
return strdup(llvm::unwrap(tm)->getTarget().getShortDescription());
}
const char* LLVMTargetMachineGetTriple(LLVMTargetMachineRef tm)
{
return strdup(llvm::unwrap(tm)->getTargetTriple().str().c_str());
}
const char* LLVMTargetMachineGetCPU(LLVMTargetMachineRef tm)
{
return strdup(llvm::unwrap(tm)->getTargetCPU().str().c_str());
}
const char* LLVMTargetMachineGetFS(LLVMTargetMachineRef tm)
{
return strdup(llvm::unwrap(tm)->getTargetFeatureString().str().c_str());
}
void LLVMPrintRegisteredTargetsForVersion(){
llvm::TargetRegistry::printRegisteredTargetsForVersion();
}
LLVMTargetDataRef LLVMTargetMachineGetTargetData(LLVMTargetMachineRef tm)
{
using namespace llvm;
return wrap(new TargetData(*unwrap(tm)->getTargetData()));
}
unsigned char* LLVMGetNativeCodeFromModule(LLVMModuleRef module, int assembly,
unsigned * lenp, std::string &error)
{
using namespace llvm;
assert(lenp);
Module *modulep = unwrap(module);
assert(modulep);
// select native default machine
TargetMachine * tm = EngineBuilder(modulep).selectTarget();
return LLVMTargetMachineEmitFile(wrap(tm), module, assembly, lenp, error);
}
static
llvm::AtomicOrdering atomic_ordering_from_string(const char * ordering)
@ -333,15 +465,7 @@ void LLVMEngineBuilderForceInterpreter(LLVMEngineBuilderRef eb)
void LLVMEngineBuilderSetOptLevel(LLVMEngineBuilderRef eb, int level)
{
using namespace llvm;
const CodeGenOpt::Level level_map[] = {
CodeGenOpt::None,
CodeGenOpt::Less,
CodeGenOpt::Default,
CodeGenOpt::Aggressive,
};
unwrap(eb)->setOptLevel(level_map[level]);
unwrap(eb)->setOptLevel(OptLevelMap[level]);
}

View file

@ -45,11 +45,71 @@
extern "C" {
#endif
int LLVMInitializeNativeTargetAsmPrinter();
LLVMTargetMachineRef LLVMTargetMachineLookup(const char *arch, const char *cpu,
const char *features, int opt,
std::string &error);
/*
* Wraps EngineBuilder::selectTarget
*/
LLVMTargetMachineRef LLVMTargetMachineFromEngineBuilder(LLVMEngineBuilderRef eb);
/*
* Wraps operator delete
*/
void LLVMDisposeTargetMachine(LLVMTargetMachineRef tm);
/*
* Wraps TargetMachine::addPassesToEmitFile
*/
unsigned char* LLVMTargetMachineEmitFile(LLVMTargetMachineRef tmref,
LLVMModuleRef modref,
int assembly, unsigned * lenp,
std::string &error);
/*
* Wraps TargetMachine::getTargetData
*/
LLVMTargetDataRef LLVMTargetMachineGetTargetData(LLVMTargetMachineRef tm);
/*
* Wraps TargetMachine::getTarget().getName()
*/
const char* LLVMTargetMachineGetTargetName(LLVMTargetMachineRef tm);
/*
* Wraps TargetMachine::getTarget().getShortDescription()
*/
const char* LLVMTargetMachineGetTargetShortDescription(LLVMTargetMachineRef tm);
/*
* Wraps TargetMachine::getTargetTriple
*/
const char * LLVMTargetMachineGetTriple(LLVMTargetMachineRef tm);
/*
* Wraps TargetMachine::getTargetCPU
*/
const char * LLVMTargetMachineGetCPU(LLVMTargetMachineRef tm);
/*
* Wraps TargetMachine::getTargetFeatureString
*/
const char * LLVMTargetMachineGetFS(LLVMTargetMachineRef tm);
/*
* Wraps TargetRegister::printRegisteredTargetsForVersion
*/
void LLVMPrintRegisteredTargetsForVersion();
/*
* Wraps TargetMachine::addPassesToEmitFile
*/
unsigned char* LLVMGetNativeCodeFromModule(LLVMModuleRef module, int assembly,
unsigned * lenp);
unsigned * lenp, std::string &error);
/*
* Wraps IRBuilder::CreateFence

View file

@ -19,6 +19,7 @@ inline ref wrap(const ty *P) { \
}
typedef struct LLVMOpaqueEngineBuilder *LLVMEngineBuilderRef;
typedef struct LLVMOpaqueTargetMachine *LLVMTargetMachineRef;
#ifdef __cplusplus

View file

@ -60,6 +60,7 @@ _define_std_ctor(LLVMGenericValueRef)
_define_std_ctor(LLVMPassManagerBuilderRef)
_define_std_ctor(LLVMEngineBuilderRef)
_define_std_ctor(LLVMTargetMachineRef)
PyObject *ctor_int(int i)
{

View file

@ -93,6 +93,7 @@ _declare_std_ctor(LLVMGenericValueRef)
// extra LLVM classes
_declare_std_ctor(LLVMPassManagerBuilderRef)
_declare_std_ctor(LLVMEngineBuilderRef)
_declare_std_ctor(LLVMTargetMachineRef)
/* standard types */
_declare_std_ctor(int)
@ -145,6 +146,17 @@ PyObject *make_list_from_LLVMValueRef_array(LLVMValueRef *p, unsigned n);
******************************************************************************
*****************************************************************************/
#define _wrap_none2none(func) \
static PyObject * \
_w ## func(PyObject * self, PyObject * args) \
{ \
if (!PyArg_ParseTuple(args, "")) \
return NULL; \
func(); \
Py_RETURN_NONE; \
}
/**
* Wrap LLVM functions of the type
* outtype func(intype1 arg1)

View file

@ -78,11 +78,15 @@ def call_setup(llvm_config):
incdir = _run(llvm_config + ' --includedir')
libdir = _run(llvm_config + ' --libdir')
ldflags = _run(llvm_config + ' --ldflags')
ptx_components = ['ptx', 'ptxasmprinter', 'ptxcodegen', 'ptxdesc', 'ptxinfo']
libs_core, objs_core = get_libs_and_objs(llvm_config,
['core', 'analysis', 'scalaropts', 'executionengine',
'jit', 'native', 'interpreter', 'bitreader', 'bitwriter',
'instrumentation', 'ipa', 'ipo', 'transformutils',
'asmparser', 'linker', 'support'])
'asmparser', 'linker', 'support', 'vectorize']
+ ptx_components)
std_libs = [ 'pthread', 'm', 'stdc++' ]
extra_link_args = ["-fPIC"]
@ -91,7 +95,7 @@ def call_setup(llvm_config):
if "darwin" in sys.platform:
std_libs.append("ffi")
extra_link_args += ['-framework', 'Python']
ext_core = Extension(
'llvm._core',

52
test/targetmachines.py Normal file
View file

@ -0,0 +1,52 @@
from llvm.core import *
from llvm.ee import TargetMachine, EngineBuilder, print_registered_targets
import unittest
class TestTargetMachines(unittest.TestCase):
'''Exercise target machines
Require PTX backend
'''
def test_native(self):
m, _ = self._build_module()
tm = EngineBuilder.new(m).select_target()
self.assertTrue(tm.target_name)
self.assertTrue(tm.target_data)
self.assertTrue(tm.target_short_description)
self.assertTrue(tm.triple)
self.assertIn('foo', tm.emit_assembly(m).decode('utf-8'))
def test_ptx(self):
m, func = self._build_module()
func.calling_convention = CC_PTX_KERNEL # set calling conv
ptxtm = TargetMachine.lookup(arch='ptx64', cpu='compute_20',
features='-double')
self.assertTrue(ptxtm.triple)
self.assertTrue(ptxtm.cpu)
self.assertTrue(ptxtm.feature_string)
ptxasm = ptxtm.emit_assembly(m).decode('utf-8')
self.assertIn('foo', ptxasm)
self.assertIn('map_f64_to_f32', ptxasm)
self.assertIn('compute_10', ptxasm)
def _build_module(self):
m = Module.new('TestTargetMachines')
fnty = Type.function(Type.void(), [])
func = m.add_function(fnty, name='foo')
bldr = Builder.new(func.append_basic_block('entry'))
bldr.ret_void()
m.verify()
return m, func
def _build_bad_archname(self):
with self.assertRaises(RuntimeError):
tm = TargetMachine.lookup("ain't no arch name")
if __name__ == '__main__':
unittest.main()