Add binding for Intrinsics.
Add support for functions that free the resource but is not a destructor.
This commit is contained in:
parent
aa5b969961
commit
11cc78d780
8 changed files with 92 additions and 4 deletions
|
|
@ -92,8 +92,12 @@ _cache = defaultdict(WeakValueDictionary)
|
||||||
def release_ownership(old):
|
def release_ownership(old):
|
||||||
logger.debug('Release %s', old)
|
logger.debug('Release %s', old)
|
||||||
addr = Capsule.getPointer(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")
|
raise Exception("Already released")
|
||||||
_addr2dtor[addr] = None
|
_addr2dtor[addr] = None
|
||||||
|
|
||||||
|
|
@ -117,7 +121,7 @@ def wrap(cap, owned=False):
|
||||||
try: # lookup cached object
|
try: # lookup cached object
|
||||||
return _cache[cls][addr]
|
return _cache[cls][addr]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
if not owned and hasattr(cls, '_delete_'):
|
if not owned and cls._has_dtor():
|
||||||
_addr2dtor[addr] = cls._delete_
|
_addr2dtor[addr] = cls._delete_
|
||||||
obj = cap.instantiate()
|
obj = cap.instantiate()
|
||||||
_cache[cls][addr] = obj # cache it
|
_cache[cls][addr] = obj # cache it
|
||||||
|
|
@ -164,6 +168,10 @@ class Wrapper(object):
|
||||||
def _downcast(self, newcls):
|
def _downcast(self, newcls):
|
||||||
return downcast(self, newcls)
|
return downcast(self, newcls)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _has_dtor(cls):
|
||||||
|
return hasattr(cls, '_delete_')
|
||||||
|
|
||||||
def downcast(obj, cls):
|
def downcast(obj, cls):
|
||||||
import _api
|
import _api
|
||||||
if type(obj) is cls:
|
if type(obj) is cls:
|
||||||
|
|
|
||||||
|
|
@ -283,6 +283,7 @@ class Method(object):
|
||||||
self.signatures = []
|
self.signatures = []
|
||||||
self.includes = set()
|
self.includes = set()
|
||||||
self._add_signature(return_type, *args)
|
self._add_signature(return_type, *args)
|
||||||
|
self.disowning = False
|
||||||
|
|
||||||
def _add_signature(self, return_type, *args):
|
def _add_signature(self, return_type, *args):
|
||||||
prev_lens = set(map(len, self.signatures))
|
prev_lens = set(map(len, self.signatures))
|
||||||
|
|
@ -350,6 +351,8 @@ class Method(object):
|
||||||
decl = writer.function(self.name, args=('self',), varargs='args')
|
decl = writer.function(self.name, args=('self',), varargs='args')
|
||||||
with decl as (this, varargs):
|
with decl as (this, varargs):
|
||||||
unwrap_this = writer.unwrap(this)
|
unwrap_this = writer.unwrap(this)
|
||||||
|
if self.disowning:
|
||||||
|
writer.release_ownership(unwrap_this)
|
||||||
unwrapped = writer.unwrap_many(varargs)
|
unwrapped = writer.unwrap_many(varargs)
|
||||||
self.process_ownedptr_args(writer, unwrapped)
|
self.process_ownedptr_args(writer, unwrapped)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
#include <llvm/Module.h>
|
#include <llvm/Module.h>
|
||||||
#include <llvm/Analysis/Verifier.h>
|
#include <llvm/Analysis/Verifier.h>
|
||||||
#include <llvm/Constants.h>
|
#include <llvm/Constants.h>
|
||||||
|
#include <llvm/Intrinsics.h>
|
||||||
|
|
||||||
#include "auto_pyobject.h"
|
#include "auto_pyobject.h"
|
||||||
|
|
||||||
|
|
@ -694,3 +695,21 @@ PyObject* ConstantVector_get(PyObject* Elems)
|
||||||
return pycapsule_new(ary, "llvm::Value", "llvm::Constant");
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
from binding import *
|
from binding import *
|
||||||
from namespace import llvm
|
from namespace import llvm
|
||||||
from Value import GlobalValue, Constant, Function, Argument
|
from Value import GlobalValue, Constant, Function, Argument
|
||||||
|
from BasicBlock import BasicBlock
|
||||||
|
from Attributes import Attributes
|
||||||
from Type import Type
|
from Type import Type
|
||||||
from DerivedTypes import FunctionType
|
from DerivedTypes import FunctionType
|
||||||
from LLVMContext import LLVMContext
|
from LLVMContext import LLVMContext
|
||||||
|
|
@ -21,6 +23,33 @@ class Function:
|
||||||
getCallingConv = Method(CallingConv.ID)
|
getCallingConv = Method(CallingConv.ID)
|
||||||
setCallingConv = Method(Void, 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)
|
getArgumentList = CustomMethod('Function_getArgumentList', PyObjectPtr)
|
||||||
getBasicBlockList = CustomMethod('Function_getBasicBlockList', 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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,4 +44,6 @@ class GlobalValue:
|
||||||
isDeclaration = Method(cast(Bool, bool))
|
isDeclaration = Method(cast(Bool, bool))
|
||||||
removeFromParent = Method()
|
removeFromParent = Method()
|
||||||
eraseFromParent = Method()
|
eraseFromParent = Method()
|
||||||
|
eraseFromParent.disowning = True
|
||||||
|
|
||||||
getParent = Method(ptr(Module))
|
getParent = Method(ptr(Module))
|
||||||
|
|
|
||||||
|
|
@ -45,5 +45,5 @@ class GlobalVariable:
|
||||||
# isExternallyInitialized = Method(cast(Bool, bool))
|
# isExternallyInitialized = Method(cast(Bool, bool))
|
||||||
# setExternallyinitialized = Method(Void, cast(bool, Bool))
|
# setExternallyinitialized = Method(Void, cast(bool, Bool))
|
||||||
|
|
||||||
eraseFromParent = Method()
|
|
||||||
|
|
||||||
17
newbinding/src/Intrinsics.py
Normal file
17
newbinding/src/Intrinsics.py
Normal 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)
|
||||||
|
|
@ -319,6 +319,16 @@ def test_constants():
|
||||||
aryconst = api.ConstantArray.get(ary_int32x4, [intconst] * 4)
|
aryconst = api.ConstantArray.get(ary_int32x4, [intconst] * 4)
|
||||||
assert str(aryconst.getAggregateElement(0)) == str(intconst)
|
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():
|
def main():
|
||||||
for name, value in globals().items():
|
for name, value in globals().items():
|
||||||
if name.startswith('test_') and callable(value):
|
if name.startswith('test_') and callable(value):
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue