Commit bdf1058f authored by Dag Sverre Seljebotn's avatar Dag Sverre Seljebotn

Buffer bounds checking can be turned off via compilation options

--HG--
rename : tests/run/options.pyx => tests/compile/c_options.pyx
parent c19b1ad4
...@@ -235,7 +235,7 @@ def put_assign_to_buffer(lhs_cname, rhs_cname, buffer_aux, buffer_type, ...@@ -235,7 +235,7 @@ def put_assign_to_buffer(lhs_cname, rhs_cname, buffer_aux, buffer_type,
code.putln('}') code.putln('}')
def put_access(entry, index_signeds, index_cnames, pos, code): def put_access(entry, index_signeds, index_cnames, options, pos, code):
"""Returns a c string which can be used to access the buffer """Returns a c string which can be used to access the buffer
for reading or writing. for reading or writing.
...@@ -244,46 +244,43 @@ def put_access(entry, index_signeds, index_cnames, pos, code): ...@@ -244,46 +244,43 @@ def put_access(entry, index_signeds, index_cnames, pos, code):
body. The lookup however is delegated to a inline function that is instantiated body. The lookup however is delegated to a inline function that is instantiated
once per ndim (lookup with suboffsets tend to get quite complicated). once per ndim (lookup with suboffsets tend to get quite complicated).
""" """
code.globalstate.use_utility_code(access_utility_code)
bufaux = entry.buffer_aux bufaux = entry.buffer_aux
bufstruct = bufaux.buffer_info_var.cname bufstruct = bufaux.buffer_info_var.cname
# Check bounds and fix negative indices
boundscheck = True
nonegs = True
tmp_cname = code.funcstate.allocate_temp(PyrexTypes.c_int_type)
if boundscheck: if options['boundscheck']:
# Check bounds and fix negative indices.
# We allocate a temporary which is initialized to -1, meaning OK (!).
# If an error occurs, the temp is set to the dimension index the
# error is occuring at.
tmp_cname = code.funcstate.allocate_temp(PyrexTypes.c_int_type)
code.putln("%s = -1;" % tmp_cname) code.putln("%s = -1;" % tmp_cname)
for idx, (signed, cname, shape) in enumerate(zip(index_signeds, index_cnames, for dim, (signed, cname, shape) in enumerate(zip(index_signeds, index_cnames,
bufaux.shapevars)): bufaux.shapevars)):
if signed != 0: if signed != 0:
nonegs = False # not unsigned, deal with negative index
# not unsigned, deal with negative index code.putln("if (%s < 0) {" % cname)
code.putln("if (%s < 0) {" % cname) code.putln("%s += %s;" % (cname, shape.cname))
code.putln("%s += %s;" % (cname, shape.cname))
if boundscheck:
code.putln("if (%s) %s = %d;" % ( code.putln("if (%s) %s = %d;" % (
code.unlikely("%s < 0" % cname), tmp_cname, idx)) code.unlikely("%s < 0" % cname), tmp_cname, dim))
code.put("} else ") code.put("} else ")
else:
if idx > 0: code.put("else ")
if boundscheck:
# check bounds in positive direction # check bounds in positive direction
code.putln("if (%s) %s = %d;" % ( code.putln("if (%s) %s = %d;" % (
code.unlikely("%s >= %s" % (cname, shape.cname)), code.unlikely("%s >= %s" % (cname, shape.cname)),
tmp_cname, idx)) tmp_cname, dim))
if boundscheck: code.globalstate.use_utility_code(raise_indexerror_code)
code.put("if (%s) " % code.unlikely("%s != -1" % tmp_cname)) code.put("if (%s) " % code.unlikely("%s != -1" % tmp_cname))
code.begin_block() code.begin_block()
code.putln('__Pyx_BufferIndexError(%s);' % tmp_cname) code.putln('__Pyx_RaiseBufferIndexError(%s);' % tmp_cname)
code.putln(code.error_goto(pos)) code.putln(code.error_goto(pos))
code.end_block() code.end_block()
code.funcstate.release_temp(tmp_cname) code.funcstate.release_temp(tmp_cname)
else:
# Only fix negative indices.
for signed, cname, shape in zip(index_signeds, index_cnames,
bufaux.shapevars):
if signed != 0:
code.putln("if (%s < 0) %s += %s;" % (cname, cname, shape.cname))
# Create buffer lookup and return it # Create buffer lookup and return it
params = [] params = []
nd = entry.type.ndim nd = entry.type.ndim
...@@ -536,11 +533,11 @@ def use_py2_buffer_functions(env): ...@@ -536,11 +533,11 @@ def use_py2_buffer_functions(env):
# Utility function to set the right exception # Utility function to set the right exception
# The caller should immediately goto_error # The caller should immediately goto_error
access_utility_code = [ raise_indexerror_code = [
"""\ """\
static void __Pyx_BufferIndexError(int axis); /*proto*/ static void __Pyx_RaiseBufferIndexError(int axis); /*proto*/
""","""\ ""","""\
static void __Pyx_BufferIndexError(int axis) { static void __Pyx_RaiseBufferIndexError(int axis) {
PyErr_Format(PyExc_IndexError, PyErr_Format(PyExc_IndexError,
"Out of bounds on buffer access (axis %d)", axis); "Out of bounds on buffer access (axis %d)", axis);
} }
......
...@@ -104,7 +104,7 @@ def report_error(err): ...@@ -104,7 +104,7 @@ def report_error(err):
def error(position, message): def error(position, message):
#print "Errors.error:", repr(position), repr(message) ### #print "Errors.error:", repr(position), repr(message) ###
err = CompileError(position, message) err = CompileError(position, message)
# if position is not None: raise Exception(err) # debug #if position is not None: raise Exception(err) # debug
report_error(err) report_error(err)
return err return err
......
...@@ -1525,7 +1525,6 @@ class IndexNode(ExprNode): ...@@ -1525,7 +1525,6 @@ class IndexNode(ExprNode):
self.generate_subexpr_disposal_code(code) self.generate_subexpr_disposal_code(code)
def buffer_access_code(self, code): def buffer_access_code(self, code):
print self.options
# Assign indices to temps # Assign indices to temps
index_temps = [code.funcstate.allocate_temp(i.type) for i in self.indices] index_temps = [code.funcstate.allocate_temp(i.type) for i in self.indices]
for temp, index in zip(index_temps, self.indices): for temp, index in zip(index_temps, self.indices):
...@@ -1535,7 +1534,9 @@ class IndexNode(ExprNode): ...@@ -1535,7 +1534,9 @@ class IndexNode(ExprNode):
valuecode = Buffer.put_access(entry=self.base.entry, valuecode = Buffer.put_access(entry=self.base.entry,
index_signeds=[i.type.signed for i in self.indices], index_signeds=[i.type.signed for i in self.indices],
index_cnames=index_temps, index_cnames=index_temps,
options=self.options,
pos=self.pos, code=code) pos=self.pos, code=code)
return valuecode return valuecode
......
#cython: boundscheck=False #cython: boundscheck=False
print 3
def f(object[int, 2] buf): def f(object[int, 2] buf):
print buf[3, 2] print buf[3, 2]
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