Merge branch 'master' of github.com:llvmpy/llvmpy
This commit is contained in:
commit
0c42b2c40e
5 changed files with 175 additions and 3 deletions
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
19
llvm/core.py
19
llvm/core.py
|
|
@ -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!?")
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
53
test/native.py
Executable 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()
|
||||
Loading…
Add table
Add a link
Reference in a new issue