Add Module bitcode writer/parser
This commit is contained in:
parent
961c5e99e1
commit
168510222f
7 changed files with 138 additions and 14 deletions
|
|
@ -26,6 +26,11 @@ class Namespace(object):
|
||||||
self.functions.append(fn)
|
self.functions.append(fn)
|
||||||
return fn
|
return fn
|
||||||
|
|
||||||
|
def CustomFunction(self, *args):
|
||||||
|
fn = CustomFunction(self, *args)
|
||||||
|
self.functions.append(fn)
|
||||||
|
return fn
|
||||||
|
|
||||||
def Enum(self, name, *value_names):
|
def Enum(self, name, *value_names):
|
||||||
enum = Enum(*value_names)
|
enum = Enum(*value_names)
|
||||||
enum.parent = self
|
enum.parent = self
|
||||||
|
|
@ -444,13 +449,22 @@ class Function(Method):
|
||||||
with writer.function(self.name, varargs='args') as varargs:
|
with writer.function(self.name, varargs='args') as varargs:
|
||||||
unwrapped = writer.unwrap_many(varargs)
|
unwrapped = writer.unwrap_many(varargs)
|
||||||
self.process_ownedptr_args(writer, unwrapped)
|
self.process_ownedptr_args(writer, unwrapped)
|
||||||
func = self.fullname.split('::', 1)[1].replace('::', '.')
|
func = self.name
|
||||||
ret = writer.call('_api.%s' % func,
|
ret = writer.call('_api.%s' % func,
|
||||||
varargs=unwrapped)
|
varargs=unwrapped)
|
||||||
wrapped = writer.wrap(ret, self.is_return_ownedptr())
|
wrapped = writer.wrap(ret, self.is_return_ownedptr())
|
||||||
writer.return_value(wrapped)
|
writer.return_value(wrapped)
|
||||||
writer.println()
|
writer.println()
|
||||||
|
|
||||||
|
class CustomFunction(Function):
|
||||||
|
def __init__(self, parent, name, realname, return_type=Void, *args):
|
||||||
|
super(CustomFunction, self).__init__(parent, name, return_type, *args)
|
||||||
|
self.realname = realname
|
||||||
|
|
||||||
|
@property
|
||||||
|
def fullname(self):
|
||||||
|
return self.realname
|
||||||
|
|
||||||
class Destructor(Method):
|
class Destructor(Method):
|
||||||
_kind_ = 'dtor'
|
_kind_ = 'dtor'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@
|
||||||
#include <llvm/Value.h>
|
#include <llvm/Value.h>
|
||||||
#include <llvm/Function.h>
|
#include <llvm/Function.h>
|
||||||
#include <llvm/Support/raw_ostream.h>
|
#include <llvm/Support/raw_ostream.h>
|
||||||
|
#include <llvm/Support/MemoryBuffer.h>
|
||||||
|
#include <llvm/Bitcode/ReaderWriter.h>
|
||||||
#include <llvm/ExecutionEngine/ExecutionEngine.h>
|
#include <llvm/ExecutionEngine/ExecutionEngine.h>
|
||||||
#include <llvm/ExecutionEngine/GenericValue.h>
|
#include <llvm/ExecutionEngine/GenericValue.h>
|
||||||
|
|
||||||
|
|
@ -405,3 +407,61 @@ PyObject* EngineBuilder_selectTarget(llvm::EngineBuilder* eb,
|
||||||
return pycapsule_new(eb, "llvm::EngineBuilder");
|
return pycapsule_new(eb, "llvm::EngineBuilder");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static
|
||||||
|
PyObject* llvm_ParseBitCodeFile(llvm::StringRef Buf, llvm::LLVMContext& Ctx,
|
||||||
|
PyObject* FObj=NULL)
|
||||||
|
{
|
||||||
|
using namespace llvm;
|
||||||
|
MemoryBuffer* MB = MemoryBuffer::getMemBuffer(Buf);
|
||||||
|
Module* M;
|
||||||
|
if (FObj) {
|
||||||
|
std::string ErrStr;
|
||||||
|
M = ParseBitcodeFile(MB, Ctx, &ErrStr);
|
||||||
|
if (-1 == PyFile_WriteString(ErrStr.c_str(), FObj)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
M = ParseBitcodeFile(MB, Ctx);
|
||||||
|
}
|
||||||
|
delete MB;
|
||||||
|
return pycapsule_new(M, "llvm::Module");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static
|
||||||
|
PyObject* llvm_WriteBitcodeToFile(const llvm::Module *M, PyObject* FObj)
|
||||||
|
{
|
||||||
|
using namespace llvm;
|
||||||
|
llvm::SmallVector<char, 32> sv;
|
||||||
|
llvm::raw_svector_ostream rso(sv);
|
||||||
|
llvm::WriteBitcodeToFile(M, rso);
|
||||||
|
rso.flush();
|
||||||
|
StringRef ref = rso.str();
|
||||||
|
PyObject* buf = PyString_FromStringAndSize(ref.data(), ref.size());
|
||||||
|
if (-1 == PyFile_WriteObject(buf, FObj, Py_PRINT_RAW)){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
PyObject* llvm_getBitcodeTargetTriple(llvm::StringRef Buf,
|
||||||
|
llvm::LLVMContext& Ctx,
|
||||||
|
PyObject* FObj = NULL)
|
||||||
|
{
|
||||||
|
using namespace llvm;
|
||||||
|
MemoryBuffer* MB = MemoryBuffer::getMemBuffer(Buf);
|
||||||
|
std::string Triple;
|
||||||
|
if (FObj) {
|
||||||
|
std::string ErrStr;
|
||||||
|
Triple = getBitcodeTargetTriple(MB, Ctx, &ErrStr);
|
||||||
|
if (-1 == PyFile_WriteString(ErrStr.c_str(), FObj)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Triple = getBitcodeTargetTriple(MB, Ctx);
|
||||||
|
}
|
||||||
|
delete MB;
|
||||||
|
return PyString_FromString(Triple.c_str());
|
||||||
|
}
|
||||||
|
|
|
||||||
30
newbinding/src/Bitcode/ReaderWriter.py
Normal file
30
newbinding/src/Bitcode/ReaderWriter.py
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
from binding import *
|
||||||
|
from ..namespace import llvm
|
||||||
|
from ..ADT.StringRef import StringRef
|
||||||
|
from ..Module import Module
|
||||||
|
from ..LLVMContext import LLVMContext
|
||||||
|
|
||||||
|
llvm.includes.add('llvm/Bitcode/ReaderWriter.h')
|
||||||
|
|
||||||
|
ParseBitCodeFile = llvm.CustomFunction('ParseBitCodeFile',
|
||||||
|
'llvm_ParseBitCodeFile',
|
||||||
|
PyObjectPtr, # returns Module*
|
||||||
|
cast(str, StringRef),
|
||||||
|
ref(LLVMContext),
|
||||||
|
PyObjectPtr, # file-like object
|
||||||
|
).require_only(2)
|
||||||
|
|
||||||
|
WriteBitcodeToFile = llvm.CustomFunction('WriteBitcodeToFile',
|
||||||
|
'llvm_WriteBitcodeToFile',
|
||||||
|
PyObjectPtr, # return None
|
||||||
|
ptr(Module),
|
||||||
|
PyObjectPtr, # file-like object
|
||||||
|
)
|
||||||
|
|
||||||
|
getBitcodeTargetTriple = llvm.CustomFunction('getBitcodeTargetTriple',
|
||||||
|
'llvm_getBitcodeTargetTriple',
|
||||||
|
PyObjectPtr, # return str
|
||||||
|
cast(str, StringRef),
|
||||||
|
ref(LLVMContext),
|
||||||
|
PyObjectPtr, # file-like object
|
||||||
|
).require_only(2)
|
||||||
10
newbinding/src/Bitcode/__init__.py
Normal file
10
newbinding/src/Bitcode/__init__.py
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
import os.path, importlib
|
||||||
|
|
||||||
|
def _init():
|
||||||
|
for fname in os.listdir(os.path.dirname(__file__)):
|
||||||
|
if ((fname.endswith('.py') or fname.endswith('.pyc')) and
|
||||||
|
not fname.startswith('__init__')):
|
||||||
|
modname = os.path.basename(fname).rsplit('.', 1)[0]
|
||||||
|
importlib.import_module('.' + modname, __name__)
|
||||||
|
|
||||||
|
_init()
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
from binding import *
|
|
||||||
from ..namespace import llvm
|
|
||||||
|
|
||||||
MemoryBuffer = llvm.Class()
|
|
||||||
|
|
||||||
@MemoryBuffer
|
|
||||||
class MemoryBuffer:
|
|
||||||
_include_ = 'llvm/Support/MemoryBuffer.h'
|
|
||||||
|
|
||||||
|
|
@ -1,12 +1,15 @@
|
||||||
import os.path, importlib
|
import os.path, importlib
|
||||||
|
|
||||||
def _init():
|
def _init():
|
||||||
for fname in os.listdir(os.path.dirname(__file__)):
|
base = os.path.dirname(__file__)
|
||||||
if ((fname.endswith('.py') or fname.endswith('.pyc')) and
|
for fname in os.listdir(base):
|
||||||
not fname.startswith('__init__')):
|
print fname
|
||||||
|
is_python_script = fname.endswith('.py') or fname.endswith('.pyc')
|
||||||
|
is_init_script = fname.startswith('__init__')
|
||||||
|
is_directory = os.path.isdir(os.path.join(base, fname))
|
||||||
|
if (is_directory or is_python_script) and not is_init_script :
|
||||||
modname = os.path.basename(fname).rsplit('.', 1)[0]
|
modname = os.path.basename(fname).rsplit('.', 1)[0]
|
||||||
importlib.import_module('.' + modname, __name__)
|
importlib.import_module('.' + modname, __name__)
|
||||||
|
|
||||||
_init()
|
_init()
|
||||||
|
|
||||||
import Transforms, ADT, Support, Assembly, ExecutionEngine, CodeGen, Target
|
|
||||||
|
|
|
||||||
|
|
@ -135,6 +135,22 @@ def test_basic_jit_use():
|
||||||
|
|
||||||
assert 44 == gvR.toUnsignedInt()
|
assert 44 == gvR.toUnsignedInt()
|
||||||
|
|
||||||
|
# write bitcode
|
||||||
|
bc_buffer = StringIO()
|
||||||
|
api.WriteBitcodeToFile(m, bc_buffer)
|
||||||
|
bc = bc_buffer.getvalue()
|
||||||
|
bc_buffer.close()
|
||||||
|
|
||||||
|
# read bitcode
|
||||||
|
errbuf = StringIO()
|
||||||
|
m2 = api.ParseBitCodeFile(bc, context, errbuf)
|
||||||
|
if not m2:
|
||||||
|
raise Exception(errbuf.getvalue())
|
||||||
|
else:
|
||||||
|
m2.setModuleIdentifier(m.getModuleIdentifier())
|
||||||
|
assert str(m2) == str(m)
|
||||||
|
|
||||||
|
|
||||||
def test_engine_builder():
|
def test_engine_builder():
|
||||||
api.InitializeNativeTarget()
|
api.InitializeNativeTarget()
|
||||||
context = api.getGlobalContext()
|
context = api.getGlobalContext()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue