Buffer bounds checking can be turned off via compilation options
authorDag Sverre Seljebotn <dagss@student.matnat.uio.no>
Mon, 4 Aug 2008 13:58:26 +0000 (15:58 +0200)
committerDag Sverre Seljebotn <dagss@student.matnat.uio.no>
Mon, 4 Aug 2008 13:58:26 +0000 (15:58 +0200)
--HG--
rename : tests/run/options.pyx => tests/compile/c_options.pyx

Cython/Compiler/Buffer.py
Cython/Compiler/Errors.py
Cython/Compiler/ExprNodes.py
tests/compile/c_options.pyx [moved from tests/run/options.pyx with 89% similarity]

index 85a07f24218b2bcb6fe2f473e1d6900d6a961f04..6e591c97819d40be74bb74b0e0895ba73f02afc0 100644 (file)
@@ -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);
 }
index 57ce5334c8ff80e8eea18535c283b93b7670d20a..a8ad03aff4dfeb8d89abcec68802fb2a4988a473 100644 (file)
@@ -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
 
index 1da3f1e24ea3f00d0ba80b8370159bbfdf124190..d72ee402bcd3c9348a55221e2df3536c5e9ffd35 100644 (file)
@@ -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
 
 
similarity index 89%
rename from tests/run/options.pyx
rename to tests/compile/c_options.pyx
index c56bb5d0ce4d2ed726e14e1d2fcd6ae5804e8592..eda8a7dcbc0666ae0a984f31a10e2b0430f3ea29 100644 (file)
@@ -1,4 +1,6 @@
 #cython: boundscheck=False
 
+print 3
+
 def f(object[int, 2] buf):
     print buf[3, 2]