Coverage Report

Created: 2025-07-12 07:23

/src/glib-2.80.0/subprojects/libffi/src/prep_cif.c
Line
Count
Source (jump to first uncovered line)
1
/* -----------------------------------------------------------------------
2
   prep_cif.c - Copyright (c) 2011, 2012  Anthony Green
3
                Copyright (c) 1996, 1998, 2007  Red Hat, Inc.
4
5
   Permission is hereby granted, free of charge, to any person obtaining
6
   a copy of this software and associated documentation files (the
7
   ``Software''), to deal in the Software without restriction, including
8
   without limitation the rights to use, copy, modify, merge, publish,
9
   distribute, sublicense, and/or sell copies of the Software, and to
10
   permit persons to whom the Software is furnished to do so, subject to
11
   the following conditions:
12
13
   The above copyright notice and this permission notice shall be included
14
   in all copies or substantial portions of the Software.
15
16
   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
17
   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
   DEALINGS IN THE SOFTWARE.
24
   ----------------------------------------------------------------------- */
25
26
#include <ffi.h>
27
#include <ffi_common.h>
28
#include <stdlib.h>
29
30
/* Round up to FFI_SIZEOF_ARG. */
31
32
#define STACK_ARG_SIZE(x) FFI_ALIGN(x, FFI_SIZEOF_ARG)
33
34
/* Perform machine independent initialization of aggregate type
35
   specifications. */
36
37
static ffi_status initialize_aggregate(ffi_type *arg, size_t *offsets)
38
0
{
39
0
  ffi_type **ptr;
40
41
0
  if (UNLIKELY(arg == NULL || arg->elements == NULL))
42
0
    return FFI_BAD_TYPEDEF;
43
44
0
  arg->size = 0;
45
0
  arg->alignment = 0;
46
47
0
  ptr = &(arg->elements[0]);
48
49
0
  if (UNLIKELY(ptr == 0))
50
0
    return FFI_BAD_TYPEDEF;
51
52
0
  while ((*ptr) != NULL)
53
0
    {
54
0
      if (UNLIKELY(((*ptr)->size == 0)
55
0
        && (initialize_aggregate((*ptr), NULL) != FFI_OK)))
56
0
  return FFI_BAD_TYPEDEF;
57
58
      /* Perform a sanity check on the argument type */
59
0
      FFI_ASSERT_VALID_TYPE(*ptr);
60
61
0
      arg->size = FFI_ALIGN(arg->size, (*ptr)->alignment);
62
0
      if (offsets)
63
0
  *offsets++ = arg->size;
64
0
      arg->size += (*ptr)->size;
65
66
0
      arg->alignment = (arg->alignment > (*ptr)->alignment) ?
67
0
  arg->alignment : (*ptr)->alignment;
68
69
0
      ptr++;
70
0
    }
71
72
  /* Structure size includes tail padding.  This is important for
73
     structures that fit in one register on ABIs like the PowerPC64
74
     Linux ABI that right justify small structs in a register.
75
     It's also needed for nested structure layout, for example
76
     struct A { long a; char b; }; struct B { struct A x; char y; };
77
     should find y at an offset of 2*sizeof(long) and result in a
78
     total size of 3*sizeof(long).  */
79
0
  arg->size = FFI_ALIGN (arg->size, arg->alignment);
80
81
  /* On some targets, the ABI defines that structures have an additional
82
     alignment beyond the "natural" one based on their elements.  */
83
#ifdef FFI_AGGREGATE_ALIGNMENT
84
  if (FFI_AGGREGATE_ALIGNMENT > arg->alignment)
85
    arg->alignment = FFI_AGGREGATE_ALIGNMENT;
86
#endif
87
88
0
  if (arg->size == 0)
89
0
    return FFI_BAD_TYPEDEF;
90
0
  else
91
0
    return FFI_OK;
92
0
}
93
94
#ifndef __CRIS__
95
/* The CRIS ABI specifies structure elements to have byte
96
   alignment only, so it completely overrides this functions,
97
   which assumes "natural" alignment and padding.  */
98
99
/* Perform machine independent ffi_cif preparation, then call
100
   machine dependent routine. */
101
102
/* For non variadic functions isvariadic should be 0 and
103
   nfixedargs==ntotalargs.
104
105
   For variadic calls, isvariadic should be 1 and nfixedargs
106
   and ntotalargs set as appropriate. nfixedargs must always be >=1 */
107
108
109
ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi,
110
           unsigned int isvariadic,
111
                             unsigned int nfixedargs,
112
                             unsigned int ntotalargs,
113
           ffi_type *rtype, ffi_type **atypes)
114
0
{
115
0
  unsigned bytes = 0;
116
0
  unsigned int i;
117
0
  ffi_type **ptr;
118
119
0
  FFI_ASSERT(cif != NULL);
120
0
  FFI_ASSERT((!isvariadic) || (nfixedargs >= 1));
121
0
  FFI_ASSERT(nfixedargs <= ntotalargs);
122
123
0
  if (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI))
124
0
    return FFI_BAD_ABI;
125
126
0
  cif->abi = abi;
127
0
  cif->arg_types = atypes;
128
0
  cif->nargs = ntotalargs;
129
0
  cif->rtype = rtype;
130
131
0
  cif->flags = 0;
132
133
#ifdef _M_ARM64
134
  cif->isVariadic = isvariadic;
135
#endif
136
#if HAVE_LONG_DOUBLE_VARIANT
137
  ffi_prep_types (abi);
138
#endif
139
140
  /* Initialize the return type if necessary */
141
0
  if ((cif->rtype->size == 0)
142
0
      && (initialize_aggregate(cif->rtype, NULL) != FFI_OK))
143
0
    return FFI_BAD_TYPEDEF;
144
145
#ifndef FFI_TARGET_HAS_COMPLEX_TYPE
146
  if (rtype->type == FFI_TYPE_COMPLEX)
147
    abort();
148
#endif
149
  /* Perform a sanity check on the return type */
150
0
  FFI_ASSERT_VALID_TYPE(cif->rtype);
151
152
  /* x86, x86-64 and s390 stack space allocation is handled in prep_machdep. */
153
#if !defined FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
154
  /* Make space for the return structure pointer */
155
  if (cif->rtype->type == FFI_TYPE_STRUCT
156
#ifdef TILE
157
      && (cif->rtype->size > 10 * FFI_SIZEOF_ARG)
158
#endif
159
#ifdef XTENSA
160
      && (cif->rtype->size > 16)
161
#endif
162
#ifdef NIOS2
163
      && (cif->rtype->size > 8)
164
#endif
165
     )
166
    bytes = STACK_ARG_SIZE(sizeof(void*));
167
#endif
168
169
0
  for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
170
0
    {
171
172
      /* Initialize any uninitialized aggregate type definitions */
173
0
      if (((*ptr)->size == 0)
174
0
    && (initialize_aggregate((*ptr), NULL) != FFI_OK))
175
0
  return FFI_BAD_TYPEDEF;
176
177
#ifndef FFI_TARGET_HAS_COMPLEX_TYPE
178
      if ((*ptr)->type == FFI_TYPE_COMPLEX)
179
  abort();
180
#endif
181
      /* Perform a sanity check on the argument type, do this
182
   check after the initialization.  */
183
0
      FFI_ASSERT_VALID_TYPE(*ptr);
184
185
#if !defined FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
186
  {
187
    /* Add any padding if necessary */
188
    if (((*ptr)->alignment - 1) & bytes)
189
      bytes = (unsigned)FFI_ALIGN(bytes, (*ptr)->alignment);
190
191
#ifdef TILE
192
    if (bytes < 10 * FFI_SIZEOF_ARG &&
193
        bytes + STACK_ARG_SIZE((*ptr)->size) > 10 * FFI_SIZEOF_ARG)
194
      {
195
        /* An argument is never split between the 10 parameter
196
     registers and the stack.  */
197
        bytes = 10 * FFI_SIZEOF_ARG;
198
      }
199
#endif
200
#ifdef XTENSA
201
    if (bytes <= 6*4 && bytes + STACK_ARG_SIZE((*ptr)->size) > 6*4)
202
      bytes = 6*4;
203
#endif
204
205
    bytes += (unsigned int)STACK_ARG_SIZE((*ptr)->size);
206
  }
207
#endif
208
0
    }
209
210
0
  cif->bytes = bytes;
211
212
  /* Perform machine dependent cif processing */
213
#ifdef FFI_TARGET_SPECIFIC_VARIADIC
214
  if (isvariadic)
215
  return ffi_prep_cif_machdep_var(cif, nfixedargs, ntotalargs);
216
#endif
217
218
0
  return ffi_prep_cif_machdep(cif);
219
0
}
220
#endif /* not __CRIS__ */
221
222
ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
223
           ffi_type *rtype, ffi_type **atypes)
224
0
{
225
0
  return ffi_prep_cif_core(cif, abi, 0, nargs, nargs, rtype, atypes);
226
0
}
227
228
ffi_status ffi_prep_cif_var(ffi_cif *cif,
229
                            ffi_abi abi,
230
                            unsigned int nfixedargs,
231
                            unsigned int ntotalargs,
232
                            ffi_type *rtype,
233
                            ffi_type **atypes)
234
0
{
235
0
  return ffi_prep_cif_core(cif, abi, 1, nfixedargs, ntotalargs, rtype, atypes);
236
0
}
237
238
#if FFI_CLOSURES
239
240
ffi_status
241
ffi_prep_closure (ffi_closure* closure,
242
      ffi_cif* cif,
243
      void (*fun)(ffi_cif*,void*,void**,void*),
244
      void *user_data)
245
0
{
246
0
  return ffi_prep_closure_loc (closure, cif, fun, user_data, closure);
247
0
}
248
249
#endif
250
251
ffi_status
252
ffi_get_struct_offsets (ffi_abi abi, ffi_type *struct_type, size_t *offsets)
253
0
{
254
0
  if (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI))
255
0
    return FFI_BAD_ABI;
256
0
  if (struct_type->type != FFI_TYPE_STRUCT)
257
0
    return FFI_BAD_TYPEDEF;
258
259
#if HAVE_LONG_DOUBLE_VARIANT
260
  ffi_prep_types (abi);
261
#endif
262
263
0
  return initialize_aggregate(struct_type, offsets);
264
0
}