1
/* cairo - a vector graphics library with display and print output
2
 *
3
 * Copyright © 2002 University of Southern California
4
 * Copyright © 2005 Red Hat, Inc.
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it either under the terms of the GNU Lesser General Public
8
 * License version 2.1 as published by the Free Software Foundation
9
 * (the "LGPL") or, at your option, under the terms of the Mozilla
10
 * Public License Version 1.1 (the "MPL"). If you do not alter this
11
 * notice, a recipient may use your version of this file under either
12
 * the MPL or the LGPL.
13
 *
14
 * You should have received a copy of the LGPL along with this library
15
 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
16
 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
17
 * You should have received a copy of the MPL along with this library
18
 * in the file COPYING-MPL-1.1
19
 *
20
 * The contents of this file are subject to the Mozilla Public License
21
 * Version 1.1 (the "License"); you may not use this file except in
22
 * compliance with the License. You may obtain a copy of the License at
23
 * http://www.mozilla.org/MPL/
24
 *
25
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
26
 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
27
 * the specific language governing rights and limitations.
28
 *
29
 * The Original Code is the cairo graphics library.
30
 *
31
 * The Initial Developer of the Original Code is University of Southern
32
 * California.
33
 *
34
 * Contributor(s):
35
 *	Carl D. Worth <cworth@cworth.org>
36
 */
37

            
38
#ifndef CAIRO_COMPILER_PRIVATE_H
39
#define CAIRO_COMPILER_PRIVATE_H
40

            
41
#include "cairo.h"
42

            
43
#include "config.h"
44

            
45
#include <stddef.h> /* size_t */
46
#include <stdint.h> /* SIZE_MAX */
47

            
48
/* Size in bytes of buffer to use off the stack per functions.
49
 * Mostly used by text functions.  For larger allocations, they'll
50
 * malloc(). */
51
#ifndef CAIRO_STACK_BUFFER_SIZE
52
#define CAIRO_STACK_BUFFER_SIZE (512 * sizeof (int))
53
#endif
54

            
55
#define CAIRO_STACK_ARRAY_LENGTH(T) (CAIRO_STACK_BUFFER_SIZE / sizeof(T))
56

            
57
#if defined (__GNUC__)
58
#ifdef __MINGW32__
59
#define CAIRO_PRINTF_FORMAT(fmt_index, va_index)                        \
60
	__attribute__((__format__(__MINGW_PRINTF_FORMAT, fmt_index, va_index)))
61
#else
62
#define CAIRO_PRINTF_FORMAT(fmt_index, va_index)                        \
63
	__attribute__((__format__(__printf__, fmt_index, va_index)))
64
#endif
65
#else
66
#define CAIRO_PRINTF_FORMAT(fmt_index, va_index)
67
#endif
68

            
69
#define CAIRO_HAS_HIDDEN_SYMBOLS 1
70
#if defined(__GNUC__) && \
71
    (defined(__ELF__) || defined(__APPLE__)) && \
72
    !defined(__sun)
73
#define cairo_private_no_warn	__attribute__((__visibility__("hidden")))
74
#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
75
#define cairo_private_no_warn	__hidden
76
#else /* not gcc >= 3.3 and not Sun Studio >= 8 */
77
#define cairo_private_no_warn
78
#undef CAIRO_HAS_HIDDEN_SYMBOLS
79
#endif
80

            
81
#ifndef WARN_UNUSED_RESULT
82
#define WARN_UNUSED_RESULT
83
#endif
84

            
85
/* Add attribute(warn_unused_result) if supported */
86
#define cairo_warn	    WARN_UNUSED_RESULT
87
#define cairo_private	    cairo_private_no_warn cairo_warn
88

            
89
/* This macro allow us to deprecate a function by providing an alias
90
   for the old function name to the new function name. With this
91
   macro, binary compatibility is preserved. The macro only works on
92
   some platforms --- tough.
93

            
94
   Meanwhile, new definitions in the public header file break the
95
   source code so that it will no longer link against the old
96
   symbols. Instead it will give a descriptive error message
97
   indicating that the old function has been deprecated by the new
98
   function.
99
*/
100
#if defined (__GNUC__) && defined(__ELF__)
101
# define CAIRO_FUNCTION_ALIAS(old, new)		\
102
	extern __typeof (new) old		\
103
	__asm__ ("" #old)			\
104
	__attribute__((__alias__("" #new)))
105
#else
106
# define CAIRO_FUNCTION_ALIAS(old, new)
107
#endif
108

            
109
/*
110
 * Cairo uses the following function attributes in order to improve the
111
 * generated code (effectively by manual inter-procedural analysis).
112
 *
113
 *   'cairo_pure': The function is only allowed to read from its arguments
114
 *                 and global memory (i.e. following a pointer argument or
115
 *                 accessing a shared variable). The return value should
116
 *                 only depend on its arguments, and for an identical set of
117
 *                 arguments should return the same value.
118
 *
119
 *   'cairo_const': The function is only allowed to read from its arguments.
120
 *                  It is not allowed to access global memory. The return
121
 *                  value should only depend its arguments, and for an
122
 *                  identical set of arguments should return the same value.
123
 *                  This is currently the most strict function attribute.
124
 *
125
 * Both these function attributes allow gcc to perform CSE and
126
 * constant-folding, with 'cairo_const 'also guaranteeing that pointer contents
127
 * do not change across the function call.
128
 */
129
#if defined (__GNUC__)
130
#define cairo_pure __attribute__((pure))
131
#define cairo_const __attribute__((const))
132
#define cairo_always_inline inline __attribute__((always_inline))
133
#elif defined (_MSC_VER)
134
#define cairo_pure
135
#define cairo_const
136
#define cairo_always_inline __forceinline
137
#else
138
#define cairo_pure
139
#define cairo_const
140
#define cairo_always_inline inline
141
#endif
142

            
143
#if defined(__GNUC__) && defined(__OPTIMIZE__)
144
#define likely(expr) (__builtin_expect (!!(expr), 1))
145
#define unlikely(expr) (__builtin_expect (!!(expr), 0))
146
#else
147
#define likely(expr) (expr)
148
#define unlikely(expr) (expr)
149
#endif
150

            
151
#if !defined(__GNUC__) && !defined (__clang__)
152
#undef __attribute__
153
#define __attribute__(x)
154
#endif
155

            
156
#if (defined(__WIN32__) && !defined(__WINE__)) || defined(_MSC_VER)
157
#define access _access
158
#ifndef R_OK
159
#define R_OK 4
160
#endif
161
#define fdopen _fdopen
162
#define hypot _hypot
163
#define pclose _pclose
164
#define popen _popen
165
#define strdup _strdup
166
#define unlink _unlink
167
#if _MSC_VER < 1900
168
  #define vsnprintf _vsnprintf // TODO
169
  #define snprintf _snprintf
170
#endif
171
#endif
172

            
173
#if defined(_MSC_VER) && defined(_M_IX86)
174
/* When compiling with /Gy and /OPT:ICF identical functions will be folded in together.
175
   The CAIRO_ENSURE_UNIQUE macro ensures that a function is always unique and
176
   will never be folded into another one. Something like this might eventually
177
   be needed for GCC but it seems fine for now. */
178
#define CAIRO_ENSURE_UNIQUE                       \
179
    do {                                          \
180
	char file[] = __FILE__;                   \
181
	__asm {                                   \
182
	    __asm jmp __internal_skip_line_no     \
183
	    __asm _emit (__COUNTER__ & 0xff)      \
184
	    __asm _emit ((__COUNTER__>>8) & 0xff) \
185
	    __asm _emit ((__COUNTER__>>16) & 0xff)\
186
	    __asm _emit ((__COUNTER__>>24) & 0xff)\
187
	    __asm lea eax, dword ptr file         \
188
	    __asm __internal_skip_line_no:        \
189
	};                                        \
190
    } while (0)
191
#else
192
#define CAIRO_ENSURE_UNIQUE    do { } while (0)
193
#endif
194

            
195
#ifdef __STRICT_ANSI__
196
#undef inline
197
#define inline __inline__
198
#endif
199

            
200
/* size_t add/multiply with overflow check.
201
 *
202
 * These _cairo_fallback_*_size_t_overflow() functions are always defined
203
 * to allow them to be tested in the test suite.  They are used
204
 * if no compiler builtin is available.
205
 */
206
static cairo_always_inline cairo_bool_t
207
_cairo_fallback_add_size_t_overflow(size_t a, size_t b, size_t *c)
208
{
209
9
    if (b > SIZE_MAX - a)
210
3
        return 1;
211

            
212
6
    *c = a + b;
213
6
    return 0;
214
}
215

            
216
static cairo_always_inline cairo_bool_t
217
_cairo_fallback_mul_size_t_overflow(size_t a, size_t b, size_t *c)
218
{
219
6
    if (b != 0 && a > SIZE_MAX / b)
220
3
        return 1;
221

            
222
3
    *c = a * b;
223
3
    return 0;
224
}
225

            
226
/* Clang defines __GNUC__ so check clang builtins before gcc.
227
 * MSVC does not support feature macros so hide the __has_builtin inside the #if __clang__ block
228
 */
229
#ifdef __clang__
230
#if defined(__has_builtin) && __has_builtin(__builtin_add_overflow)
231
#define _cairo_add_size_t_overflow(a, b, c)  __builtin_add_overflow((size_t)(a), (size_t)(b), (size_t*)(c))
232
#define _cairo_mul_size_t_overflow(a, b, c)  __builtin_mul_overflow((size_t)(a), (size_t)(b), (size_t*)(c))
233
#endif
234
#elif __GNUC__ >= 8 || (__GNUC__ >= 5 && (INTPTR_MAX == INT64_MAX))
235
/* Overflow builtins are available in gcc 5 but the 32-bit version is broken on gcc < 8.
236
 *   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82274
237
 */
238
#define _cairo_add_size_t_overflow(a, b, c)  __builtin_add_overflow((size_t)(a), (size_t)(b), (size_t*)(c))
239
#define _cairo_mul_size_t_overflow(a, b, c)  __builtin_mul_overflow((size_t)(a), (size_t)(b), (size_t*)(c))
240
#elif defined(_MSC_VER) && defined(HAVE_INTSAFE_H)
241
#include <intsafe.h>
242
#define _cairo_add_size_t_overflow(a,b,c) (SizeTAdd((size_t)(a), (size_t)(b), (size_t*)(c)) != S_OK)
243
#define _cairo_mul_size_t_overflow(a,b,c) (SizeTMult((size_t)(a), (size_t)(b), (size_t*)(c)) != S_OK)
244
#endif
245

            
246
#ifndef _cairo_add_size_t_overflow
247
#define _cairo_add_size_t_overflow _cairo_fallback_add_size_t_overflow
248
#define _cairo_mul_size_t_overflow _cairo_fallback_mul_size_t_overflow
249
#endif
250

            
251
#endif