Commit 10e71628 authored by Robert Bradshaw's avatar Robert Bradshaw

Overflow initialization checking

also adds error checking for init utility code blocks
parent e8bb8ff0
...@@ -68,10 +68,18 @@ class UtilityCodeBase(object): ...@@ -68,10 +68,18 @@ class UtilityCodeBase(object):
Code sections in the file can be specified as follows: Code sections in the file can be specified as follows:
##### MyUtility.proto ##### ##### MyUtility.proto #####
[proto declarations]
##### MyUtility.init #####
[code run at module initialization]
##### MyUtility ##### ##### MyUtility #####
#@requires: MyOtherUtility #@requires: MyOtherUtility
#@substitute: naming #@substitute: naming
[definitions]
for prototypes and implementation respectively. For non-python or for prototypes and implementation respectively. For non-python or
-cython files backslashes should be used instead. 5 to 30 comment -cython files backslashes should be used instead. 5 to 30 comment
...@@ -374,10 +382,13 @@ class UtilityCode(UtilityCodeBase): ...@@ -374,10 +382,13 @@ class UtilityCode(UtilityCodeBase):
output['utility_code_def'].put(self.format_code(self.impl)) output['utility_code_def'].put(self.format_code(self.impl))
if self.init: if self.init:
writer = output['init_globals'] writer = output['init_globals']
writer.putln("/* %s.init */" % self.name)
if isinstance(self.init, basestring): if isinstance(self.init, basestring):
writer.put(self.format_code(self.init)) writer.put(self.format_code(self.init))
else: else:
self.init(writer, output.module_pos) self.init(writer, output.module_pos)
writer.putln(writer.error_goto_if_PyErr(output.module_pos))
writer.putln()
if self.cleanup and Options.generate_cleanup_code: if self.cleanup and Options.generate_cleanup_code:
writer = output['cleanup_globals'] writer = output['cleanup_globals']
if isinstance(self.cleanup, basestring): if isinstance(self.cleanup, basestring):
...@@ -400,13 +411,14 @@ def sub_tempita(s, context, file=None, name=None): ...@@ -400,13 +411,14 @@ def sub_tempita(s, context, file=None, name=None):
return sub(s, **context) return sub(s, **context)
class TempitaUtilityCode(UtilityCode): class TempitaUtilityCode(UtilityCode):
def __init__(self, name=None, proto=None, impl=None, file=None, context=None, **kwargs): def __init__(self, name=None, proto=None, impl=None, init=None, file=None, context=None, **kwargs):
if context is None: if context is None:
context = {} context = {}
proto = sub_tempita(proto, context, file, name) proto = sub_tempita(proto, context, file, name)
impl = sub_tempita(impl, context, file, name) impl = sub_tempita(impl, context, file, name)
init = sub_tempita(init, context, file, name)
super(TempitaUtilityCode, self).__init__( super(TempitaUtilityCode, self).__init__(
proto, impl, name=name, file=file, **kwargs) proto, impl, init=init, name=name, file=file, **kwargs)
def none_or_sub(self, s, context): def none_or_sub(self, s, context):
""" """
......
...@@ -402,6 +402,15 @@ class CTypedefType(BaseType): ...@@ -402,6 +402,15 @@ class CTypedefType(BaseType):
# delegation # delegation
return self.typedef_base_type.create_from_py_utility_code(env) return self.typedef_base_type.create_from_py_utility_code(env)
def overflow_check_binop(self, binop, env):
env.use_utility_code(UtilityCode.load("Common", "Overflow.c"))
type = self.declaration_code("")
name = self.specialization_name()
_load_overflow_base(env)
env.use_utility_code(TempitaUtilityCode.load("SizeCheck", "Overflow.c", context={'TYPE': type, 'NAME': name}))
env.use_utility_code(TempitaUtilityCode.load("Binop", "Overflow.c", context={'TYPE': type, 'NAME': name, 'BINOP': binop}))
return "__Pyx_%s_%s_checking_overflow" % (binop, name)
def error_condition(self, result_code): def error_condition(self, result_code):
if self.typedef_is_external: if self.typedef_is_external:
if self.exception_value: if self.exception_value:
...@@ -1546,7 +1555,7 @@ class CIntType(CNumericType): ...@@ -1546,7 +1555,7 @@ class CIntType(CNumericType):
# We do not really know the size of the type, so return # We do not really know the size of the type, so return
# a 32-bit literal and rely on casting to final type. It will # a 32-bit literal and rely on casting to final type. It will
# be negative for signed ints, which is good. # be negative for signed ints, which is good.
return "0xbad0bad0"; return "0xbad0bad0"
def overflow_check_binop(self, binop, env): def overflow_check_binop(self, binop, env):
env.use_utility_code(UtilityCode.load("Common", "Overflow.c")) env.use_utility_code(UtilityCode.load("Common", "Overflow.c"))
...@@ -1561,6 +1570,7 @@ class CIntType(CNumericType): ...@@ -1561,6 +1570,7 @@ class CIntType(CNumericType):
return "__Pyx_%s_%s_no_overflow" % (binop, name) return "__Pyx_%s_%s_no_overflow" % (binop, name)
else: else:
_load_overflow_base(env) _load_overflow_base(env)
env.use_utility_code(TempitaUtilityCode.load("SizeCheck", "Overflow.c", context={'TYPE': type, 'NAME': name}))
env.use_utility_code(TempitaUtilityCode.load("Binop", "Overflow.c", context={'TYPE': type, 'NAME': name, 'BINOP': binop})) env.use_utility_code(TempitaUtilityCode.load("Binop", "Overflow.c", context={'TYPE': type, 'NAME': name, 'BINOP': binop}))
return "__Pyx_%s_%s_checking_overflow" % (binop, name) return "__Pyx_%s_%s_checking_overflow" % (binop, name)
......
...@@ -46,7 +46,9 @@ static int __Pyx_check_twos_complement() { ...@@ -46,7 +46,9 @@ static int __Pyx_check_twos_complement() {
#define __Pyx_div_no_overflow(a, b, overflow) ((a) / (b)) #define __Pyx_div_no_overflow(a, b, overflow) ((a) / (b))
#define __Pyx_div_const_no_overflow(a, b, overflow) ((a) / (b)) #define __Pyx_div_const_no_overflow(a, b, overflow) ((a) / (b))
/////////////// Common.init ///////////////
__Pyx_check_twos_complement();
/////////////// BaseCaseUnsigned.proto /////////////// /////////////// BaseCaseUnsigned.proto ///////////////
...@@ -217,10 +219,14 @@ static CYTHON_INLINE {{INT}} __Pyx_div_{{NAME}}_checking_overflow({{INT}} a, {{I ...@@ -217,10 +219,14 @@ static CYTHON_INLINE {{INT}} __Pyx_div_{{NAME}}_checking_overflow({{INT}} a, {{I
} }
/////////////// SizeCheck.init ///////////////
__Pyx_check_sane_{{NAME}}();
/////////////// SizeCheck.proto /////////////// /////////////// SizeCheck.proto ///////////////
static int __Pyx_check_sane_{{TYPE}}() { static int __Pyx_check_sane_{{NAME}}() {
if (sizeof({{TYPE}}) == sizeof(int) || if (sizeof({{TYPE}}) <= sizeof(int) ||
sizeof({{TYPE}}) == sizeof(long) || sizeof({{TYPE}}) == sizeof(long) ||
sizeof({{TYPE}}) == sizeof(long long)) { sizeof({{TYPE}}) == sizeof(long long)) {
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment