1 /*
2  * Copyright (c) 2015-2018, Intel Corporation
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *  * Redistributions of source code must retain the above copyright notice,
8  *    this list of conditions and the following disclaimer.
9  *  * Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *  * Neither the name of Intel Corporation nor the names of its contributors
13  *    may be used to endorse or promote products derived from this software
14  *    without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /** \file
30  * \brief Core UE2 global types, defines, utilities.
31  *
32  * NOTE WELL: this file is included into both C and C++ source code, so
33  * be sure to remain compatible with both.
34  */
35 
36 #ifndef UE2COMMON_H
37 #define UE2COMMON_H
38 
39 #include "config.h"
40 
41 /* standard types used across ue2 */
42 
43 // We use the size_t type all over the place, usually defined in stddef.h.
44 #include <stddef.h>
45 // stdint.h for things like uintptr_t and friends
46 #include <stdint.h>
47 
48 /* ick */
49 #if defined(_WIN32)
50 #define ALIGN_ATTR(x) __declspec(align(x))
51 #else
52 #define ALIGN_ATTR(x) __attribute__((aligned((x))))
53 #endif
54 
55 #define ALIGN_DIRECTIVE ALIGN_ATTR(16)
56 #define ALIGN_AVX_DIRECTIVE ALIGN_ATTR(32)
57 #define ALIGN_CL_DIRECTIVE ALIGN_ATTR(64)
58 
59 typedef signed char s8;
60 typedef unsigned char u8;
61 typedef signed short s16;
62 typedef unsigned short u16;
63 typedef unsigned int u32;
64 typedef signed int s32;
65 
66 /* We append the 'a' for aligned, since these aren't common, garden variety
67  * 64 bit values. The alignment is necessary for structs on some platforms,
68  * so we don't end up performing accidental unaligned accesses. */
69 #if defined(_WIN32) && ! defined(_WIN64)
70 typedef unsigned long long ALIGN_ATTR(4) u64a;
71 typedef signed long long ALIGN_ATTR(4) s64a;
72 #else
73 typedef unsigned long long ALIGN_ATTR(8) u64a;
74 typedef signed long long ALIGN_ATTR(8) s64a;
75 #endif
76 
77 /* get the SIMD types */
78 #include "util/simd_types.h"
79 
80 /** \brief Report identifier, used for internal IDs and external IDs (those
81  * reported on match). */
82 typedef u32 ReportID;
83 
84 /* Shorthand for attribute to mark a function as part of our public API.
85  * Functions without this attribute will be hidden. */
86 #if !defined(_WIN32)
87 #define HS_PUBLIC_API     __attribute__((visibility("default")))
88 #else
89 // TODO: dllexport defines for windows
90 #define HS_PUBLIC_API
91 #endif
92 
93 #define ARRAY_LENGTH(a) (sizeof(a)/sizeof((a)[0]))
94 
95 /** \brief Shorthand for the attribute to shut gcc about unused parameters */
96 #if !defined(_WIN32)
97 #define UNUSED __attribute__ ((unused))
98 #else
99 #define UNUSED
100 #endif
101 
102 /* really_inline forces inlining always */
103 #if !defined(_WIN32)
104 #if defined(HS_OPTIMIZE)
105 #define really_inline inline __attribute__ ((always_inline, unused))
106 #else
107 #define really_inline __attribute__ ((unused))
108 #endif
109 
110 /** no, seriously, inline it, even if building in debug mode */
111 #define really_really_inline inline __attribute__ ((always_inline, unused))
112 #define never_inline __attribute__ ((noinline))
113 #define alignof __alignof
114 #define HAVE_TYPEOF 1
115 
116 #else // ms windows
117 #define really_inline __forceinline
118 #define really_really_inline __forceinline
119 #define never_inline
120 #define __builtin_prefetch(...) do {} while(0)
121 #if defined(__cplusplus)
122 #define __typeof__ decltype
123 #define HAVE_TYPEOF 1
124 #else // C
125 /* msvc doesn't have decltype or typeof in C */
126 #define inline __inline
127 #define alignof __alignof
128 #endif
129 #endif
130 
131 
132 // We use C99-style "restrict".
133 #ifdef _WIN32
134 #ifdef __cplusplus
135 #define restrict
136 #else
137 #define restrict __restrict
138 #endif
139 #else
140 #define restrict __restrict
141 #endif
142 
143 
144 // Align to 16-byte boundary
145 #define ROUNDUP_16(a) (((a) + 0xf) & ~0xf)
146 #define ROUNDDOWN_16(a) ((a) & ~0xf)
147 
148 // Align to N-byte boundary
149 #define ROUNDUP_N(a, n) (((a) + ((n)-1)) & ~((n)-1))
150 #define ROUNDDOWN_N(a, n) ((a) & ~((n)-1))
151 
152 // Align to a cacheline - assumed to be 64 bytes
153 #define ROUNDUP_CL(a) ROUNDUP_N(a, 64)
154 
155 // Align ptr to next N-byte boundary
156 #if defined(HAVE_TYPEOF)
157 #define ROUNDUP_PTR(ptr, n)   (__typeof__(ptr))(ROUNDUP_N((uintptr_t)(ptr), (n)))
158 #define ROUNDDOWN_PTR(ptr, n) (__typeof__(ptr))(ROUNDDOWN_N((uintptr_t)(ptr), (n)))
159 #else
160 #define ROUNDUP_PTR(ptr, n)   (void*)(ROUNDUP_N((uintptr_t)(ptr), (n)))
161 #define ROUNDDOWN_PTR(ptr, n) (void*)(ROUNDDOWN_N((uintptr_t)(ptr), (n)))
162 #endif
163 
164 #define ISALIGNED_N(ptr, n) (((uintptr_t)(ptr) & ((n) - 1)) == 0)
165 #define ISALIGNED_16(ptr)   ISALIGNED_N((ptr), 16)
166 #define ISALIGNED_CL(ptr)   ISALIGNED_N((ptr), 64)
167 #if defined(HAVE_TYPEOF)
168 #define ISALIGNED(ptr)      ISALIGNED_N((ptr), alignof(__typeof__(*(ptr))))
169 #else
170 /* we should probably avoid using this test in C */
171 #define ISALIGNED(ptr)      (1)
172 #endif
173 #define N_CHARS 256
174 
175 // Maximum offset representable in the 'unsigned long long' we use to return
176 // offset values.
177 #define MAX_OFFSET 0xffffffffffffffffULL
178 
179 #if !defined(MIN)
180   #define MIN(a,b)      ((a) < (b) ? (a) : (b))
181 #endif
182 #if !defined(MAX)
183   #define MAX(a,b)      ((a) > (b) ? (a) : (b))
184 #endif
185 
186 #define LIMIT_TO_AT_MOST(a, b) (*(a) = MIN(*(a),(b)))
187 #define ENSURE_AT_LEAST(a, b) (*(a) = MAX(*(a),(b)))
188 
189 #ifndef _WIN32
190 #ifndef likely
191   #define likely(x)     __builtin_expect(!!(x), 1)
192 #endif
193 #ifndef unlikely
194   #define unlikely(x)   __builtin_expect(!!(x), 0)
195 #endif
196 #else
197 #define likely(x)   (x)
198 #define unlikely(x) (x)
199 #endif
200 
201 #if !defined(RELEASE_BUILD) || defined(DEBUG)
202 #ifdef _WIN32
203 #define PATH_SEP '\\'
204 #else
205 #define PATH_SEP '/'
206 #endif
207 #endif
208 
209 #if defined(DEBUG) && !defined(DEBUG_PRINTF)
210 #include <string.h>
211 #include <stdio.h>
212 #define DEBUG_PRINTF(format, ...) printf("%s:%s:%d:" format, \
213                                          strrchr(__FILE__, PATH_SEP) + 1, \
214                                          __func__, __LINE__,  ## __VA_ARGS__)
215 #elif !defined(DEBUG_PRINTF)
216 #define DEBUG_PRINTF(format, ...) do { } while(0)
217 #endif
218 
219 #if !defined(RELEASE_BUILD)
220 #include <string.h>
221 #include <stdio.h>
222 #define ADEBUG_PRINTF(format, ...) printf("!%s:%s:%d:" format, \
223                                           strrchr(__FILE__, PATH_SEP) + 1, \
224                                           __func__, __LINE__,  ## __VA_ARGS__)
225 #else
226 #define ADEBUG_PRINTF(format, ...) do { } while(0)
227 #endif
228 
229 #include <assert.h>
230 
231 #endif
232