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

Last change on this file since 72 was 72, checked in by gb, 14 years ago

Synthesize 256-bit vector types (AVX), too.

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