Try to fix invalid dtor call

This commit is contained in:
Siu Kwan Lam 2013-02-13 17:12:54 -06:00
commit d2dc34cdd3
6 changed files with 108 additions and 67 deletions

View file

@ -475,28 +475,31 @@ class Module(llvm.Wrapper):
def add_function(self, ty, name): def add_function(self, ty, name):
"""Add a function of given type with given name.""" """Add a function of given type with given name."""
fn = self.get_function_named(name) return Function.new(self, ty, name)
if fn is not None: # fn = self.get_function_named(name)
raise llvm.LLVMException("Duplicated function %s" % name) # if fn is not None:
return self.get_or_insert_function(ty, name) # raise llvm.LLVMException("Duplicated function %s" % name)
# return self.get_or_insert_function(ty, name)
def get_function_named(self, name): def get_function_named(self, name):
"""Return a Function object representing function with given name.""" """Return a Function object representing function with given name."""
fn = self._ptr.getFunction(name) return Function.get(self, name)
if fn is not None: # fn = self._ptr.getFunction(name)
return _make_value(fn) # if fn is not None:
# return _make_value(fn)
def get_or_insert_function(self, ty, name): def get_or_insert_function(self, ty, name):
"""Like get_function_named(), but does add_function() first, if """Like get_function_named(), but does add_function() first, if
function is not present.""" function is not present."""
constant = self._ptr.getOrInsertFunction(name, ty._ptr) return Function.get_or_insert(self, ty, name)
try: # constant = self._ptr.getOrInsertFunction(name, ty._ptr)
fn = constant._downcast(api.llvm.Function) # try:
except ValueError: # fn = constant._downcast(api.llvm.Function)
# bitcasted to function type # except ValueError:
return _make_value(constant) # # bitcasted to function type
else: # return _make_value(constant)
return _make_value(fn) # else:
# return _make_value(fn)
@property @property
def functions(self): def functions(self):
@ -616,6 +619,10 @@ class Type(llvm.Wrapper):
ptr = ptr._downcast(type(self)._type_) ptr = ptr._downcast(type(self)._type_)
super(Type, self).__init__(ptr) super(Type, self).__init__(ptr)
@property
def kind(self):
return self._ptr.getTypeID()
@staticmethod @staticmethod
def int(bits=32): def int(bits=32):
"""Create an integer type having the given bit width.""" """Create an integer type having the given bit width."""
@ -830,7 +837,6 @@ class FunctionType(Type):
return self._ptr.getNumParams() return self._ptr.getNumParams()
class StructType(Type): class StructType(Type):
"""Represents a structure type.""" """Represents a structure type."""
_type_ = api.llvm.StructType _type_ = api.llvm.StructType
@ -1385,15 +1391,32 @@ class Function(GlobalValue):
@staticmethod @staticmethod
def new(module, func_ty, name): def new(module, func_ty, name):
return module.add_function(func_ty, name) try:
fn = Function.get(module, name)
except llvm.LLVMException:
return Function.get_or_insert(module, func_ty, name)
else:
raise llvm.LLVMException("Duplicated function %s" % name)
@staticmethod @staticmethod
def get_or_insert(module, func_ty, name): def get_or_insert(module, func_ty, name):
return module.get_or_insert_function(func_ty, name) constant = module._ptr.getOrInsertFunction(name, func_ty._ptr)
try:
fn = constant._downcast(api.llvm.Function)
except ValueError:
# bitcasted to function type
return _make_value(constant)
else:
return _make_value(fn)
@staticmethod @staticmethod
def get(module, name): def get(module, name):
return module.get_function_named(name) fn = module._ptr.getFunction(name)
if fn is None:
raise llvm.LLVMException("no function named `%s`" % name)
else:
return _make_value(fn)
@staticmethod @staticmethod
def intrinsic(module, intrinsic_id, types): def intrinsic(module, intrinsic_id, types):
@ -1450,6 +1473,10 @@ class Function(GlobalValue):
assert self.basic_block_count assert self.basic_block_count
return _make_value(self._ptr.getEntryBlock()) return _make_value(self._ptr.getEntryBlock())
def get_entry_basic_block(self):
"Deprecated. Use entry_basic_block instead"
return self.entry_basic_block
def append_basic_block(self, name): def append_basic_block(self, name):
context = api.llvm.getGlobalContext() context = api.llvm.getGlobalContext()
bb = api.llvm.BasicBlock.Create(context, name, self._ptr, None) bb = api.llvm.BasicBlock.Create(context, name, self._ptr, None)
@ -1857,6 +1884,7 @@ class Builder(llvm.Wrapper):
"""Position the builder at the end of the given block. """Position the builder at the end of the given block.
Next instruction inserted will be last one in the block.""" Next instruction inserted will be last one in the block."""
self._ptr.SetInsertPoint(bblk._ptr) self._ptr.SetInsertPoint(bblk._ptr)
def position_before(self, instr): def position_before(self, instr):
@ -2111,9 +2139,9 @@ class Builder(llvm.Wrapper):
def insert_value(self, retval, rhs, idx, name=""): def insert_value(self, retval, rhs, idx, name=""):
return _make_value(self._ptr.CreateInsertValue(retval._ptr, return _make_value(self._ptr.CreateInsertValue(retval._ptr,
rhs._ptr, rhs._ptr,
[idx], [idx],
name)) name))
def phi(self, ty, name=""): def phi(self, ty, name=""):
return _make_value(self._ptr.CreatePHI(ty._ptr, 2, name)) return _make_value(self._ptr.CreatePHI(ty._ptr, 2, name))

View file

@ -19,13 +19,14 @@ def set_debug(enabled):
def _capsule_weakref_dtor(item): def _capsule_weakref_dtor(item):
addr = item.pointer addr = item.pointer
name = item.name
_addr2refct[addr] -= 1 _addr2refct[addr] -= 1
refct = _addr2refct[addr] refct = _addr2refct[addr]
assert refct >= 0, "RefCt drop below 0" assert refct >= 0, "RefCt drop below 0"
if refct == 0: if refct == 0:
dtor = _addr2dtor.pop(addr, None) dtor = _addr2dtor.pop((name, addr), None)
if dtor is not None: if dtor is not None:
logger.debug('Destroy %s %s', item.name, hex(item.pointer)) logger.debug('Destroy %s %s', name, hex(addr))
dtor(item.capsule) dtor(item.capsule)
class Capsule(object): class Capsule(object):
@ -92,26 +93,28 @@ _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)
name = Capsule.getName(old)
if _addr2dtor.get(addr) is None: if _addr2dtor.get((name, addr)) is None:
clsname = Capsule.getClassName(old) clsname = Capsule.getClassName(old)
if not _pyclasses[clsname]._has_dtor(): if not _pyclasses[clsname]._has_dtor():
return return
# Guard duplicated release # Guard duplicated release
raise Exception("Already released") raise Exception("Already released")
_addr2dtor[addr] = None _addr2dtor[(name, addr)] = None
def obtain_ownership(cap): def obtain_ownership(cap):
cls = cap.get_class() cls = cap.get_class()
if cls._has_dtor(): if cls._has_dtor():
addr = cap.pointer addr = cap.pointer
name = cap.name
assert _addr2dtor[addr] is None assert _addr2dtor[addr] is None
_addr2dtor[addr] = cls._delete_ _addr2dtor[(name, addr)] = cls._delete_
def has_ownership(cap): def has_ownership(cap):
addr = Capsule.getPointer(cap) addr = Capsule.getPointer(cap)
return _addr2dtor.get(addr) is not None name = Capsule.getName(cap)
return _addr2dtor.get((name, addr)) is not None
def wrap(cap, owned=False): def wrap(cap, owned=False):
'''Wrap a PyCapsule with the corresponding Wrapper class. '''Wrap a PyCapsule with the corresponding Wrapper class.
@ -125,11 +128,12 @@ def wrap(cap, owned=False):
cap = Capsule(cap) cap = Capsule(cap)
cls = cap.get_class() cls = cap.get_class()
addr = cap.pointer addr = cap.pointer
name = cap.name
try: # lookup cached object try: # lookup cached object
return _cache[cls][addr] return _cache[cls][addr]
except KeyError: except KeyError:
if not owned and cls._has_dtor(): if not owned and cls._has_dtor():
_addr2dtor[addr] = cls._delete_ _addr2dtor[(name, addr)] = cls._delete_
obj = cap.instantiate() obj = cap.instantiate()
_cache[cls][addr] = obj # cache it _cache[cls][addr] = obj # cache it
return obj return obj

View file

@ -329,7 +329,7 @@ class Class(SubModule, _Type):
fmt = 'PyCapsule_GetPointer(%(val)s, "%(name)s")' fmt = 'PyCapsule_GetPointer(%(val)s, "%(name)s")'
name = self.capsule_name name = self.capsule_name
raw = writer.declare('void*', fmt % locals()) raw = writer.declare('void*', fmt % locals())
writer.die_if_false(raw) writer.die_if_false(raw, verbose=name)
ptrty = ptr(self).fullname ptrty = ptr(self).fullname
ty = self.fullname ty = self.fullname
fmt = 'typecast< %(ty)s >::from(%(raw)s)' fmt = 'typecast< %(ty)s >::from(%(raw)s)'

View file

@ -208,8 +208,10 @@ class CppCodeWriter(CodeWriterBase):
self.return_null() self.return_null()
return ret return ret
def die_if_false(self, val): def die_if_false(self, val, verbose=None):
with self.block('if(!%(val)s)' % locals()): with self.block('if(!%(val)s)' % locals()):
if verbose:
self.println('puts("Error: %s");' % verbose)
self.return_null() self.return_null()
def raises(self, exccls, msg): def raises(self, exccls, msg):

View file

@ -294,7 +294,7 @@ class IRBuilder:
_CreateInsertValue.realname = 'CreateInsertValue' _CreateInsertValue.realname = 'CreateInsertValue'
@CustomPythonMethod @CustomPythonMethod
def CreateInsertValue(self, args): def CreateInsertValue(self, *args):
from llvmpy import extra from llvmpy import extra
args = list(args) args = list(args)
valuelist = args[2] valuelist = args[2]

View file

@ -120,16 +120,17 @@ class Instruction:
@AtomicCmpXchgInst @AtomicCmpXchgInst
class AtomicCmpXchgInst: class AtomicCmpXchgInst:
pass _downcast_ = Value, Instruction
@AtomicRMWInst @AtomicRMWInst
class AtomicRMWInst: class AtomicRMWInst:
_downcast_ = Value, Instruction
BinOp = Enum('Xchg', 'Add', 'Sub', 'And', 'Nand', 'Or', 'Xor', 'Max', 'Min', BinOp = Enum('Xchg', 'Add', 'Sub', 'And', 'Nand', 'Or', 'Xor', 'Max', 'Min',
'UMax', 'UMin', 'FIRST_BINOP', 'LAST_BINOP', 'BAD_BINOP') 'UMax', 'UMin', 'FIRST_BINOP', 'LAST_BINOP', 'BAD_BINOP')
@BinaryOperator @BinaryOperator
class BinaryOperator: class BinaryOperator:
pass _downcast_ = Value, Instruction
@CallInst @CallInst
class CallInst: class CallInst:
@ -159,6 +160,7 @@ class CallInst:
@CmpInst @CmpInst
class CmpInst: class CmpInst:
_downcast_ = Value, Instruction
Predicate = Enum('FCMP_FALSE', 'FCMP_OEQ', 'FCMP_OGT', 'FCMP_OGE', Predicate = Enum('FCMP_FALSE', 'FCMP_OEQ', 'FCMP_OGT', 'FCMP_OGE',
'FCMP_OLT', 'FCMP_OLE', 'FCMP_ONE', 'FCMP_ORD', 'FCMP_UNO', 'FCMP_OLT', 'FCMP_OLE', 'FCMP_ONE', 'FCMP_ORD', 'FCMP_UNO',
'FCMP_UEQ', 'FCMP_UGT', 'FCMP_UGE', 'FCMP_ULT', 'FCMP_ULE', 'FCMP_UEQ', 'FCMP_UGT', 'FCMP_UGE', 'FCMP_ULT', 'FCMP_ULE',
@ -175,30 +177,31 @@ class CmpInst:
@ExtractElementInst @ExtractElementInst
class ExtractElementInst: class ExtractElementInst:
pass _downcast_ = Value, Instruction
@FenceInst @FenceInst
class FenceInst: class FenceInst:
pass _downcast_ = Value, Instruction
@GetElementPtrInst @GetElementPtrInst
class GetElementPtrInst: class GetElementPtrInst:
pass _downcast_ = Value, Instruction
@InsertElementInst @InsertElementInst
class InsertElementInst: class InsertElementInst:
pass _downcast_ = Value, Instruction
@InsertValueInst @InsertValueInst
class InsertValueInst: class InsertValueInst:
pass _downcast_ = Value, Instruction
@LandingPadInst @LandingPadInst
class LandingPadInst: class LandingPadInst:
pass _downcast_ = Value, Instruction
@PHINode @PHINode
class PHINode: class PHINode:
_downcast_ = Value, Instruction
getNumIncomingValues = Method(cast(Unsigned, int)) getNumIncomingValues = Method(cast(Unsigned, int))
getIncomingValue = Method(ptr(Value), cast(int, Unsigned)) getIncomingValue = Method(ptr(Value), cast(int, Unsigned))
setIncomingValue = Method(Void, cast(int, Unsigned), ptr(Value)) setIncomingValue = Method(Void, cast(int, Unsigned), ptr(Value))
@ -210,15 +213,15 @@ class PHINode:
@SelectInst @SelectInst
class SelectInst: class SelectInst:
pass _downcast_ = Value, Instruction
@ShuffleVectorInst @ShuffleVectorInst
class ShuffleVectorInst: class ShuffleVectorInst:
pass _downcast_ = Value, Instruction
@StoreInst @StoreInst
class StoreInst: class StoreInst:
_downcast_ = Instruction _downcast_ = Value, Instruction
isVolatile = Method(cast(Bool, bool)) isVolatile = Method(cast(Bool, bool))
isSimple = Method(cast(Bool, bool)) isSimple = Method(cast(Bool, bool))
isUnordered = Method(cast(Bool, bool)) isUnordered = Method(cast(Bool, bool))
@ -237,38 +240,40 @@ class StoreInst:
@TerminatorInst @TerminatorInst
class TerminatorInst: class TerminatorInst:
_downcast_ = Value, Instruction
getNumSuccessors = Method(cast(Unsigned, int)) getNumSuccessors = Method(cast(Unsigned, int))
getSuccessor = Method(ptr(BasicBlock), cast(int, Unsigned)) getSuccessor = Method(ptr(BasicBlock), cast(int, Unsigned))
setSuccessor = Method(Void, cast(int, Unsigned), ptr(BasicBlock)) setSuccessor = Method(Void, cast(int, Unsigned), ptr(BasicBlock))
@UnaryInstruction @UnaryInstruction
class UnaryInstruction: class UnaryInstruction:
pass _downcast_ = Value, Instruction
#call #call
@IntrinsicInst @IntrinsicInst
class IntrinsicInst: class IntrinsicInst:
pass _include_ = 'llvm/IntrinsicInst.h'
_downcast_ = Value, Instruction
#compare #compare
@FCmpInst @FCmpInst
class FCmpInst: class FCmpInst:
pass _downcast_ = Value, Instruction
@ICmpInst @ICmpInst
class ICmpInst: class ICmpInst:
pass _downcast_ = Value, Instruction
# terminator # terminator
@BranchInst @BranchInst
class BranchInst: class BranchInst:
pass _downcast_ = Value, Instruction
@IndirectBrInst @IndirectBrInst
class IndirectBrInst: class IndirectBrInst:
pass _downcast_ = Value, Instruction
@InvokeInst @InvokeInst
class InvokeInst: class InvokeInst:
@ -284,14 +289,16 @@ class InvokeInst:
@ResumeInst @ResumeInst
class ResumeInst: class ResumeInst:
pass _downcast_ = Value, Instruction
@ReturnInst @ReturnInst
class ReturnInst: class ReturnInst:
pass _downcast_ = Value, Instruction
@SwitchInst @SwitchInst
class SwitchInst: class SwitchInst:
_downcast_ = Value, Instruction
getCondition = Method(ptr(Value)) getCondition = Method(ptr(Value))
setCondition = Method(Void, ptr(Value)) setCondition = Method(Void, ptr(Value))
getDefaultDest = Method(ptr(BasicBlock)) getDefaultDest = Method(ptr(BasicBlock))
@ -302,20 +309,20 @@ class SwitchInst:
@UnreachableInst @UnreachableInst
class UnreachableInst: class UnreachableInst:
pass _downcast_ = Value, Instruction
# unary # unary
@AllocaInst @AllocaInst
class AllocaInst: class AllocaInst:
pass _downcast_ = Value, Instruction
@CastInst @CastInst
class CastInst: class CastInst:
pass _downcast_ = Value, Instruction
@ExtractValueInst @ExtractValueInst
class ExtractValueInst: class ExtractValueInst:
pass _downcast_ = Value, Instruction
@LoadInst @LoadInst
class LoadInst: class LoadInst:
@ -338,46 +345,46 @@ class LoadInst:
@VAArgInst @VAArgInst
class VAArgInst: class VAArgInst:
pass _downcast_ = Value, Instruction
# intrinsic # intrinsic
@DbgInfoIntrinsic @DbgInfoIntrinsic
class DbgInfoIntrinsic: class DbgInfoIntrinsic:
pass _downcast_ = Value, Instruction
@MemIntrinsic @MemIntrinsic
class MemIntrinsic: class MemIntrinsic:
pass _downcast_ = Value, Instruction
@VACopyInst @VACopyInst
class VACopyInst: class VACopyInst:
pass _downcast_ = Value, Instruction
@VAEndInst @VAEndInst
class VAEndInst: class VAEndInst:
pass _downcast_ = Value, Instruction
@VAStartInst @VAStartInst
class VAStartInst: class VAStartInst:
pass _downcast_ = Value, Instruction
@BitCastInst @BitCastInst
class BitCastInst: class BitCastInst:
pass _downcast_ = Value, Instruction
@FPExtInst @FPExtInst
class FPExtInst: class FPExtInst:
pass _downcast_ = Value, Instruction
@FPToSIInst @FPToSIInst
class FPToSIInst: class FPToSIInst:
pass _downcast_ = Value, Instruction
@FPToUIInst @FPToUIInst
class FPToUIInst: class FPToUIInst:
pass _downcast_ = Value, Instruction
@FPTruncInst @FPTruncInst
class FPTruncInst: class FPTruncInst:
pass _downcast_ = Value, Instruction