~ubuntu-branches/ubuntu/lucid/gauche-c-wrapper/lucid

« back to all changes in this revision

Viewing changes to libffi/src/prep_cif.c

  • Committer: Bazaar Package Importer
  • Author(s): NIIBE Yutaka
  • Date: 2008-04-07 09:15:03 UTC
  • Revision ID: james.westby@ubuntu.com-20080407091503-wu0h414koe95kj4i
Tags: upstream-0.5.2
ImportĀ upstreamĀ versionĀ 0.5.2

Show diffs side-by-side

added added

removed removed

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