[pygobject/llvm: 12/12] [llvm] Add support for int64/boxed
- From: Johan Dahlin <johan src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygobject/llvm: 12/12] [llvm] Add support for int64/boxed
- Date: Thu, 8 Jul 2010 17:56:32 +0000 (UTC)
commit 5ce55d5105271e537da7caf94d4eebbe589d0ba7
Author: Johan Dahlin <johan gnome org>
Date: Thu Jul 8 14:53:16 2010 -0300
[llvm] Add support for int64/boxed
gi/llvm-compiler.cpp | 198 +++++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 170 insertions(+), 28 deletions(-)
---
diff --git a/gi/llvm-compiler.cpp b/gi/llvm-compiler.cpp
index acf0355..563e4e0 100644
--- a/gi/llvm-compiler.cpp
+++ b/gi/llvm-compiler.cpp
@@ -30,7 +30,7 @@
#define NO_IMPORT_PYGOBJECT
#include <pygobject.h>
#include "pygobject-external.h"
-#include "pygi.h"
+#include "pygi-private.h"
#include "pygi-info.h"
#include <llvm/Analysis/Verifier.h>
@@ -53,7 +53,8 @@
*/
// FIXME: replace with o->ob_type == &Py_Type
long _PyLong_Check(PyObject *o) {
- return PyLong_Check(o) || PyInt_Check(o);
+ int r = PyLong_Check(o) || PyInt_Check(o);
+ return r;
}
long _PyFloat_Check(PyObject *o) {
@@ -81,6 +82,31 @@ PyObject* _PyGObject_New(GObject *o) {
return pygobject_new(o);
}
+PyObject* _PyGBoxed_New(GType gtype,
+ gpointer boxed) {
+ PyObject *py_type = _pygi_type_get_from_g_type(gtype);
+ if (py_type == NULL)
+ return NULL;
+ PyObject *py_boxed = _pygi_boxed_new((PyTypeObject *)py_type, boxed, TRUE);
+ Py_DECREF(py_type);
+ return py_boxed;
+}
+
+gpointer _PyGBoxed_Get(PyObject *object) {
+ return pyg_boxed_get(object, void);
+}
+
+PY_LONG_LONG _PyLong_AsUnsignedLongLong(PyObject *o) {
+ PY_LONG_LONG i = 0;
+ i = PyLong_AsUnsignedLongLong(o);
+ return i;
+}
+
+PyObject *_PyLong_FromUnsignedLongLong(PY_LONG_LONG v) {
+ PY_LONG_LONG i = 0;
+ PyObject *rv = PyLong_FromUnsignedLongLong(v);
+ return rv;
+}
/*
* LLVMCompiler
@@ -93,12 +119,17 @@ static llvm::IRBuilder<> Builder(llvm::getGlobalContext());
// PyTupleObject = { ssize_t ob_refcnt, struct* ob_type, ssize_t ob_size, PyObject* }
static llvm::Type* pyObjectPtr = NULL;
static llvm::Type* gObjectPtr = NULL;
+static llvm::Type* voidPtr = NULL;
static llvm::Function *_PyGObject_GetFunc = NULL;
static llvm::Function *_PyGObject_NewFunc = NULL;
+static llvm::Function *_PyGBoxed_GetFunc = NULL;
+static llvm::Function *_PyGBoxed_NewFunc = NULL;
static llvm::Function *_PyLong_CheckFunc = NULL;
static llvm::Function *_PyFloat_CheckFunc = NULL;
static llvm::Function *_PyString_CheckFunc = NULL;
static llvm::Function *_PyGObject_CheckFunc = NULL;
+static llvm::Function *_PyLong_AsUnsignedLongLongFunc = NULL;
+static llvm::Function *_PyLong_FromUnsignedLongLongFunc = NULL;
static llvm::Value *_PyExc_TypeErrorVar = NULL;
LLVMCompiler::LLVMCompiler(llvm::LLVMContext &ctx) :
@@ -130,12 +161,23 @@ LLVMCompiler::getTypeFromTypeInfo(GITypeInfo *typeInfo)
switch (g_type_info_get_tag(typeInfo)) {
case GI_TYPE_TAG_VOID:
return llvm::Type::getVoidTy(mCtx);
+ case GI_TYPE_TAG_BOOLEAN:
+ return llvm::Type::getInt1Ty(mCtx);
case GI_TYPE_TAG_DOUBLE:
return llvm::Type::getDoubleTy(mCtx);
case GI_TYPE_TAG_INT8:
case GI_TYPE_TAG_UINT8:
return llvm::Type::getInt8Ty(mCtx);
+ case GI_TYPE_TAG_LONG:
+ case GI_TYPE_TAG_ULONG:
+ if (sizeof(long) == 4)
+ return llvm::Type::getInt32Ty(mCtx);
+ else if (sizeof(long) == 8)
+ return llvm::Type::getInt64Ty(mCtx);
+ else
+ g_assert_not_reached();
case GI_TYPE_TAG_INT:
+ case GI_TYPE_TAG_UINT:
if (sizeof(int) == 4)
return llvm::Type::getInt32Ty(mCtx);
else if (sizeof(int) == 8)
@@ -145,12 +187,28 @@ LLVMCompiler::getTypeFromTypeInfo(GITypeInfo *typeInfo)
case GI_TYPE_TAG_INT32:
case GI_TYPE_TAG_UINT32:
return llvm::Type::getInt32Ty(mCtx);
+ case GI_TYPE_TAG_INT64:
+ case GI_TYPE_TAG_UINT64:
+ return llvm::Type::getInt64Ty(mCtx);
case GI_TYPE_TAG_ARRAY:
return llvm::PointerType::getUnqual(llvm::Type::getInt32Ty(mCtx));
case GI_TYPE_TAG_UTF8:
return llvm::PointerType::getUnqual(llvm::Type::getInt8Ty(mCtx));
- case GI_TYPE_TAG_INTERFACE:
- return gObjectPtr;
+ case GI_TYPE_TAG_INTERFACE: {
+ GIBaseInfo *ifaceInfo = g_type_info_get_interface(typeInfo);
+ GType type = g_registered_type_info_get_g_type((GIRegisteredTypeInfo *)ifaceInfo);
+ if (g_type_is_a(type, G_TYPE_OBJECT)) {
+ return gObjectPtr;
+ } else if (g_type_is_a(type, G_TYPE_BOXED)) {
+ return voidPtr;
+ } else if (g_type_is_a(type, G_TYPE_VALUE)) {
+ return voidPtr;
+ } else if (g_type_is_a(type, G_TYPE_POINTER)) {
+ return voidPtr;
+ } else {
+ g_error("%s: unsupported info tag: %s %d\n", __FUNCTION__, g_type_name(type), g_base_info_get_type(ifaceInfo));
+ }
+ }
default:
g_error("%s: unsupported type tag: %d\n", __FUNCTION__, g_type_info_get_tag(typeInfo));
return 0;
@@ -194,6 +252,8 @@ LLVMCompiler::formatTypeForException(GITypeInfo *typeInfo)
return "a number";
case GI_TYPE_TAG_UTF8:
return "a string";
+ case GI_TYPE_TAG_INTERFACE:
+ return "an object";
default:
g_warning("%s: unsupported type tag: %d\n", __FUNCTION__, g_type_info_get_tag(typeInfo));
return "an unknown type";
@@ -210,7 +270,6 @@ LLVMCompiler::createException(GICallableInfo *callableInfo,
llvm::Function *parent = block->getParent();
llvm::BasicBlock* exitBB = llvm::BasicBlock::Create(mCtx, "bb", parent, 0);
Builder.SetInsertPoint(exitBB);
-
llvm::Constant *f = mModule->getOrInsertFunction("PyErr_Format",
llvm::Type::getVoidTy(mCtx),
pyObjectPtr, llvm::PointerType::getUnqual(llvm::IntegerType::get(mCtx, 8)), NULL);
@@ -223,8 +282,7 @@ LLVMCompiler::createException(GICallableInfo *callableInfo,
Builder.CreateLoad(_PyExc_TypeErrorVar),
Builder.CreateGlobalStringPtr(msg, "format"));
g_free(msg);
-
- Builder.CreateRet(llvm::ConstantInt::get(llvm::Type::getInt32Ty(mCtx), 0));
+ Builder.CreateRet(llvm::ConstantExpr::getNullValue(pyObjectPtr));
return exitBB;
}
@@ -249,7 +307,9 @@ LLVMCompiler::typeCheck(GICallableInfo *callableInfo,
case GI_TYPE_TAG_INT16:
case GI_TYPE_TAG_UINT16:
case GI_TYPE_TAG_INT32:
- case GI_TYPE_TAG_UINT32: {
+ case GI_TYPE_TAG_UINT32:
+ case GI_TYPE_TAG_INT64:
+ case GI_TYPE_TAG_UINT64: {
llvm::Value *v = Builder.CreateCall(_PyLong_CheckFunc, value);
llvm::BasicBlock *excBlock = this->createException(callableInfo, argInfo, typeInfo, i, *block);
this->createIf(block, llvm::ICmpInst::ICMP_EQ, v, llvm::ConstantInt::get(llvm::Type::getInt32Ty(mCtx), 0), excBlock);
@@ -278,6 +338,10 @@ LLVMCompiler::typeCheck(GICallableInfo *callableInfo,
this->createIf(block, llvm::ICmpInst::ICMP_EQ, v, llvm::ConstantInt::get(llvm::Type::getInt32Ty(mCtx), 0), excBlock);
break;
}
+ case GI_INFO_TYPE_STRUCT: {
+ /* FIXME */
+ break;
+ }
default:
g_error("%s: unsupported info type: %d\n", __FUNCTION__, infoType);
break;
@@ -296,6 +360,7 @@ LLVMCompiler::valueAsNative(GITypeInfo *typeInfo,
llvm::Value *value)
{
llvm::Value *retval;
+ const llvm::Type *valueType = this->getTypeFromTypeInfo(typeInfo);
bool isSigned = false;
switch (g_type_info_get_tag(typeInfo)) {
case GI_TYPE_TAG_DOUBLE: {
@@ -316,8 +381,23 @@ LLVMCompiler::valueAsNative(GITypeInfo *typeInfo,
case GI_TYPE_TAG_UINT32: {
llvm::Constant *f = mModule->getOrInsertFunction("PyLong_AsLong",
llvm::Type::getInt32Ty(mCtx), pyObjectPtr, NULL);
- llvm::Value *v = Builder.CreateCall(f, value);
- retval = Builder.CreateIntCast(v, this->getTypeFromTypeInfo(typeInfo), isSigned, "cast");
+ retval = Builder.CreateCall(f, value);
+ if (retval->getType() != valueType)
+ retval = Builder.CreateIntCast(retval, valueType, isSigned, "cast");
+ break;
+ }
+ case GI_TYPE_TAG_INT64: {
+ llvm::Constant *f = mModule->getOrInsertFunction("PyLong_AsLongLong",
+ llvm::Type::getInt64Ty(mCtx), pyObjectPtr, NULL);
+ retval = Builder.CreateCall(f, value);
+ if (retval->getType() != valueType)
+ retval = Builder.CreateIntCast(retval, valueType, true, "cast");
+ break;
+ }
+ case GI_TYPE_TAG_UINT64: {
+ retval = Builder.CreateCall(_PyLong_AsUnsignedLongLongFunc, value);
+ if (retval->getType() != valueType)
+ retval = Builder.CreateIntCast(retval, valueType, false, "cast");
break;
}
case GI_TYPE_TAG_UTF8: {
@@ -340,6 +420,10 @@ LLVMCompiler::valueAsNative(GITypeInfo *typeInfo,
retval = Builder.CreateCall(_PyGObject_GetFunc, value);
break;
}
+ case GI_INFO_TYPE_STRUCT: {
+ retval = Builder.CreateCall(_PyGBoxed_GetFunc, value);
+ break;
+ }
default:
g_error("%s: unsupported info type: %d\n", __FUNCTION__, infoType);
retval = 0;
@@ -361,6 +445,7 @@ LLVMCompiler::valueFromNative(GITypeInfo *typeInfo,
llvm::Value *value)
{
llvm::Value *retval;
+ const llvm::Type *valueType = this->getTypeFromTypeInfo(typeInfo);
bool isSigned = false;
switch (g_type_info_get_tag(typeInfo)) {
case GI_TYPE_TAG_DOUBLE: {
@@ -369,19 +454,37 @@ LLVMCompiler::valueFromNative(GITypeInfo *typeInfo,
retval = Builder.CreateCall(f, value);
break;
}
+ case GI_TYPE_TAG_INT:
case GI_TYPE_TAG_INT8:
case GI_TYPE_TAG_INT16:
case GI_TYPE_TAG_INT32:
+ case GI_TYPE_TAG_LONG:
isSigned = true;
+ case GI_TYPE_TAG_BOOLEAN:
+ case GI_TYPE_TAG_ULONG:
+ case GI_TYPE_TAG_UINT:
case GI_TYPE_TAG_UINT8:
- case GI_TYPE_TAG_UINT16:
- case GI_TYPE_TAG_UINT32: {
+ case GI_TYPE_TAG_UINT16: {
llvm::Constant *f = mModule->getOrInsertFunction("PyLong_FromLong",
pyObjectPtr, llvm::Type::getInt32Ty(mCtx), NULL);
llvm::Value *casted = Builder.CreateIntCast(value, llvm::Type::getInt32Ty(mCtx), isSigned, "cast");
retval = Builder.CreateCall(f, casted);
break;
}
+ case GI_TYPE_TAG_INT64:
+ isSigned = true;
+ case GI_TYPE_TAG_UINT32: {
+ llvm::Constant *f = mModule->getOrInsertFunction("PyLong_FromLongLong",
+ pyObjectPtr, llvm::Type::getInt64Ty(mCtx), NULL);
+ llvm::Value *casted = Builder.CreateIntCast(value, llvm::Type::getInt64Ty(mCtx), isSigned, "cast");
+ retval = Builder.CreateCall(f, casted);
+ break;
+ }
+ case GI_TYPE_TAG_UINT64: {
+ llvm::Value *casted = Builder.CreateIntCast(value, llvm::Type::getInt64Ty(mCtx), false, "cast");
+ retval = Builder.CreateCall(_PyLong_FromUnsignedLongLongFunc, casted);
+ break;
+ }
case GI_TYPE_TAG_UTF8: {
llvm::Constant *f = mModule->getOrInsertFunction("PyString_FromString",
pyObjectPtr, llvm::PointerType::getUnqual(llvm::IntegerType::get(mCtx, 8)), NULL);
@@ -397,15 +500,28 @@ LLVMCompiler::valueFromNative(GITypeInfo *typeInfo,
g_assert(ifaceInfo != NULL);
GIInfoType infoType = g_base_info_get_type(ifaceInfo);
switch (infoType) {
- case GI_INFO_TYPE_OBJECT: {
- retval = Builder.CreateCall(_PyGObject_NewFunc, value);
- this->pyIncRef(retval);
- break;
- }
- default:
- g_error("%s: unsupported info type: %d\n", __FUNCTION__, infoType);
- retval = 0;
- break;
+ case GI_INFO_TYPE_OBJECT: {
+ retval = Builder.CreateCall(_PyGObject_NewFunc, value);
+ break;
+ }
+ case GI_INFO_TYPE_BOXED:
+ case GI_INFO_TYPE_UNION:
+ case GI_INFO_TYPE_STRUCT: {
+ GType type = g_registered_type_info_get_g_type((GIRegisteredTypeInfo *)ifaceInfo);
+ if (g_type_is_a(type, G_TYPE_BOXED)) {
+ retval = Builder.CreateCall2(_PyGBoxed_NewFunc,
+ llvm::ConstantInt::get(llvm::Type::getInt32Ty(mCtx), type),
+ value);
+ this->pyIncRef(retval);
+ } else {
+ g_error("%s: unsupported GType for struct/boxed/union: %s\n", __FUNCTION__, g_type_name(type));
+ }
+ break;
+ }
+ default:
+ g_error("%s: unsupported info type: %d\n", __FUNCTION__, infoType);
+ retval = 0;
+ break;
}
g_base_info_unref((GIBaseInfo*)ifaceInfo);
break;
@@ -497,6 +613,12 @@ LLVMCompiler::loadSymbols()
mModule->addTypeName("GObject", gObject);
gObjectPtr = llvm::PointerType::getUnqual(gObject);
+ const llvm::Type *void_ = llvm::Type::getInt8Ty(mCtx);
+ mModule->addTypeName("void", gObject);
+ voidPtr = llvm::PointerType::getUnqual(void_);
+
+ const llvm::Type * gType = llvm::Type::getInt32Ty(mCtx);
+
_PyLong_CheckFunc =
llvm::cast<llvm::Function>(mModule->getOrInsertFunction("_PyLong_Check",
llvm::Type::getInt32Ty(mCtx), pyObjectPtr, NULL));
@@ -514,15 +636,29 @@ LLVMCompiler::loadSymbols()
_PyGObject_CheckFunc
= llvm::cast<llvm::Function>(mModule->getOrInsertFunction("_PyGObject_Check",
- llvm::Type::getInt32Ty(mCtx), pyObjectPtr,
- llvm::Type::getInt32Ty(mCtx), NULL));
+ llvm::Type::getInt32Ty(mCtx), pyObjectPtr, gType, NULL));
mEE->updateGlobalMapping(llvm::cast<llvm::Function>(_PyGObject_CheckFunc), (void*)&_PyGObject_Check);
- _PyGObject_GetFunc = llvm::cast<llvm::Function>(mModule->getOrInsertFunction("_PyGObject_Get", pyObjectPtr, gObjectPtr, NULL));
+ _PyLong_AsUnsignedLongLongFunc
+ = llvm::cast<llvm::Function>(mModule->getOrInsertFunction("PyLong_AsUnsignedLongLong",
+ llvm::Type::getInt64Ty(mCtx), pyObjectPtr, NULL));
+ mEE->updateGlobalMapping(llvm::cast<llvm::Function>(_PyLong_AsUnsignedLongLongFunc), (void*)&_PyLong_AsUnsignedLongLong);
+
+ _PyLong_FromUnsignedLongLongFunc
+ = llvm::cast<llvm::Function>(mModule->getOrInsertFunction("_PyLong_FromUnsignedLongLong",
+ pyObjectPtr, llvm::Type::getInt64Ty(mCtx), NULL));
+ mEE->updateGlobalMapping(llvm::cast<llvm::Function>(_PyLong_FromUnsignedLongLongFunc), (void*)&_PyLong_FromUnsignedLongLong);
+
+ _PyGObject_GetFunc = llvm::cast<llvm::Function>(mModule->getOrInsertFunction("_PyGObject_Get", gObjectPtr, pyObjectPtr, NULL));
mEE->updateGlobalMapping(llvm::cast<llvm::Function>(_PyGObject_GetFunc), (void*)&_PyGObject_Get);
_PyGObject_NewFunc = llvm::cast<llvm::Function>(mModule->getOrInsertFunction("_PyGObject_New", pyObjectPtr, gObjectPtr, NULL));
mEE->updateGlobalMapping(llvm::cast<llvm::Function>(_PyGObject_NewFunc), (void*)&_PyGObject_New);
+ _PyGBoxed_GetFunc = llvm::cast<llvm::Function>(mModule->getOrInsertFunction("_PyGBoxed_Get", voidPtr, pyObjectPtr, NULL));
+ mEE->updateGlobalMapping(llvm::cast<llvm::Function>(_PyGBoxed_GetFunc), (void*)&_PyGBoxed_Get);
+ _PyGBoxed_NewFunc = llvm::cast<llvm::Function>(mModule->getOrInsertFunction("_PyGBoxed_New", pyObjectPtr, gType, voidPtr, NULL));
+ mEE->updateGlobalMapping(llvm::cast<llvm::Function>(_PyGBoxed_NewFunc), (void*)&_PyGBoxed_New);
+
_PyExc_TypeErrorVar = new llvm::GlobalVariable(pyObjectPtr, true, llvm::GlobalValue::ExternalLinkage, 0, "PyExc_TypeError");
}
@@ -611,16 +747,22 @@ LLVMCompiler::compile(GIFunctionInfo *info)
g_base_info_unref((GIBaseInfo*)retTypeInfo);
-#if DEBUG
- mModule->dump();
-#endif
-
// JIT it
+ //llvm::verifyFunction(*wrapperFunc);
PyCFunction f = (PyCFunction)mEE->getPointerToFunction(wrapperFunc);
+ //printf("PyC: %p %p\n", f, &f);
+ //G_BREAKPOINT();
#if TIMEIT
struct timeval end_tv;
gettimeofday(&end_tv, NULL);
+#endif
+
+#if DEBUG
+ mModule->dump();
+#endif
+
+#if TIMEIT
g_print("Compiled: %s in %2.2f ms\n", g_function_info_get_symbol(info),
(end_tv.tv_usec-start_tv.tv_usec)/1000.0);
#elif DEBUG
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]