Fix cbuilder CDefinition specialization design and magic
This commit is contained in:
parent
87a44e3117
commit
bd377de198
1 changed files with 39 additions and 41 deletions
80
builder.py
80
builder.py
|
|
@ -709,24 +709,6 @@ class CBuilder(object):
|
||||||
md = lc.MetaData.get(self.function.module, [const_one])
|
md = lc.MetaData.get(self.function.module, [const_one])
|
||||||
ldst.set_metadata('nontemporal', md)
|
ldst.set_metadata('nontemporal', md)
|
||||||
|
|
||||||
class _DeclareCDef(object):
|
|
||||||
'''create a function a CDefinition to use with `CBuilder.depends`
|
|
||||||
|
|
||||||
An instance of this class is created by the constructor of CDefinition.
|
|
||||||
Do not use directly.
|
|
||||||
'''
|
|
||||||
def __init__(self, cdef):
|
|
||||||
self.cdef = cdef
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.cdef._name_
|
|
||||||
|
|
||||||
def __call__(self, module):
|
|
||||||
try:
|
|
||||||
func = self.cdef.define(module)
|
|
||||||
except FunctionAlreadyExists as e:
|
|
||||||
(func,) = e
|
|
||||||
return func
|
|
||||||
|
|
||||||
class CFuncRef(object):
|
class CFuncRef(object):
|
||||||
'''create a function reference to use with `CBuilder.depends`
|
'''create a function reference to use with `CBuilder.depends`
|
||||||
|
|
@ -766,7 +748,8 @@ class CFuncRef(object):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self._name
|
return self._name
|
||||||
|
|
||||||
class CDefinition(CBuilder):
|
|
||||||
|
class CDefinition(object):
|
||||||
'''represents function definition
|
'''represents function definition
|
||||||
|
|
||||||
Inherit from this class to create a new function definition.
|
Inherit from this class to create a new function definition.
|
||||||
|
|
@ -782,31 +765,33 @@ class CDefinition(CBuilder):
|
||||||
_retty_ = types.void # return type; can overide in subclass
|
_retty_ = types.void # return type; can overide in subclass
|
||||||
_argtys_ = [] # a list of tuple(name, type, [attributes]); can overide in subclass
|
_argtys_ = [] # a list of tuple(name, type, [attributes]); can overide in subclass
|
||||||
|
|
||||||
def __new__(cls, *args, **kws):
|
def __init__(self, *args, **kwargs):
|
||||||
if cls.is_generic():
|
self.specialize(*args, **kwargs)
|
||||||
# Call specialize if it is defined.
|
self.cbuilder = None
|
||||||
cls = type('%s_Specialized' % cls.__name__, (cls,), {})
|
|
||||||
cls.specialize(*args, **kws)
|
|
||||||
|
|
||||||
obj = object.__new__(_DeclareCDef)
|
def specialize(self, *args, **kwargs):
|
||||||
obj.__init__(cls)
|
"""
|
||||||
return obj
|
Override in subclasses
|
||||||
|
"""
|
||||||
|
|
||||||
@classmethod
|
def specialize_name(self):
|
||||||
def is_generic(cls):
|
"""
|
||||||
'''Is this a generic definition?
|
Specialize the class name to enable multiple function definitions
|
||||||
'''
|
"""
|
||||||
return hasattr(cls, 'specialize')
|
cls = type(self)
|
||||||
|
|
||||||
@classmethod
|
counter = getattr(cls, 'counter', 0)
|
||||||
def define(cls, module):
|
cls._name_ = "%s_%d" % (cls._name_, counter)
|
||||||
|
cls.counter = counter + 1
|
||||||
|
|
||||||
|
def define(self, module):
|
||||||
'''define the function in the module.
|
'''define the function in the module.
|
||||||
|
|
||||||
Raises NameError if a function of the same name has already been
|
Raises NameError if a function of the same name has already been
|
||||||
defined.
|
defined.
|
||||||
'''
|
'''
|
||||||
functype = lc.Type.function(cls._retty_, [arg[1] for arg in cls._argtys_])
|
functype = lc.Type.function(self._retty_, [arg[1] for arg in self._argtys_])
|
||||||
name = cls._name_
|
name = self._name_
|
||||||
if not name:
|
if not name:
|
||||||
raise AttributeError("Function name cannot be empty.")
|
raise AttributeError("Function name cannot be empty.")
|
||||||
|
|
||||||
|
|
@ -816,17 +801,17 @@ class CDefinition(CBuilder):
|
||||||
raise FunctionAlreadyExists(func)
|
raise FunctionAlreadyExists(func)
|
||||||
|
|
||||||
# Name all arguments
|
# Name all arguments
|
||||||
for i, arginfo in enumerate(cls._argtys_):
|
for i, arginfo in enumerate(self._argtys_):
|
||||||
name = arginfo[0]
|
name = arginfo[0]
|
||||||
func.args[i].name = name
|
func.args[i].name = name
|
||||||
if len(arginfo) > 2:
|
if len(arginfo) > 2:
|
||||||
for attr in arginfo[2]:
|
for attr in arginfo[2]:
|
||||||
func.args[i].add_attribute(attr)
|
func.args[i].add_attribute(attr)
|
||||||
|
|
||||||
# Create builder and populate body
|
# Create builder and populate body
|
||||||
cbuilder = object.__new__(cls)
|
self.cbuilder = CBuilder(func)
|
||||||
cbuilder.__init__(func)
|
self.body(*self.cbuilder.args)
|
||||||
cbuilder.body(*cbuilder.args)
|
self.cbuilder.close()
|
||||||
cbuilder.close()
|
|
||||||
|
|
||||||
# optimize
|
# optimize
|
||||||
fpm = lp.FunctionPassManager.new(module)
|
fpm = lp.FunctionPassManager.new(module)
|
||||||
|
|
@ -837,11 +822,24 @@ class CDefinition(CBuilder):
|
||||||
fpm.run(func)
|
fpm.run(func)
|
||||||
return func
|
return func
|
||||||
|
|
||||||
|
def __call__(self, module):
|
||||||
|
# We don't really have to overload __call__ to do things like
|
||||||
|
# defining functions...
|
||||||
|
try:
|
||||||
|
func = self.define(module)
|
||||||
|
except FunctionAlreadyExists as e:
|
||||||
|
(func,) = e
|
||||||
|
return func
|
||||||
|
|
||||||
|
def __getattr__(self, attr):
|
||||||
|
return getattr(self.cbuilder, attr)
|
||||||
|
|
||||||
def body(self):
|
def body(self):
|
||||||
'''overide this function to define the body.
|
'''overide this function to define the body.
|
||||||
'''
|
'''
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
class CValue(object):
|
class CValue(object):
|
||||||
def __init__(self, parent, handle):
|
def __init__(self, parent, handle):
|
||||||
self.__parent = parent
|
self.__parent = parent
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue