diff --git a/CHANGELOG b/CHANGELOG index cf8ea8f..e628a23 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,8 @@ 0.6, in progress: + * Inline function (Corrado Zoccolo). + * Get pointer to function (Corrado Zoccolo). * More properties/methods for TargetData (Florian Noding) (Issue #16). * Value.uses API. * Fetch operands of instructions (Seth Warn). diff --git a/llvm/_core.c b/llvm/_core.c index 7d18c61..933e0c7 100644 --- a/llvm/_core.c +++ b/llvm/_core.c @@ -917,6 +917,23 @@ _wLLVMCreateExecutionEngine(PyObject *self, PyObject *args) return ret; } +static PyObject * +_wLLVMGetPointerToFunction(PyObject *self, PyObject *args) +{ + PyObject *obj_ee; + PyObject *obj_fn; + LLVMExecutionEngineRef ee; + LLVMValueRef fn; + + if (!PyArg_ParseTuple(args, "OO", &obj_ee, &obj_fn)) + return NULL; + + ee = (LLVMExecutionEngineRef) PyCObject_AsVoidPtr(obj_ee); + fn = (LLVMValueRef) PyCObject_AsVoidPtr(obj_fn); + + return PyLong_FromVoidPtr(LLVMGetPointerToFunction(ee,fn)); +} + /* the args should have been ptr, num */ LLVMGenericValueRef LLVMRunFunction2(LLVMExecutionEngineRef EE, LLVMValueRef F, LLVMGenericValueRef *Args, unsigned NumArgs) @@ -976,6 +993,26 @@ _wLLVMCreateGenericValueOfFloat(PyObject *self, PyObject *args) return ctor_LLVMGenericValueRef(gv); } +static PyObject * +_wLLVMCreateGenericValueOfPointer(PyObject *self, PyObject *args) +{ + PyObject *obj1; + LLVMTypeRef ty; + unsigned long long n_; + size_t n; + LLVMGenericValueRef gv; + + if (!PyArg_ParseTuple(args, "OL", &obj1, &n_)) + return NULL; + + n=n_; + + ty = (LLVMTypeRef) PyCObject_AsVoidPtr(obj1); + + gv = LLVMCreateGenericValueOfPointer((void*)n); + return ctor_LLVMGenericValueRef(gv); +} + static PyObject * _wLLVMGenericValueToInt(PyObject *self, PyObject *args) { @@ -1013,6 +1050,22 @@ _wLLVMGenericValueToFloat(PyObject *self, PyObject *args) return PyFloat_FromDouble(val); } +static PyObject * +_wLLVMGenericValueToPointer(PyObject *self, PyObject *args) +{ + PyObject *obj1; + LLVMGenericValueRef gv; + void * val; + + if (!PyArg_ParseTuple(args, "O", &obj1)) + return NULL; + + gv = (LLVMGenericValueRef) PyCObject_AsVoidPtr(obj1); + + val = LLVMGenericValueToPointer(gv); + return PyLong_FromVoidPtr(val); +} + _wrap_obj2none(LLVMDisposeGenericValue, LLVMGenericValueRef) @@ -1046,6 +1099,8 @@ _wLLVMLoadLibraryPermanently(PyObject *self, PyObject *args) Py_RETURN_NONE; } +_wrap_obj2obj(LLVMInlineFunction, LLVMValueRef, int) + /* Expose the void* inside a PyCObject as a PyLong. This allows us to * use it as a unique ID. */ static PyObject * @@ -1503,6 +1558,7 @@ static PyMethodDef core_methods[] = { _method( LLVMCreateExecutionEngine ) _method( LLVMDisposeExecutionEngine ) _method( LLVMRunFunction2 ) + _method( LLVMGetPointerToFunction ) _method( LLVMGetExecutionEngineTargetData ) _method( LLVMRunStaticConstructors ) _method( LLVMRunStaticDestructors ) @@ -1512,13 +1568,16 @@ static PyMethodDef core_methods[] = { /* Generic Value */ _method( LLVMCreateGenericValueOfInt ) _method( LLVMCreateGenericValueOfFloat ) + _method( LLVMCreateGenericValueOfPointer ) _method( LLVMGenericValueToInt ) _method( LLVMGenericValueToFloat ) + _method( LLVMGenericValueToPointer ) _method( LLVMDisposeGenericValue ) /* Misc */ _method( LLVMGetIntrinsic ) _method( LLVMLoadLibraryPermanently ) + _method( LLVMInlineFunction ) _method( PyCObjectVoidPtrToPyLong ) { NULL } diff --git a/llvm/core.py b/llvm/core.py index 2ba1a9b..2c32313 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -1946,3 +1946,7 @@ def load_library_permanently(filename): if isinstance(ret, str): raise llvm.LLVMException, ret +def inline_function(call): + check_is_value(call) + return _core.LLVMInlineFunction(call.ptr) + diff --git a/llvm/ee.py b/llvm/ee.py index 6969653..835dcc0 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -141,6 +141,12 @@ class GenericValue(object): ptr = _core.LLVMCreateGenericValueOfFloat(ty.ptr, floatval) return GenericValue(ptr) + @staticmethod + def pointer(ty, intval): + core.check_is_type(ty) + ptr = _core.LLVMCreateGenericValueOfPointer(ty.ptr, intval) + return GenericValue(ptr) + def __init__(self, ptr): self.ptr = ptr @@ -157,6 +163,9 @@ class GenericValue(object): core.check_is_type(ty) # only float or double return _core.LLVMGenericValueToFloat(ty.ptr, self.ptr) + def as_pointer(self): + return _core.LLVMGenericValueToPointer(self.ptr) + # helper functions for generic value objects def check_is_generic_value(obj): _util.check_gen(obj, GenericValue) @@ -192,6 +201,10 @@ class ExecutionEngine(object): gvptr = _core.LLVMRunFunction2(self.ptr, fn.ptr, ptrs) return GenericValue(gvptr) + def get_pointer_to_function(self, fn): + core.check_is_function(fn) + return _core.LLVMGetPointerToFunction(self.ptr,fn.ptr) + def run_static_ctors(self): _core.LLVMRunStaticConstructors(self.ptr) diff --git a/llvm/extra.cpp b/llvm/extra.cpp index 72074e7..12ddeb9 100644 --- a/llvm/extra.cpp +++ b/llvm/extra.cpp @@ -56,15 +56,18 @@ #include "llvm/Assembly/Parser.h" #include "llvm/System/DynamicLibrary.h" #include "llvm/PassManager.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/Analysis/LoopPass.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h" #include "llvm/Transforms/Instrumentation.h" +#include "llvm/Transforms/Utils/Cloning.h" #include "llvm/Linker.h" // LLVM-C includes #include "llvm-c/Core.h" +#include "llvm-c/ExecutionEngine.h" // our includes #include "extra.h" @@ -463,6 +466,27 @@ unsigned LLVMLoadLibraryPermanently(const char* filename, char **errmsg) return 1; } +void *LLVMGetPointerToFunction(LLVMExecutionEngineRef ee, LLVMValueRef fn) +{ + llvm::ExecutionEngine *eep = llvm::unwrap(ee); + assert(eep); + + llvm::Function *fnp = llvm::unwrap(fn); + assert(fnp); + + return eep->getPointerToFunction(fnp); +} + +int LLVMInlineFunction(LLVMValueRef call) +{ + llvm::Value *callp = llvm::unwrap(call); + assert(callp); + + llvm::CallSite cs = llvm::CallSite::get(callp); + + return llvm::InlineFunction(cs); +} + /* Passes. A few passes (listed below) are used directly from LLVM-C, * rest are defined here. diff --git a/llvm/extra.h b/llvm/extra.h index fb88ef7..2dd293c 100644 --- a/llvm/extra.h +++ b/llvm/extra.h @@ -165,6 +165,15 @@ unsigned char *LLVMGetBitcodeFromModule(LLVMModuleRef module, unsigned *len); * use, via LLVMDisposeMessage(). */ unsigned LLVMLoadLibraryPermanently(const char* filename, char **errmsg); +/* Wraps llvm::ExecutionEngine::getPointerToFunction(). Returns a pointer + * to the JITted function. */ +void *LLVMGetPointerToFunction(LLVMExecutionEngineRef ee, LLVMValueRef fn); + +/* Wraps llvm::InlineFunction(). Inlines a function. C is the call + * instruction, created by LLVMBuildCall. Even if it fails, the Function + * containing the call is still in a proper state (not changed). */ +int LLVMInlineFunction(LLVMValueRef call); + /* Passes. A few passes (listed below) are used directly from LLVM-C, * rest are declared here. *