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):
|
||||
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:
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -44,4 +44,6 @@ class GlobalValue:
|
|||
isDeclaration = Method(cast(Bool, bool))
|
||||
removeFromParent = Method()
|
||||
eraseFromParent = Method()
|
||||
eraseFromParent.disowning = True
|
||||
|
||||
getParent = Method(ptr(Module))
|
||||
|
|
|
|||
|
|
@ -45,5 +45,5 @@ class GlobalVariable:
|
|||
# isExternallyInitialized = Method(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)
|
||||
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):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue