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;
|
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 *
|
static PyObject *
|
||||||
_wLLVMLinkModules(PyObject *self, PyObject *args)
|
_wLLVMLinkModules(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
|
|
@ -873,6 +897,8 @@ _wLLVMInitializePasses(PyObject * self, PyObject * args)
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_wrap_none2obj(LLVMInitializeNativeTarget, int)
|
||||||
|
|
||||||
|
|
||||||
/*===----------------------------------------------------------------------===*/
|
/*===----------------------------------------------------------------------===*/
|
||||||
/* Passes */
|
/* Passes */
|
||||||
|
|
@ -1335,6 +1361,7 @@ static PyMethodDef core_methods[] = {
|
||||||
_method( LLVMGetModuleFromAssembly )
|
_method( LLVMGetModuleFromAssembly )
|
||||||
_method( LLVMGetModuleFromBitcode )
|
_method( LLVMGetModuleFromBitcode )
|
||||||
_method( LLVMGetBitcodeFromModule )
|
_method( LLVMGetBitcodeFromModule )
|
||||||
|
_method( LLVMGetNativeCodeFromModule )
|
||||||
_method( LLVMModuleGetPointerSize )
|
_method( LLVMModuleGetPointerSize )
|
||||||
_method( LLVMModuleGetOrInsertFunction )
|
_method( LLVMModuleGetOrInsertFunction )
|
||||||
_method( LLVMLinkModules )
|
_method( LLVMLinkModules )
|
||||||
|
|
@ -1717,6 +1744,7 @@ static PyMethodDef core_methods[] = {
|
||||||
_method( LLVMDumpPasses )
|
_method( LLVMDumpPasses )
|
||||||
_method( LLVMAddPassByName )
|
_method( LLVMAddPassByName )
|
||||||
_method( LLVMInitializePasses )
|
_method( LLVMInitializePasses )
|
||||||
|
_method( LLVMInitializeNativeTarget )
|
||||||
|
|
||||||
/* Passes */
|
/* 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)
|
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
|
# Types
|
||||||
#===----------------------------------------------------------------------===
|
#===----------------------------------------------------------------------===
|
||||||
|
|
@ -2126,3 +2136,12 @@ def inline_function(call):
|
||||||
check_is_value(call)
|
check_is_value(call)
|
||||||
return _core.LLVMInlineFunction(call.ptr)
|
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/TypeSymbolTable.h"
|
||||||
#include "llvm/Support/MemoryBuffer.h"
|
#include "llvm/Support/MemoryBuffer.h"
|
||||||
#include "llvm/Support/CallSite.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/IntrinsicInst.h"
|
||||||
#include "llvm/Analysis/Verifier.h"
|
#include "llvm/Analysis/Verifier.h"
|
||||||
#include "llvm/Assembly/Parser.h"
|
#include "llvm/Assembly/Parser.h"
|
||||||
|
|
@ -69,8 +73,6 @@
|
||||||
#include "llvm/Linker.h"
|
#include "llvm/Linker.h"
|
||||||
#include "llvm/Support/SourceMgr.h"
|
#include "llvm/Support/SourceMgr.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// LLVM-C includes
|
// LLVM-C includes
|
||||||
#include "llvm-c/Core.h"
|
#include "llvm-c/Core.h"
|
||||||
#include "llvm-c/ExecutionEngine.h"
|
#include "llvm-c/ExecutionEngine.h"
|
||||||
|
|
@ -110,6 +112,72 @@ char *do_print(W obj)
|
||||||
p->print(buf);
|
p->print(buf);
|
||||||
return strdup(buf.str().c_str());
|
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
|
static
|
||||||
llvm::AtomicOrdering atomic_ordering_from_string(const char * ordering)
|
llvm::AtomicOrdering atomic_ordering_from_string(const char * ordering)
|
||||||
{
|
{
|
||||||
|
|
@ -353,7 +421,6 @@ void LLVMInitializePasses(){
|
||||||
initializeTarget(registry);
|
initializeTarget(registry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const char * LLVMDumpPasses()
|
const char * LLVMDumpPasses()
|
||||||
{
|
{
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,11 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wraps TargetMachine::addPassesToEmitFile
|
||||||
|
*/
|
||||||
|
unsigned char* LLVMGetNativeCodeFromModule(LLVMModuleRef module, int assembly,
|
||||||
|
unsigned * lenp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wraps IRBuilder::CreateFence
|
* 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