Coverage Report

Created: 2023-04-25 07:07

/root/.opam/4.11.2/lib/ocaml/caml/misc.h
Line
Count
Source (jump to first uncovered line)
1
/**************************************************************************/
2
/*                                                                        */
3
/*                                 OCaml                                  */
4
/*                                                                        */
5
/*          Xavier Leroy and Damien Doligez, INRIA Rocquencourt           */
6
/*                                                                        */
7
/*   Copyright 1996 Institut National de Recherche en Informatique et     */
8
/*     en Automatique.                                                    */
9
/*                                                                        */
10
/*   All rights reserved.  This file is distributed under the terms of    */
11
/*   the GNU Lesser General Public License version 2.1, with the          */
12
/*   special exception on linking described in the file LICENSE.          */
13
/*                                                                        */
14
/**************************************************************************/
15
16
/* Miscellaneous macros and variables. */
17
18
#ifndef CAML_MISC_H
19
#define CAML_MISC_H
20
21
#ifndef CAML_NAME_SPACE
22
#include "compatibility.h"
23
#endif
24
#include "config.h"
25
26
/* Standard definitions */
27
28
#include <stddef.h>
29
#include <stdlib.h>
30
#include <stdarg.h>
31
32
/* Basic types and constants */
33
34
typedef size_t asize_t;
35
36
#if defined(__GNUC__) || defined(__clang__)
37
  /* Supported since at least GCC 3.1 */
38
  #define CAMLdeprecated_typedef(name, type) \
39
    typedef type name __attribute ((deprecated))
40
#elif _MSC_VER >= 1310
41
  /* NB deprecated("message") only supported from _MSC_VER >= 1400 */
42
  #define CAMLdeprecated_typedef(name, type) \
43
    typedef __declspec(deprecated) type name
44
#else
45
  #define CAMLdeprecated_typedef(name, type) typedef type name
46
#endif
47
48
#ifdef CAML_INTERNALS
49
CAMLdeprecated_typedef(addr, char *);
50
#endif /* CAML_INTERNALS */
51
52
/* Noreturn is preserved for compatibility reasons.
53
   Instead of the legacy GCC/Clang-only
54
     foo Noreturn;
55
   you should prefer
56
     CAMLnoreturn_start foo CAMLnoreturn_end;
57
   which supports both GCC/Clang and MSVC.
58
59
   Note: CAMLnoreturn is a different macro defined in memory.h,
60
   to be used in function bodies rather than as a prototype attribute.
61
*/
62
#ifdef __GNUC__
63
  /* Works only in GCC 2.5 and later */
64
  #define CAMLnoreturn_start
65
  #define CAMLnoreturn_end __attribute__ ((noreturn))
66
  #define Noreturn __attribute__ ((noreturn))
67
#elif _MSC_VER >= 1500
68
  #define CAMLnoreturn_start __declspec(noreturn)
69
  #define CAMLnoreturn_end
70
  #define Noreturn
71
#else
72
  #define CAMLnoreturn_start
73
  #define CAMLnoreturn_end
74
  #define Noreturn
75
#endif
76
77
78
79
/* Export control (to mark primitives and to handle Windows DLL) */
80
81
#define CAMLexport
82
#define CAMLprim
83
#define CAMLextern extern
84
85
/* Weak function definitions that can be overridden by external libs */
86
/* Conservatively restricted to ELF and MacOSX platforms */
87
#if defined(__GNUC__) && (defined (__ELF__) || defined(__APPLE__))
88
#define CAMLweakdef __attribute__((weak))
89
#else
90
#define CAMLweakdef
91
#endif
92
93
/* Alignment is necessary for domain_state.h, since the code generated */
94
/* by ocamlopt makes direct references into the domain state structure,*/
95
/* which is stored in a register on many platforms. For this to work, */
96
/* we need to be able to compute the exact offset of each member. */
97
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
98
#define CAMLalign(n) _Alignas(n)
99
#elif defined(__cplusplus) && (__cplusplus >= 201103L || _MSC_VER >= 1900)
100
#define CAMLalign(n) alignas(n)
101
#elif defined(SUPPORTS_ALIGNED_ATTRIBUTE)
102
#define CAMLalign(n) __attribute__((aligned(n)))
103
#elif _MSC_VER >= 1500
104
#define CAMLalign(n) __declspec(align(n))
105
#else
106
#error "How do I align values on this platform?"
107
#endif
108
109
/* CAMLunused is preserved for compatibility reasons.
110
   Instead of the legacy GCC/Clang-only
111
     CAMLunused foo;
112
   you should prefer
113
     CAMLunused_start foo CAMLunused_end;
114
   which supports both GCC/Clang and MSVC.
115
*/
116
#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 7))
117
  #define CAMLunused_start __attribute__ ((unused))
118
  #define CAMLunused_end
119
  #define CAMLunused __attribute__ ((unused))
120
#elif _MSC_VER >= 1500
121
  #define CAMLunused_start  __pragma( warning (push) )           \
122
    __pragma( warning (disable:4189 ) )
123
  #define CAMLunused_end __pragma( warning (pop))
124
  #define CAMLunused
125
#else
126
  #define CAMLunused_start
127
  #define CAMLunused_end
128
  #define CAMLunused
129
#endif
130
131
#ifdef __cplusplus
132
extern "C" {
133
#endif
134
135
/* GC timing hooks. These can be assigned by the user. These hooks
136
   must not allocate, change any heap value, nor call OCaml code.
137
*/
138
typedef void (*caml_timing_hook) (void);
139
extern caml_timing_hook caml_major_slice_begin_hook, caml_major_slice_end_hook;
140
extern caml_timing_hook caml_minor_gc_begin_hook, caml_minor_gc_end_hook;
141
extern caml_timing_hook caml_finalise_begin_hook, caml_finalise_end_hook;
142
143
#define CAML_STATIC_ASSERT_3(b, l) \
144
  CAMLunused_start \
145
    CAMLextern char static_assertion_failure_line_##l[(b) ? 1 : -1] \
146
  CAMLunused_end
147
148
#define CAML_STATIC_ASSERT_2(b, l) CAML_STATIC_ASSERT_3(b, l)
149
#define CAML_STATIC_ASSERT(b) CAML_STATIC_ASSERT_2(b, __LINE__)
150
151
/* Windows Unicode support (rest below - char_os is needed earlier) */
152
153
#ifdef _WIN32
154
typedef wchar_t char_os;
155
#else
156
typedef char char_os;
157
#endif
158
159
/* Assertions */
160
161
#ifdef DEBUG
162
163
#ifdef UNICODE
164
/* See https://msdn.microsoft.com/ja-jp/library/b0084kay(v=vs.71).aspx
165
   It's not clear why this isn't so obviously documented, as it doesn't
166
   seem to have been superseded by a more sensible mechanism! */
167
#define CAML_WIDEN_STRING_LITERAL2(x) L##x
168
#define CAML_WIDEN_STRING_LITERAL(x) CAML_WIDEN_STRING_LITERAL2(x)
169
#define __OSFILE__ CAML_WIDEN_STRING_LITERAL(__FILE__)
170
#else
171
#define __OSFILE__ __FILE__
172
#endif
173
174
#define CAMLassert(x) \
175
  ((x) ? (void) 0 : caml_failed_assert ( #x , __OSFILE__, __LINE__))
176
CAMLnoreturn_start
177
CAMLextern void caml_failed_assert (char *, char_os *, int)
178
CAMLnoreturn_end;
179
#else
180
443k
#define CAMLassert(x) ((void) 0)
181
#endif
182
183
/* This hook is called when a fatal error occurs in the OCaml
184
   runtime. It is given arguments to be passed to the [vprintf]-like
185
   functions in order to synthetize the error message.
186
   If it returns, the runtime calls [abort()].
187
188
   If it is [NULL], the error message is printed on stderr and then
189
   [abort()] is called. */
190
extern void (*caml_fatal_error_hook) (char *msg, va_list args);
191
192
CAMLnoreturn_start
193
CAMLextern void caml_fatal_error (char *, ...)
194
#ifdef __GNUC__
195
  __attribute__ ((format (printf, 1, 2)))
196
#endif
197
CAMLnoreturn_end;
198
199
/* Detection of available C built-in functions, the Clang way. */
200
201
#ifdef __has_builtin
202
#define Caml_has_builtin(x) __has_builtin(x)
203
#else
204
#define Caml_has_builtin(x) 0
205
#endif
206
207
/* Integer arithmetic with overflow detection.
208
   The functions return 0 if no overflow, 1 if overflow.
209
   The result of the operation is always stored at [*res].
210
   If no overflow is reported, this is the exact result.
211
   If overflow is reported, this is the exact result modulo 2 to the word size.
212
*/
213
214
Caml_inline int caml_uadd_overflow(uintnat a, uintnat b, uintnat * res)
215
0
{
216
0
#if __GNUC__ >= 5 || Caml_has_builtin(__builtin_add_overflow)
217
0
  return __builtin_add_overflow(a, b, res);
218
0
#else
219
0
  uintnat c = a + b;
220
0
  *res = c;
221
0
  return c < a;
222
0
#endif
223
0
}
224
225
Caml_inline int caml_usub_overflow(uintnat a, uintnat b, uintnat * res)
226
0
{
227
0
#if __GNUC__ >= 5 || Caml_has_builtin(__builtin_sub_overflow)
228
0
  return __builtin_sub_overflow(a, b, res);
229
0
#else
230
0
  uintnat c = a - b;
231
0
  *res = c;
232
0
  return a < b;
233
0
#endif
234
0
}
235
236
#if __GNUC__ >= 5 || Caml_has_builtin(__builtin_mul_overflow)
237
Caml_inline int caml_umul_overflow(uintnat a, uintnat b, uintnat * res)
238
0
{
239
0
  return __builtin_mul_overflow(a, b, res);
240
0
}
241
#else
242
extern int caml_umul_overflow(uintnat a, uintnat b, uintnat * res);
243
#endif
244
245
/* From floats.c */
246
extern double caml_log1p(double);
247
248
/* Windows Unicode support */
249
250
#ifdef _WIN32
251
252
#ifdef CAML_INTERNALS
253
#define T(x) L ## x
254
#endif
255
256
#define access_os _waccess
257
#define open_os _wopen
258
#define stat_os _wstati64
259
#define unlink_os _wunlink
260
#define rename_os caml_win32_rename
261
#define chdir_os _wchdir
262
#define getcwd_os _wgetcwd
263
#define system_os _wsystem
264
#define rmdir_os _wrmdir
265
#define putenv_os _wputenv
266
#define chmod_os _wchmod
267
#define execv_os _wexecv
268
#define execve_os _wexecve
269
#define execvp_os _wexecvp
270
#define execvpe_os _wexecvpe
271
#define strcmp_os wcscmp
272
#define strlen_os wcslen
273
#define sscanf_os swscanf
274
#define strcpy_os wcscpy
275
#define mktemp_os _wmktemp
276
#define fopen_os _wfopen
277
278
#define caml_stat_strdup_os caml_stat_wcsdup
279
#define caml_stat_strconcat_os caml_stat_wcsconcat
280
281
#define caml_stat_strdup_to_os caml_stat_strdup_to_utf16
282
#define caml_stat_strdup_of_os caml_stat_strdup_of_utf16
283
#define caml_copy_string_of_os caml_copy_string_of_utf16
284
285
#else /* _WIN32 */
286
287
#ifdef CAML_INTERNALS
288
#define T(x) x
289
#endif
290
291
#define access_os access
292
#define open_os open
293
#define stat_os stat
294
#define unlink_os unlink
295
#define rename_os rename
296
#define chdir_os chdir
297
#define getcwd_os getcwd
298
#define system_os system
299
#define rmdir_os rmdir
300
#define putenv_os putenv
301
#define chmod_os chmod
302
#define execv_os execv
303
#define execve_os execve
304
#define execvp_os execvp
305
#define execvpe_os execvpe
306
#define strcmp_os strcmp
307
#define strlen_os strlen
308
#define sscanf_os sscanf
309
#define strcpy_os strcpy
310
#define mktemp_os mktemp
311
#define fopen_os fopen
312
313
#define caml_stat_strdup_os caml_stat_strdup
314
#define caml_stat_strconcat_os caml_stat_strconcat
315
316
#define caml_stat_strdup_to_os caml_stat_strdup
317
#define caml_stat_strdup_of_os caml_stat_strdup
318
#define caml_copy_string_of_os caml_copy_string
319
320
#endif /* _WIN32 */
321
322
323
/* Data structures */
324
325
struct ext_table {
326
  int size;
327
  int capacity;
328
  void ** contents;
329
};
330
331
extern void caml_ext_table_init(struct ext_table * tbl, int init_capa);
332
extern int caml_ext_table_add(struct ext_table * tbl, void * data);
333
extern void caml_ext_table_remove(struct ext_table * tbl, void * data);
334
extern void caml_ext_table_free(struct ext_table * tbl, int free_entries);
335
extern void caml_ext_table_clear(struct ext_table * tbl, int free_entries);
336
337
CAMLextern int caml_read_directory(char_os * dirname,
338
                                   struct ext_table * contents);
339
340
/* Deprecated aliases */
341
#define caml_aligned_malloc caml_stat_alloc_aligned_noexc
342
#define caml_strdup caml_stat_strdup
343
#define caml_strconcat caml_stat_strconcat
344
345
#ifdef CAML_INTERNALS
346
347
/* GC flags and messages */
348
349
extern uintnat caml_verb_gc;
350
void caml_gc_message (int, char *, ...)
351
#ifdef __GNUC__
352
  __attribute__ ((format (printf, 2, 3)))
353
#endif
354
;
355
356
/* Runtime warnings */
357
extern uintnat caml_runtime_warnings;
358
int caml_runtime_warnings_active(void);
359
360
#ifdef DEBUG
361
#ifdef ARCH_SIXTYFOUR
362
#define Debug_tag(x) (INT64_LITERAL(0xD700D7D7D700D6D7u) \
363
                      | ((uintnat) (x) << 16) \
364
                      | ((uintnat) (x) << 48))
365
#else
366
#define Debug_tag(x) (0xD700D6D7ul | ((uintnat) (x) << 16))
367
#endif /* ARCH_SIXTYFOUR */
368
369
/*
370
  00 -> free words in minor heap
371
  01 -> fields of free list blocks in major heap
372
  03 -> heap chunks deallocated by heap shrinking
373
  04 -> fields deallocated by [caml_obj_truncate]
374
  05 -> unused child pointers in large free blocks
375
  10 -> uninitialised fields of minor objects
376
  11 -> uninitialised fields of major objects
377
  15 -> uninitialised words of [caml_stat_alloc_aligned] blocks
378
  85 -> filler bytes of [caml_stat_alloc_aligned]
379
  99 -> the magic prefix of a memory block allocated by [caml_stat_alloc]
380
381
  special case (byte by byte):
382
  D7 -> uninitialised words of [caml_stat_alloc] blocks
383
*/
384
#define Debug_free_minor     Debug_tag (0x00)
385
#define Debug_free_major     Debug_tag (0x01)
386
#define Debug_free_shrink    Debug_tag (0x03)
387
#define Debug_free_truncate  Debug_tag (0x04)
388
#define Debug_free_unused    Debug_tag (0x05)
389
#define Debug_uninit_minor   Debug_tag (0x10)
390
#define Debug_uninit_major   Debug_tag (0x11)
391
#define Debug_uninit_align   Debug_tag (0x15)
392
#define Debug_filler_align   Debug_tag (0x85)
393
#define Debug_pool_magic     Debug_tag (0x99)
394
395
#define Debug_uninit_stat    0xD7
396
397
/* Note: the first argument is in fact a [value] but we don't have this
398
   type available yet because we can't include [mlvalues.h] in this file.
399
*/
400
extern void caml_set_fields (intnat v, uintnat, uintnat);
401
#endif /* DEBUG */
402
403
404
/* snprintf emulation for Win32 */
405
406
#ifdef _WIN32
407
#ifndef _UCRT
408
extern int caml_snprintf(char * buf, size_t size, const char * format, ...);
409
#define snprintf caml_snprintf
410
#endif
411
412
extern int caml_snwprintf(wchar_t * buf,
413
                          size_t size,
414
                          const wchar_t * format, ...);
415
#define snprintf_os caml_snwprintf
416
#else
417
#define snprintf_os snprintf
418
#endif
419
420
/* Macro used to deactivate thread and address sanitizers on some
421
   functions. */
422
#define CAMLno_tsan
423
#define CAMLno_asan
424
#if defined(__has_feature)
425
#  if __has_feature(thread_sanitizer)
426
#    undef CAMLno_tsan
427
#    define CAMLno_tsan __attribute__((no_sanitize("thread")))
428
#  endif
429
#  if __has_feature(address_sanitizer)
430
#    undef CAMLno_asan
431
#    define CAMLno_asan __attribute__((no_sanitize("address")))
432
#  endif
433
#endif
434
435
#endif /* CAML_INTERNALS */
436
437
/* The [backtrace_slot] type represents values stored in
438
 * [Caml_state->backtrace_buffer].  In bytecode, it is the same as a
439
 * [code_t], in native code it is either a [frame_descr *] or a [debuginfo],
440
 * depending on the second-lowest bit.  In any case, the lowest bit must
441
 * be 0.
442
 * The representation doesn't matter for code outside [backtrace_{byt,nat}.c],
443
 * so it is just exposed as a [void *].
444
 */
445
typedef void * backtrace_slot;
446
447
#ifdef __cplusplus
448
}
449
#endif
450
451
#endif /* CAML_MISC_H */