summaryrefslogtreecommitdiff
path: root/m4/malloc-align.m4
blob: 11682da01ae0affd6fd381412ade5ea2b99af954 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# malloc-align.m4 serial 1
dnl Copyright (C) 2020-2023 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.

dnl Defines a C macro MALLOC_ALIGNMENT, whose value is a numeric constant,
dnl a power of 2, with the property that
dnl   (uintptr_t) malloc (N)
dnl is always guaranteed to be a multiple of MALLOC_ALIGNMENT.

AC_DEFUN([gl_MALLOC_ALIGNMENT],
[
  AC_REQUIRE([AC_CANONICAL_HOST])
  AC_CACHE_CHECK([for the malloc() alignment],
    [gl_cv_malloc_alignment],
    [gl_cv_malloc_alignment=
     AC_RUN_IFELSE(
       [AC_LANG_PROGRAM(
          [[#include <stdio.h>
            #include <stdlib.h>
            #if defined _WIN32 && !defined __CYGWIN__
            # include <inttypes.h>
            /* uintptr_t is equivalent to 'unsigned long long' if _WIN64,
               or to 'unsigned long' otherwise.  */
            #else
            # undef uintptr_t
            # define uintptr_t unsigned long
            #endif
          ]],
          [[FILE *fp = fopen ("conftest.out", "w");
            if (fp == NULL)
              return 1;
            {
              uintptr_t bits = 0;
              bits |= (uintptr_t) malloc (1);
              bits |= (uintptr_t) malloc (1);
              bits |= (uintptr_t) malloc (1);
              bits |= (uintptr_t) malloc (2);
              bits |= (uintptr_t) malloc (2);
              bits |= (uintptr_t) malloc (2);
              bits |= (uintptr_t) malloc (3);
              bits |= (uintptr_t) malloc (3);
              bits |= (uintptr_t) malloc (3);
              bits |= (uintptr_t) malloc (5);
              bits |= (uintptr_t) malloc (8);
              bits |= (uintptr_t) malloc (8);
              bits |= (uintptr_t) malloc (13);
              bits |= (uintptr_t) malloc (13);
              bits |= (uintptr_t) malloc (19);
              bits |= (uintptr_t) malloc (19);
              bits |= (uintptr_t) malloc (28);
              bits |= (uintptr_t) malloc (28);
              bits |= (uintptr_t) malloc (37);
              bits |= (uintptr_t) malloc (37);
              bits |= (uintptr_t) malloc (73);
              bits |= (uintptr_t) malloc (73);
              bits |= (uintptr_t) malloc (117);
              bits |= (uintptr_t) malloc (117);
              bits |= (uintptr_t) malloc (351);
              bits |= (uintptr_t) malloc (351);
              bits |= (uintptr_t) malloc (914);
              bits |= (uintptr_t) malloc (914);
              bits |= (uintptr_t) malloc (1712);
              bits |= (uintptr_t) malloc (1712);
              bits |= (uintptr_t) malloc (4021);
              bits |= (uintptr_t) malloc (4021);
              bits |= (uintptr_t) malloc (7641);
              bits |= (uintptr_t) malloc (7641);
              bits |= (uintptr_t) malloc (17027);
              bits |= (uintptr_t) malloc (17027);
              bits |= (uintptr_t) malloc (81231);
              bits |= (uintptr_t) malloc (81231);
              fprintf (fp, "%u\n", (unsigned int) (((bits ^ (bits - 1)) + 1) >> 1));
            }
            if (fclose (fp) != 0)
              return 2;
            return 0;
          ]])
       ],
       [gl_cv_malloc_alignment=`cat conftest.out`],
       [gl_cv_malloc_alignment="unknown"],
       [dnl When cross-compiling, guess a value. Note that it's OK to return
        dnl a smaller value (e.g. 4 instead of 8 or 16).
        gl_cv_malloc_alignment="unknown"
        case "$host_os" in
          linux* | mingw*)
            dnl On Linux:
            dnl - It's 8 on most 32-bit platforms, except 16 on x86_64-x32 and
            dnl   (with newer versions of glibc) on i386 and powerpc.  8 is a
            dnl   safe guess.
            dnl - It's 16 on all 64-bit platforms.
            dnl On Windows: It's 8 on 32-bit Windows, 16 on 64-bit Windows.
            for nn in 4 8 16 32; do
              AC_COMPILE_IFELSE(
                [AC_LANG_PROGRAM([[
                   #define MALLOC_ALIGN (2 * sizeof (void *))
                   int test [MALLOC_ALIGN <= $nn ? 1 : -1];
                   ]])
                ],
                [gl_cv_malloc_alignment="guessing $nn"
                 break
                ],
                [:])
            done
            ;;
          *)
            dnl If we don't know, assume the worst.
            dnl This minimum is e.g. reached on NetBSD/i386 and NetBSD/sparc.
            for nn in 4 8 16; do
              AC_COMPILE_IFELSE(
                [AC_LANG_PROGRAM([[
                   #define MALLOC_ALIGN (sizeof (void *))
                   int test [MALLOC_ALIGN <= $nn ? 1 : -1];
                   ]])
                ],
                [gl_cv_malloc_alignment="guessing $nn"
                 break
                ],
                [:])
            done
            ;;
        esac
       ])
    ])
  case "$gl_cv_malloc_alignment" in
    "unknown")
      dnl Assume the worst.
      value=4
    ;;
    "guessing "*)
      value=`echo "$gl_cv_malloc_alignment" | sed -e 's/guessing //'`
      ;;
    *)
      value="$gl_cv_malloc_alignment"
      ;;
  esac
  AC_DEFINE_UNQUOTED([MALLOC_ALIGNMENT], [$value],
    [Define to the guaranteed alignment of malloc() return values.])
])