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

This commit is contained in:
Travis E. Oliphant 2012-08-10 08:53:04 -05:00
commit 0c42b2c40e
5 changed files with 175 additions and 3 deletions

View file

@ -184,6 +184,30 @@ _wLLVMGetBitcodeFromModule(PyObject *self, PyObject *args)
return ret;
}
static PyObject *
_wLLVMGetNativeCodeFromModule(PyObject * self, PyObject * args)
{
PyObject * ret;
unsigned len;
unsigned char * bytes;
LLVMModuleRef m;
PyObject * arg_m;
int arg_use_asm;
if (!PyArg_ParseTuple(args, "Oi", &arg_m, &arg_use_asm))
return NULL;
m = (LLVMModuleRef) PyCapsule_GetPointer(arg_m, NULL);
if ( !(bytes = LLVMGetNativeCodeFromModule(m, arg_use_asm, &len)) )
Py_RETURN_NONE;
ret = PyBytes_FromStringAndSize((char *)bytes, (Py_ssize_t)len);
delete [] bytes;
return ret;
}
static PyObject *
_wLLVMLinkModules(PyObject *self, PyObject *args)
{
@ -873,6 +897,8 @@ _wLLVMInitializePasses(PyObject * self, PyObject * args)
Py_RETURN_NONE;
}
_wrap_none2obj(LLVMInitializeNativeTarget, int)
/*===----------------------------------------------------------------------===*/
/* Passes */
@ -1335,6 +1361,7 @@ static PyMethodDef core_methods[] = {
_method( LLVMGetModuleFromAssembly )
_method( LLVMGetModuleFromBitcode )
_method( LLVMGetBitcodeFromModule )
_method( LLVMGetNativeCodeFromModule )
_method( LLVMModuleGetPointerSize )
_method( LLVMModuleGetOrInsertFunction )
_method( LLVMLinkModules )
@ -1717,6 +1744,7 @@ static PyMethodDef core_methods[] = {
_method( LLVMDumpPasses )
_method( LLVMAddPassByName )
_method( LLVMInitializePasses )
_method( LLVMInitializeNativeTarget )
/* Passes */

View file

@ -516,6 +516,16 @@ class Module(llvm.Ownable, llvm.Cacheable):
id = property(_get_id, _set_id)
def to_native_object(self):
'''returns byte string of the module as native object code
'''
return _core.LLVMGetNativeCodeFromModule(self.ptr, 0)
def to_native_assembly(self):
'''returns byte string of the module as native assembly code
'''
return _core.LLVMGetNativeCodeFromModule(self.ptr, 1)
#===----------------------------------------------------------------------===
# Types
#===----------------------------------------------------------------------===
@ -2126,3 +2136,12 @@ def inline_function(call):
check_is_value(call)
return _core.LLVMInlineFunction(call.ptr)
#===----------------------------------------------------------------------===
# Initialization
#===----------------------------------------------------------------------===
if _core.LLVMInitializeNativeTarget():
raise llvm.LLVMException("No native target!?")

View file

@ -52,6 +52,10 @@
//#include "llvm/TypeSymbolTable.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/CallSite.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Assembly/Parser.h"
@ -69,8 +73,6 @@
#include "llvm/Linker.h"
#include "llvm/Support/SourceMgr.h"
// LLVM-C includes
#include "llvm-c/Core.h"
#include "llvm-c/ExecutionEngine.h"
@ -110,6 +112,72 @@ char *do_print(W obj)
p->print(buf);
return strdup(buf.str().c_str());
}
unsigned char* LLVMGetNativeCodeFromModule(LLVMModuleRef module, int assembly,
unsigned * lenp)
{
using namespace llvm;
assert(lenp);
InitializeNativeTargetAsmPrinter();
Module *modulep = unwrap(module);
assert(modulep);
// get objectcode into a string
std::string s;
raw_string_ostream buf(s);
formatted_raw_ostream fso(buf);
TargetMachine * tm = EngineBuilder(modulep).selectTarget();
PassManager pm;
if (!tm->getTargetData()){
printf("No target data in target machine");
return NULL;
}
//printf("%s\n", modulep->getDataLayout().c_str());
pm.add(new TargetData(*tm->getTargetData()));
bool failed;
if( assembly ) {
failed = tm->addPassesToEmitFile(pm, fso, TargetMachine::CGFT_AssemblyFile);
} else {
failed = tm->addPassesToEmitFile(pm, fso, TargetMachine::CGFT_ObjectFile);
}
if ( failed ) {
printf("No support\n");
printf("%s\n", tm->getTargetData()->getStringRepresentation().c_str());
return NULL;
}
pm.run(*modulep);
// flush all streams
fso.flush();
buf.flush();
const std::string& bc = buf.str();
// and then into a new buffer
size_t bclen = bc.size();
unsigned char *bytes = new unsigned char[bclen];
if (!bytes){
return NULL;
}
memcpy(bytes, bc.data(), bclen);
/* return */
*lenp = bclen;
return bytes;
}
static
llvm::AtomicOrdering atomic_ordering_from_string(const char * ordering)
{
@ -353,7 +421,6 @@ void LLVMInitializePasses(){
initializeTarget(registry);
}
const char * LLVMDumpPasses()
{
using namespace llvm;

View file

@ -45,6 +45,11 @@
extern "C" {
#endif
/*
* Wraps TargetMachine::addPassesToEmitFile
*/
unsigned char* LLVMGetNativeCodeFromModule(LLVMModuleRef module, int assembly,
unsigned * lenp);
/*
* Wraps IRBuilder::CreateFence

53
test/native.py Executable file
View file

@ -0,0 +1,53 @@
#!/usr/bin/env python
from llvm import *
from llvm.core import *
import unittest, subprocess
class TestNative(unittest.TestCase):
def _make_module(self):
m = Module.new('module1')
m.add_global_variable(Type.int(), 'i')
fty = Type.function(Type.int(), [])
f = m.add_function(fty, name='main')
bldr = Builder.new(f.append_basic_block('entry'))
bldr.ret(Constant.int(Type.int(), 0xab))
return m
def _compile(self, src):
dst = '/tmp/llvmobj.out'
s = subprocess.call(['cc', '-o', dst, src])
if s != 0:
raise Exception("Cannot compile")
s = subprocess.call([dst])
self.assertEqual(s, 0xab)
def test_assembly(self):
m = self._make_module()
output = m.to_native_assembly()
src = '/tmp/llvmasm.s'
with open(src, 'wb') as fout:
fout.write(output)
self._compile(src)
def test_object(self):
m = self._make_module()
output = m.to_native_object()
src = '/tmp/llvmobj.o'
with open(src, 'wb') as fout:
fout.write(output)
self._compile(src)
if __name__ == '__main__':
unittest.main()