From ec71908874eed91e5b1efa77b70bc5aff58256d7 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 14 Aug 2012 12:04:28 -0700 Subject: [PATCH 1/5] Add target machine --- llvm/_core.cpp | 42 +++++++++++++++++++++++++++++++++++++++++ llvm/ee.py | 28 +++++++++++++++++++++++++++ llvm/extra.cpp | 46 ++++++++++++++++++++++++++++++++++++--------- llvm/extra.h | 14 ++++++++++++++ llvm/llvm_c_extra.h | 1 + llvm/wrap.cpp | 1 + llvm/wrap.h | 1 + 7 files changed, 124 insertions(+), 9 deletions(-) diff --git a/llvm/_core.cpp b/llvm/_core.cpp index 3366d58..9fc776c 100644 --- a/llvm/_core.cpp +++ b/llvm/_core.cpp @@ -993,6 +993,43 @@ _wrap_pass( UnifyFunctionExitNodes ) _wrap_pass( Internalize2 ) */ + + +/*===----------------------------------------------------------------------===*/ +/* Target Machine */ +/*===----------------------------------------------------------------------===*/ + +_wrap_obj2obj(LLVMTargetMachineFromEngineBuilder, LLVMEngineBuilderRef, + LLVMTargetMachineRef) +_wrap_obj2none(LLVMDisposeTargetMachine, LLVMTargetMachineRef) + + +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); + + if ( !(bytes = LLVMTargetMachineEmitFile(tm, m, arg_use_asm, &len)) ) + Py_RETURN_NONE; + + ret = PyBytes_FromStringAndSize((char *)bytes, (Py_ssize_t)len); + delete [] bytes; + return ret; +} + /*===----------------------------------------------------------------------===*/ /* Target Data */ /*===----------------------------------------------------------------------===*/ @@ -1835,6 +1872,11 @@ static PyMethodDef core_methods[] = { _pass( Internalize2 ) */ + /* Target Machine */ + _method( LLVMTargetMachineFromEngineBuilder ) + _method( LLVMDisposeTargetMachine ) + _method( LLVMTargetMachineEmitFile ) + /* Target Data */ _method( LLVMCreateTargetData ) _method( LLVMDisposeTargetData ) diff --git a/llvm/ee.py b/llvm/ee.py index 904716e..384c220 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -293,3 +293,31 @@ class ExecutionEngine(object): td._own(self) return td + +#===----------------------------------------------------------------------=== +# Target machine +#===----------------------------------------------------------------------=== + +class TargetMachine(object): + @staticmethod + def from_engine_builder(eb): + '''Construct a TargetMachine from an EngineBuilder + ''' + ptr = _core.LLVMTargetMachineFromEngineBuilder(eb.ptr) + 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) diff --git a/llvm/extra.cpp b/llvm/extra.cpp index 5d22200..b11dd1e 100644 --- a/llvm/extra.cpp +++ b/llvm/extra.cpp @@ -84,6 +84,7 @@ namespace llvm{ DEFINE_SIMPLE_CONVERSION_FUNCTIONS(EngineBuilder, LLVMEngineBuilderRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef) } /* * For use in LLVMDumpPasses to dump passes. @@ -113,15 +114,29 @@ char *do_print(W obj) return strdup(buf.str().c_str()); } -unsigned char* LLVMGetNativeCodeFromModule(LLVMModuleRef module, int assembly, - unsigned * lenp) + +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) { using namespace llvm; assert(lenp); InitializeNativeTargetAsmPrinter(); - Module *modulep = unwrap(module); + Module *modulep = unwrap(modref); assert(modulep); // get objectcode into a string @@ -130,17 +145,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"); + fprintf(stderr, "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 +164,8 @@ unsigned char* LLVMGetNativeCodeFromModule(LLVMModuleRef module, int assembly, } if ( failed ) { - printf("No support\n"); - printf("%s\n", tm->getTargetData()->getStringRepresentation().c_str()); + fprintf(stderr, "No support\n"); + fprintf(stderr, "%s\n", tm->getTargetData()->getStringRepresentation().c_str()); return NULL; } @@ -177,6 +190,21 @@ unsigned char* LLVMGetNativeCodeFromModule(LLVMModuleRef module, int assembly, return bytes; } +unsigned char* LLVMGetNativeCodeFromModule(LLVMModuleRef module, int assembly, + unsigned * lenp) +{ + 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); +} + static llvm::AtomicOrdering atomic_ordering_from_string(const char * ordering) diff --git a/llvm/extra.h b/llvm/extra.h index f405679..f3f5bda 100644 --- a/llvm/extra.h +++ b/llvm/extra.h @@ -45,6 +45,20 @@ extern "C" { #endif +/* + * Wraps EngineBuilder::selectTarget + */ +LLVMTargetMachineRef LLVMTargetMachineFromEngineBuilder(LLVMEngineBuilderRef eb); + +/* + * Wraps operator delete + */ +void LLVMDisposeTargetMachine(LLVMTargetMachineRef tm); + +unsigned char* LLVMTargetMachineEmitFile(LLVMTargetMachineRef tmref, + LLVMModuleRef modref, + int assembly, unsigned * lenp); + /* * Wraps TargetMachine::addPassesToEmitFile */ diff --git a/llvm/llvm_c_extra.h b/llvm/llvm_c_extra.h index fc2b711..53fe71c 100644 --- a/llvm/llvm_c_extra.h +++ b/llvm/llvm_c_extra.h @@ -19,6 +19,7 @@ inline ref wrap(const ty *P) { \ } typedef struct LLVMOpaqueEngineBuilder *LLVMEngineBuilderRef; +typedef struct LLVMOpaqueTargetMachine *LLVMTargetMachineRef; #ifdef __cplusplus diff --git a/llvm/wrap.cpp b/llvm/wrap.cpp index 4527912..6ccd443 100644 --- a/llvm/wrap.cpp +++ b/llvm/wrap.cpp @@ -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) { diff --git a/llvm/wrap.h b/llvm/wrap.h index bceca87..4a4dd53 100644 --- a/llvm/wrap.h +++ b/llvm/wrap.h @@ -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) From f85713a736750bc658d4fd67cf9988e4efefc832 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 14 Aug 2012 15:05:22 -0700 Subject: [PATCH 2/5] Enable PTX backend --- llvm/_core.cpp | 36 ++++++++++++++++++++++++++++-------- llvm/core.py | 9 ++++++++- llvm/ee.py | 45 +++++++++++++++++++++++++++++++++++++++------ llvm/extra.cpp | 46 +++++++++++++++++++++++++++++++++++++++++++--- llvm/extra.h | 41 +++++++++++++++++++++++++++++++++++++++++ llvm/wrap.h | 11 +++++++++++ setup.py | 8 ++++++-- 7 files changed, 176 insertions(+), 20 deletions(-) diff --git a/llvm/_core.cpp b/llvm/_core.cpp index 9fc776c..32705db 100644 --- a/llvm/_core.cpp +++ b/llvm/_core.cpp @@ -888,16 +888,14 @@ _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(LLVMInitializePTXAsmPrinter) /*===----------------------------------------------------------------------===*/ @@ -1030,6 +1028,16 @@ _wLLVMTargetMachineEmitFile(PyObject * self, PyObject * args) 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 */ /*===----------------------------------------------------------------------===*/ @@ -1781,7 +1789,12 @@ static PyMethodDef core_methods[] = { _method( LLVMDumpPasses ) _method( LLVMAddPassByName ) _method( LLVMInitializePasses ) + _method( LLVMInitializeNativeTarget ) + _method( LLVMInitializeNativeTargetAsmPrinter ) + _method( LLVMInitializePTXTarget ) + _method( LLVMInitializePTXTargetInfo ) + _method( LLVMInitializePTXAsmPrinter ) /* Passes */ @@ -1876,6 +1889,13 @@ static PyMethodDef core_methods[] = { _method( LLVMTargetMachineFromEngineBuilder ) _method( LLVMDisposeTargetMachine ) _method( LLVMTargetMachineEmitFile ) + _method( LLVMTargetMachineGetTargetData ) + _method( LLVMTargetMachineGetTargetName ) + _method( LLVMTargetMachineGetTargetShortDescription ) + _method( LLVMTargetMachineGetTriple ) + _method( LLVMTargetMachineGetCPU ) + _method( LLVMTargetMachineGetFS ) + _method( LLVMPrintRegisteredTargetsForVersion ) /* Target Data */ _method( LLVMCreateTargetData ) diff --git a/llvm/core.py b/llvm/core.py index 7366d41..2f47762 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -2143,5 +2143,12 @@ 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.LLVMInitializePTXAsmPrinter() diff --git a/llvm/ee.py b/llvm/ee.py index 384c220..8dfb504 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -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 #===----------------------------------------------------------------------=== @@ -298,13 +304,13 @@ class ExecutionEngine(object): # Target machine #===----------------------------------------------------------------------=== +def print_registered_targets(): + ''' + Note: print directly to stdout + ''' + _core.LLVMPrintRegisteredTargetsForVersion() + class TargetMachine(object): - @staticmethod - def from_engine_builder(eb): - '''Construct a TargetMachine from an EngineBuilder - ''' - ptr = _core.LLVMTargetMachineFromEngineBuilder(eb.ptr) - return TargetMachine(ptr) def __init__(self, ptr): self.ptr = ptr @@ -321,3 +327,30 @@ class TargetMachine(object): '''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) diff --git a/llvm/extra.cpp b/llvm/extra.cpp index b11dd1e..2baf98a 100644 --- a/llvm/extra.cpp +++ b/llvm/extra.cpp @@ -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" @@ -114,6 +115,11 @@ char *do_print(W obj) return strdup(buf.str().c_str()); } +int LLVMInitializeNativeTargetAsmPrinter() +{ + return llvm::InitializeNativeTargetAsmPrinter(); +} + LLVMTargetMachineRef LLVMTargetMachineFromEngineBuilder(LLVMEngineBuilderRef eb) { @@ -134,8 +140,6 @@ unsigned char* LLVMTargetMachineEmitFile(LLVMTargetMachineRef tmref, using namespace llvm; assert(lenp); - InitializeNativeTargetAsmPrinter(); - Module *modulep = unwrap(modref); assert(modulep); @@ -190,6 +194,43 @@ unsigned char* LLVMTargetMachineEmitFile(LLVMTargetMachineRef tmref, 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) { @@ -205,7 +246,6 @@ unsigned char* LLVMGetNativeCodeFromModule(LLVMModuleRef module, int assembly, return LLVMTargetMachineEmitFile(wrap(tm), module, assembly, lenp); } - static llvm::AtomicOrdering atomic_ordering_from_string(const char * ordering) { diff --git a/llvm/extra.h b/llvm/extra.h index f3f5bda..e5ad2a8 100644 --- a/llvm/extra.h +++ b/llvm/extra.h @@ -45,6 +45,9 @@ extern "C" { #endif +int LLVMInitializeNativeTargetAsmPrinter(); + + /* * Wraps EngineBuilder::selectTarget */ @@ -55,10 +58,48 @@ LLVMTargetMachineRef LLVMTargetMachineFromEngineBuilder(LLVMEngineBuilderRef eb) */ void LLVMDisposeTargetMachine(LLVMTargetMachineRef tm); +/* + * Wraps TargetMachine::addPassesToEmitFile + */ unsigned char* LLVMTargetMachineEmitFile(LLVMTargetMachineRef tmref, LLVMModuleRef modref, int assembly, unsigned * lenp); +/* + * 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 */ diff --git a/llvm/wrap.h b/llvm/wrap.h index 4a4dd53..5d1c736 100644 --- a/llvm/wrap.h +++ b/llvm/wrap.h @@ -146,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) diff --git a/setup.py b/setup.py index d1450b8..f9d3e10 100755 --- a/setup.py +++ b/setup.py @@ -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', From 8b273490a9432048531588e5868d0ca2d995d4f9 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 14 Aug 2012 16:50:32 -0700 Subject: [PATCH 3/5] Can create PTX target machine and print PTX asm --- llvm/_core.cpp | 17 ++++++++++++ llvm/core.py | 1 + llvm/ee.py | 16 +++++++++++ llvm/extra.cpp | 73 +++++++++++++++++++++++++++++++++++++++++++------- llvm/extra.h | 3 +++ 5 files changed, 101 insertions(+), 9 deletions(-) diff --git a/llvm/_core.cpp b/llvm/_core.cpp index 32705db..b0f1919 100644 --- a/llvm/_core.cpp +++ b/llvm/_core.cpp @@ -895,6 +895,7 @@ _wrap_none2obj(LLVMInitializeNativeTarget, int) _wrap_none2obj(LLVMInitializeNativeTargetAsmPrinter, int) _wrap_none2none(LLVMInitializePTXTarget) _wrap_none2none(LLVMInitializePTXTargetInfo) +_wrap_none2none( LLVMInitializePTXTargetMC ) _wrap_none2none(LLVMInitializePTXAsmPrinter) @@ -1001,6 +1002,20 @@ _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; + + LLVMTargetMachineRef tm = LLVMTargetMachineLookup(arch, cpu, features, opt); + return ctor_LLVMTargetMachineRef(tm); +} static PyObject * _wLLVMTargetMachineEmitFile(PyObject * self, PyObject * args) @@ -1794,6 +1809,7 @@ static PyMethodDef core_methods[] = { _method( LLVMInitializeNativeTargetAsmPrinter ) _method( LLVMInitializePTXTarget ) _method( LLVMInitializePTXTargetInfo ) + _method( LLVMInitializePTXTargetMC ) _method( LLVMInitializePTXAsmPrinter ) /* Passes */ @@ -1888,6 +1904,7 @@ static PyMethodDef core_methods[] = { /* Target Machine */ _method( LLVMTargetMachineFromEngineBuilder ) _method( LLVMDisposeTargetMachine ) + _method( LLVMTargetMachineLookup ) _method( LLVMTargetMachineEmitFile ) _method( LLVMTargetMachineGetTargetData ) _method( LLVMTargetMachineGetTargetName ) diff --git a/llvm/core.py b/llvm/core.py index 2f47762..d49e32a 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -2151,4 +2151,5 @@ if _core.LLVMInitializeNativeTargetAsmPrinter(): if True: # use PTX _core.LLVMInitializePTXTarget() _core.LLVMInitializePTXTargetInfo() + _core.LLVMInitializePTXTargetMC() _core.LLVMInitializePTXAsmPrinter() diff --git a/llvm/ee.py b/llvm/ee.py index 8dfb504..5cfe407 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -312,6 +312,22 @@ def print_registered_targets(): 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 diff --git a/llvm/extra.cpp b/llvm/extra.cpp index 2baf98a..7e27d10 100644 --- a/llvm/extra.cpp +++ b/llvm/extra.cpp @@ -115,12 +115,75 @@ char *do_print(W obj) return strdup(buf.str().c_str()); } +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) +{ + using namespace llvm; + std::string error; + 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) { + fprintf(stderr, "%s\n", error.c_str()); + 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()){ + fprintf(stderr, "No target machine for %s\n", 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){ + fprintf(stderr, "Cannot create target machine!\n"); + return NULL; + } + return wrap(tm); +} + + LLVMTargetMachineRef LLVMTargetMachineFromEngineBuilder(LLVMEngineBuilderRef eb) { using namespace llvm; @@ -401,15 +464,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]); } diff --git a/llvm/extra.h b/llvm/extra.h index e5ad2a8..832d725 100644 --- a/llvm/extra.h +++ b/llvm/extra.h @@ -48,6 +48,9 @@ extern "C" { int LLVMInitializeNativeTargetAsmPrinter(); +LLVMTargetMachineRef LLVMTargetMachineLookup(const char *arch, const char *cpu, + const char *features, int opt); + /* * Wraps EngineBuilder::selectTarget */ From 1b7fc6c8037b63f7fca8c99b97ccbb1871ab33c1 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 14 Aug 2012 16:56:33 -0700 Subject: [PATCH 4/5] Add test for target machines (native + PTX) --- test/targetmachines.py | 47 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 test/targetmachines.py diff --git a/test/targetmachines.py b/test/targetmachines.py new file mode 100644 index 0000000..a91411d --- /dev/null +++ b/test/targetmachines.py @@ -0,0 +1,47 @@ +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 + +if __name__ == '__main__': + unittest.main() + From 8eb6a34d549ab2497d55fcaa8a0f6417d5ed08ab Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 15 Aug 2012 15:22:08 -0700 Subject: [PATCH 5/5] Replace fprintf with exception --- llvm/_core.cpp | 23 ++++++++++++++++++----- llvm/extra.cpp | 23 ++++++++++++----------- llvm/extra.h | 8 +++++--- test/targetmachines.py | 5 +++++ 4 files changed, 40 insertions(+), 19 deletions(-) diff --git a/llvm/_core.cpp b/llvm/_core.cpp index b0f1919..2f99ae3 100644 --- a/llvm/_core.cpp +++ b/llvm/_core.cpp @@ -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; @@ -1013,7 +1016,13 @@ _wLLVMTargetMachineLookup(PyObject * self, PyObject * args) if (!PyArg_ParseTuple(args, "sssi", &arch, &cpu, &features, &opt)) return NULL; - LLVMTargetMachineRef tm = LLVMTargetMachineLookup(arch, cpu, features, opt); + 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); } @@ -1035,8 +1044,12 @@ _wLLVMTargetMachineEmitFile(PyObject * self, PyObject * args) tm = (LLVMTargetMachineRef) PyCapsule_GetPointer(arg_tm, NULL); m = (LLVMModuleRef) PyCapsule_GetPointer(arg_m, NULL); - if ( !(bytes = LLVMTargetMachineEmitFile(tm, m, arg_use_asm, &len)) ) - Py_RETURN_NONE; + 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; diff --git a/llvm/extra.cpp b/llvm/extra.cpp index 7e27d10..2fde2ba 100644 --- a/llvm/extra.cpp +++ b/llvm/extra.cpp @@ -133,10 +133,10 @@ int LLVMInitializeNativeTargetAsmPrinter() LLVMTargetMachineRef LLVMTargetMachineLookup(const char *arch, const char *cpu, - const char *features, int opt) + const char *features, int opt, + std::string &error) { using namespace llvm; - std::string error; Triple TheTriple; // begin borrow from LLVM 3.2 code @@ -153,7 +153,7 @@ LLVMTargetMachineRef LLVMTargetMachineLookup(const char *arch, const char *cpu, } if (!TheTarget) { - fprintf(stderr, "%s\n", error.c_str()); + error = "Unknown arch"; return NULL; } @@ -165,7 +165,7 @@ LLVMTargetMachineRef LLVMTargetMachineLookup(const char *arch, const char *cpu, // end borrow from LLVM 3.2 code if (!TheTarget->hasTargetMachine()){ - fprintf(stderr, "No target machine for %s\n", arch); + error = "No target machine for the arch"; return NULL; } @@ -177,7 +177,7 @@ LLVMTargetMachineRef LLVMTargetMachineLookup(const char *arch, const char *cpu, OptLevelMap[opt]); if (!tm){ - fprintf(stderr, "Cannot create target machine!\n"); + error = "Cannot create target machine"; return NULL; } return wrap(tm); @@ -198,7 +198,8 @@ void LLVMDisposeTargetMachine(LLVMTargetMachineRef tm){ unsigned char* LLVMTargetMachineEmitFile(LLVMTargetMachineRef tmref, LLVMModuleRef modref, - int assembly, unsigned * lenp) + int assembly, unsigned * lenp, + std::string &error) { using namespace llvm; assert(lenp); @@ -217,7 +218,7 @@ unsigned char* LLVMTargetMachineEmitFile(LLVMTargetMachineRef tmref, PassManager pm; if (!tm->getTargetData()){ - fprintf(stderr, "No target data in target machine"); + error = "No target data in target machine"; return NULL; } @@ -231,8 +232,7 @@ unsigned char* LLVMTargetMachineEmitFile(LLVMTargetMachineRef tmref, } if ( failed ) { - fprintf(stderr, "No support\n"); - fprintf(stderr, "%s\n", tm->getTargetData()->getStringRepresentation().c_str()); + error = "No support for emit file"; return NULL; } @@ -248,6 +248,7 @@ unsigned char* LLVMTargetMachineEmitFile(LLVMTargetMachineRef tmref, 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); @@ -295,7 +296,7 @@ LLVMTargetDataRef LLVMTargetMachineGetTargetData(LLVMTargetMachineRef tm) } unsigned char* LLVMGetNativeCodeFromModule(LLVMModuleRef module, int assembly, - unsigned * lenp) + unsigned * lenp, std::string &error) { using namespace llvm; assert(lenp); @@ -306,7 +307,7 @@ unsigned char* LLVMGetNativeCodeFromModule(LLVMModuleRef module, int assembly, // select native default machine TargetMachine * tm = EngineBuilder(modulep).selectTarget(); - return LLVMTargetMachineEmitFile(wrap(tm), module, assembly, lenp); + return LLVMTargetMachineEmitFile(wrap(tm), module, assembly, lenp, error); } static diff --git a/llvm/extra.h b/llvm/extra.h index 832d725..a335a58 100644 --- a/llvm/extra.h +++ b/llvm/extra.h @@ -49,7 +49,8 @@ int LLVMInitializeNativeTargetAsmPrinter(); LLVMTargetMachineRef LLVMTargetMachineLookup(const char *arch, const char *cpu, - const char *features, int opt); + const char *features, int opt, + std::string &error); /* * Wraps EngineBuilder::selectTarget @@ -66,7 +67,8 @@ void LLVMDisposeTargetMachine(LLVMTargetMachineRef tm); */ unsigned char* LLVMTargetMachineEmitFile(LLVMTargetMachineRef tmref, LLVMModuleRef modref, - int assembly, unsigned * lenp); + int assembly, unsigned * lenp, + std::string &error); /* * Wraps TargetMachine::getTargetData @@ -107,7 +109,7 @@ void LLVMPrintRegisteredTargetsForVersion(); * Wraps TargetMachine::addPassesToEmitFile */ unsigned char* LLVMGetNativeCodeFromModule(LLVMModuleRef module, int assembly, - unsigned * lenp); + unsigned * lenp, std::string &error); /* * Wraps IRBuilder::CreateFence diff --git a/test/targetmachines.py b/test/targetmachines.py index a91411d..9ce85dd 100644 --- a/test/targetmachines.py +++ b/test/targetmachines.py @@ -42,6 +42,11 @@ class TestTargetMachines(unittest.TestCase): 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()