source: trunk/ffigen4/source/ffi.c@ 44

Last change on this file since 44 was 44, checked in by gb, 16 years ago

There seems to be an issue with (at least) anonymous unions that have the 'transparent_union' attribute. The symptom is:

1) a type for such a union is generated and passed to the debug hook 'ffi_debug_type_decl', and we output it. This type doesn't seem to have the transparent_union attribute bit set (yet).

2) later, a type declaration that (conceptually) refers to this anonymous type; the anonymous union object which is the target type is not EQ to the one which we've processed (and, in fact, we've never seen the target type object before, though we saw another anonymous union with the same fields.

A crude workaround is check for this case when processing a typedef and emit the new type (the anonymous union) before emitting the deftype; that means that both versions of the anonymous union are written to the .ffi file (one of them referenced and the other not.)

It's not clear that this is an adequate fix: there may be other ways of referencing these types (e.g., via a pointer type or as a record field). This does seem to fix the one case I saw (involving the
SOCKADDR_ARG and CONST_SOCKADDR_ARG types in <sys/socket.h> on Linux. Really handling that case
might involve other FFI changes not related to the translator.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 31.1 KB
Line 
1/* ffi.c - generate .ffi file from .h file
2 Copyright (C) 2001, 2005 Clozure Associates.
3 Copyright (C) 2004, Helmut Eller
4
5This file is part of GNU CC (or, more accurately, part of a work
6derived from GNU CC.)
7
8GNU CC is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; either version 2, or (at your option)
11any later version.
12
13GNU CC is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with GNU CC; see the file COPYING. If not, write to
20the Free Software Foundation, 59 Temple Place - Suite 330,
21Boston, MA 02111-1307, USA. */
22
23#include "config.h"
24#include "system.h"
25#include "coretypes.h"
26#include "tm.h"
27#include "tree.h"
28#include "c-tree.h"
29#include "c-common.h"
30#include "ggc.h"
31#include "flags.h"
32#include "debug.h"
33#include "diagnostic.h" /* for errorcount */
34#include "objc/objc-act.h"
35#include "ffi-version.h"
36
37/* Prototypes */
38
39void ffi_rest_of_decl_compilation (tree, int, int);
40void ffi_rest_of_type_compilation (tree, int);
41void ffi_early_init (void);
42void ffi_init (FILE *_file, char *);
43void ffi_rest_of_objc_class_compilation (tree);
44void ffi_rest_of_objc_category_compilation (tree);
45void print_ffi_version(FILE *, char *);
46
47
48
49void
50print_ffi_version(FILE *out, char *indent)
51{
52 fprintf (out, "%s%sFFIGEN version %s\n", indent, *indent != 0 ? " " : "", ffi_version);
53}
54
55FILE *ffifile;
56
57int ffi_initialized = 0;
58
59struct ffi_input_file {
60 char *pathname;
61 struct ffi_input_file *prev;
62};
63
64struct ffi_input_file *current_ffi_input_file = NULL;
65char *ffi_current_source_file;
66char *ffi_primary_source_file;
67
68static int ffi_indent_count = 1;
69
70static void
71ffi_debug_start_source_file (unsigned int line ATTRIBUTE_UNUSED,
72 const char *file)
73{
74 struct ffi_input_file *savef = xmalloc (sizeof *savef);
75 ffi_indent_count = 1;
76 savef->pathname = ffi_current_source_file;
77 savef->prev = current_ffi_input_file;
78 current_ffi_input_file = savef;
79 ffi_current_source_file = (char *) xstrdup (file);
80}
81
82static void
83ffi_debug_end_source_file (unsigned lineno ATTRIBUTE_UNUSED)
84{
85 struct ffi_input_file *currf = current_ffi_input_file;
86 current_ffi_input_file = currf->prev;
87 free (ffi_current_source_file);
88 ffi_current_source_file = currf->pathname;
89 free (currf);
90}
91
92static void
93ffi_indent (void)
94{
95 int i;
96
97 fprintf (ffifile, "\n");
98
99 for (i = 0; i < ffi_indent_count; i++) {
100 fprintf (ffifile, " ");
101 }
102 ffi_indent_count++;
103}
104
105static void
106ffi_unindent (int n)
107{
108 ffi_indent_count -= n;
109}
110
111enum ffi_typestatus {FFI_TYPE_UNDEFINED = 0,
112 FFI_TYPE_PRIMITIVE,
113 FFI_TYPE_TYPEDEF,
114 FFI_TYPE_STRUCT,
115 FFI_TYPE_UNION,
116 FFI_TYPE_ENUM,
117 FFI_TYPE_POINTER,
118 FFI_TYPE_FUNCTION,
119 FFI_TYPE_ARRAY,
120 FFI_TYPE_FIELD};
121
122static void ffi_define_type (tree decl, enum ffi_typestatus status);
123
124
125struct ffi_typeinfo {
126 enum ffi_typestatus status;
127 int type_number;
128 tree type;
129 const char *name;
130 char *source_file;
131 unsigned source_line;
132 int ref_type_number; /* For pointer & array types, at least */
133 int array_size;
134 int first_field;
135};
136
137struct ffi_typeinfo *ffi_typevec;
138
139static void ffi_emit_type (struct ffi_typeinfo *, tree);
140
141int ffi_typevec_len = 0;
142int next_ffi_type_number = 1;
143
144typedef struct {
145 const char *gcc_name;
146 const char *ffi_name;
147} ffi_primitive_name_map;
148
149static ffi_primitive_name_map ffi_primitive_names[] =
150{
151 {"int", "int"},
152 {"char", "char"},
153 {"float", "float"},
154 {"double", "double"},
155 {"long double", "long-double"},
156 {"void", "void"},
157 {"long int", "long"},
158 {"unsigned int", "unsigned"},
159 {"long unsigned int", "unsigned-long"},
160 {"long long int", "long-long"},
161 {"long long unsigned int", "unsigned-long-long"},
162 {"short int", "short"},
163 {"short unsigned int", "unsigned-short"},
164 {"signed char", "signed-char"},
165 {"unsigned char", "unsigned-char"},
166 {"complex int", "complex-int"},
167 {"complex float", "complex-float"},
168 {"complex double", "complex-double"},
169 {"complex long double", "complex-long-double"},
170 {"__vector unsigned char", "__vector-unsigned-char"},
171 {"__vector signed char", "__vector-signed-char"},
172 {"__vector bool char", "__vector-bool-char"},
173 {"__vector unsigned short", "__vector-unsigned-short"},
174 {"__vector signed short", "__vector-signed-short"},
175 {"__vector bool short", "__vector-bool-short"},
176 {"__vector unsigned long", "__vector-unsigned-long"},
177 {"__vector signed long", "__vector-signed-long"},
178 {"__vector bool long", "__vector-bool-long"},
179 {"__vector float", "__vector-short-float"},
180 {"__vector pixel", "__vector-pixel"},
181 {"__vector", "__vector"},
182 {"_Bool", "unsigned"},
183 {"__int128_t", "long-long-long"},
184 {"__uint128_t", "unsigned-long-long-long"},
185 {NULL, NULL}
186};
187
188/* Return the Lisp'y name for the type GCC_NAME */
189static char *
190to_primitive_type_name (char* gcc_name)
191{
192 ffi_primitive_name_map *map = ffi_primitive_names;
193 for (; map->gcc_name; ++map)
194 if (!strcmp (map->gcc_name, gcc_name))
195 return (char*)map->ffi_name;
196 fprintf (stderr, "Bug: couldn't find primitive name for %s\n", gcc_name);
197 abort ();
198}
199
200static char *
201ffi_primitive_type_name (tree decl)
202{
203 char *gcc_name = (char*)IDENTIFIER_POINTER (DECL_NAME (decl));
204 return to_primitive_type_name (gcc_name);
205}
206
207static struct ffi_typeinfo *
208find_ffi_type_info (tree type)
209{
210 int index = TYPE_SYMTAB_ADDRESS (type);
211 struct ffi_typeinfo * info;
212
213 if (index == 0)
214 {
215 index = next_ffi_type_number++;
216 TYPE_SYMTAB_ADDRESS (type) = index;
217
218 if (next_ffi_type_number == ffi_typevec_len)
219 {
220 ffi_typevec
221 = (struct ffi_typeinfo *) xrealloc (ffi_typevec,
222 ffi_typevec_len * 2 *
223 sizeof ffi_typevec[0]);
224 memset ((char *) (ffi_typevec + ffi_typevec_len), 0,
225 ffi_typevec_len * sizeof ffi_typevec[0]);
226 ffi_typevec_len *= 2;
227 }
228 }
229
230 info = ffi_typevec + index;
231 info->type_number = index;
232 info->type = type;
233 return info;
234}
235
236
237/*
238 'type' may be an unnamed scalar type. Why does it even exist ?
239*/
240static struct ffi_typeinfo *
241ffi_maybe_synthesize_integer_type (tree type, struct ffi_typeinfo *info)
242{
243 if (TREE_CODE (type) == INTEGER_TYPE)
244 {
245
246 int is_unsigned = TYPE_UNSIGNED (type);
247 HOST_WIDE_INT nbytes = int_size_in_bytes (type);
248
249 switch (nbytes)
250 {
251 case 1:
252 info->name = is_unsigned ? "unsigned-char" : "signed-char";
253 info->status = FFI_TYPE_PRIMITIVE;
254 break;
255 case 2:
256 info->name = is_unsigned ? "unsigned-short" : "short";
257 info->status = FFI_TYPE_PRIMITIVE;
258 break;
259 case 4:
260 info->name = is_unsigned ? "unsigned" : "int";
261 info->status = FFI_TYPE_PRIMITIVE;
262 break;
263 case 8:
264 info->name = is_unsigned ? "unsigned-long-long" : "long-long";
265 info->status = FFI_TYPE_PRIMITIVE;
266 break;
267 case 16:
268 info->name = is_unsigned ? "unsigned-long-long-long" : "long-long-long";
269 info->status = FFI_TYPE_PRIMITIVE;
270 break;
271 }
272 }
273 return info;
274}
275
276static struct ffi_typeinfo *
277ffi_maybe_synthesize_vector_type (tree type, struct ffi_typeinfo *info)
278{
279 if (TREE_CODE (type) == VECTOR_TYPE)
280 {
281
282 HOST_WIDE_INT nbytes = int_size_in_bytes (type);
283
284 switch (nbytes)
285 {
286 case 16:
287 info->name = "vec128";
288 info->status = FFI_TYPE_PRIMITIVE;
289 break;
290 case 8:
291 info->name = "vec64";
292 info->status = FFI_TYPE_PRIMITIVE;
293 break;
294 default:
295 break;
296 }
297 }
298 return info;
299}
300
301
302
303static struct ffi_typeinfo *
304ffi_create_type_info (tree type)
305{
306 struct ffi_typeinfo *info;
307 tree lookup_type = type;
308
309 if (TYPE_READONLY (type) || TYPE_VOLATILE (type))
310 lookup_type = TYPE_MAIN_VARIANT (type);
311
312 info = find_ffi_type_info (lookup_type);
313
314 if (info->status != FFI_TYPE_UNDEFINED)
315 return info;
316
317
318 switch (TREE_CODE (type))
319 {
320
321 case POINTER_TYPE:
322 case REFERENCE_TYPE:
323 {
324 tree pointer_target_type = TREE_TYPE (type);
325 struct ffi_typeinfo *pointer_type_info;
326
327 info->status = FFI_TYPE_POINTER;
328 pointer_type_info = ffi_create_type_info (pointer_target_type);
329
330 /* 'info' might have moved */
331 info = find_ffi_type_info (type);
332 info->ref_type_number = pointer_type_info->type_number;
333 }
334 break;
335
336 case FUNCTION_TYPE:
337 {
338 tree arg_type;
339 info->status = FFI_TYPE_FUNCTION;
340 ffi_create_type_info (TREE_TYPE (type));
341 for (arg_type = TYPE_ARG_TYPES (type); arg_type; arg_type = TREE_CHAIN (arg_type))
342 {
343 ffi_create_type_info (TREE_VALUE (arg_type));
344 }
345 info = find_ffi_type_info (type);
346 }
347 break;
348
349 case ARRAY_TYPE:
350 {
351 tree array_element_type = TREE_TYPE (type);
352 struct ffi_typeinfo *element_type_info;
353 int array_size_in_bits = 0, element_size_in_bits, array_size_in_elements;
354
355 info->status = FFI_TYPE_ARRAY;
356 element_type_info = ffi_create_type_info (array_element_type);
357 info = find_ffi_type_info (type);
358 info->ref_type_number = element_type_info->type_number;
359 element_size_in_bits = TREE_INT_CST_LOW ( TYPE_SIZE (array_element_type));
360 if (TYPE_SIZE (type))
361 array_size_in_bits = TREE_INT_CST_LOW ( TYPE_SIZE (type));
362 array_size_in_elements = array_size_in_bits / element_size_in_bits;
363 if (array_size_in_bits % element_size_in_bits)
364 {
365 fprintf (stderr, "screw : array size not integral\n");
366 abort ();
367 }
368 info->array_size = array_size_in_elements;
369 }
370 break;
371
372 case RECORD_TYPE:
373 case UNION_TYPE:
374 case ENUMERAL_TYPE:
375 {
376 tree field;
377 tree name = TYPE_NAME (type);
378 if (name)
379 {
380 if (TREE_CODE (name) == IDENTIFIER_NODE)
381 info->name = (char *) xstrdup (IDENTIFIER_POINTER (name));
382 else if (TREE_CODE (name) == TYPE_DECL
383 && DECL_NAME (name))
384 info->name = (char *) xstrdup (IDENTIFIER_POINTER (DECL_NAME (name)));
385 }
386 if (! info->name)
387 {
388 char buf[2048];
389 sprintf(buf, "%d_%s", info->type_number, ffi_primary_source_file);
390 info->name = (char *) xstrdup (buf);
391 }
392 if (TREE_CODE (type) == ENUMERAL_TYPE)
393 {
394 info->status = FFI_TYPE_ENUM;
395 break;
396 }
397
398 info->status = (TREE_CODE (type) == RECORD_TYPE) ? FFI_TYPE_STRUCT : FFI_TYPE_UNION;
399
400 for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
401 {
402 ffi_create_type_info (TREE_TYPE (field));
403 }
404 info = find_ffi_type_info (type);
405 }
406 break;
407 case VOID_TYPE:
408 ffi_define_type (TYPE_NAME (type), FFI_TYPE_PRIMITIVE);
409 info = ffi_create_type_info (type);
410 break;
411 case INTEGER_TYPE:
412 case VECTOR_TYPE:
413 if (TREE_CODE (type) == INTEGER_TYPE)
414 info = ffi_maybe_synthesize_integer_type (type, info);
415 else
416 info = ffi_maybe_synthesize_vector_type (type, info);
417 if (info->status != FFI_TYPE_UNDEFINED)
418 return info;
419 /* else fall through */
420 default:
421 fprintf (stderr, "Need to create info for type:\n");
422 debug_tree (type);
423 abort ();
424 }
425 return info;
426}
427
428static void
429emit_ffi_type_reference (tree target_type)
430{
431 struct ffi_typeinfo *info;
432 tree lookup_type = target_type;
433
434 if (TYPE_READONLY (target_type) || TYPE_VOLATILE (target_type))
435 lookup_type = TYPE_MAIN_VARIANT (target_type);
436
437 info = ffi_create_type_info (lookup_type);
438
439 switch (info->status)
440 {
441 case FFI_TYPE_PRIMITIVE:
442 fprintf (ffifile, "(%s ())", info->name); /* No quotes around primitive name. */
443 return;
444
445 case FFI_TYPE_TYPEDEF:
446 fprintf (ffifile, "(typedef \"%s\")", info->name);
447 return;
448
449 case FFI_TYPE_FUNCTION:
450 {
451 tree arg, arg_type;
452 /* struct ffi_typeinfo *arg_type_info; */
453 /*
454 It seems like functions that take a fixed number of arguments
455 have a "void" argument after the fixed arguments, while those
456 that take an indefinite number don't.
457 That's perfectly sane, but the opposite of what LCC does.
458 So, if there's a "void" argument at the end of the arglist,
459 don't emit it; if there wasn't, emit one.
460 Sheesh.
461 */
462 int had_void_arg = 0, args_emitted = 0;
463 fprintf (ffifile, "(function");
464 ffi_indent ();
465 fprintf (ffifile, "(");
466 for (arg = TYPE_ARG_TYPES (target_type); arg ; arg = TREE_CHAIN (arg))
467 {
468 if (args_emitted)
469 fprintf (ffifile, " ");
470 arg_type = TREE_VALUE (arg);
471 if (TREE_CODE (arg_type) != VOID_TYPE) {
472 emit_ffi_type_reference (arg_type);
473 args_emitted = 1;
474 }
475 else
476 {
477 had_void_arg = 1;
478 break;
479 }
480 }
481 if (! had_void_arg) {
482 if (args_emitted)
483 fprintf (ffifile, " ");
484 fprintf (ffifile, "(void ())");
485 }
486 fprintf (ffifile, ")");
487 ffi_unindent (1);
488 ffi_indent ();
489 arg_type = TREE_TYPE (target_type);
490 emit_ffi_type_reference (arg_type);
491 ffi_unindent (1);
492 fprintf (ffifile, ")");
493 }
494 break;
495
496 case FFI_TYPE_POINTER:
497 {
498 tree pointer_target = TREE_TYPE (target_type);
499
500 fprintf (ffifile, "(pointer ");
501 emit_ffi_type_reference (pointer_target);
502 fprintf (ffifile, ")");
503 return;
504 }
505
506 case FFI_TYPE_STRUCT:
507 fprintf (ffifile, "(struct-ref \"%s\")", info->name);
508 break;
509
510 case FFI_TYPE_UNION:
511 fprintf (ffifile, "(union-ref \"%s\")", info->name);
512 break;
513
514 case FFI_TYPE_ENUM:
515 fprintf (ffifile, "(enum-ref \"%s\")", info->name);
516 break;
517
518 case FFI_TYPE_ARRAY:
519 {
520 tree element_type = TREE_TYPE (target_type);
521
522 fprintf (ffifile, "(array %d ", info->array_size);
523 emit_ffi_type_reference (element_type);
524 fprintf (ffifile, ")");
525 }
526 break;
527
528 default:
529 fprintf (stderr, "need to emit reference to this type\n");
530 debug_tree (target_type);
531 abort ();
532 }
533}
534
535static void
536ffi_emit_type_decl (struct ffi_typeinfo *info, tree decl)
537{
538 /* struct ffi_typeinfo *target_info; */
539 tree target;
540 struct ffi_typeinfo *target_info;
541
542 if (TREE_ASM_WRITTEN (decl))
543 return;
544
545
546 target = DECL_ORIGINAL_TYPE (decl);
547 if (target == NULL)
548 target = TREE_TYPE (decl);
549
550 TREE_ASM_WRITTEN (decl) = 1;
551
552 if (! TYPE_SYMTAB_ADDRESS (target))
553 switch (TREE_CODE (target))
554 {
555 case RECORD_TYPE:
556 case UNION_TYPE:
557 target_info = ffi_create_type_info (target);
558 ffi_emit_type (target_info, target);
559 break;
560 default:
561 break;
562 }
563
564 fprintf (ffifile, "(type (\"%s\" %d)", info->source_file, info->source_line);
565 ffi_indent ();
566 fprintf (ffifile, "\"%s\"", info->name);
567 ffi_unindent (1);
568 ffi_indent ();
569 emit_ffi_type_reference (target);
570 ffi_unindent (1);
571 fprintf (ffifile, ")\n");
572}
573
574static char *
575ffi_decl_name (tree decl)
576{
577 return (char*) (DECL_NAME (decl)
578 ? IDENTIFIER_POINTER (DECL_NAME (decl))
579 : "");
580}
581
582static void
583ffi_emit_integer_constant (tree val)
584{
585 if (TREE_CODE (val) != INTEGER_CST)
586 {
587 fprintf (stderr, "Expected integer_cst, got:\n");
588 debug_tree (val);
589 abort ();
590 }
591 if (TREE_INT_CST_HIGH (val) == 0)
592 fprintf (ffifile, HOST_WIDE_INT_PRINT_UNSIGNED, TREE_INT_CST_LOW (val));
593 else if (TREE_INT_CST_HIGH (val) == -1
594 && TREE_INT_CST_LOW (val) != 0)
595 {
596 fprintf (ffifile, "-");
597 fprintf (ffifile, HOST_WIDE_INT_PRINT_UNSIGNED,
598 -TREE_INT_CST_LOW (val));
599 }
600 else
601 fprintf (ffifile, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
602 TREE_INT_CST_HIGH (val), TREE_INT_CST_LOW (val));
603}
604
605static void
606ffi_emit_enum_values (tree val)
607{
608 fprintf (ffifile, "(");
609 while (val)
610 {
611 fprintf (ffifile, "(\"%s\" ", IDENTIFIER_POINTER (TREE_PURPOSE (val)));
612 ffi_emit_integer_constant (TREE_VALUE (val));
613 fprintf (ffifile, ")");
614 val = TREE_CHAIN (val);
615 }
616 fprintf (ffifile, ")");
617}
618
619static void
620ffi_herald (tree decl, const char *prefix)
621{
622 const char *source_file = "";
623 int line = 0;
624
625 if (DECL_P (decl))
626 {
627 source_file = DECL_SOURCE_FILE (decl);
628 line = DECL_SOURCE_LINE (decl);
629 }
630
631 if (source_file == NULL)
632 source_file = "";
633
634 fprintf (ffifile, "(%s (\"%s\" %d)", prefix, source_file, line);
635}
636
637static void
638ffi_emit_enum_idents (tree val)
639{
640 while (val)
641 {
642 fprintf (ffifile, "(enum-ident (\"\" 0)");
643 ffi_indent ();
644 fprintf (ffifile, "\"%s\" ", IDENTIFIER_POINTER (TREE_PURPOSE (val)));
645 ffi_emit_integer_constant (TREE_VALUE (val));
646 ffi_unindent (1);
647 fprintf(ffifile, ")\n");
648 val = TREE_CHAIN (val);
649 }
650}
651
652/*
653 It's hard to know exactly how to translate bit-fields.
654 LCC only allows bit-fields to be of type "int" or "unsigned" (and
655 doesn't even allow aliases to these types to be used.)
656 LCC-FFIGEN therefore generates something like:
657
658 ("x" (bit-field ("<type>" ()) <start-byte> <size-in-bytes> <a> <b> <c> <d>))
659
660 where :
661 <type> is one of int, unsigned
662 <start-byte, size-in-bytes> refer to a properly-aligned fullword that
663 "contains" the bit-field
664 <a> is what lcc calls the "fieldleft" of the bit-field
665 <b> is what lcc calls the "fieldright" of the bit-field
666 <c> is the width of the bit-field
667 <d> is a mask: (1- (ash 1 <c>))
668
669 Hmm. That doesn't have too much to do with the information that GCC
670 provides, but we could probably fake it. It seems silly to discard
671 the information that GCC -does- provide, so let's instead generate:
672
673 ("x" (bitfield ("<type>" ()) <start-bit> <size-in-bits>))
674
675 where <start-bit> is the field position starting in bits, of
676 the bit closest to the beginning of the structure.
677
678 Note that a GCC FIELD_DECL node X denotes a bit-field iff
679 DECL_BIT_FIELD (X) is true and DECL_SIZE (X) is non-null.
680*/
681
682static void
683ffi_emit_field_list (tree field, int public_only)
684{
685 int indentp = 0;
686 ffi_indent ();
687 fprintf (ffifile, "(");
688 for (; field; field = TREE_CHAIN (field), indentp = 1)
689 {
690 if (!public_only || (!TREE_PRIVATE (field)))
691 {
692 /*
693 fprintf (stderr, "\nEmit field:\n");
694 debug_tree (field);
695 */
696 if (indentp)
697 ffi_indent ();
698 if (DECL_BIT_FIELD (field))
699 {
700 tree type = DECL_BIT_FIELD_TYPE (field);
701 int bit_position = int_bit_position (field);
702 int size_in_bits = tree_low_cst (DECL_SIZE (field), 1);
703 fprintf (ffifile, "(\"%s\" (bitfield ", ffi_decl_name (field));
704 emit_ffi_type_reference (type);
705 fprintf (ffifile, " %d %d))", bit_position, size_in_bits);
706 }
707 else
708 {
709 tree type = TREE_TYPE (field);
710 int bit_position = int_bit_position (field);
711 tree size = TYPE_SIZE (type);
712 int type_size = (size
713 ? tree_low_cst (size, 1)
714 : 0); /* flex array */
715 fprintf (ffifile, "(\"%s\" (field ", ffi_decl_name (field));
716 emit_ffi_type_reference (type);
717 fprintf (ffifile, " %d %d))", bit_position >> 3, type_size >> 3);
718 }
719 if (indentp)
720 ffi_unindent (1);
721 }
722 }
723 fprintf (ffifile, ")");
724 ffi_unindent (1);
725}
726
727static void
728ffi_emit_type (struct ffi_typeinfo *info, tree type)
729{
730 char *source_file = (char*) (info->source_file ? info->source_file : "");
731 int line_number = info->source_line;
732 /* tree field; */
733
734
735 switch (info->status)
736 {
737 case FFI_TYPE_STRUCT:
738 fprintf (ffifile, "(struct (\"%s\" %d)", source_file, line_number);
739 ffi_indent ();
740 fprintf (ffifile, "\"%s\"", info->name);
741 ffi_unindent (1);
742 ffi_emit_field_list (TYPE_FIELDS (type), 0);
743 fprintf (ffifile, ")\n");
744 break;
745
746 case FFI_TYPE_UNION:
747 fprintf (ffifile, "(union (\"%s\" %d)", source_file, line_number);
748 ffi_indent ();
749 fprintf (ffifile, "\"%s\"", info->name);
750 ffi_unindent (1);
751 ffi_emit_field_list (TYPE_FIELDS (type), 0);
752 fprintf (ffifile, ")\n");
753 break;
754
755 case FFI_TYPE_ENUM:
756 fprintf (ffifile, "(enum (\"%s\" %d)", source_file, line_number);
757 ffi_indent ();
758 fprintf (ffifile, "\"%s\"", info->name);
759 ffi_unindent (1);
760 ffi_emit_enum_values (TYPE_VALUES (type));
761 fprintf (ffifile, ")\n");
762 ffi_emit_enum_idents (TYPE_VALUES (type));
763 break;
764
765 default:
766 fprintf (stderr, "Unknown type!\n");
767 debug_tree (type);
768 abort ();
769 }
770}
771
772static void
773ffi_define_type (tree decl, enum ffi_typestatus status)
774{
775 tree type = TREE_TYPE(decl);
776 struct ffi_typeinfo *info = find_ffi_type_info (type);
777
778 /* fprintf (stderr, "Defining this type\n");
779 debug_tree (type);
780 */
781 switch (status)
782 {
783 case FFI_TYPE_PRIMITIVE:
784 info->name = ffi_primitive_type_name (decl);
785 info->source_file = NULL;
786 info->source_line = 0;
787 break;
788 case FFI_TYPE_TYPEDEF:
789 info->name = (char *) xstrdup(IDENTIFIER_POINTER (DECL_NAME (decl)));
790 info->source_file = (char *) xstrdup (DECL_SOURCE_FILE (decl));
791 info->source_line = DECL_SOURCE_LINE (decl);
792 ffi_emit_type_decl (info, decl);
793 break;
794 default:
795 fprintf (stderr, "Ignoring this type\n");
796 debug_tree (type);
797 abort ();
798 }
799 info = find_ffi_type_info (type); /* Might have moved. */
800 info->status = status;
801}
802
803static void
804ffi_define_builtin_type (tree type)
805{
806 tree name;
807
808 if (type && TYPE_P (type))
809 switch (TREE_CODE (type))
810 {
811 case INTEGER_TYPE:
812 case REAL_TYPE:
813 case COMPLEX_TYPE:
814 case VOID_TYPE:
815 case CHAR_TYPE:
816 case BOOLEAN_TYPE:
817 case VECTOR_TYPE:
818 name = TYPE_NAME (type);
819 if (name)
820 ffi_define_type (name, FFI_TYPE_PRIMITIVE);
821 else {
822 fprintf(stderr, "Unnamed builtin vector type:\n");
823 debug_tree(type);
824 }
825 break;
826 case POINTER_TYPE:
827 case ARRAY_TYPE:
828 ffi_create_type_info (type);
829 break;
830 default:
831 fprintf (stderr, "\nSkippped this type.\n");
832 debug_tree(type);
833 break;
834 }
835}
836
837
838
839
840static void
841ffi_define_variable (tree decl)
842{
843 tree type = TREE_TYPE (decl);
844
845 ffi_herald (decl, "var");
846 ffi_indent ();
847 fprintf (ffifile, "\"%s\"", IDENTIFIER_POINTER (DECL_NAME (decl)));
848 ffi_unindent (1);
849 ffi_indent ();
850 emit_ffi_type_reference (type);
851 if (DECL_EXTERNAL (decl))
852 fprintf (ffifile, " (extern))\n");
853 else
854 fprintf (ffifile, " (static))\n");
855 ffi_unindent (1);
856}
857
858static void
859ffi_define_function (tree decl)
860{
861 tree type = TREE_TYPE (decl);
862
863 ffi_herald (decl, "function");
864 ffi_indent ();
865 fprintf (ffifile, "\"%s\"", IDENTIFIER_POINTER (DECL_NAME (decl)));
866 ffi_unindent (1);
867 ffi_indent ();
868 emit_ffi_type_reference (TYPE_MAIN_VARIANT(type));
869 if (DECL_EXTERNAL (decl))
870 fprintf (ffifile, " (extern))\n");
871 else
872 fprintf (ffifile, " (static))\n");
873 ffi_unindent (1);
874}
875
876
877
878/*
879 Stolen/copied from 'objc_method_parm_type' in objc-act.c
880*/
881static tree
882ffi_objc_method_parm_type (tree type)
883{
884 type = TREE_VALUE (TREE_TYPE (type));
885 if (TREE_CODE (type) == TYPE_DECL)
886 type = TREE_TYPE (type);
887#if 0
888 return TYPE_MAIN_VARIANT (type);
889#else
890 return type;
891#endif
892}
893
894
895static void
896ffi_define_objc_class (tree node)
897{
898 const char *super_name = NULL;
899 tree
900 pl = CLASS_PROTOCOL_LIST (node),
901 p;
902
903 if (CLASS_SUPER_NAME (node))
904 super_name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (node));
905
906
907 ffi_herald (node, "objc-class");
908 ffi_indent ();
909 fprintf (ffifile, "\"%s\"", IDENTIFIER_POINTER (CLASS_NAME (node)));
910 ffi_unindent (1);
911 ffi_indent ();
912 fprintf (ffifile, "(");
913 if (super_name)
914 fprintf (ffifile, "\"%s\")", super_name);
915 else
916 fprintf (ffifile, "void)");
917 ffi_unindent (1);
918 ffi_indent ();
919 fprintf (ffifile, "(");
920 for (pl = CLASS_PROTOCOL_LIST (node); pl; pl = TREE_CHAIN (pl))
921 {
922 p = TREE_VALUE (pl);
923 fprintf(ffifile, "\"%s\"", IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
924 if (TREE_CHAIN (pl))
925 fprintf (ffifile, " ");
926 }
927 fprintf (ffifile, ")");
928 ffi_unindent (1);
929 ffi_emit_field_list (CLASS_IVARS (node), 1);
930 fprintf (ffifile, ")\n");
931}
932
933static void
934ffi_define_objc_method (const char *method_kind, tree m, tree c, const char *category_name)
935{
936 tree param;
937 int i;
938
939 ffi_herald(m, method_kind);
940 ffi_indent ();
941 fprintf (ffifile, "\"%s\"", IDENTIFIER_POINTER (CLASS_NAME (c)));
942 ffi_unindent(1);
943 ffi_indent ();
944 if (category_name)
945 fprintf (ffifile, "(\"%s\")", category_name);
946 else
947 fprintf (ffifile, "()");
948 ffi_unindent (1);
949 ffi_indent ();
950 fprintf (ffifile, "\"%s\"", IDENTIFIER_POINTER (METHOD_SEL_NAME (m)));
951 ffi_unindent (1);
952 ffi_indent ();
953 fprintf (ffifile, "(");
954 for (i = 0, param = METHOD_SEL_ARGS (m);
955 param;
956 i++, param = TREE_CHAIN (param)) {
957 if (i > 0) {
958 fprintf (ffifile, " ");
959 }
960 emit_ffi_type_reference (ffi_objc_method_parm_type (param));
961 }
962 if (METHOD_ADD_ARGS (m))
963 if (TREE_PUBLIC (METHOD_ADD_ARGS (m)))
964 {
965 if (i)
966 fprintf (ffifile, " ");
967 fprintf (ffifile, "(void ())");
968 }
969 fprintf (ffifile, ")");
970 ffi_unindent (1);
971 ffi_indent ();
972 emit_ffi_type_reference (ffi_objc_method_parm_type (m));
973 ffi_unindent (1);
974 fprintf (ffifile, ")\n");
975}
976
977
978static void
979ffi_define_objc_class_method (tree m, tree c, const char *category_name)
980{
981 ffi_define_objc_method ("objc-class-method", m, c, category_name);
982}
983
984static void
985ffi_define_objc_instance_method (tree m, tree c, const char *category_name)
986{
987 ffi_define_objc_method ("objc-instance-method", m, c, category_name);
988}
989
990void
991ffi_rest_of_objc_class_compilation (tree node)
992{
993 tree n;
994 char *category_name = NULL;
995
996 ffi_define_objc_class (node);
997
998 for (n = CLASS_CLS_METHODS (node); n; n = TREE_CHAIN (n))
999 ffi_define_objc_class_method (n, node, category_name);
1000 for (n = CLASS_NST_METHODS (node); n; n = TREE_CHAIN (n))
1001 ffi_define_objc_instance_method (n, node, category_name);
1002}
1003
1004void
1005ffi_rest_of_objc_category_compilation (tree category)
1006{
1007 tree n;
1008 const char *category_name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (category));
1009
1010 for (n = CLASS_CLS_METHODS (category); n; n = TREE_CHAIN (n))
1011 ffi_define_objc_class_method (n, category, category_name);
1012 for (n = CLASS_NST_METHODS (category); n; n = TREE_CHAIN (n))
1013 ffi_define_objc_instance_method (n, category, category_name);
1014}
1015
1016void
1017ffi_rest_of_objc_protocol_compilation (tree p)
1018{
1019 tree n;
1020 char *category_name;
1021
1022 for (n = PROTOCOL_CLS_METHODS (p); n; n = TREE_CHAIN (n))
1023 ffi_define_objc_method ("objc-protocol-class-method",
1024 n,
1025 p,
1026 category_name);
1027 for (n = PROTOCOL_NST_METHODS (p); n; n = TREE_CHAIN (n))
1028 ffi_define_objc_method ("objc-protocol-instance-method",
1029 n,
1030 p,
1031 category_name);
1032}
1033
1034void
1035ffi_rest_of_decl_compilation (tree decl,
1036 int top_level ATTRIBUTE_UNUSED,
1037 int at_end ATTRIBUTE_UNUSED)
1038{
1039 /* tree type = TREE_TYPE (decl); */
1040
1041 if ((! ffi_initialized) || errorcount)
1042 return;
1043
1044
1045 if (TREE_CODE (decl) == ERROR_MARK)
1046 return;
1047
1048#if 0
1049 fprintf(stderr, "ffi_rest_of_decl_compilation:\n");
1050 debug_tree(decl);
1051 fprintf(stderr, "\n");
1052#endif
1053
1054
1055 switch (TREE_CODE (decl))
1056 {
1057 case TYPE_DECL:
1058 break;
1059
1060 case FUNCTION_DECL:
1061 ffi_define_function (decl);
1062 break;
1063
1064 case VAR_DECL:
1065 if (DECL_SOURCE_LINE (decl))
1066 ffi_define_variable (decl);
1067 break;
1068
1069 case PARM_DECL:
1070 case RESULT_DECL:
1071 fprintf(stderr, " ??? Parm or Result \n");
1072 debug_tree (decl);
1073 abort ();
1074 break;
1075
1076 case CONST_DECL:
1077 fprintf(stderr, " --- Maybe an enum ?\n");
1078 debug_tree (decl);
1079 abort ();
1080 break;
1081
1082 default:
1083 fprintf(stderr, " ??? Unknown \n");
1084 debug_tree (decl);
1085 abort ();
1086 break;
1087 }
1088}
1089
1090void
1091ffi_rest_of_type_compilation (tree type, int top_level ATTRIBUTE_UNUSED)
1092{
1093 if ((! ffi_initialized) || errorcount)
1094 return;
1095
1096 if (TREE_CODE (type) == ERROR_MARK)
1097 return;
1098
1099 ffi_emit_type (ffi_create_type_info (type), type);
1100}
1101
1102static int
1103is_whitespace (char c)
1104{
1105 switch (c)
1106 {
1107 case ' ': case '\n': case '\t': case '\f': case '\r':
1108 return 1;
1109 default:
1110 return 0;
1111 }
1112}
1113
1114/*
1115 Emit the macro name (possibly including a parenthesized arglist).
1116 Surround whatever's emitted here with double quotes.
1117 Return a pointer to the first character of the (possibly empty) definition.
1118*/
1119static const char *
1120ffi_emit_macro_name (const char *p)
1121{
1122 int in_arglist = 0;
1123 char c;
1124
1125 putc ('\"', ffifile);
1126 while ((c = *p) != 0)
1127 {
1128 switch (c)
1129 {
1130 case '(':
1131 in_arglist = 1;
1132 /* Fall down */
1133 case ',':
1134 putc (' ', ffifile);
1135 putc (c, ffifile);
1136 putc (' ', ffifile);
1137 break;
1138
1139 case ')':
1140 putc (' ', ffifile);
1141 putc (c, ffifile);
1142 putc ('\"', ffifile);
1143
1144 while (is_whitespace (*++p));
1145 return p;
1146
1147 default:
1148 if (is_whitespace (c) && !in_arglist)
1149 {
1150 putc ('\"', ffifile);
1151 while (is_whitespace (*++p));
1152 return p;
1153 }
1154 putc (c, ffifile);
1155 }
1156 ++p;
1157 }
1158 putc ('\"', ffifile);
1159 return p;
1160}
1161
1162static void
1163ffi_emit_macro_expansion (char *p)
1164{
1165 char c;
1166 char *q = p + strlen (p);
1167
1168 while ((q > p) && is_whitespace (q[-1])) q--;
1169 *q = '\0';
1170
1171 fprintf (ffifile, " \"");
1172
1173 while ((c = *p++) != '\0')
1174 {
1175 if (c == '\"')
1176 fputc ('\\', ffifile);
1177 fputc (c, ffifile);
1178 }
1179 fputc ('\"', ffifile);
1180}
1181
1182static void
1183ffi_debug_define (unsigned lineno, const char *macro)
1184{
1185 if (ffifile) {
1186 fprintf (ffifile, "(macro (\"%s\" %d) ", ffi_current_source_file, lineno);
1187 ffi_emit_macro_expansion ((char*)ffi_emit_macro_name (macro));
1188 fprintf (ffifile, ")\n");
1189 }
1190}
1191
1192static void
1193ffi_debug_undef (unsigned lineno ATTRIBUTE_UNUSED, const char *buffer)
1194{
1195 fprintf (ffifile, "(undef-macro \"%s\")\n", buffer);
1196}
1197
1198static void
1199ffi_debug_type_decl (tree decl, int local)
1200{
1201 tree type;
1202
1203 if (errorcount)
1204 return;
1205
1206 if ((! local) && ffi_initialized) {
1207 switch (TREE_CODE (decl))
1208 {
1209 case TYPE_DECL:
1210 type = TREE_TYPE (decl);
1211 if (DECL_NAME (decl))
1212 ffi_define_type (decl, FFI_TYPE_TYPEDEF);
1213 else
1214 {
1215 if (TREE_CODE (type) != ERROR_MARK)
1216 ffi_emit_type (ffi_create_type_info (type), type);
1217 }
1218 break;
1219
1220 default:
1221 fprintf (stderr, "Huh?");
1222 debug_tree (decl);
1223 abort ();
1224 }
1225 }
1226}
1227
1228
1229static struct gcc_debug_hooks ffi_debug_hooks;
1230
1231void
1232ffi_early_init (void)
1233{
1234 ffi_typevec_len = 100;
1235 ffi_typevec = xmalloc (ffi_typevec_len * sizeof ffi_typevec[0]);
1236 memset ((char *) ffi_typevec, 0, ffi_typevec_len * sizeof ffi_typevec[0]);
1237 /* Override debug hooks for macros. We don't emit assembly, so this
1238 shouldn't cause problems. */
1239 memcpy (&ffi_debug_hooks, &do_nothing_debug_hooks, sizeof ffi_debug_hooks);
1240 ffi_debug_hooks.start_source_file = ffi_debug_start_source_file;
1241 ffi_debug_hooks.end_source_file = ffi_debug_end_source_file;
1242 ffi_debug_hooks.define = ffi_debug_define;
1243 ffi_debug_hooks.undef = ffi_debug_undef;
1244 ffi_debug_hooks.type_decl = ffi_debug_type_decl;
1245 debug_hooks = &ffi_debug_hooks;
1246}
1247
1248void
1249ffi_init (FILE *ffi_file, char *input_file_name)
1250{
1251 int i;
1252
1253 ffifile = ffi_file ? ffi_file : stderr;
1254 ffi_current_source_file = (char *) xstrdup (input_file_name);
1255 ffi_primary_source_file = ffi_current_source_file;
1256
1257 for (i = 0; i < itk_none; i++)
1258 {
1259 ffi_define_builtin_type (integer_types[i]);
1260 }
1261 for (i = 0; i < TI_MAX; i++)
1262 {
1263 ffi_define_builtin_type (global_trees[i]);
1264 }
1265
1266
1267 ffi_initialized = 1;
1268}
1269
Note: See TracBrowser for help on using the repository browser.