Add Module bitcode writer/parser

This commit is contained in:
Siu Kwan Lam 2013-02-04 16:45:49 -06:00
commit 168510222f
7 changed files with 138 additions and 14 deletions

View file

@ -26,6 +26,11 @@ class Namespace(object):
self.functions.append(fn)
return fn
def CustomFunction(self, *args):
fn = CustomFunction(self, *args)
self.functions.append(fn)
return fn
def Enum(self, name, *value_names):
enum = Enum(*value_names)
enum.parent = self
@ -444,13 +449,22 @@ class Function(Method):
with writer.function(self.name, varargs='args') as varargs:
unwrapped = writer.unwrap_many(varargs)
self.process_ownedptr_args(writer, unwrapped)
func = self.fullname.split('::', 1)[1].replace('::', '.')
func = self.name
ret = writer.call('_api.%s' % func,
varargs=unwrapped)
wrapped = writer.wrap(ret, self.is_return_ownedptr())
writer.return_value(wrapped)
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):
_kind_ = 'dtor'

View file

@ -3,6 +3,8 @@
#include <llvm/Value.h>
#include <llvm/Function.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/GenericValue.h>
@ -405,3 +407,61 @@ PyObject* EngineBuilder_selectTarget(llvm::EngineBuilder* eb,
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());
}

View 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)

View 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()

View file

@ -1,9 +0,0 @@
from binding import *
from ..namespace import llvm
MemoryBuffer = llvm.Class()
@MemoryBuffer
class MemoryBuffer:
_include_ = 'llvm/Support/MemoryBuffer.h'

View file

@ -1,12 +1,15 @@
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__')):
base = os.path.dirname(__file__)
for fname in os.listdir(base):
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]
importlib.import_module('.' + modname, __name__)
_init()
import Transforms, ADT, Support, Assembly, ExecutionEngine, CodeGen, Target

View file

@ -135,6 +135,22 @@ def test_basic_jit_use():
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():
api.InitializeNativeTarget()
context = api.getGlobalContext()