1 //------------------------------------------------------------------------------
2 // GB_compiler.h: handle compiler variations
3 //------------------------------------------------------------------------------
4 
5 // SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2021, All Rights Reserved.
6 // SPDX-License-Identifier: Apache-2.0
7 
8 //------------------------------------------------------------------------------
9 
10 #ifndef GB_COMPILER_H
11 #define GB_COMPILER_H
12 
13 //------------------------------------------------------------------------------
14 // compiler variations
15 //------------------------------------------------------------------------------
16 
17 // Determine the restrict keyword, and whether or not variable-length arrays
18 // are supported.
19 
20 #if ( _MSC_VER && !__INTEL_COMPILER )
21 
22     // Microsoft Visual Studio does not have the restrict keyword, but it does
23     // support __restrict, which is equivalent.  Variable-length arrays are
24     // not supported.  OpenMP tasks are not available, GraphBLAS no longer
25     // uses OpenMP tasks.
26 
27     #define GB_MICROSOFT 1
28     #define GB_HAS_VLA  0
29     #if defined ( __cplusplus )
30         // C++ does not have the restrict keyword
31         #define restrict
32     #else
33         // C uses __restrict
34         #define restrict __restrict
35     #endif
36 
37 #elif defined ( __cplusplus )
38 
39     #define GB_MICROSOFT 0
40     #define GB_HAS_VLA  1
41     // C++ does not have the restrict keyword
42     #define restrict
43 
44 #elif GxB_STDC_VERSION >= 199901L
45 
46     // ANSI C99 and later have the restrict keyword and variable-length arrays.
47     #define GB_MICROSOFT 0
48     #define GB_HAS_VLA  1
49 
50 #else
51 
52     // ANSI C95 and earlier have neither
53     #define GB_MICROSOFT 0
54     #define GB_HAS_VLA  0
55     #define restrict
56 
57 #endif
58 
59 //------------------------------------------------------------------------------
60 // Microsoft specific include files
61 //------------------------------------------------------------------------------
62 
63 #if GB_MICROSOFT
64 #include <malloc.h>
65 #endif
66 
67 //------------------------------------------------------------------------------
68 // PGI_COMPILER_BUG
69 //------------------------------------------------------------------------------
70 
71 // If GraphBLAS is compiled with -DPGI_COMPILER_BUG, then a workaround is
72 // enabled for a bug in the PGI compiler.  The compiler does not correctly
73 // handle automatic arrays of variable size.
74 
75 #ifdef PGI_COMPILER_BUG
76 
77     // override the ANSI C compiler to turn off variable-length arrays
78     #undef  GB_HAS_VLA
79     #define GB_HAS_VLA  0
80 
81 #endif
82 
83 //------------------------------------------------------------------------------
84 // OpenMP pragmas and tasks
85 //------------------------------------------------------------------------------
86 
87 // GB_PRAGMA(x) becomes "#pragma x", but the way to do this depends on the
88 // compiler:
89 #if GB_MICROSOFT
90     // MS Visual Studio is not ANSI C11 compliant, and uses __pragma:
91     #define GB_PRAGMA(x) __pragma (x)
92 #else
93     // ANSI C11 compilers use _Pragma:
94     #define GB_PRAGMA(x) _Pragma (#x)
95 #endif
96 
97 // construct pragmas for loop vectorization:
98 #if GB_MICROSOFT
99 
100     // no #pragma omp simd is available in MS Visual Studio
101     #define GB_PRAGMA_SIMD
102     #define GB_PRAGMA_SIMD_REDUCTION(op,s)
103 
104 #else
105 
106     // create two kinds of SIMD pragmas:
107     // GB_PRAGMA_SIMD becomes "#pragma omp simd"
108     // GB_PRAGMA_SIMD_REDUCTION (+,cij) becomes
109     // "#pragma omp simd reduction(+:cij)"
110     #define GB_PRAGMA_SIMD GB_PRAGMA (omp simd)
111     #define GB_PRAGMA_SIMD_REDUCTION(op,s) GB_PRAGMA (omp simd reduction(op:s))
112 
113 #endif
114 
115 #define GB_PRAGMA_IVDEP GB_PRAGMA(ivdep)
116 
117 //------------------------------------------------------------------------------
118 // variable-length arrays
119 //------------------------------------------------------------------------------
120 
121 // If variable-length arrays are not supported, user-defined types are limited
122 // in size to 128 bytes or less.  Many of the type-generic routines allocate
123 // workspace for a single scalar of variable size, using a statement:
124 //
125 //      GB_void aij [xsize] ;
126 //
127 // To support non-variable-length arrays in ANSI C95 or earlier, this is used:
128 //
129 //      GB_void aij [GB_VLA(xsize)] ;
130 //
131 // GB_VLA(xsize) is either defined as xsize (for ANSI C99 or later), or a fixed
132 // size of 128, in which case user-defined types
133 // are limited to a max of 128 bytes.
134 
135 #if ( GB_HAS_VLA )
136 
137     // variable-length arrays are allowed
138     #define GB_VLA(s) s
139 
140 #else
141 
142     // variable-length arrays are not allowed
143     #define GB_VLA_MAXSIZE 128
144     #define GB_VLA(s) GB_VLA_MAXSIZE
145 
146 #endif
147 #endif
148 
149