From: Dag Sverre Seljebotn Date: Mon, 4 Aug 2008 13:58:26 +0000 (+0200) Subject: Buffer bounds checking can be turned off via compilation options X-Git-Tag: 0.9.8.1~49^2~22 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=bdf1058f41521de17597c06883bc6168439d83df;p=cython.git Buffer bounds checking can be turned off via compilation options --HG-- rename : tests/run/options.pyx => tests/compile/c_options.pyx --- diff --git a/Cython/Compiler/Buffer.py b/Cython/Compiler/Buffer.py index 85a07f24..6e591c97 100644 --- a/Cython/Compiler/Buffer.py +++ b/Cython/Compiler/Buffer.py @@ -235,7 +235,7 @@ def put_assign_to_buffer(lhs_cname, rhs_cname, buffer_aux, buffer_type, 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 for reading or writing. @@ -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 once per ndim (lookup with suboffsets tend to get quite complicated). """ - code.globalstate.use_utility_code(access_utility_code) bufaux = entry.buffer_aux 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) - for idx, (signed, cname, shape) in enumerate(zip(index_signeds, index_cnames, - bufaux.shapevars)): - if signed != 0: - nonegs = False - # not unsigned, deal with negative index - code.putln("if (%s < 0) {" % cname) - code.putln("%s += %s;" % (cname, shape.cname)) - if boundscheck: + for dim, (signed, cname, shape) in enumerate(zip(index_signeds, index_cnames, + bufaux.shapevars)): + if signed != 0: + # not unsigned, deal with negative index + code.putln("if (%s < 0) {" % cname) + code.putln("%s += %s;" % (cname, shape.cname)) code.putln("if (%s) %s = %d;" % ( - code.unlikely("%s < 0" % cname), tmp_cname, idx)) - code.put("} else ") - else: - if idx > 0: code.put("else ") - if boundscheck: + code.unlikely("%s < 0" % cname), tmp_cname, dim)) + code.put("} else ") # check bounds in positive direction code.putln("if (%s) %s = %d;" % ( code.unlikely("%s >= %s" % (cname, shape.cname)), - tmp_cname, idx)) - if boundscheck: + tmp_cname, dim)) + code.globalstate.use_utility_code(raise_indexerror_code) code.put("if (%s) " % code.unlikely("%s != -1" % tmp_cname)) code.begin_block() - code.putln('__Pyx_BufferIndexError(%s);' % tmp_cname) + code.putln('__Pyx_RaiseBufferIndexError(%s);' % tmp_cname) code.putln(code.error_goto(pos)) 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 params = [] nd = entry.type.ndim @@ -536,11 +533,11 @@ def use_py2_buffer_functions(env): # Utility function to set the right exception # 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, "Out of bounds on buffer access (axis %d)", axis); } diff --git a/Cython/Compiler/Errors.py b/Cython/Compiler/Errors.py index 57ce5334..a8ad03af 100644 --- a/Cython/Compiler/Errors.py +++ b/Cython/Compiler/Errors.py @@ -104,7 +104,7 @@ def report_error(err): def error(position, message): #print "Errors.error:", repr(position), repr(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) return err diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index 1da3f1e2..d72ee402 100644 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -1525,7 +1525,6 @@ class IndexNode(ExprNode): self.generate_subexpr_disposal_code(code) def buffer_access_code(self, code): - print self.options # Assign indices to temps index_temps = [code.funcstate.allocate_temp(i.type) for i in self.indices] for temp, index in zip(index_temps, self.indices): @@ -1535,7 +1534,9 @@ class IndexNode(ExprNode): valuecode = Buffer.put_access(entry=self.base.entry, index_signeds=[i.type.signed for i in self.indices], index_cnames=index_temps, + options=self.options, pos=self.pos, code=code) + return valuecode diff --git a/tests/run/options.pyx b/tests/compile/c_options.pyx similarity index 89% rename from tests/run/options.pyx rename to tests/compile/c_options.pyx index c56bb5d0..eda8a7dc 100644 --- a/tests/run/options.pyx +++ b/tests/compile/c_options.pyx @@ -1,4 +1,6 @@ #cython: boundscheck=False +print 3 + def f(object[int, 2] buf): print buf[3, 2]