Add binding for Intrinsics.

Add support for functions that free the resource but is not a destructor.
This commit is contained in:
Siu Kwan Lam 2013-02-07 13:27:03 -06:00
commit 11cc78d780
8 changed files with 92 additions and 4 deletions

View file

@ -92,8 +92,12 @@ _cache = defaultdict(WeakValueDictionary)
def release_ownership(old):
logger.debug('Release %s', old)
addr = Capsule.getPointer(old)
if _addr2dtor[addr] is None:
# Guard deduplicated release
if _addr2dtor.get(addr) is None:
clsname = Capsule.getClassName(old)
if not _pyclasses[clsname]._has_dtor():
return
# Guard duplicated release
raise Exception("Already released")
_addr2dtor[addr] = None
@ -117,7 +121,7 @@ def wrap(cap, owned=False):
try: # lookup cached object
return _cache[cls][addr]
except KeyError:
if not owned and hasattr(cls, '_delete_'):
if not owned and cls._has_dtor():
_addr2dtor[addr] = cls._delete_
obj = cap.instantiate()
_cache[cls][addr] = obj # cache it
@ -164,6 +168,10 @@ class Wrapper(object):
def _downcast(self, newcls):
return downcast(self, newcls)
@classmethod
def _has_dtor(cls):
return hasattr(cls, '_delete_')
def downcast(obj, cls):
import _api
if type(obj) is cls:

View file

@ -283,6 +283,7 @@ class Method(object):
self.signatures = []
self.includes = set()
self._add_signature(return_type, *args)
self.disowning = False
def _add_signature(self, return_type, *args):
prev_lens = set(map(len, self.signatures))
@ -350,6 +351,8 @@ class Method(object):
decl = writer.function(self.name, args=('self',), varargs='args')
with decl as (this, varargs):
unwrap_this = writer.unwrap(this)
if self.disowning:
writer.release_ownership(unwrap_this)
unwrapped = writer.unwrap_many(varargs)
self.process_ownedptr_args(writer, unwrapped)

View file

@ -13,6 +13,7 @@
#include <llvm/Module.h>
#include <llvm/Analysis/Verifier.h>
#include <llvm/Constants.h>
#include <llvm/Intrinsics.h>
#include "auto_pyobject.h"
@ -694,3 +695,21 @@ PyObject* ConstantVector_get(PyObject* Elems)
return pycapsule_new(ary, "llvm::Value", "llvm::Constant");
}
static
PyObject* Intrinsic_getDeclaration(llvm::Module* Mod,
unsigned ID,
PyObject* Types=NULL)
{
using namespace llvm;
Function* Fn = NULL;
if (Types) {
std::vector<Type*> types;
bool ok = extract<Type>::from_py_sequence(types, Types, "llvm::Type");
if (!ok) return NULL;
Fn = Intrinsic::getDeclaration(Mod, (Intrinsic::ID)ID, types);
} else {
Fn = Intrinsic::getDeclaration(Mod, (Intrinsic::ID)ID);
}
return pycapsule_new(Fn, "llvm::Value", "llvm::Function");
}

View file

@ -1,6 +1,8 @@
from binding import *
from namespace import llvm
from Value import GlobalValue, Constant, Function, Argument
from BasicBlock import BasicBlock
from Attributes import Attributes
from Type import Type
from DerivedTypes import FunctionType
from LLVMContext import LLVMContext
@ -21,6 +23,33 @@ class Function:
getCallingConv = Method(CallingConv.ID)
setCallingConv = Method(Void, CallingConv.ID)
hasGC = Method(cast(bool, Bool))
getGC = Method(cast(ConstCharPtr, str))
setGC = Method(Void, cast(str, ConstCharPtr))
getArgumentList = CustomMethod('Function_getArgumentList', PyObjectPtr)
getBasicBlockList = CustomMethod('Function_getBasicBlockList', PyObjectPtr)
getEntryBlock = Method(ref(BasicBlock))
copyAttributesFrom = Method(Void, ptr(GlobalValue))
setDoesNotThrow = Method()
doesNotThrow = Method(cast(Bool, bool))
setDoesNotReturn = Method()
doesNotReturn = Method(cast(Bool, bool))
setOnlyReadsMemory = Method()
onlyReadsMemory = Method(cast(Bool, bool))
setDoesNotAccessMemory = Method()
doesNotAccessMemory = Method(cast(Bool, bool))
deleteBody = Method()
viewCFG = Method()
viewCFGOnly = Method()
addFnAttr = Method(Void, Attributes.AttrVal)
removeFnAttr = Method(Void, ref(Attributes))
eraseFromParent = Method()
eraseFromParent.disowning = True

View file

@ -44,4 +44,6 @@ class GlobalValue:
isDeclaration = Method(cast(Bool, bool))
removeFromParent = Method()
eraseFromParent = Method()
eraseFromParent.disowning = True
getParent = Method(ptr(Module))

View file

@ -45,5 +45,5 @@ class GlobalVariable:
# isExternallyInitialized = Method(cast(Bool, bool))
# setExternallyinitialized = Method(Void, cast(bool, Bool))
eraseFromParent = Method()

View file

@ -0,0 +1,17 @@
from binding import *
from namespace import llvm
from Module import Module
from Function import Function
Intrinsic = llvm.Class() # fake class (actually a namespace)
@Intrinsic
class Intrinsic:
getDeclaration = CustomStaticMethod('Intrinsic_getDeclaration',
PyObjectPtr, # Function*
ptr(Module),
cast(int, Unsigned), # intrinsic id
PyObjectPtr, # list of Type
).require_only(2)

View file

@ -319,6 +319,16 @@ def test_constants():
aryconst = api.ConstantArray.get(ary_int32x4, [intconst] * 4)
assert str(aryconst.getAggregateElement(0)) == str(intconst)
def test_intrinsic():
context = api.getGlobalContext()
m = api.Module.new("modname", context)
INTR_SIN = 1652
floatty = api.Type.getFloatTy(context)
fn = api.Intrinsic.getDeclaration(m, INTR_SIN, [floatty])
assert 'llvm.sin.f32' in str(fn)
fn.eraseFromParent()
assert 'llvm.sin.f32' not in str(m)
def main():
for name, value in globals().items():
if name.startswith('test_') and callable(value):