Commit 8dcd1394 authored by Mark Florisson's avatar Mark Florisson Committed by Dag Sverre Seljebotn

Updated error messages & moved NaN to utility code

parent 6989e004
......@@ -499,19 +499,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
#define DL_EXPORT(t) t
#endif
#ifdef PY_LONG_LONG
#define %(LONG_LONG_MAX)s PY_LLONG_MAX
#define %(ULONG_LONG_MAX)s PY_ULLONG_MAX
#else
#define PY_LONG_LONG LONG_LONG
#if defined(LLONG_MAX)
#define %(LONG_LONG_MAX)s LLONG_MAX
#define %(ULONG_LONG_MAX)s ULLONG_MAX
#else
#define %(LONG_LONG_MAX)s LONG_MAX
#define %(ULONG_LONG_MAX)s ULONG_MAX
#endif
#ifndef PY_LONG_LONG
#define PY_LONG_LONG LONG_LONG
#endif
#if PY_VERSION_HEX < 0x02040000
......@@ -648,7 +637,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
#define __Pyx_PyInt_AsHash_t PyInt_AsSsize_t
#endif
""" % vars(Naming))
""")
code.put("""
#if PY_MAJOR_VERSION >= 3
......@@ -714,47 +703,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln("#if defined(WIN32) || defined(MS_WINDOWS)")
code.putln("#define _USE_MATH_DEFINES")
code.putln("#endif")
code.putln("""
/* Define NAN */
#ifdef Py_NAN
#include <math.h>
#define %(pyx_nan)s Py_NAN
#else
#if defined(__GNUC__)
#define _GNU_SOURCE
#endif
#include <math.h>
#ifdef NAN
#define %(pyx_nan)s NAN
#else
#if defined(HUGE_VALL)
#define %(pyx_nan)s HUGE_VALL
#elif defined(__STDC__) && __STDC_VERSION__ >= 199901L
/* C99 or greater */
#include <float.h>
#define %(pyx_nan)s LDBL_MAX
#else
static PY_LONG_LONG __pyx__nan = PY_LLONG_MAX;
#define %(pyx_nan)s (*(double*) &__pyx__nan)
#endif
#endif
#endif
#ifdef PY_LONG_LONG
#define __PYX_LONG_LONG_MAX PY_LLONG_MAX
#define __PYX_ULONG_LONG_MAX PY_ULLONG_MAX
#elif defined(LLONG_MAX)
#define __PYX_LONG_LONG_MAX LLONG_MAX
#define __PYX_ULONG_LONG_MAX ULLONG_MAX
#else
/* This should probably suffice, even if not strictly the largest value */
#define __PYX_LONG_LONG_MAX LONG_MAX
#define __PYX_ULONG_LONG_MAX ULONG_MAX
#endif
""" % {'pyx_nan': Naming.NAN})
code.putln("#include <math.h>")
code.putln("#define %s" % Naming.h_guard_prefix + self.api_name(env))
code.putln("#define %s" % Naming.api_guard_prefix + self.api_name(env))
......
......@@ -116,7 +116,7 @@ h_guard_prefix = "__PYX_HAVE__"
api_guard_prefix = "__PYX_HAVE_API__"
api_func_guard = "__PYX_HAVE_API_FUNC_"
NAN = "__PYX_NAN"
PYX_NAN = "__PYX_NAN"
HUGE_VAL = "Py_HUGE_VAL"
LONG_LONG_MAX = "__PYX_LONG_LONG_MAX"
ULONG_LONG_MAX = "__PYX_ULONG_LONG_MAX"
......
......@@ -5891,7 +5891,7 @@ class ParallelStatNode(StatNode, ParallelNode):
def analyse_expressions(self, env):
self.body.analyse_expressions(env)
self.analyse_sharing_attributes(env)
self.check_use_unitialized_privates()
self.check_independent_iterations()
def analyse_sharing_attributes(self, env):
"""
......@@ -5997,9 +5997,9 @@ class ParallelStatNode(StatNode, ParallelNode):
code.putln("%s = %s;" % (cname, entry.cname))
entry.cname = cname
def check_use_unitialized_privates(self):
def check_independent_iterations(self):
"""
This checks for uninitialized private variables, it's far from
This checks for uninitialized thread-private variables, it's far from
fool-proof as it does not take control flow into account, nor
assignment to a variable as both the lhs and rhs. So it detects only
cases like this:
......@@ -6009,7 +6009,8 @@ class ParallelStatNode(StatNode, ParallelNode):
x = i
Fortunately, it doesn't need to be perfect, as we still initialize
private variables to maximum values, NULL or NaN whenever possible.
private variables to "invalid" values, such as NULL or NaN whenever
possible.
"""
from Cython.Compiler import ParseTreeTransforms
......@@ -6023,18 +6024,25 @@ class ParallelStatNode(StatNode, ParallelNode):
# Reading reduction variables is valid (in fact necessary)
# before assignment
if not op and pos < assignment_pos:
error(pos, "Private variable referenced before assignment")
if self.is_prange:
error(pos, "Expression value depends on previous loop "
"iteration, cannot execute in parallel")
else:
error(pos, "Expression depends on an uninitialized "
"thread-private variable")
def initialize_privates_to_nan(self, code, exclude=None):
code.putln("/* Initialize private variables to invalid values */")
for entry, op in self.privates.iteritems():
if not op and (not exclude or entry != exclude):
max_value = entry.type.max_value()
invalid_value = entry.type.invalid_value()
if max_value:
if invalid_value:
code.globalstate.use_utility_code(
invalid_values_utility_code)
code.putln("%s = %s;" % (entry.cname,
entry.type.cast_code(max_value)))
entry.type.cast_code(invalid_value)))
def declare_closure_privates(self, code):
"""
......@@ -7553,3 +7561,39 @@ bad:
'EMPTY_BYTES' : Naming.empty_bytes,
"MODULE": Naming.module_cname,
})
################ Utility code for cython.parallel stuff ################
invalid_values_utility_code = UtilityCode(proto="""
#ifdef HAVE_LONG_LONG
#define %(LONG_LONG_MAX)s PY_LLONG_MAX
#define %(ULONG_LONG_MAX)s PY_ULLONG_MAX
#else
#define PY_LONG_LONG LONG_LONG
#if defined(LLONG_MAX)
#define %(LONG_LONG_MAX)s LLONG_MAX
#define %(ULONG_LONG_MAX)s ULLONG_MAX
#else
#define %(LONG_LONG_MAX)s LONG_MAX
#define %(ULONG_LONG_MAX)s ULONG_MAX
#endif
#endif
/* Define NAN */
#ifdef Py_NAN
#define %(PYX_NAN)s Py_NAN
#elif defined(NAN)
#define %(PYX_NAN)s NAN
#elif defined(HUGE_VALL)
#define %(PYX_NAN)s HUGE_VALL
#elif defined(__STDC__) && __STDC_VERSION__ >= 199901L
/* C99 or greater */
#include <float.h>
#define %(PYX_NAN)s LDBL_MAX
#else
static PY_LONG_LONG __pyx__nan = %(LONG_LONG_MAX)s;
#define %(PYX_NAN)s (*(double*) &__pyx__nan)
#endif
""" % vars(Naming))
......@@ -27,10 +27,10 @@ class BaseType(object):
else:
return base_code
def max_value(self):
def invalid_value(self):
"""
Returns the maximum or most invalid value an object of this type can
assume as a C expression string. Returns None if no such value exists.
Returns the most invalid value an object of this type can assume as a
C expression string. Returns None if no such value exists.
"""
class PyrexType(BaseType):
......@@ -384,8 +384,8 @@ class PyObjectType(PyrexType):
else:
return cname
def max_value(self):
return "NULL"
def invalid_value(self):
return "1"
class BuiltinObjectType(PyObjectType):
......@@ -912,7 +912,7 @@ class CIntType(CNumericType):
def assignable_from_resolved_type(self, src_type):
return src_type.is_int or src_type.is_enum or src_type is error_type
def max_value(self):
def invalid_value(self):
return typename_to_maxval[rank_to_type_name[self.rank]][not self.signed]
class CAnonEnumType(CIntType):
......@@ -1121,8 +1121,8 @@ class CFloatType(CNumericType):
def assignable_from_resolved_type(self, src_type):
return (src_type.is_numeric and not src_type.is_complex) or src_type is error_type
def max_value(self):
return Naming.NAN
def invalid_value(self):
return Naming.PYX_NAN
class CComplexType(CNumericType):
......@@ -1636,8 +1636,8 @@ class CPtrType(CType):
else:
return CPtrType(base_type)
def max_value(self):
return "NULL"
def invalid_value(self):
return "1"
class CNullPtrType(CPtrType):
......@@ -2375,7 +2375,7 @@ typename_to_maxval = {
"int" : ("INT_MAX", "UINT_MAX"),
"long" : ("LONG_MAX", "ULONG_MAX"),
"PY_LONG_LONG" : (Naming.LONG_LONG_MAX, Naming.ULONG_LONG_MAX),
# CFloatType overrides max_value
# CFloatType overrides invalid_value
}
RANK_INT = list(rank_to_type_name).index('int')
......
......@@ -73,7 +73,7 @@ e_cython_parallel.pyx:30:9: Can only iterate over an iteration variable
e_cython_parallel.pyx:33:10: Must be of numeric type, not int *
e_cython_parallel.pyx:36:33: Closely nested 'with parallel:' blocks are disallowed
e_cython_parallel.pyx:39:12: The parallel directive must be called
e_cython_parallel.pyx:45:10: Private variable referenced before assignment
e_cython_parallel.pyx:55:9: Private variable referenced before assignment
e_cython_parallel.pyx:45:10: Expression value depends on previous loop iteration, cannot execute in parallel
e_cython_parallel.pyx:55:9: Expression depends on an uninitialized thread-private variable
e_cython_parallel.pyx:60:6: Reduction operator '*' is inconsistent with previous reduction operator '+'
"""
......@@ -214,7 +214,7 @@ def test_nan_init():
d1 == 10 or d2 == 10 or
e1 == 10 or e2 == 10 or
f == 10.0 or g == 10.0 or h == 10.0 or
p != NULL):
p == <void *> 10):
errp[0] = 1
......
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