1 /* com.c -- Implementation File (module.c template V1.0)
2 Copyright (C) 1995-1998 Free Software Foundation, Inc.
3 Contributed by James Craig Burley.
5 This file is part of GNU Fortran.
7 GNU Fortran is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Fortran is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Fortran; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
26 Contains compiler-specific functions.
31 /* Understanding this module means understanding the interface between
32 the g77 front end and the gcc back end (or, perhaps, some other
33 back end). In here are the functions called by the front end proper
34 to notify whatever back end is in place about certain things, and
35 also the back-end-specific functions. It's a bear to deal with, so
36 lately I've been trying to simplify things, especially with regard
37 to the gcc-back-end-specific stuff.
39 Building expressions generally seems quite easy, but building decls
40 has been challenging and is undergoing revision. gcc has several
43 TYPE_DECL -- a type (int, float, struct, function, etc.)
44 CONST_DECL -- a constant of some type other than function
45 LABEL_DECL -- a variable or a constant?
46 PARM_DECL -- an argument to a function (a variable that is a dummy)
47 RESULT_DECL -- the return value of a function (a variable)
48 VAR_DECL -- other variable (can hold a ptr-to-function, struct, int, etc.)
49 FUNCTION_DECL -- a function (either the actual function or an extern ref)
50 FIELD_DECL -- a field in a struct or union (goes into types)
52 g77 has a set of functions that somewhat parallels the gcc front end
53 when it comes to building decls:
55 Internal Function (one we define, not just declare as extern):
57 yes = suspend_momentary ();
58 if (is_nested) push_f_function_context ();
59 start_function (get_identifier ("function_name"), function_type,
60 is_nested, is_public);
61 // for each arg, build PARM_DECL and call push_parm_decl (decl) with it;
62 store_parm_decls (is_main_program);
63 ffecom_start_compstmt ();
64 // for stmts and decls inside function, do appropriate things;
65 ffecom_end_compstmt ();
66 finish_function (is_nested);
67 if (is_nested) pop_f_function_context ();
68 if (is_nested) resume_momentary (yes);
74 yes = suspend_momentary ();
75 // fill in external, public, static, &c for decl, and
76 // set DECL_INITIAL to error_mark_node if going to initialize
77 // set is_top_level TRUE only if not at top level and decl
78 // must go in top level (i.e. not within current function decl context)
79 d = start_decl (decl, is_top_level);
80 init = ...; // if have initializer
81 finish_decl (d, init, is_top_level);
82 resume_momentary (yes);
89 #if FFECOM_targetCURRENT == FFECOM_targetGCC
94 #include "output.j" /* Must follow tree.j so TREE_CODE is defined! */
96 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
98 #define FFECOM_GCC_INCLUDE 1 /* Enable -I. */
100 /* BEGIN stuff from gcc/cccp.c. */
102 /* The following symbols should be autoconfigured:
109 In the mean time, we'll get by with approximations based
110 on existing GCC configuration symbols. */
113 # ifndef HAVE_STDLIB_H
114 # define HAVE_STDLIB_H 1
116 # ifndef HAVE_UNISTD_H
117 # define HAVE_UNISTD_H 1
119 # ifndef STDC_HEADERS
120 # define STDC_HEADERS 1
122 #endif /* defined (POSIX) */
124 #if defined (POSIX) || (defined (USG) && !defined (VMS))
125 # ifndef HAVE_FCNTL_H
126 # define HAVE_FCNTL_H 1
133 # if TIME_WITH_SYS_TIME
134 # include <sys/time.h>
138 # include <sys/time.h>
143 # include <sys/resource.h>
150 /* This defines "errno" properly for VMS, and gives us EACCES. */
163 /* VMS-specific definitions */
166 #define O_RDONLY 0 /* Open arg for Read/Only */
167 #define O_WRONLY 1 /* Open arg for Write/Only */
168 #define read(fd,buf,size) VMS_read (fd,buf,size)
169 #define write(fd,buf,size) VMS_write (fd,buf,size)
170 #define open(fname,mode,prot) VMS_open (fname,mode,prot)
171 #define fopen(fname,mode) VMS_fopen (fname,mode)
172 #define freopen(fname,mode,ofile) VMS_freopen (fname,mode,ofile)
173 #define strncat(dst,src,cnt) VMS_strncat (dst,src,cnt)
174 #define fstat(fd,stbuf) VMS_fstat (fd,stbuf)
175 static int VMS_fstat (), VMS_stat ();
176 static char * VMS_strncat ();
177 static int VMS_read ();
178 static int VMS_write ();
179 static int VMS_open ();
180 static FILE * VMS_fopen ();
181 static FILE * VMS_freopen ();
182 static void hack_vms_include_specification ();
183 typedef struct { unsigned :16, :16, :16; } vms_ino_t;
184 #define ino_t vms_ino_t
185 #define INCLUDE_LEN_FUDGE 10 /* leave room for VMS syntax conversion */
187 #define BSTRING /* VMS/GCC supplies the bstring routines */
188 #endif /* __GNUC__ */
195 /* END stuff from gcc/cccp.c. */
197 #define FFECOM_DETERMINE_TYPES 1 /* for com.h */
214 /* Externals defined here. */
216 #if FFECOM_targetCURRENT == FFECOM_targetGCC
218 /* tree.h declares a bunch of stuff that it expects the front end to
219 define. Here are the definitions, which in the C front end are
220 found in the file c-decl.c. */
222 tree integer_zero_node;
223 tree integer_one_node;
224 tree null_pointer_node;
225 tree error_mark_node;
227 tree integer_type_node;
228 tree unsigned_type_node;
230 tree current_function_decl;
232 /* ~~gcc/tree.h *should* declare this, because toplev.c and dwarfout.c
235 char *language_string = "GNU F77";
237 /* Stream for reading from the input file. */
240 /* These definitions parallel those in c-decl.c so that code from that
241 module can be used pretty much as is. Much of these defs aren't
242 otherwise used, i.e. by g77 code per se, except some of them are used
243 to build some of them that are. The ones that are global (i.e. not
244 "static") are those that ste.c and such might use (directly
245 or by using com macros that reference them in their definitions). */
247 static tree short_integer_type_node;
248 tree long_integer_type_node;
249 static tree long_long_integer_type_node;
251 static tree short_unsigned_type_node;
252 static tree long_unsigned_type_node;
253 static tree long_long_unsigned_type_node;
255 static tree unsigned_char_type_node;
256 static tree signed_char_type_node;
258 static tree float_type_node;
259 static tree double_type_node;
260 static tree complex_float_type_node;
261 tree complex_double_type_node;
262 static tree long_double_type_node;
263 static tree complex_integer_type_node;
264 static tree complex_long_double_type_node;
266 tree string_type_node;
268 static tree double_ftype_double;
269 static tree float_ftype_float;
270 static tree ldouble_ftype_ldouble;
272 /* The rest of these are inventions for g77, though there might be
273 similar things in the C front end. As they are found, these
274 inventions should be renamed to be canonical. Note that only
275 the ones currently required to be global are so. */
277 static tree ffecom_tree_fun_type_void;
278 static tree ffecom_tree_ptr_to_fun_type_void;
280 tree ffecom_integer_type_node; /* Abbrev for _tree_type[blah][blah]. */
281 tree ffecom_integer_zero_node; /* Like *_*_* with g77's integer type. */
282 tree ffecom_integer_one_node; /* " */
283 tree ffecom_tree_type[FFEINFO_basictype][FFEINFO_kindtype];
285 /* _fun_type things are the f2c-specific versions. For -fno-f2c,
286 just use build_function_type and build_pointer_type on the
287 appropriate _tree_type array element. */
289 static tree ffecom_tree_fun_type[FFEINFO_basictype][FFEINFO_kindtype];
290 static tree ffecom_tree_ptr_to_fun_type[FFEINFO_basictype][FFEINFO_kindtype];
291 static tree ffecom_tree_subr_type;
292 static tree ffecom_tree_ptr_to_subr_type;
293 static tree ffecom_tree_blockdata_type;
295 static tree ffecom_tree_xargc_;
297 ffecomSymbol ffecom_symbol_null_
306 ffeinfoKindtype ffecom_pointer_kind_ = FFEINFO_basictypeNONE;
307 ffeinfoKindtype ffecom_label_kind_ = FFEINFO_basictypeNONE;
309 int ffecom_f2c_typecode_[FFEINFO_basictype][FFEINFO_kindtype];
310 tree ffecom_f2c_integer_type_node;
311 tree ffecom_f2c_ptr_to_integer_type_node;
312 tree ffecom_f2c_address_type_node;
313 tree ffecom_f2c_real_type_node;
314 tree ffecom_f2c_ptr_to_real_type_node;
315 tree ffecom_f2c_doublereal_type_node;
316 tree ffecom_f2c_complex_type_node;
317 tree ffecom_f2c_doublecomplex_type_node;
318 tree ffecom_f2c_longint_type_node;
319 tree ffecom_f2c_logical_type_node;
320 tree ffecom_f2c_flag_type_node;
321 tree ffecom_f2c_ftnlen_type_node;
322 tree ffecom_f2c_ftnlen_zero_node;
323 tree ffecom_f2c_ftnlen_one_node;
324 tree ffecom_f2c_ftnlen_two_node;
325 tree ffecom_f2c_ptr_to_ftnlen_type_node;
326 tree ffecom_f2c_ftnint_type_node;
327 tree ffecom_f2c_ptr_to_ftnint_type_node;
328 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
330 /* Simple definitions and enumerations. */
332 #ifndef FFECOM_sizeMAXSTACKITEM
333 #define FFECOM_sizeMAXSTACKITEM 32*1024 /* Keep user-declared things
334 larger than this # bytes
335 off stack if possible. */
338 /* For systems that have large enough stacks, they should define
339 this to 0, and here, for ease of use later on, we just undefine
342 #if FFECOM_sizeMAXSTACKITEM == 0
343 #undef FFECOM_sizeMAXSTACKITEM
349 FFECOM_rttypeVOIDSTAR_, /* C's `void *' type. */
350 FFECOM_rttypeFTNINT_, /* f2c's `ftnint' type. */
351 FFECOM_rttypeINTEGER_, /* f2c's `integer' type. */
352 FFECOM_rttypeLONGINT_, /* f2c's `longint' type. */
353 FFECOM_rttypeLOGICAL_, /* f2c's `logical' type. */
354 FFECOM_rttypeREAL_F2C_, /* f2c's `real' returned as `double'. */
355 FFECOM_rttypeREAL_GNU_, /* `real' returned as such. */
356 FFECOM_rttypeCOMPLEX_F2C_, /* f2c's `complex' returned via 1st arg. */
357 FFECOM_rttypeCOMPLEX_GNU_, /* f2c's `complex' returned directly. */
358 FFECOM_rttypeDOUBLE_, /* C's `double' type. */
359 FFECOM_rttypeDOUBLEREAL_, /* f2c's `doublereal' type. */
360 FFECOM_rttypeDBLCMPLX_F2C_, /* f2c's `doublecomplex' returned via 1st arg. */
361 FFECOM_rttypeDBLCMPLX_GNU_, /* f2c's `doublecomplex' returned directly. */
362 FFECOM_rttypeCHARACTER_, /* f2c `char *'/`ftnlen' pair. */
366 /* Internal typedefs. */
368 #if FFECOM_targetCURRENT == FFECOM_targetGCC
369 typedef struct _ffecom_concat_list_ ffecomConcatList_;
370 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
372 /* Private include files. */
375 /* Internal structure definitions. */
377 #if FFECOM_targetCURRENT == FFECOM_targetGCC
378 struct _ffecom_concat_list_
383 ffetargetCharacterSize minlen;
384 ffetargetCharacterSize maxlen;
386 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
388 /* Static functions (internal). */
390 #if FFECOM_targetCURRENT == FFECOM_targetGCC
391 static tree ffecom_arglist_expr_ (const char *argstring, ffebld args);
392 static tree ffecom_widest_expr_type_ (ffebld list);
393 static bool ffecom_overlap_ (tree dest_decl, tree dest_offset,
394 tree dest_size, tree source_tree,
395 ffebld source, bool scalar_arg);
396 static bool ffecom_args_overlapping_ (tree dest_tree, ffebld dest,
397 tree args, tree callee_commons,
399 static tree ffecom_build_f2c_string_ (int i, const char *s);
400 static tree ffecom_call_ (tree fn, ffeinfoKindtype kt,
401 bool is_f2c_complex, tree type,
402 tree args, tree dest_tree,
403 ffebld dest, bool *dest_used,
404 tree callee_commons, bool scalar_args, tree hook);
405 static tree ffecom_call_binop_ (tree fn, ffeinfoKindtype kt,
406 bool is_f2c_complex, tree type,
407 ffebld left, ffebld right,
408 tree dest_tree, ffebld dest,
409 bool *dest_used, tree callee_commons,
410 bool scalar_args, tree hook);
411 static void ffecom_char_args_x_ (tree *xitem, tree *length,
412 ffebld expr, bool with_null);
413 static tree ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy);
414 static tree ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s);
415 static ffecomConcatList_
416 ffecom_concat_list_gather_ (ffecomConcatList_ catlist,
418 ffetargetCharacterSize max);
419 static void ffecom_concat_list_kill_ (ffecomConcatList_ catlist);
420 static ffecomConcatList_ ffecom_concat_list_new_ (ffebld expr,
421 ffetargetCharacterSize max);
422 static void ffecom_debug_kludge_ (tree aggr, const char *aggr_type,
423 ffesymbol member, tree member_type,
424 ffetargetOffset offset);
425 static void ffecom_do_entry_ (ffesymbol fn, int entrynum);
426 static tree ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
427 bool *dest_used, bool assignp, bool widenp);
428 static tree ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
429 ffebld dest, bool *dest_used);
430 static tree ffecom_expr_power_integer_ (ffebld expr);
431 static void ffecom_expr_transform_ (ffebld expr);
432 static void ffecom_f2c_make_type_ (tree *type, int tcode, const char *name);
433 static void ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size,
435 static ffeglobal ffecom_finish_global_ (ffeglobal global);
436 static ffesymbol ffecom_finish_symbol_transform_ (ffesymbol s);
437 static tree ffecom_get_appended_identifier_ (char us, const char *text);
438 static tree ffecom_get_external_identifier_ (ffesymbol s);
439 static tree ffecom_get_identifier_ (const char *text);
440 static tree ffecom_gen_sfuncdef_ (ffesymbol s,
443 static const char *ffecom_gfrt_args_ (ffecomGfrt ix);
444 static tree ffecom_gfrt_tree_ (ffecomGfrt ix);
445 static tree ffecom_init_zero_ (tree decl);
446 static tree ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg,
448 static tree ffecom_intrinsic_len_ (ffebld expr);
449 static void ffecom_let_char_ (tree dest_tree,
451 ffetargetCharacterSize dest_size,
453 static void ffecom_make_gfrt_ (ffecomGfrt ix);
454 static void ffecom_member_phase1_ (ffestorag mst, ffestorag st);
455 #ifdef SOMEONE_GETS_DEBUG_SUPPORT_WORKING
456 static void ffecom_member_phase2_ (ffestorag mst, ffestorag st);
458 static void ffecom_prepare_let_char_ (ffetargetCharacterSize dest_size,
460 static void ffecom_push_dummy_decls_ (ffebld dumlist,
462 static void ffecom_start_progunit_ (void);
463 static ffesymbol ffecom_sym_transform_ (ffesymbol s);
464 static ffesymbol ffecom_sym_transform_assign_ (ffesymbol s);
465 static void ffecom_transform_common_ (ffesymbol s);
466 static void ffecom_transform_equiv_ (ffestorag st);
467 static tree ffecom_transform_namelist_ (ffesymbol s);
468 static void ffecom_tree_canonize_ptr_ (tree *decl, tree *offset,
470 static void ffecom_tree_canonize_ref_ (tree *decl, tree *offset,
471 tree *size, tree tree);
472 static tree ffecom_tree_divide_ (tree tree_type, tree left, tree right,
473 tree dest_tree, ffebld dest,
474 bool *dest_used, tree hook);
475 static tree ffecom_type_localvar_ (ffesymbol s,
478 static tree ffecom_type_namelist_ (void);
480 static tree ffecom_type_permanent_copy_ (tree t);
482 static tree ffecom_type_vardesc_ (void);
483 static tree ffecom_vardesc_ (ffebld expr);
484 static tree ffecom_vardesc_array_ (ffesymbol s);
485 static tree ffecom_vardesc_dims_ (ffesymbol s);
486 static tree ffecom_convert_narrow_ (tree type, tree expr);
487 static tree ffecom_convert_widen_ (tree type, tree expr);
488 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
490 /* These are static functions that parallel those found in the C front
491 end and thus have the same names. */
493 #if FFECOM_targetCURRENT == FFECOM_targetGCC
494 static tree bison_rule_compstmt_ (void);
495 static void bison_rule_pushlevel_ (void);
496 static tree builtin_function (const char *name, tree type,
497 enum built_in_function function_code,
498 const char *library_name);
499 static void delete_block (tree block);
500 static int duplicate_decls (tree newdecl, tree olddecl);
501 static void finish_decl (tree decl, tree init, bool is_top_level);
502 static void finish_function (int nested);
503 static char *lang_printable_name (tree decl, int v);
504 static tree lookup_name_current_level (tree name);
505 static struct binding_level *make_binding_level (void);
506 static void pop_f_function_context (void);
507 static void push_f_function_context (void);
508 static void push_parm_decl (tree parm);
509 static tree pushdecl_top_level (tree decl);
510 static int kept_level_p (void);
511 static tree storedecls (tree decls);
512 static void store_parm_decls (int is_main_program);
513 static tree start_decl (tree decl, bool is_top_level);
514 static void start_function (tree name, tree type, int nested, int public);
515 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
516 #if FFECOM_GCC_INCLUDE
517 static void ffecom_file_ (char *name);
518 static void ffecom_initialize_char_syntax_ (void);
519 static void ffecom_close_include_ (FILE *f);
520 static int ffecom_decode_include_option_ (char *spec);
521 static FILE *ffecom_open_include_ (char *name, ffewhereLine l,
523 #endif /* FFECOM_GCC_INCLUDE */
525 /* Static objects accessed by functions in this module. */
527 static ffesymbol ffecom_primary_entry_ = NULL;
528 static ffesymbol ffecom_nested_entry_ = NULL;
529 static ffeinfoKind ffecom_primary_entry_kind_;
530 static bool ffecom_primary_entry_is_proc_;
531 #if FFECOM_targetCURRENT == FFECOM_targetGCC
532 static tree ffecom_outer_function_decl_;
533 static tree ffecom_previous_function_decl_;
534 static tree ffecom_which_entrypoint_decl_;
535 static tree ffecom_float_zero_ = NULL_TREE;
536 static tree ffecom_float_half_ = NULL_TREE;
537 static tree ffecom_double_zero_ = NULL_TREE;
538 static tree ffecom_double_half_ = NULL_TREE;
539 static tree ffecom_func_result_;/* For functions. */
540 static tree ffecom_func_length_;/* For CHARACTER fns. */
541 static ffebld ffecom_list_blockdata_;
542 static ffebld ffecom_list_common_;
543 static ffebld ffecom_master_arglist_;
544 static ffeinfoBasictype ffecom_master_bt_;
545 static ffeinfoKindtype ffecom_master_kt_;
546 static ffetargetCharacterSize ffecom_master_size_;
547 static int ffecom_num_fns_ = 0;
548 static int ffecom_num_entrypoints_ = 0;
549 static bool ffecom_is_altreturning_ = FALSE;
550 static tree ffecom_multi_type_node_;
551 static tree ffecom_multi_retval_;
553 ffecom_multi_fields_[FFEINFO_basictype][FFEINFO_kindtype];
554 static bool ffecom_member_namelisted_; /* _member_phase1_ namelisted? */
555 static bool ffecom_doing_entry_ = FALSE;
556 static bool ffecom_transform_only_dummies_ = FALSE;
557 static int ffecom_typesize_pointer_;
558 static int ffecom_typesize_integer1_;
560 /* Holds pointer-to-function expressions. */
562 static tree ffecom_gfrt_[FFECOM_gfrt]
565 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) NULL_TREE,
566 #include "com-rt.def"
570 /* Holds the external names of the functions. */
572 static const char *ffecom_gfrt_name_[FFECOM_gfrt]
575 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) NAME,
576 #include "com-rt.def"
580 /* Whether the function returns. */
582 static bool ffecom_gfrt_volatile_[FFECOM_gfrt]
585 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) VOLATILE,
586 #include "com-rt.def"
590 /* Whether the function returns type complex. */
592 static bool ffecom_gfrt_complex_[FFECOM_gfrt]
595 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) COMPLEX,
596 #include "com-rt.def"
600 /* Type code for the function return value. */
602 static ffecomRttype_ ffecom_gfrt_type_[FFECOM_gfrt]
605 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) TYPE,
606 #include "com-rt.def"
610 /* String of codes for the function's arguments. */
612 static const char *ffecom_gfrt_argstring_[FFECOM_gfrt]
615 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) ARGS,
616 #include "com-rt.def"
619 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
621 /* Internal macros. */
623 #if FFECOM_targetCURRENT == FFECOM_targetGCC
625 /* We let tm.h override the types used here, to handle trivial differences
626 such as the choice of unsigned int or long unsigned int for size_t.
627 When machines start needing nontrivial differences in the size type,
628 it would be best to do something here to figure out automatically
629 from other information what type to use. */
632 #define SIZE_TYPE "long unsigned int"
635 #define ffecom_concat_list_count_(catlist) ((catlist).count)
636 #define ffecom_concat_list_expr_(catlist,i) ((catlist).exprs[(i)])
637 #define ffecom_concat_list_maxlen_(catlist) ((catlist).maxlen)
638 #define ffecom_concat_list_minlen_(catlist) ((catlist).minlen)
640 #define ffecom_char_args_(i,l,e) ffecom_char_args_x_((i),(l),(e),FALSE)
641 #define ffecom_char_args_with_null_(i,l,e) ffecom_char_args_x_((i),(l),(e),TRUE)
643 /* For each binding contour we allocate a binding_level structure
644 * which records the names defined in that contour.
647 * 1) one for each function definition,
648 * where internal declarations of the parameters appear.
650 * The current meaning of a name can be found by searching the levels from
651 * the current one out to the global one.
654 /* Note that the information in the `names' component of the global contour
655 is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers. */
659 /* A chain of _DECL nodes for all variables, constants, functions,
660 and typedef types. These are in the reverse of the order supplied.
664 /* For each level (except not the global one),
665 a chain of BLOCK nodes for all the levels
666 that were entered and exited one level down. */
669 /* The BLOCK node for this level, if one has been preallocated.
670 If 0, the BLOCK is allocated (if needed) when the level is popped. */
673 /* The binding level which this one is contained in (inherits from). */
674 struct binding_level *level_chain;
676 /* 0: no ffecom_prepare_* functions called at this level yet;
677 1: ffecom_prepare* functions called, except not ffecom_prepare_end;
678 2: ffecom_prepare_end called. */
682 #define NULL_BINDING_LEVEL (struct binding_level *) NULL
684 /* The binding level currently in effect. */
686 static struct binding_level *current_binding_level;
688 /* A chain of binding_level structures awaiting reuse. */
690 static struct binding_level *free_binding_level;
692 /* The outermost binding level, for names of file scope.
693 This is created when the compiler is started and exists
694 through the entire run. */
696 static struct binding_level *global_binding_level;
698 /* Binding level structures are initialized by copying this one. */
700 static struct binding_level clear_binding_level
702 {NULL, NULL, NULL, NULL_BINDING_LEVEL, 0};
704 /* Language-dependent contents of an identifier. */
706 struct lang_identifier
708 struct tree_identifier ignore;
709 tree global_value, local_value, label_value;
713 /* Macros for access to language-specific slots in an identifier. */
714 /* Each of these slots contains a DECL node or null. */
716 /* This represents the value which the identifier has in the
717 file-scope namespace. */
718 #define IDENTIFIER_GLOBAL_VALUE(NODE) \
719 (((struct lang_identifier *)(NODE))->global_value)
720 /* This represents the value which the identifier has in the current
722 #define IDENTIFIER_LOCAL_VALUE(NODE) \
723 (((struct lang_identifier *)(NODE))->local_value)
724 /* This represents the value which the identifier has as a label in
725 the current label scope. */
726 #define IDENTIFIER_LABEL_VALUE(NODE) \
727 (((struct lang_identifier *)(NODE))->label_value)
728 /* This is nonzero if the identifier was "made up" by g77 code. */
729 #define IDENTIFIER_INVENTED(NODE) \
730 (((struct lang_identifier *)(NODE))->invented)
732 /* In identifiers, C uses the following fields in a special way:
733 TREE_PUBLIC to record that there was a previous local extern decl.
734 TREE_USED to record that such a decl was used.
735 TREE_ADDRESSABLE to record that the address of such a decl was used. */
737 /* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
738 that have names. Here so we can clear out their names' definitions
739 at the end of the function. */
741 static tree named_labels;
743 /* A list of LABEL_DECLs from outer contexts that are currently shadowed. */
745 static tree shadowed_labels;
747 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
749 /* Return the subscript expression, modified to do range-checking.
751 `array' is the array to be checked against.
752 `element' is the subscript expression to check.
753 `dim' is the dimension number (starting at 0).
754 `total_dims' is the total number of dimensions (0 for CHARACTER substring).
758 ffecom_subscript_check_ (tree array, tree element, int dim, int total_dims,
761 tree low = TYPE_MIN_VALUE (TYPE_DOMAIN (array));
762 tree high = TYPE_MAX_VALUE (TYPE_DOMAIN (array));
767 if (element == error_mark_node)
770 if (TREE_TYPE (low) != TREE_TYPE (element))
772 if (TYPE_PRECISION (TREE_TYPE (low))
773 > TYPE_PRECISION (TREE_TYPE (element)))
774 element = convert (TREE_TYPE (low), element);
777 low = convert (TREE_TYPE (element), low);
779 high = convert (TREE_TYPE (element), high);
783 element = ffecom_save_tree (element);
784 cond = ffecom_2 (LE_EXPR, integer_type_node,
789 cond = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
791 ffecom_2 (LE_EXPR, integer_type_node,
808 var = xmalloc (strlen (array_name) + 20);
809 sprintf (&var[0], "%s[%s-substring]",
811 dim ? "end" : "start");
812 len = strlen (var) + 1;
816 len = strlen (array_name) + 1;
821 var = xmalloc (strlen (array_name) + 40);
822 sprintf (&var[0], "%s[subscript-%d-of-%d]",
824 dim + 1, total_dims);
825 len = strlen (var) + 1;
829 arg1 = build_string (len, var);
835 = build_type_variant (build_array_type (char_type_node,
839 build_int_2 (len, 0))),
841 TREE_CONSTANT (arg1) = 1;
842 TREE_STATIC (arg1) = 1;
843 arg1 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg1)),
846 /* s_rnge adds one to the element to print it, so bias against
847 that -- want to print a faithful *subscript* value. */
848 arg2 = convert (ffecom_f2c_ftnint_type_node,
849 ffecom_2 (MINUS_EXPR,
852 convert (TREE_TYPE (element),
855 proc = xmalloc ((len = strlen (input_filename)
856 + IDENTIFIER_LENGTH (DECL_NAME (current_function_decl))
859 sprintf (&proc[0], "%s/%s",
861 IDENTIFIER_POINTER (DECL_NAME (current_function_decl)));
862 arg3 = build_string (len, proc);
867 = build_type_variant (build_array_type (char_type_node,
871 build_int_2 (len, 0))),
873 TREE_CONSTANT (arg3) = 1;
874 TREE_STATIC (arg3) = 1;
875 arg3 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg3)),
878 arg4 = convert (ffecom_f2c_ftnint_type_node,
879 build_int_2 (lineno, 0));
881 arg1 = build_tree_list (NULL_TREE, arg1);
882 arg2 = build_tree_list (NULL_TREE, arg2);
883 arg3 = build_tree_list (NULL_TREE, arg3);
884 arg4 = build_tree_list (NULL_TREE, arg4);
885 TREE_CHAIN (arg3) = arg4;
886 TREE_CHAIN (arg2) = arg3;
887 TREE_CHAIN (arg1) = arg2;
891 die = ffecom_call_gfrt (FFECOM_gfrtRANGE,
893 TREE_SIDE_EFFECTS (die) = 1;
895 element = ffecom_3 (COND_EXPR,
904 /* Return the computed element of an array reference.
906 `item' is NULL_TREE, or the transformed pointer to the array.
907 `expr' is the original opARRAYREF expression, which is transformed
908 if `item' is NULL_TREE.
909 `want_ptr' is non-zero if a pointer to the element, instead of
910 the element itself, is to be returned. */
913 ffecom_arrayref_ (tree item, ffebld expr, int want_ptr)
915 ffebld dims[FFECOM_dimensionsMAX];
918 int flatten = ffe_is_flatten_arrays ();
928 if (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER)
929 array_name = ffesymbol_text (ffebld_symter (ffebld_left (expr)));
931 array_name = "[expr?]";
933 /* Build up ARRAY_REFs in reverse order (since we're column major
934 here in Fortran land). */
936 for (i = 0, list = ffebld_right (expr);
938 ++i, list = ffebld_trail (list))
940 dims[i] = ffebld_head (list);
941 type = ffeinfo_type (ffebld_basictype (dims[i]),
942 ffebld_kindtype (dims[i]));
944 && ffecom_typesize_pointer_ > ffecom_typesize_integer1_
945 && ffetype_size (type) > ffecom_typesize_integer1_)
946 /* E.g. ARRAY(INDEX), given INTEGER*8 INDEX, on a system with 64-bit
947 pointers and 32-bit integers. Do the full 64-bit pointer
948 arithmetic, for codes using arrays for nonstandard heap-like
955 need_ptr = want_ptr || flatten;
960 item = ffecom_ptr_to_expr (ffebld_left (expr));
962 item = ffecom_expr (ffebld_left (expr));
964 if (item == error_mark_node)
967 if (ffeinfo_where (ffebld_info (expr)) == FFEINFO_whereFLEETING
968 && ! mark_addressable (item))
969 return error_mark_node;
972 if (item == error_mark_node)
979 for (--i, array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
981 --i, array = TYPE_MAIN_VARIANT (TREE_TYPE (array)))
983 min = TYPE_MIN_VALUE (TYPE_DOMAIN (array));
984 element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
985 if (ffe_is_subscript_check ())
986 element = ffecom_subscript_check_ (array, element, i, total_dims,
988 if (element == error_mark_node)
991 /* Widen integral arithmetic as desired while preserving
993 tree_type = TREE_TYPE (element);
994 tree_type_x = tree_type;
996 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
997 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
998 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
1000 if (TREE_TYPE (min) != tree_type_x)
1001 min = convert (tree_type_x, min);
1002 if (TREE_TYPE (element) != tree_type_x)
1003 element = convert (tree_type_x, element);
1005 item = ffecom_2 (PLUS_EXPR,
1006 build_pointer_type (TREE_TYPE (array)),
1008 size_binop (MULT_EXPR,
1009 size_in_bytes (TREE_TYPE (array)),
1010 fold (build (MINUS_EXPR,
1017 item = ffecom_1 (INDIRECT_REF,
1018 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))),
1028 array = TYPE_MAIN_VARIANT (TREE_TYPE (item));
1030 element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
1031 if (ffe_is_subscript_check ())
1032 element = ffecom_subscript_check_ (array, element, i, total_dims,
1034 if (element == error_mark_node)
1037 /* Widen integral arithmetic as desired while preserving
1039 tree_type = TREE_TYPE (element);
1040 tree_type_x = tree_type;
1042 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
1043 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
1044 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
1046 element = convert (tree_type_x, element);
1048 item = ffecom_2 (ARRAY_REF,
1049 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))),
1058 /* This is like gcc's stabilize_reference -- in fact, most of the code
1059 comes from that -- but it handles the situation where the reference
1060 is going to have its subparts picked at, and it shouldn't change
1061 (or trigger extra invocations of functions in the subtrees) due to
1062 this. save_expr is a bit overzealous, because we don't need the
1063 entire thing calculated and saved like a temp. So, for DECLs, no
1064 change is needed, because these are stable aggregates, and ARRAY_REF
1065 and such might well be stable too, but for things like calculations,
1066 we do need to calculate a snapshot of a value before picking at it. */
1068 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1070 ffecom_stabilize_aggregate_ (tree ref)
1073 enum tree_code code = TREE_CODE (ref);
1080 /* No action is needed in this case. */
1086 case FIX_TRUNC_EXPR:
1087 case FIX_FLOOR_EXPR:
1088 case FIX_ROUND_EXPR:
1090 result = build_nt (code, stabilize_reference (TREE_OPERAND (ref, 0)));
1094 result = build_nt (INDIRECT_REF,
1095 stabilize_reference_1 (TREE_OPERAND (ref, 0)));
1099 result = build_nt (COMPONENT_REF,
1100 stabilize_reference (TREE_OPERAND (ref, 0)),
1101 TREE_OPERAND (ref, 1));
1105 result = build_nt (BIT_FIELD_REF,
1106 stabilize_reference (TREE_OPERAND (ref, 0)),
1107 stabilize_reference_1 (TREE_OPERAND (ref, 1)),
1108 stabilize_reference_1 (TREE_OPERAND (ref, 2)));
1112 result = build_nt (ARRAY_REF,
1113 stabilize_reference (TREE_OPERAND (ref, 0)),
1114 stabilize_reference_1 (TREE_OPERAND (ref, 1)));
1118 result = build_nt (COMPOUND_EXPR,
1119 stabilize_reference_1 (TREE_OPERAND (ref, 0)),
1120 stabilize_reference (TREE_OPERAND (ref, 1)));
1124 result = build1 (INDIRECT_REF, TREE_TYPE (ref),
1125 save_expr (build1 (ADDR_EXPR,
1126 build_pointer_type (TREE_TYPE (ref)),
1132 return save_expr (ref);
1135 return error_mark_node;
1138 TREE_TYPE (result) = TREE_TYPE (ref);
1139 TREE_READONLY (result) = TREE_READONLY (ref);
1140 TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (ref);
1141 TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (ref);
1142 TREE_RAISES (result) = TREE_RAISES (ref);
1148 /* A rip-off of gcc's convert.c convert_to_complex function,
1149 reworked to handle complex implemented as C structures
1150 (RECORD_TYPE with two fields, real and imaginary `r' and `i'). */
1152 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1154 ffecom_convert_to_complex_ (tree type, tree expr)
1156 register enum tree_code form = TREE_CODE (TREE_TYPE (expr));
1159 assert (TREE_CODE (type) == RECORD_TYPE);
1161 subtype = TREE_TYPE (TYPE_FIELDS (type));
1163 if (form == REAL_TYPE || form == INTEGER_TYPE || form == ENUMERAL_TYPE)
1165 expr = convert (subtype, expr);
1166 return ffecom_2 (COMPLEX_EXPR, type, expr,
1167 convert (subtype, integer_zero_node));
1170 if (form == RECORD_TYPE)
1172 tree elt_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr)));
1173 if (TYPE_MAIN_VARIANT (elt_type) == TYPE_MAIN_VARIANT (subtype))
1177 expr = save_expr (expr);
1178 return ffecom_2 (COMPLEX_EXPR,
1181 ffecom_1 (REALPART_EXPR,
1182 TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))),
1185 ffecom_1 (IMAGPART_EXPR,
1186 TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))),
1191 if (form == POINTER_TYPE || form == REFERENCE_TYPE)
1192 error ("pointer value used where a complex was expected");
1194 error ("aggregate value used where a complex was expected");
1196 return ffecom_2 (COMPLEX_EXPR, type,
1197 convert (subtype, integer_zero_node),
1198 convert (subtype, integer_zero_node));
1202 /* Like gcc's convert(), but crashes if widening might happen. */
1204 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1206 ffecom_convert_narrow_ (type, expr)
1209 register tree e = expr;
1210 register enum tree_code code = TREE_CODE (type);
1212 if (type == TREE_TYPE (e)
1213 || TREE_CODE (e) == ERROR_MARK)
1215 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
1216 return fold (build1 (NOP_EXPR, type, e));
1217 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
1218 || code == ERROR_MARK)
1219 return error_mark_node;
1220 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
1222 assert ("void value not ignored as it ought to be" == NULL);
1223 return error_mark_node;
1225 assert (code != VOID_TYPE);
1226 if ((code != RECORD_TYPE)
1227 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
1228 assert ("converting COMPLEX to REAL" == NULL);
1229 assert (code != ENUMERAL_TYPE);
1230 if (code == INTEGER_TYPE)
1232 assert ((TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE
1233 && TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)))
1234 || (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
1235 && (TYPE_PRECISION (type)
1236 == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (e))))));
1237 return fold (convert_to_integer (type, e));
1239 if (code == POINTER_TYPE)
1241 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
1242 return fold (convert_to_pointer (type, e));
1244 if (code == REAL_TYPE)
1246 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
1247 assert (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)));
1248 return fold (convert_to_real (type, e));
1250 if (code == COMPLEX_TYPE)
1252 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
1253 assert (TYPE_PRECISION (TREE_TYPE (type)) <= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
1254 return fold (convert_to_complex (type, e));
1256 if (code == RECORD_TYPE)
1258 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
1259 /* Check that at least the first field name agrees. */
1260 assert (DECL_NAME (TYPE_FIELDS (type))
1261 == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e))));
1262 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1263 <= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
1264 if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1265 == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))))
1267 return fold (ffecom_convert_to_complex_ (type, e));
1270 assert ("conversion to non-scalar type requested" == NULL);
1271 return error_mark_node;
1275 /* Like gcc's convert(), but crashes if narrowing might happen. */
1277 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1279 ffecom_convert_widen_ (type, expr)
1282 register tree e = expr;
1283 register enum tree_code code = TREE_CODE (type);
1285 if (type == TREE_TYPE (e)
1286 || TREE_CODE (e) == ERROR_MARK)
1288 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
1289 return fold (build1 (NOP_EXPR, type, e));
1290 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
1291 || code == ERROR_MARK)
1292 return error_mark_node;
1293 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
1295 assert ("void value not ignored as it ought to be" == NULL);
1296 return error_mark_node;
1298 assert (code != VOID_TYPE);
1299 if ((code != RECORD_TYPE)
1300 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
1301 assert ("narrowing COMPLEX to REAL" == NULL);
1302 assert (code != ENUMERAL_TYPE);
1303 if (code == INTEGER_TYPE)
1305 assert ((TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE
1306 && TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)))
1307 || (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
1308 && (TYPE_PRECISION (type)
1309 == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (e))))));
1310 return fold (convert_to_integer (type, e));
1312 if (code == POINTER_TYPE)
1314 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
1315 return fold (convert_to_pointer (type, e));
1317 if (code == REAL_TYPE)
1319 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
1320 assert (TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)));
1321 return fold (convert_to_real (type, e));
1323 if (code == COMPLEX_TYPE)
1325 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
1326 assert (TYPE_PRECISION (TREE_TYPE (type)) >= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
1327 return fold (convert_to_complex (type, e));
1329 if (code == RECORD_TYPE)
1331 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
1332 /* Check that at least the first field name agrees. */
1333 assert (DECL_NAME (TYPE_FIELDS (type))
1334 == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e))));
1335 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1336 >= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
1337 if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1338 == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))))
1340 return fold (ffecom_convert_to_complex_ (type, e));
1343 assert ("conversion to non-scalar type requested" == NULL);
1344 return error_mark_node;
1348 /* Handles making a COMPLEX type, either the standard
1349 (but buggy?) gbe way, or the safer (but less elegant?)
1352 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1354 ffecom_make_complex_type_ (tree subtype)
1360 if (ffe_is_emulate_complex ())
1362 type = make_node (RECORD_TYPE);
1363 realfield = ffecom_decl_field (type, NULL_TREE, "r", subtype);
1364 imagfield = ffecom_decl_field (type, realfield, "i", subtype);
1365 TYPE_FIELDS (type) = realfield;
1370 type = make_node (COMPLEX_TYPE);
1371 TREE_TYPE (type) = subtype;
1379 /* Chooses either the gbe or the f2c way to build a
1380 complex constant. */
1382 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1384 ffecom_build_complex_constant_ (tree type, tree realpart, tree imagpart)
1388 if (ffe_is_emulate_complex ())
1390 bothparts = build_tree_list (TYPE_FIELDS (type), realpart);
1391 TREE_CHAIN (bothparts) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), imagpart);
1392 bothparts = build (CONSTRUCTOR, type, NULL_TREE, bothparts);
1396 bothparts = build_complex (type, realpart, imagpart);
1403 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1405 ffecom_arglist_expr_ (const char *c, ffebld expr)
1408 tree *plist = &list;
1409 tree trail = NULL_TREE; /* Append char length args here. */
1410 tree *ptrail = &trail;
1415 tree wanted = NULL_TREE;
1416 static char zed[] = "0";
1421 while (expr != NULL)
1444 wanted = ffecom_f2c_complex_type_node;
1448 wanted = ffecom_f2c_doublereal_type_node;
1452 wanted = ffecom_f2c_doublecomplex_type_node;
1456 wanted = ffecom_f2c_real_type_node;
1460 wanted = ffecom_f2c_integer_type_node;
1464 wanted = ffecom_f2c_longint_type_node;
1468 assert ("bad argstring code" == NULL);
1474 exprh = ffebld_head (expr);
1478 if ((wanted == NULL_TREE)
1481 (ffecom_tree_type[ffeinfo_basictype (ffebld_info (exprh))]
1482 [ffeinfo_kindtype (ffebld_info (exprh))])
1483 == TYPE_MODE (wanted))))
1485 = build_tree_list (NULL_TREE,
1486 ffecom_arg_ptr_to_expr (exprh,
1490 item = ffecom_arg_expr (exprh, &length);
1491 item = ffecom_convert_widen_ (wanted, item);
1494 item = ffecom_1 (ADDR_EXPR,
1495 build_pointer_type (TREE_TYPE (item)),
1499 = build_tree_list (NULL_TREE,
1503 plist = &TREE_CHAIN (*plist);
1504 expr = ffebld_trail (expr);
1505 if (length != NULL_TREE)
1507 *ptrail = build_tree_list (NULL_TREE, length);
1508 ptrail = &TREE_CHAIN (*ptrail);
1512 /* We've run out of args in the call; if the implementation expects
1513 more, supply null pointers for them, which the implementation can
1514 check to see if an arg was omitted. */
1516 while (*c != '\0' && *c != '0')
1521 assert ("missing arg to run-time routine!" == NULL);
1536 assert ("bad arg string code" == NULL);
1540 = build_tree_list (NULL_TREE,
1542 plist = &TREE_CHAIN (*plist);
1551 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1553 ffecom_widest_expr_type_ (ffebld list)
1556 ffebld widest = NULL;
1558 ffetype widest_type = NULL;
1561 for (; list != NULL; list = ffebld_trail (list))
1563 item = ffebld_head (list);
1566 if ((widest != NULL)
1567 && (ffeinfo_basictype (ffebld_info (item))
1568 != ffeinfo_basictype (ffebld_info (widest))))
1570 type = ffeinfo_type (ffeinfo_basictype (ffebld_info (item)),
1571 ffeinfo_kindtype (ffebld_info (item)));
1572 if ((widest == FFEINFO_kindtypeNONE)
1573 || (ffetype_size (type)
1574 > ffetype_size (widest_type)))
1581 assert (widest != NULL);
1582 t = ffecom_tree_type[ffeinfo_basictype (ffebld_info (widest))]
1583 [ffeinfo_kindtype (ffebld_info (widest))];
1584 assert (t != NULL_TREE);
1589 /* Check whether a partial overlap between two expressions is possible.
1591 Can *starting* to write a portion of expr1 change the value
1592 computed (perhaps already, *partially*) by expr2?
1594 Currently, this is a concern only for a COMPLEX expr1. But if it
1595 isn't in COMMON or local EQUIVALENCE, since we don't support
1596 aliasing of arguments, it isn't a concern. */
1599 ffecom_possible_partial_overlap_ (ffebld expr1, ffebld expr2)
1604 switch (ffebld_op (expr1))
1606 case FFEBLD_opSYMTER:
1607 sym = ffebld_symter (expr1);
1610 case FFEBLD_opARRAYREF:
1611 if (ffebld_op (ffebld_left (expr1)) != FFEBLD_opSYMTER)
1613 sym = ffebld_symter (ffebld_left (expr1));
1620 if (ffesymbol_where (sym) != FFEINFO_whereCOMMON
1621 && (ffesymbol_where (sym) != FFEINFO_whereLOCAL
1622 || ! (st = ffesymbol_storage (sym))
1623 || ! ffestorag_parent (st)))
1626 /* It's in COMMON or local EQUIVALENCE. */
1631 /* Check whether dest and source might overlap. ffebld versions of these
1632 might or might not be passed, will be NULL if not.
1634 The test is really whether source_tree is modifiable and, if modified,
1635 might overlap destination such that the value(s) in the destination might
1636 change before it is finally modified. dest_* are the canonized
1637 destination itself. */
1639 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1641 ffecom_overlap_ (tree dest_decl, tree dest_offset, tree dest_size,
1642 tree source_tree, ffebld source UNUSED,
1650 if (source_tree == NULL_TREE)
1653 switch (TREE_CODE (source_tree))
1656 case IDENTIFIER_NODE:
1667 case TRUNC_DIV_EXPR:
1669 case FLOOR_DIV_EXPR:
1670 case ROUND_DIV_EXPR:
1671 case TRUNC_MOD_EXPR:
1673 case FLOOR_MOD_EXPR:
1674 case ROUND_MOD_EXPR:
1676 case EXACT_DIV_EXPR:
1677 case FIX_TRUNC_EXPR:
1679 case FIX_FLOOR_EXPR:
1680 case FIX_ROUND_EXPR:
1695 case BIT_ANDTC_EXPR:
1697 case TRUTH_ANDIF_EXPR:
1698 case TRUTH_ORIF_EXPR:
1699 case TRUTH_AND_EXPR:
1701 case TRUTH_XOR_EXPR:
1702 case TRUTH_NOT_EXPR:
1718 return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1719 TREE_OPERAND (source_tree, 1), NULL,
1723 return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1724 TREE_OPERAND (source_tree, 0), NULL,
1729 case NON_LVALUE_EXPR:
1731 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1734 ffecom_tree_canonize_ptr_ (&source_decl, &source_offset,
1736 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1741 ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1742 TREE_OPERAND (source_tree, 1), NULL,
1744 || ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1745 TREE_OPERAND (source_tree, 2), NULL,
1750 ffecom_tree_canonize_ref_ (&source_decl, &source_offset,
1752 TREE_OPERAND (source_tree, 0));
1756 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1759 source_decl = source_tree;
1760 source_offset = size_zero_node;
1761 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1765 case REFERENCE_EXPR:
1766 case PREDECREMENT_EXPR:
1767 case PREINCREMENT_EXPR:
1768 case POSTDECREMENT_EXPR:
1769 case POSTINCREMENT_EXPR:
1777 /* Come here when source_decl, source_offset, and source_size filled
1778 in appropriately. */
1780 if (source_decl == NULL_TREE)
1781 return FALSE; /* No decl involved, so no overlap. */
1783 if (source_decl != dest_decl)
1784 return FALSE; /* Different decl, no overlap. */
1786 if (TREE_CODE (dest_size) == ERROR_MARK)
1787 return TRUE; /* Assignment into entire assumed-size
1788 array? Shouldn't happen.... */
1790 t = ffecom_2 (LE_EXPR, integer_type_node,
1791 ffecom_2 (PLUS_EXPR, TREE_TYPE (dest_offset),
1793 convert (TREE_TYPE (dest_offset),
1795 convert (TREE_TYPE (dest_offset),
1798 if (integer_onep (t))
1799 return FALSE; /* Destination precedes source. */
1802 || (source_size == NULL_TREE)
1803 || (TREE_CODE (source_size) == ERROR_MARK)
1804 || integer_zerop (source_size))
1805 return TRUE; /* No way to tell if dest follows source. */
1807 t = ffecom_2 (LE_EXPR, integer_type_node,
1808 ffecom_2 (PLUS_EXPR, TREE_TYPE (source_offset),
1810 convert (TREE_TYPE (source_offset),
1812 convert (TREE_TYPE (source_offset),
1815 if (integer_onep (t))
1816 return FALSE; /* Destination follows source. */
1818 return TRUE; /* Destination and source overlap. */
1822 /* Check whether dest might overlap any of a list of arguments or is
1823 in a COMMON area the callee might know about (and thus modify). */
1825 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1827 ffecom_args_overlapping_ (tree dest_tree, ffebld dest UNUSED,
1828 tree args, tree callee_commons,
1836 ffecom_tree_canonize_ref_ (&dest_decl, &dest_offset, &dest_size,
1839 if (dest_decl == NULL_TREE)
1840 return FALSE; /* Seems unlikely! */
1842 /* If the decl cannot be determined reliably, or if its in COMMON
1843 and the callee isn't known to not futz with COMMON via other
1844 means, overlap might happen. */
1846 if ((TREE_CODE (dest_decl) == ERROR_MARK)
1847 || ((callee_commons != NULL_TREE)
1848 && TREE_PUBLIC (dest_decl)))
1851 for (; args != NULL_TREE; args = TREE_CHAIN (args))
1853 if (((arg = TREE_VALUE (args)) != NULL_TREE)
1854 && ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1855 arg, NULL, scalar_args))
1863 /* Build a string for a variable name as used by NAMELIST. This means that
1864 if we're using the f2c library, we build an uppercase string, since
1867 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1869 ffecom_build_f2c_string_ (int i, const char *s)
1871 if (!ffe_is_f2c_library ())
1872 return build_string (i, s);
1881 if (((size_t) i) > ARRAY_SIZE (space))
1882 tmp = malloc_new_ks (malloc_pool_image (), "f2c_string", i);
1886 for (p = s, q = tmp; *p != '\0'; ++p, ++q)
1887 *q = ffesrc_toupper (*p);
1890 t = build_string (i, tmp);
1892 if (((size_t) i) > ARRAY_SIZE (space))
1893 malloc_kill_ks (malloc_pool_image (), tmp, i);
1900 /* Returns CALL_EXPR or equivalent with given type (pass NULL_TREE for
1901 type to just get whatever the function returns), handling the
1902 f2c value-returning convention, if required, by prepending
1903 to the arglist a pointer to a temporary to receive the return value. */
1905 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1907 ffecom_call_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1908 tree type, tree args, tree dest_tree,
1909 ffebld dest, bool *dest_used, tree callee_commons,
1910 bool scalar_args, tree hook)
1915 if (dest_used != NULL)
1920 if ((dest_used == NULL)
1922 || (ffeinfo_basictype (ffebld_info (dest))
1923 != FFEINFO_basictypeCOMPLEX)
1924 || (ffeinfo_kindtype (ffebld_info (dest)) != kt)
1925 || ((type != NULL_TREE) && (TREE_TYPE (dest_tree) != type))
1926 || ffecom_args_overlapping_ (dest_tree, dest, args,
1931 tempvar = ffecom_make_tempvar (ffecom_tree_type
1932 [FFEINFO_basictypeCOMPLEX][kt],
1933 FFETARGET_charactersizeNONE,
1943 tempvar = dest_tree;
1948 = build_tree_list (NULL_TREE,
1949 ffecom_1 (ADDR_EXPR,
1950 build_pointer_type (TREE_TYPE (tempvar)),
1952 TREE_CHAIN (item) = args;
1954 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1957 if (tempvar != dest_tree)
1958 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item, tempvar);
1961 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1964 if ((type != NULL_TREE) && (TREE_TYPE (item) != type))
1965 item = ffecom_convert_narrow_ (type, item);
1971 /* Given two arguments, transform them and make a call to the given
1972 function via ffecom_call_. */
1974 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1976 ffecom_call_binop_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1977 tree type, ffebld left, ffebld right,
1978 tree dest_tree, ffebld dest, bool *dest_used,
1979 tree callee_commons, bool scalar_args, tree hook)
1986 left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
1987 right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
1989 left_tree = build_tree_list (NULL_TREE, left_tree);
1990 right_tree = build_tree_list (NULL_TREE, right_tree);
1991 TREE_CHAIN (left_tree) = right_tree;
1993 if (left_length != NULL_TREE)
1995 left_length = build_tree_list (NULL_TREE, left_length);
1996 TREE_CHAIN (right_tree) = left_length;
1999 if (right_length != NULL_TREE)
2001 right_length = build_tree_list (NULL_TREE, right_length);
2002 if (left_length != NULL_TREE)
2003 TREE_CHAIN (left_length) = right_length;
2005 TREE_CHAIN (right_tree) = right_length;
2008 return ffecom_call_ (fn, kt, is_f2c_complex, type, left_tree,
2009 dest_tree, dest, dest_used, callee_commons,
2014 /* Return ptr/length args for char subexpression
2016 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
2017 subexpressions by constructing the appropriate trees for the ptr-to-
2018 character-text and length-of-character-text arguments in a calling
2021 Note that if with_null is TRUE, and the expression is an opCONTER,
2022 a null byte is appended to the string. */
2024 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2026 ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
2030 ffetargetCharacter1 val;
2031 ffetargetCharacterSize newlen;
2033 switch (ffebld_op (expr))
2035 case FFEBLD_opCONTER:
2036 val = ffebld_constant_character1 (ffebld_conter (expr));
2037 newlen = ffetarget_length_character1 (val);
2040 /* Begin FFETARGET-NULL-KLUDGE. */
2044 *length = build_int_2 (newlen, 0);
2045 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2046 high = build_int_2 (newlen, 0);
2047 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
2048 item = build_string (newlen,
2049 ffetarget_text_character1 (val));
2050 /* End FFETARGET-NULL-KLUDGE. */
2052 = build_type_variant
2056 (ffecom_f2c_ftnlen_type_node,
2057 ffecom_f2c_ftnlen_one_node,
2060 TREE_CONSTANT (item) = 1;
2061 TREE_STATIC (item) = 1;
2062 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
2066 case FFEBLD_opSYMTER:
2068 ffesymbol s = ffebld_symter (expr);
2070 item = ffesymbol_hook (s).decl_tree;
2071 if (item == NULL_TREE)
2073 s = ffecom_sym_transform_ (s);
2074 item = ffesymbol_hook (s).decl_tree;
2076 if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
2078 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
2079 *length = ffesymbol_hook (s).length_tree;
2082 *length = build_int_2 (ffesymbol_size (s), 0);
2083 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2086 else if (item == error_mark_node)
2087 *length = error_mark_node;
2089 /* FFEINFO_kindFUNCTION. */
2090 *length = NULL_TREE;
2091 if (!ffesymbol_hook (s).addr
2092 && (item != error_mark_node))
2093 item = ffecom_1 (ADDR_EXPR,
2094 build_pointer_type (TREE_TYPE (item)),
2099 case FFEBLD_opARRAYREF:
2101 ffecom_char_args_ (&item, length, ffebld_left (expr));
2103 if (item == error_mark_node || *length == error_mark_node)
2105 item = *length = error_mark_node;
2109 item = ffecom_arrayref_ (item, expr, 1);
2113 case FFEBLD_opSUBSTR:
2117 ffebld thing = ffebld_right (expr);
2124 assert (ffebld_op (thing) == FFEBLD_opITEM);
2125 start = ffebld_head (thing);
2126 thing = ffebld_trail (thing);
2127 assert (ffebld_trail (thing) == NULL);
2128 end = ffebld_head (thing);
2130 /* Determine name for pretty-printing range-check errors. */
2131 for (left_symter = ffebld_left (expr);
2132 left_symter && ffebld_op (left_symter) == FFEBLD_opARRAYREF;
2133 left_symter = ffebld_left (left_symter))
2135 if (ffebld_op (left_symter) == FFEBLD_opSYMTER)
2136 char_name = ffesymbol_text (ffebld_symter (left_symter));
2138 char_name = "[expr?]";
2140 ffecom_char_args_ (&item, length, ffebld_left (expr));
2142 if (item == error_mark_node || *length == error_mark_node)
2144 item = *length = error_mark_node;
2148 array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
2150 /* ~~~~Handle INTEGER*8 start/end, a la FFEBLD_opARRAYREF. */
2158 end_tree = ffecom_expr (end);
2159 if (ffe_is_subscript_check ())
2160 end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
2162 end_tree = convert (ffecom_f2c_ftnlen_type_node,
2165 if (end_tree == error_mark_node)
2167 item = *length = error_mark_node;
2176 start_tree = ffecom_expr (start);
2177 if (ffe_is_subscript_check ())
2178 start_tree = ffecom_subscript_check_ (array, start_tree, 0, 0,
2180 start_tree = convert (ffecom_f2c_ftnlen_type_node,
2183 if (start_tree == error_mark_node)
2185 item = *length = error_mark_node;
2189 start_tree = ffecom_save_tree (start_tree);
2191 item = ffecom_2 (PLUS_EXPR, TREE_TYPE (item),
2193 ffecom_2 (MINUS_EXPR,
2194 TREE_TYPE (start_tree),
2196 ffecom_f2c_ftnlen_one_node));
2200 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
2201 ffecom_f2c_ftnlen_one_node,
2202 ffecom_2 (MINUS_EXPR,
2203 ffecom_f2c_ftnlen_type_node,
2209 end_tree = ffecom_expr (end);
2210 if (ffe_is_subscript_check ())
2211 end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
2213 end_tree = convert (ffecom_f2c_ftnlen_type_node,
2216 if (end_tree == error_mark_node)
2218 item = *length = error_mark_node;
2222 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
2223 ffecom_f2c_ftnlen_one_node,
2224 ffecom_2 (MINUS_EXPR,
2225 ffecom_f2c_ftnlen_type_node,
2226 end_tree, start_tree));
2232 case FFEBLD_opFUNCREF:
2234 ffesymbol s = ffebld_symter (ffebld_left (expr));
2237 ffetargetCharacterSize size = ffeinfo_size (ffebld_info (expr));
2240 if (size == FFETARGET_charactersizeNONE)
2241 /* ~~Kludge alert! This should someday be fixed. */
2244 *length = build_int_2 (size, 0);
2245 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2247 if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
2248 == FFEINFO_whereINTRINSIC)
2252 /* Invocation of an intrinsic returning CHARACTER*1. */
2253 item = ffecom_expr_intrinsic_ (expr, NULL_TREE,
2257 ix = ffeintrin_gfrt_direct (ffebld_symter_implementation (ffebld_left (expr)));
2258 assert (ix != FFECOM_gfrt);
2259 item = ffecom_gfrt_tree_ (ix);
2264 item = ffesymbol_hook (s).decl_tree;
2265 if (item == NULL_TREE)
2267 s = ffecom_sym_transform_ (s);
2268 item = ffesymbol_hook (s).decl_tree;
2270 if (item == error_mark_node)
2272 item = *length = error_mark_node;
2276 if (!ffesymbol_hook (s).addr)
2277 item = ffecom_1_fn (item);
2281 tempvar = ffecom_push_tempvar (char_type_node, size, -1, TRUE);
2283 tempvar = ffebld_nonter_hook (expr);
2286 tempvar = ffecom_1 (ADDR_EXPR,
2287 build_pointer_type (TREE_TYPE (tempvar)),
2290 args = build_tree_list (NULL_TREE, tempvar);
2292 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT) /* Sfunc args by value. */
2293 TREE_CHAIN (args) = ffecom_list_expr (ffebld_right (expr));
2296 TREE_CHAIN (args) = build_tree_list (NULL_TREE, *length);
2297 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
2299 TREE_CHAIN (TREE_CHAIN (args))
2300 = ffecom_arglist_expr_ (ffecom_gfrt_args_ (ix),
2301 ffebld_right (expr));
2305 TREE_CHAIN (TREE_CHAIN (args))
2306 = ffecom_list_ptr_to_expr (ffebld_right (expr));
2310 item = ffecom_3s (CALL_EXPR,
2311 TREE_TYPE (TREE_TYPE (TREE_TYPE (item))),
2312 item, args, NULL_TREE);
2313 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item,
2318 case FFEBLD_opCONVERT:
2320 ffecom_char_args_ (&item, length, ffebld_left (expr));
2322 if (item == error_mark_node || *length == error_mark_node)
2324 item = *length = error_mark_node;
2328 if ((ffebld_size_known (ffebld_left (expr))
2329 == FFETARGET_charactersizeNONE)
2330 || (ffebld_size_known (ffebld_left (expr)) < (ffebld_size (expr))))
2331 { /* Possible blank-padding needed, copy into
2338 tempvar = ffecom_make_tempvar (char_type_node,
2339 ffebld_size (expr), -1);
2341 tempvar = ffebld_nonter_hook (expr);
2344 tempvar = ffecom_1 (ADDR_EXPR,
2345 build_pointer_type (TREE_TYPE (tempvar)),
2348 newlen = build_int_2 (ffebld_size (expr), 0);
2349 TREE_TYPE (newlen) = ffecom_f2c_ftnlen_type_node;
2351 args = build_tree_list (NULL_TREE, tempvar);
2352 TREE_CHAIN (args) = build_tree_list (NULL_TREE, item);
2353 TREE_CHAIN (TREE_CHAIN (args)) = build_tree_list (NULL_TREE, newlen);
2354 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (args)))
2355 = build_tree_list (NULL_TREE, *length);
2357 item = ffecom_call_gfrt (FFECOM_gfrtCOPY, args, NULL_TREE);
2358 TREE_SIDE_EFFECTS (item) = 1;
2359 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), fold (item),
2364 { /* Just truncate the length. */
2365 *length = build_int_2 (ffebld_size (expr), 0);
2366 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2371 assert ("bad op for single char arg expr" == NULL);
2380 /* Check the size of the type to be sure it doesn't overflow the
2381 "portable" capacities of the compiler back end. `dummy' types
2382 can generally overflow the normal sizes as long as the computations
2383 themselves don't overflow. A particular target of the back end
2384 must still enforce its size requirements, though, and the back
2385 end takes care of this in stor-layout.c. */
2387 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2389 ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy)
2391 if (TREE_CODE (type) == ERROR_MARK)
2394 if (TYPE_SIZE (type) == NULL_TREE)
2397 if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
2400 if ((tree_int_cst_sgn (TYPE_SIZE (type)) < 0)
2401 || (!dummy && (((TREE_INT_CST_HIGH (TYPE_SIZE (type)) != 0))
2402 || TREE_OVERFLOW (TYPE_SIZE (type)))))
2404 ffebad_start (FFEBAD_ARRAY_LARGE);
2405 ffebad_string (ffesymbol_text (s));
2406 ffebad_here (0, ffesymbol_where_line (s), ffesymbol_where_column (s));
2409 return error_mark_node;
2416 /* Builds a length argument (PARM_DECL). Also wraps type in an array type
2417 where the dimension info is (1:size) where <size> is ffesymbol_size(s) if
2418 known, length_arg if not known (FFETARGET_charactersizeNONE). */
2420 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2422 ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s)
2424 ffetargetCharacterSize sz = ffesymbol_size (s);
2429 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
2430 tlen = NULL_TREE; /* A statement function, no length passed. */
2433 if (ffesymbol_where (s) == FFEINFO_whereDUMMY)
2434 tlen = ffecom_get_invented_identifier ("__g77_length_%s",
2435 ffesymbol_text (s), -1);
2437 tlen = ffecom_get_invented_identifier ("__g77_%s",
2439 tlen = build_decl (PARM_DECL, tlen, ffecom_f2c_ftnlen_type_node);
2441 DECL_ARTIFICIAL (tlen) = 1;
2445 if (sz == FFETARGET_charactersizeNONE)
2447 assert (tlen != NULL_TREE);
2448 highval = variable_size (tlen);
2452 highval = build_int_2 (sz, 0);
2453 TREE_TYPE (highval) = ffecom_f2c_ftnlen_type_node;
2456 type = build_array_type (type,
2457 build_range_type (ffecom_f2c_ftnlen_type_node,
2458 ffecom_f2c_ftnlen_one_node,
2466 /* ffecom_concat_list_gather_ -- Gather list of concatenated string exprs
2468 ffecomConcatList_ catlist;
2469 ffebld expr; // expr of CHARACTER basictype.
2470 ffetargetCharacterSize max; // max chars to gather or _...NONE if no max
2471 catlist = ffecom_concat_list_gather_(catlist,expr,max);
2473 Scans expr for character subexpressions, updates and returns catlist
2476 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2477 static ffecomConcatList_
2478 ffecom_concat_list_gather_ (ffecomConcatList_ catlist, ffebld expr,
2479 ffetargetCharacterSize max)
2481 ffetargetCharacterSize sz;
2483 recurse: /* :::::::::::::::::::: */
2488 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen >= max))
2489 return catlist; /* Don't append any more items. */
2491 switch (ffebld_op (expr))
2493 case FFEBLD_opCONTER:
2494 case FFEBLD_opSYMTER:
2495 case FFEBLD_opARRAYREF:
2496 case FFEBLD_opFUNCREF:
2497 case FFEBLD_opSUBSTR:
2498 case FFEBLD_opCONVERT: /* Callers should strip this off beforehand
2499 if they don't need to preserve it. */
2500 if (catlist.count == catlist.max)
2501 { /* Make a (larger) list. */
2505 newmax = (catlist.max == 0) ? 8 : catlist.max * 2;
2506 newx = malloc_new_ks (malloc_pool_image (), "catlist",
2507 newmax * sizeof (newx[0]));
2508 if (catlist.max != 0)
2510 memcpy (newx, catlist.exprs, catlist.max * sizeof (newx[0]));
2511 malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2512 catlist.max * sizeof (newx[0]));
2514 catlist.max = newmax;
2515 catlist.exprs = newx;
2517 if ((sz = ffebld_size_known (expr)) != FFETARGET_charactersizeNONE)
2518 catlist.minlen += sz;
2520 ++catlist.minlen; /* Not true for F90; can be 0 length. */
2521 if ((sz = ffebld_size_max (expr)) == FFETARGET_charactersizeNONE)
2522 catlist.maxlen = sz;
2524 catlist.maxlen += sz;
2525 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen > max))
2526 { /* This item overlaps (or is beyond) the end
2527 of the destination. */
2528 switch (ffebld_op (expr))
2530 case FFEBLD_opCONTER:
2531 case FFEBLD_opSYMTER:
2532 case FFEBLD_opARRAYREF:
2533 case FFEBLD_opFUNCREF:
2534 case FFEBLD_opSUBSTR:
2535 /* ~~Do useful truncations here. */
2539 assert ("op changed or inconsistent switches!" == NULL);
2543 catlist.exprs[catlist.count++] = expr;
2546 case FFEBLD_opPAREN:
2547 expr = ffebld_left (expr);
2548 goto recurse; /* :::::::::::::::::::: */
2550 case FFEBLD_opCONCATENATE:
2551 catlist = ffecom_concat_list_gather_ (catlist, ffebld_left (expr), max);
2552 expr = ffebld_right (expr);
2553 goto recurse; /* :::::::::::::::::::: */
2555 #if 0 /* Breaks passing small actual arg to larger
2556 dummy arg of sfunc */
2557 case FFEBLD_opCONVERT:
2558 expr = ffebld_left (expr);
2560 ffetargetCharacterSize cmax;
2562 cmax = catlist.len + ffebld_size_known (expr);
2564 if ((max == FFETARGET_charactersizeNONE) || (max > cmax))
2567 goto recurse; /* :::::::::::::::::::: */
2574 assert ("bad op in _gather_" == NULL);
2580 /* ffecom_concat_list_kill_ -- Kill list of concatenated string exprs
2582 ffecomConcatList_ catlist;
2583 ffecom_concat_list_kill_(catlist);
2585 Anything allocated within the list info is deallocated. */
2587 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2589 ffecom_concat_list_kill_ (ffecomConcatList_ catlist)
2591 if (catlist.max != 0)
2592 malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2593 catlist.max * sizeof (catlist.exprs[0]));
2597 /* Make list of concatenated string exprs.
2599 Returns a flattened list of concatenated subexpressions given a
2600 tree of such expressions. */
2602 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2603 static ffecomConcatList_
2604 ffecom_concat_list_new_ (ffebld expr, ffetargetCharacterSize max)
2606 ffecomConcatList_ catlist;
2608 catlist.maxlen = catlist.minlen = catlist.max = catlist.count = 0;
2609 return ffecom_concat_list_gather_ (catlist, expr, max);
2614 /* Provide some kind of useful info on member of aggregate area,
2615 since current g77/gcc technology does not provide debug info
2616 on these members. */
2618 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2620 ffecom_debug_kludge_ (tree aggr, const char *aggr_type, ffesymbol member,
2621 tree member_type UNUSED, ffetargetOffset offset)
2631 for (type_id = member_type;
2632 TREE_CODE (type_id) != IDENTIFIER_NODE;
2635 switch (TREE_CODE (type_id))
2639 type_id = TYPE_NAME (type_id);
2644 type_id = TREE_TYPE (type_id);
2648 assert ("no IDENTIFIER_NODE for type!" == NULL);
2649 type_id = error_mark_node;
2655 if (ffecom_transform_only_dummies_
2656 || !ffe_is_debug_kludge ())
2657 return; /* Can't do this yet, maybe later. */
2660 + strlen (aggr_type)
2661 + IDENTIFIER_LENGTH (DECL_NAME (aggr));
2663 + IDENTIFIER_LENGTH (type_id);
2666 if (((size_t) len) >= ARRAY_SIZE (space))
2667 buff = malloc_new_ks (malloc_pool_image (), "debug_kludge", len + 1);
2671 sprintf (&buff[0], "At (%s) `%s' plus %ld bytes",
2673 IDENTIFIER_POINTER (DECL_NAME (aggr)),
2676 value = build_string (len, buff);
2678 = build_type_variant (build_array_type (char_type_node,
2682 build_int_2 (strlen (buff), 0))),
2684 decl = build_decl (VAR_DECL,
2685 ffecom_get_identifier_ (ffesymbol_text (member)),
2687 TREE_CONSTANT (decl) = 1;
2688 TREE_STATIC (decl) = 1;
2689 DECL_INITIAL (decl) = error_mark_node;
2690 DECL_IN_SYSTEM_HEADER (decl) = 1; /* Don't let -Wunused complain. */
2691 decl = start_decl (decl, FALSE);
2692 finish_decl (decl, value, FALSE);
2694 if (buff != &space[0])
2695 malloc_kill_ks (malloc_pool_image (), buff, len + 1);
2699 /* ffecom_do_entry_ -- Do compilation of a particular entrypoint
2701 ffesymbol fn; // the SUBROUTINE, FUNCTION, or ENTRY symbol itself
2702 int i; // entry# for this entrypoint (used by master fn)
2703 ffecom_do_entrypoint_(s,i);
2705 Makes a public entry point that calls our private master fn (already
2708 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2710 ffecom_do_entry_ (ffesymbol fn, int entrynum)
2713 tree type; /* Type of function. */
2714 tree multi_retval; /* Var holding return value (union). */
2715 tree result; /* Var holding result. */
2716 ffeinfoBasictype bt;
2720 bool charfunc; /* All entry points return same type
2722 bool cmplxfunc; /* Use f2c way of returning COMPLEX. */
2723 bool multi; /* Master fn has multiple return types. */
2724 bool altreturning = FALSE; /* This entry point has alternate returns. */
2726 int old_lineno = lineno;
2727 char *old_input_filename = input_filename;
2729 input_filename = ffesymbol_where_filename (fn);
2730 lineno = ffesymbol_where_filelinenum (fn);
2732 /* c-parse.y indeed does call suspend_momentary and not only ignores the
2733 return value, but also never calls resume_momentary, when starting an
2734 outer function (see "fndef:", "setspecs:", and so on). So g77 does the
2735 same thing. It shouldn't be a problem since start_function calls
2736 temporary_allocation, but it might be necessary. If it causes a problem
2737 here, then maybe there's a bug lurking in gcc. NOTE: This identical
2738 comment appears twice in thist file. */
2740 suspend_momentary ();
2742 ffecom_doing_entry_ = TRUE; /* Don't bother with array dimensions. */
2744 switch (ffecom_primary_entry_kind_)
2746 case FFEINFO_kindFUNCTION:
2748 /* Determine actual return type for function. */
2750 gt = FFEGLOBAL_typeFUNC;
2751 bt = ffesymbol_basictype (fn);
2752 kt = ffesymbol_kindtype (fn);
2753 if (bt == FFEINFO_basictypeNONE)
2755 ffeimplic_establish_symbol (fn);
2756 if (ffesymbol_funcresult (fn) != NULL)
2757 ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
2758 bt = ffesymbol_basictype (fn);
2759 kt = ffesymbol_kindtype (fn);
2762 if (bt == FFEINFO_basictypeCHARACTER)
2763 charfunc = TRUE, cmplxfunc = FALSE;
2764 else if ((bt == FFEINFO_basictypeCOMPLEX)
2765 && ffesymbol_is_f2c (fn))
2766 charfunc = FALSE, cmplxfunc = TRUE;
2768 charfunc = cmplxfunc = FALSE;
2771 type = ffecom_tree_fun_type_void;
2772 else if (ffesymbol_is_f2c (fn))
2773 type = ffecom_tree_fun_type[bt][kt];
2775 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
2777 if ((type == NULL_TREE)
2778 || (TREE_TYPE (type) == NULL_TREE))
2779 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */
2781 multi = (ffecom_master_bt_ == FFEINFO_basictypeNONE);
2784 case FFEINFO_kindSUBROUTINE:
2785 gt = FFEGLOBAL_typeSUBR;
2786 bt = FFEINFO_basictypeNONE;
2787 kt = FFEINFO_kindtypeNONE;
2788 if (ffecom_is_altreturning_)
2789 { /* Am _I_ altreturning? */
2790 for (item = ffesymbol_dummyargs (fn);
2792 item = ffebld_trail (item))
2794 if (ffebld_op (ffebld_head (item)) == FFEBLD_opSTAR)
2796 altreturning = TRUE;
2801 type = ffecom_tree_subr_type;
2803 type = ffecom_tree_fun_type_void;
2806 type = ffecom_tree_fun_type_void;
2813 assert ("say what??" == NULL);
2815 case FFEINFO_kindANY:
2816 gt = FFEGLOBAL_typeANY;
2817 bt = FFEINFO_basictypeNONE;
2818 kt = FFEINFO_kindtypeNONE;
2819 type = error_mark_node;
2826 /* build_decl uses the current lineno and input_filename to set the decl
2827 source info. So, I've putzed with ffestd and ffeste code to update that
2828 source info to point to the appropriate statement just before calling
2829 ffecom_do_entrypoint (which calls this fn). */
2831 start_function (ffecom_get_external_identifier_ (fn),
2833 0, /* nested/inline */
2834 1); /* TREE_PUBLIC */
2836 if (((g = ffesymbol_global (fn)) != NULL)
2837 && ((ffeglobal_type (g) == gt)
2838 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
2840 ffeglobal_set_hook (g, current_function_decl);
2843 /* Reset args in master arg list so they get retransitioned. */
2845 for (item = ffecom_master_arglist_;
2847 item = ffebld_trail (item))
2852 arg = ffebld_head (item);
2853 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2854 continue; /* Alternate return or some such thing. */
2855 s = ffebld_symter (arg);
2856 ffesymbol_hook (s).decl_tree = NULL_TREE;
2857 ffesymbol_hook (s).length_tree = NULL_TREE;
2860 /* Build dummy arg list for this entry point. */
2862 yes = suspend_momentary ();
2864 if (charfunc || cmplxfunc)
2865 { /* Prepend arg for where result goes. */
2870 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
2872 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
2874 result = ffecom_get_invented_identifier ("__g77_%s",
2877 /* Make length arg _and_ enhance type info for CHAR arg itself. */
2880 length = ffecom_char_enhance_arg_ (&type, fn);
2882 length = NULL_TREE; /* Not ref'd if !charfunc. */
2884 type = build_pointer_type (type);
2885 result = build_decl (PARM_DECL, result, type);
2887 push_parm_decl (result);
2888 ffecom_func_result_ = result;
2892 push_parm_decl (length);
2893 ffecom_func_length_ = length;
2897 result = DECL_RESULT (current_function_decl);
2899 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (fn), FALSE);
2901 resume_momentary (yes);
2903 store_parm_decls (0);
2905 ffecom_start_compstmt ();
2906 /* Disallow temp vars at this level. */
2907 current_binding_level->prep_state = 2;
2909 /* Make local var to hold return type for multi-type master fn. */
2913 yes = suspend_momentary ();
2915 multi_retval = ffecom_get_invented_identifier ("__g77_%s",
2916 "multi_retval", -1);
2917 multi_retval = build_decl (VAR_DECL, multi_retval,
2918 ffecom_multi_type_node_);
2919 multi_retval = start_decl (multi_retval, FALSE);
2920 finish_decl (multi_retval, NULL_TREE, FALSE);
2922 resume_momentary (yes);
2925 multi_retval = NULL_TREE; /* Not actually ref'd if !multi. */
2927 /* Here we emit the actual code for the entry point. */
2933 tree arglist = NULL_TREE;
2934 tree *plist = &arglist;
2940 /* Prepare actual arg list based on master arg list. */
2942 for (list = ffecom_master_arglist_;
2944 list = ffebld_trail (list))
2946 arg = ffebld_head (list);
2947 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2949 s = ffebld_symter (arg);
2950 if (ffesymbol_hook (s).decl_tree == NULL_TREE
2951 || ffesymbol_hook (s).decl_tree == error_mark_node)
2952 actarg = null_pointer_node; /* We don't have this arg. */
2954 actarg = ffesymbol_hook (s).decl_tree;
2955 *plist = build_tree_list (NULL_TREE, actarg);
2956 plist = &TREE_CHAIN (*plist);
2959 /* This code appends the length arguments for character
2960 variables/arrays. */
2962 for (list = ffecom_master_arglist_;
2964 list = ffebld_trail (list))
2966 arg = ffebld_head (list);
2967 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2969 s = ffebld_symter (arg);
2970 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
2971 continue; /* Only looking for CHARACTER arguments. */
2972 if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
2973 continue; /* Only looking for variables and arrays. */
2974 if (ffesymbol_hook (s).length_tree == NULL_TREE
2975 || ffesymbol_hook (s).length_tree == error_mark_node)
2976 actarg = ffecom_f2c_ftnlen_zero_node; /* We don't have this arg. */
2978 actarg = ffesymbol_hook (s).length_tree;
2979 *plist = build_tree_list (NULL_TREE, actarg);
2980 plist = &TREE_CHAIN (*plist);
2983 /* Prepend character-value return info to actual arg list. */
2987 prepend = build_tree_list (NULL_TREE, ffecom_func_result_);
2988 TREE_CHAIN (prepend)
2989 = build_tree_list (NULL_TREE, ffecom_func_length_);
2990 TREE_CHAIN (TREE_CHAIN (prepend)) = arglist;
2994 /* Prepend multi-type return value to actual arg list. */
2999 = build_tree_list (NULL_TREE,
3000 ffecom_1 (ADDR_EXPR,
3001 build_pointer_type (TREE_TYPE (multi_retval)),
3003 TREE_CHAIN (prepend) = arglist;
3007 /* Prepend my entry-point number to the actual arg list. */
3009 prepend = build_tree_list (NULL_TREE, build_int_2 (entrynum, 0));
3010 TREE_CHAIN (prepend) = arglist;
3013 /* Build the call to the master function. */
3015 master_fn = ffecom_1_fn (ffecom_previous_function_decl_);
3016 call = ffecom_3s (CALL_EXPR,
3017 TREE_TYPE (TREE_TYPE (TREE_TYPE (master_fn))),
3018 master_fn, arglist, NULL_TREE);
3020 /* Decide whether the master function is a function or subroutine, and
3021 handle the return value for my entry point. */
3023 if (charfunc || ((ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
3026 expand_expr_stmt (call);
3027 expand_null_return ();
3029 else if (multi && cmplxfunc)
3031 expand_expr_stmt (call);
3033 = ffecom_1 (INDIRECT_REF,
3034 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
3036 result = ffecom_modify (NULL_TREE, result,
3037 ffecom_2 (COMPONENT_REF, TREE_TYPE (result),
3039 ffecom_multi_fields_[bt][kt]));
3040 expand_expr_stmt (result);
3041 expand_null_return ();
3045 expand_expr_stmt (call);
3047 = ffecom_modify (NULL_TREE, result,
3048 convert (TREE_TYPE (result),
3049 ffecom_2 (COMPONENT_REF,
3050 ffecom_tree_type[bt][kt],
3052 ffecom_multi_fields_[bt][kt])));
3053 expand_return (result);
3058 = ffecom_1 (INDIRECT_REF,
3059 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
3061 result = ffecom_modify (NULL_TREE, result, call);
3062 expand_expr_stmt (result);
3063 expand_null_return ();
3067 result = ffecom_modify (NULL_TREE,
3069 convert (TREE_TYPE (result),
3071 expand_return (result);
3077 ffecom_end_compstmt ();
3079 finish_function (0);
3081 lineno = old_lineno;
3082 input_filename = old_input_filename;
3084 ffecom_doing_entry_ = FALSE;
3088 /* Transform expr into gcc tree with possible destination
3090 Recursive descent on expr while making corresponding tree nodes and
3091 attaching type info and such. If destination supplied and compatible
3092 with temporary that would be made in certain cases, temporary isn't
3093 made, destination used instead, and dest_used flag set TRUE. */
3095 #if FFECOM_targetCURRENT == FFECOM_targetGCC
3097 ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
3098 bool *dest_used, bool assignp, bool widenp)
3103 ffeinfoBasictype bt;
3106 tree dt; /* decl_tree for an ffesymbol. */
3107 tree tree_type, tree_type_x;
3110 enum tree_code code;
3112 assert (expr != NULL);
3114 if (dest_used != NULL)
3117 bt = ffeinfo_basictype (ffebld_info (expr));
3118 kt = ffeinfo_kindtype (ffebld_info (expr));
3119 tree_type = ffecom_tree_type[bt][kt];
3121 /* Widen integral arithmetic as desired while preserving signedness. */
3122 tree_type_x = NULL_TREE;
3123 if (widenp && tree_type
3124 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
3125 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
3126 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
3128 switch (ffebld_op (expr))
3130 case FFEBLD_opACCTER:
3133 ffebit bits = ffebld_accter_bits (expr);
3134 ffetargetOffset source_offset = 0;
3135 ffetargetOffset dest_offset = ffebld_accter_pad (expr);
3138 assert (dest_offset == 0
3139 || (bt == FFEINFO_basictypeCHARACTER
3140 && kt == FFEINFO_kindtypeCHARACTER1));
3145 ffebldConstantUnion cu;
3148 ffebldConstantArray ca = ffebld_accter (expr);
3150 ffebit_test (bits, source_offset, &value, &length);
3156 for (i = 0; i < length; ++i)
3158 cu = ffebld_constantarray_get (ca, bt, kt,
3161 t = ffecom_constantunion (&cu, bt, kt, tree_type);
3164 && dest_offset != 0)
3165 purpose = build_int_2 (dest_offset, 0);
3167 purpose = NULL_TREE;
3169 if (list == NULL_TREE)
3170 list = item = build_tree_list (purpose, t);
3173 TREE_CHAIN (item) = build_tree_list (purpose, t);
3174 item = TREE_CHAIN (item);
3178 source_offset += length;
3179 dest_offset += length;
3183 item = build_int_2 ((ffebld_accter_size (expr)
3184 + ffebld_accter_pad (expr)) - 1, 0);
3185 ffebit_kill (ffebld_accter_bits (expr));
3186 TREE_TYPE (item) = ffecom_integer_type_node;
3190 build_range_type (ffecom_integer_type_node,
3191 ffecom_integer_zero_node,
3193 list = build (CONSTRUCTOR, item, NULL_TREE, list);
3194 TREE_CONSTANT (list) = 1;
3195 TREE_STATIC (list) = 1;
3198 case FFEBLD_opARRTER:
3203 if (ffebld_arrter_pad (expr) == 0)
3207 assert (bt == FFEINFO_basictypeCHARACTER
3208 && kt == FFEINFO_kindtypeCHARACTER1);
3210 /* Becomes PURPOSE first time through loop. */
3211 item = build_int_2 (ffebld_arrter_pad (expr), 0);
3214 for (i = 0; i < ffebld_arrter_size (expr); ++i)
3216 ffebldConstantUnion cu
3217 = ffebld_constantarray_get (ffebld_arrter (expr), bt, kt, i);
3219 t = ffecom_constantunion (&cu, bt, kt, tree_type);
3221 if (list == NULL_TREE)
3222 /* Assume item is PURPOSE first time through loop. */
3223 list = item = build_tree_list (item, t);
3226 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
3227 item = TREE_CHAIN (item);
3232 item = build_int_2 ((ffebld_arrter_size (expr)
3233 + ffebld_arrter_pad (expr)) - 1, 0);
3234 TREE_TYPE (item) = ffecom_integer_type_node;
3238 build_range_type (ffecom_integer_type_node,
3239 ffecom_integer_zero_node,
3241 list = build (CONSTRUCTOR, item, NULL_TREE, list);
3242 TREE_CONSTANT (list) = 1;
3243 TREE_STATIC (list) = 1;
3246 case FFEBLD_opCONTER:
3247 assert (ffebld_conter_pad (expr) == 0);
3249 = ffecom_constantunion (&ffebld_constant_union (ffebld_conter (expr)),
3253 case FFEBLD_opSYMTER:
3254 if ((ffebld_symter_generic (expr) != FFEINTRIN_genNONE)
3255 || (ffebld_symter_specific (expr) != FFEINTRIN_specNONE))
3256 return ffecom_ptr_to_expr (expr); /* Same as %REF(intrinsic). */
3257 s = ffebld_symter (expr);
3258 t = ffesymbol_hook (s).decl_tree;
3261 { /* ASSIGN'ed-label expr. */
3262 if (ffe_is_ugly_assign ())
3264 /* User explicitly wants ASSIGN'ed variables to be at the same
3265 memory address as the variables when used in non-ASSIGN
3266 contexts. That can make old, arcane, non-standard code
3267 work, but don't try to do it when a pointer wouldn't fit
3268 in the normal variable (take other approach, and warn,
3273 s = ffecom_sym_transform_ (s);
3274 t = ffesymbol_hook (s).decl_tree;
3275 assert (t != NULL_TREE);
3278 if (t == error_mark_node)
3281 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (t)))
3282 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
3284 if (ffesymbol_hook (s).addr)
3285 t = ffecom_1 (INDIRECT_REF,
3286 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
3290 if (ffesymbol_hook (s).assign_tree == NULL_TREE)
3292 ffebad_start_msg ("ASSIGN'ed label cannot fit into `%A' at %0 -- using wider sibling",
3293 FFEBAD_severityWARNING);
3294 ffebad_string (ffesymbol_text (s));
3295 ffebad_here (0, ffesymbol_where_line (s),
3296 ffesymbol_where_column (s));
3301 /* Don't use the normal variable's tree for ASSIGN, though mark
3302 it as in the system header (housekeeping). Use an explicit,
3303 specially created sibling that is known to be wide enough
3304 to hold pointers to labels. */
3307 && TREE_CODE (t) == VAR_DECL)
3308 DECL_IN_SYSTEM_HEADER (t) = 1; /* Don't let -Wunused complain. */
3310 t = ffesymbol_hook (s).assign_tree;
3313 s = ffecom_sym_transform_assign_ (s);
3314 t = ffesymbol_hook (s).assign_tree;
3315 assert (t != NULL_TREE);
3322 s = ffecom_sym_transform_ (s);
3323 t = ffesymbol_hook (s).decl_tree;
3324 assert (t != NULL_TREE);
3326 if (ffesymbol_hook (s).addr)
3327 t = ffecom_1 (INDIRECT_REF,
3328 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
3332 case FFEBLD_opARRAYREF:
3333 return ffecom_arrayref_ (NULL_TREE, expr, 0);
3335 case FFEBLD_opUPLUS:
3336 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3337 return ffecom_1 (NOP_EXPR, tree_type, left);
3339 case FFEBLD_opPAREN:
3340 /* ~~~Make sure Fortran rules respected here */
3341 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3342 return ffecom_1 (NOP_EXPR, tree_type, left);
3344 case FFEBLD_opUMINUS:
3345 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3348 tree_type = tree_type_x;
3349 left = convert (tree_type, left);
3351 return ffecom_1 (NEGATE_EXPR, tree_type, left);
3354 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3355 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3358 tree_type = tree_type_x;
3359 left = convert (tree_type, left);
3360 right = convert (tree_type, right);
3362 return ffecom_2 (PLUS_EXPR, tree_type, left, right);
3364 case FFEBLD_opSUBTRACT:
3365 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3366 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3369 tree_type = tree_type_x;
3370 left = convert (tree_type, left);
3371 right = convert (tree_type, right);
3373 return ffecom_2 (MINUS_EXPR, tree_type, left, right);
3375 case FFEBLD_opMULTIPLY:
3376 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3377 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3380 tree_type = tree_type_x;
3381 left = convert (tree_type, left);
3382 right = convert (tree_type, right);
3384 return ffecom_2 (MULT_EXPR, tree_type, left, right);
3386 case FFEBLD_opDIVIDE:
3387 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3388 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3391 tree_type = tree_type_x;
3392 left = convert (tree_type, left);
3393 right = convert (tree_type, right);
3395 return ffecom_tree_divide_ (tree_type, left, right,
3396 dest_tree, dest, dest_used,
3397 ffebld_nonter_hook (expr));
3399 case FFEBLD_opPOWER:
3401 ffebld left = ffebld_left (expr);
3402 ffebld right = ffebld_right (expr);
3404 ffeinfoKindtype rtkt;
3405 ffeinfoKindtype ltkt;
3407 switch (ffeinfo_basictype (ffebld_info (right)))
3409 case FFEINFO_basictypeINTEGER:
3412 item = ffecom_expr_power_integer_ (expr);
3413 if (item != NULL_TREE)
3417 rtkt = FFEINFO_kindtypeINTEGER1;
3418 switch (ffeinfo_basictype (ffebld_info (left)))
3420 case FFEINFO_basictypeINTEGER:
3421 if ((ffeinfo_kindtype (ffebld_info (left))
3422 == FFEINFO_kindtypeINTEGER4)
3423 || (ffeinfo_kindtype (ffebld_info (right))
3424 == FFEINFO_kindtypeINTEGER4))
3426 code = FFECOM_gfrtPOW_QQ;
3427 ltkt = FFEINFO_kindtypeINTEGER4;
3428 rtkt = FFEINFO_kindtypeINTEGER4;
3432 code = FFECOM_gfrtPOW_II;
3433 ltkt = FFEINFO_kindtypeINTEGER1;
3437 case FFEINFO_basictypeREAL:
3438 if (ffeinfo_kindtype (ffebld_info (left))
3439 == FFEINFO_kindtypeREAL1)
3441 code = FFECOM_gfrtPOW_RI;
3442 ltkt = FFEINFO_kindtypeREAL1;
3446 code = FFECOM_gfrtPOW_DI;
3447 ltkt = FFEINFO_kindtypeREAL2;
3451 case FFEINFO_basictypeCOMPLEX:
3452 if (ffeinfo_kindtype (ffebld_info (left))
3453 == FFEINFO_kindtypeREAL1)
3455 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */
3456 ltkt = FFEINFO_kindtypeREAL1;
3460 code = FFECOM_gfrtPOW_ZI; /* Overlapping result okay. */
3461 ltkt = FFEINFO_kindtypeREAL2;
3466 assert ("bad pow_*i" == NULL);
3467 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */
3468 ltkt = FFEINFO_kindtypeREAL1;
3471 if (ffeinfo_kindtype (ffebld_info (left)) != ltkt)
3472 left = ffeexpr_convert (left, NULL, NULL,
3473 ffeinfo_basictype (ffebld_info (left)),
3475 FFETARGET_charactersizeNONE,
3476 FFEEXPR_contextLET);
3477 if (ffeinfo_kindtype (ffebld_info (right)) != rtkt)
3478 right = ffeexpr_convert (right, NULL, NULL,
3479 FFEINFO_basictypeINTEGER,
3481 FFETARGET_charactersizeNONE,
3482 FFEEXPR_contextLET);
3485 case FFEINFO_basictypeREAL:
3486 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3487 left = ffeexpr_convert (left, NULL, NULL, FFEINFO_basictypeREAL,
3488 FFEINFO_kindtypeREALDOUBLE, 0,
3489 FFETARGET_charactersizeNONE,
3490 FFEEXPR_contextLET);
3491 if (ffeinfo_kindtype (ffebld_info (right))
3492 == FFEINFO_kindtypeREAL1)
3493 right = ffeexpr_convert (right, NULL, NULL,
3494 FFEINFO_basictypeREAL,
3495 FFEINFO_kindtypeREALDOUBLE, 0,
3496 FFETARGET_charactersizeNONE,
3497 FFEEXPR_contextLET);
3498 code = FFECOM_gfrtPOW_DD;
3501 case FFEINFO_basictypeCOMPLEX:
3502 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3503 left = ffeexpr_convert (left, NULL, NULL,
3504 FFEINFO_basictypeCOMPLEX,
3505 FFEINFO_kindtypeREALDOUBLE, 0,
3506 FFETARGET_charactersizeNONE,
3507 FFEEXPR_contextLET);
3508 if (ffeinfo_kindtype (ffebld_info (right))
3509 == FFEINFO_kindtypeREAL1)
3510 right = ffeexpr_convert (right, NULL, NULL,
3511 FFEINFO_basictypeCOMPLEX,
3512 FFEINFO_kindtypeREALDOUBLE, 0,
3513 FFETARGET_charactersizeNONE,
3514 FFEEXPR_contextLET);
3515 code = FFECOM_gfrtPOW_ZZ; /* Overlapping result okay. */
3519 assert ("bad pow_x*" == NULL);
3520 code = FFECOM_gfrtPOW_II;
3523 return ffecom_call_binop_ (ffecom_gfrt_tree_ (code),
3524 ffecom_gfrt_kindtype (code),
3525 (ffe_is_f2c_library ()
3526 && ffecom_gfrt_complex_[code]),
3527 tree_type, left, right,
3528 dest_tree, dest, dest_used,
3530 ffebld_nonter_hook (expr));
3536 case FFEINFO_basictypeLOGICAL:
3537 item = ffecom_truth_value_invert (ffecom_expr (ffebld_left (expr)));
3538 return convert (tree_type, item);
3540 case FFEINFO_basictypeINTEGER:
3541 return ffecom_1 (BIT_NOT_EXPR, tree_type,
3542 ffecom_expr (ffebld_left (expr)));
3545 assert ("NOT bad basictype" == NULL);
3547 case FFEINFO_basictypeANY:
3548 return error_mark_node;
3552 case FFEBLD_opFUNCREF:
3553 assert (ffeinfo_basictype (ffebld_info (expr))
3554 != FFEINFO_basictypeCHARACTER);
3556 case FFEBLD_opSUBRREF:
3557 if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
3558 == FFEINFO_whereINTRINSIC)
3559 { /* Invocation of an intrinsic. */
3560 item = ffecom_expr_intrinsic_ (expr, dest_tree, dest,
3564 s = ffebld_symter (ffebld_left (expr));
3565 dt = ffesymbol_hook (s).decl_tree;
3566 if (dt == NULL_TREE)
3568 s = ffecom_sym_transform_ (s);
3569 dt = ffesymbol_hook (s).decl_tree;
3571 if (dt == error_mark_node)
3574 if (ffesymbol_hook (s).addr)
3577 item = ffecom_1_fn (dt);
3579 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
3580 args = ffecom_list_expr (ffebld_right (expr));
3582 args = ffecom_list_ptr_to_expr (ffebld_right (expr));
3584 if (args == error_mark_node)
3585 return error_mark_node;
3587 item = ffecom_call_ (item, kt,
3588 ffesymbol_is_f2c (s)
3589 && (bt == FFEINFO_basictypeCOMPLEX)
3590 && (ffesymbol_where (s)
3591 != FFEINFO_whereCONSTANT),
3594 dest_tree, dest, dest_used,
3595 error_mark_node, FALSE,
3596 ffebld_nonter_hook (expr));
3597 TREE_SIDE_EFFECTS (item) = 1;
3603 case FFEINFO_basictypeLOGICAL:
3605 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3606 ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3607 ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3608 return convert (tree_type, item);
3610 case FFEINFO_basictypeINTEGER:
3611 return ffecom_2 (BIT_AND_EXPR, tree_type,
3612 ffecom_expr (ffebld_left (expr)),
3613 ffecom_expr (ffebld_right (expr)));
3616 assert ("AND bad basictype" == NULL);
3618 case FFEINFO_basictypeANY:
3619 return error_mark_node;
3626 case FFEINFO_basictypeLOGICAL:
3628 = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
3629 ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3630 ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3631 return convert (tree_type, item);
3633 case FFEINFO_basictypeINTEGER:
3634 return ffecom_2 (BIT_IOR_EXPR, tree_type,
3635 ffecom_expr (ffebld_left (expr)),
3636 ffecom_expr (ffebld_right (expr)));
3639 assert ("OR bad basictype" == NULL);
3641 case FFEINFO_basictypeANY:
3642 return error_mark_node;
3650 case FFEINFO_basictypeLOGICAL:
3652 = ffecom_2 (NE_EXPR, integer_type_node,
3653 ffecom_expr (ffebld_left (expr)),
3654 ffecom_expr (ffebld_right (expr)));
3655 return convert (tree_type, ffecom_truth_value (item));
3657 case FFEINFO_basictypeINTEGER:
3658 return ffecom_2 (BIT_XOR_EXPR, tree_type,
3659 ffecom_expr (ffebld_left (expr)),
3660 ffecom_expr (ffebld_right (expr)));
3663 assert ("XOR/NEQV bad basictype" == NULL);
3665 case FFEINFO_basictypeANY:
3666 return error_mark_node;
3673 case FFEINFO_basictypeLOGICAL:
3675 = ffecom_2 (EQ_EXPR, integer_type_node,
3676 ffecom_expr (ffebld_left (expr)),
3677 ffecom_expr (ffebld_right (expr)));
3678 return convert (tree_type, ffecom_truth_value (item));
3680 case FFEINFO_basictypeINTEGER:
3682 ffecom_1 (BIT_NOT_EXPR, tree_type,
3683 ffecom_2 (BIT_XOR_EXPR, tree_type,
3684 ffecom_expr (ffebld_left (expr)),
3685 ffecom_expr (ffebld_right (expr))));
3688 assert ("EQV bad basictype" == NULL);
3690 case FFEINFO_basictypeANY:
3691 return error_mark_node;
3695 case FFEBLD_opCONVERT:
3696 if (ffebld_op (ffebld_left (expr)) == FFEBLD_opANY)
3697 return error_mark_node;
3701 case FFEINFO_basictypeLOGICAL:
3702 case FFEINFO_basictypeINTEGER:
3703 case FFEINFO_basictypeREAL:
3704 return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3706 case FFEINFO_basictypeCOMPLEX:
3707 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3709 case FFEINFO_basictypeINTEGER:
3710 case FFEINFO_basictypeLOGICAL:
3711 case FFEINFO_basictypeREAL:
3712 item = ffecom_expr (ffebld_left (expr));
3713 if (item == error_mark_node)
3714 return error_mark_node;
3715 /* convert() takes care of converting to the subtype first,
3716 at least in gcc-2.7.2. */
3717 item = convert (tree_type, item);
3720 case FFEINFO_basictypeCOMPLEX:
3721 return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3724 assert ("CONVERT COMPLEX bad basictype" == NULL);
3726 case FFEINFO_basictypeANY:
3727 return error_mark_node;
3732 assert ("CONVERT bad basictype" == NULL);
3734 case FFEINFO_basictypeANY:
3735 return error_mark_node;
3741 goto relational; /* :::::::::::::::::::: */
3745 goto relational; /* :::::::::::::::::::: */
3749 goto relational; /* :::::::::::::::::::: */
3753 goto relational; /* :::::::::::::::::::: */
3757 goto relational; /* :::::::::::::::::::: */
3762 relational: /* :::::::::::::::::::: */
3763 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3765 case FFEINFO_basictypeLOGICAL:
3766 case FFEINFO_basictypeINTEGER:
3767 case FFEINFO_basictypeREAL:
3768 item = ffecom_2 (code, integer_type_node,
3769 ffecom_expr (ffebld_left (expr)),
3770 ffecom_expr (ffebld_right (expr)));
3771 return convert (tree_type, item);
3773 case FFEINFO_basictypeCOMPLEX:
3774 assert (code == EQ_EXPR || code == NE_EXPR);
3777 tree arg1 = ffecom_expr (ffebld_left (expr));
3778 tree arg2 = ffecom_expr (ffebld_right (expr));
3780 if (arg1 == error_mark_node || arg2 == error_mark_node)
3781 return error_mark_node;
3783 arg1 = ffecom_save_tree (arg1);
3784 arg2 = ffecom_save_tree (arg2);
3786 if (TREE_CODE (TREE_TYPE (arg1)) == COMPLEX_TYPE)
3788 real_type = TREE_TYPE (TREE_TYPE (arg1));
3789 assert (real_type == TREE_TYPE (TREE_TYPE (arg2)));
3793 real_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg1)));
3794 assert (real_type == TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg2))));
3798 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3799 ffecom_2 (EQ_EXPR, integer_type_node,
3800 ffecom_1 (REALPART_EXPR, real_type, arg1),
3801 ffecom_1 (REALPART_EXPR, real_type, arg2)),
3802 ffecom_2 (EQ_EXPR, integer_type_node,
3803 ffecom_1 (IMAGPART_EXPR, real_type, arg1),
3804 ffecom_1 (IMAGPART_EXPR, real_type,
3806 if (code == EQ_EXPR)
3807 item = ffecom_truth_value (item);
3809 item = ffecom_truth_value_invert (item);
3810 return convert (tree_type, item);
3813 case FFEINFO_basictypeCHARACTER:
3815 ffebld left = ffebld_left (expr);
3816 ffebld right = ffebld_right (expr);
3822 /* f2c run-time functions do the implicit blank-padding for us,
3823 so we don't usually have to implement blank-padding ourselves.
3824 (The exception is when we pass an argument to a separately
3825 compiled statement function -- if we know the arg is not the
3826 same length as the dummy, we must truncate or extend it. If
3827 we "inline" statement functions, that necessity goes away as
3830 Strip off the CONVERT operators that blank-pad. (Truncation by
3831 CONVERT shouldn't happen here, but it can happen in
3834 while (ffebld_op (left) == FFEBLD_opCONVERT)
3835 left = ffebld_left (left);
3836 while (ffebld_op (right) == FFEBLD_opCONVERT)
3837 right = ffebld_left (right);
3839 left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
3840 right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
3842 if (left_tree == error_mark_node || left_length == error_mark_node
3843 || right_tree == error_mark_node
3844 || right_length == error_mark_node)
3845 return error_mark_node;
3847 if ((ffebld_size_known (left) == 1)
3848 && (ffebld_size_known (right) == 1))
3851 = ffecom_1 (INDIRECT_REF,
3852 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3855 = ffecom_1 (INDIRECT_REF,
3856 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3860 = ffecom_2 (code, integer_type_node,
3861 ffecom_2 (ARRAY_REF,
3862 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3865 ffecom_2 (ARRAY_REF,
3866 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3872 item = build_tree_list (NULL_TREE, left_tree);
3873 TREE_CHAIN (item) = build_tree_list (NULL_TREE, right_tree);
3874 TREE_CHAIN (TREE_CHAIN (item)) = build_tree_list (NULL_TREE,
3876 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
3877 = build_tree_list (NULL_TREE, right_length);
3878 item = ffecom_call_gfrt (FFECOM_gfrtCMP, item, NULL_TREE);
3879 item = ffecom_2 (code, integer_type_node,
3881 convert (TREE_TYPE (item),
3882 integer_zero_node));
3884 item = convert (tree_type, item);
3890 assert ("relational bad basictype" == NULL);
3892 case FFEINFO_basictypeANY:
3893 return error_mark_node;
3897 case FFEBLD_opPERCENT_LOC:
3898 item = ffecom_arg_ptr_to_expr (ffebld_left (expr), &list);
3899 return convert (tree_type, item);
3903 case FFEBLD_opBOUNDS:
3904 case FFEBLD_opREPEAT:
3905 case FFEBLD_opLABTER:
3906 case FFEBLD_opLABTOK:
3907 case FFEBLD_opIMPDO:
3908 case FFEBLD_opCONCATENATE:
3909 case FFEBLD_opSUBSTR:
3911 assert ("bad op" == NULL);
3914 return error_mark_node;
3918 assert ("didn't think anything got here anymore!!" == NULL);
3920 switch (ffebld_arity (expr))
3923 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3924 TREE_OPERAND (item, 1) = ffecom_expr (ffebld_right (expr));
3925 if (TREE_OPERAND (item, 0) == error_mark_node
3926 || TREE_OPERAND (item, 1) == error_mark_node)
3927 return error_mark_node;
3931 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3932 if (TREE_OPERAND (item, 0) == error_mark_node)
3933 return error_mark_node;
3945 /* Returns the tree that does the intrinsic invocation.
3947 Note: this function applies only to intrinsics returning
3948 CHARACTER*1 or non-CHARACTER results, and to intrinsic
3951 #if FFECOM_targetCURRENT == FFECOM_targetGCC
3953 ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
3954 ffebld dest, bool *dest_used)
3957 tree saved_expr1; /* For those who need it. */
3958 tree saved_expr2; /* For those who need it. */
3959 ffeinfoBasictype bt;
3963 tree real_type; /* REAL type corresponding to COMPLEX. */
3965 ffebld list = ffebld_right (expr); /* List of (some) args. */
3966 ffebld arg1; /* For handy reference. */
3969 ffeintrinImp codegen_imp;
3972 assert (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER);
3974 if (dest_used != NULL)
3977 bt = ffeinfo_basictype (ffebld_info (expr));
3978 kt = ffeinfo_kindtype (ffebld_info (expr));
3979 tree_type = ffecom_tree_type[bt][kt];
3983 arg1 = ffebld_head (list);
3984 if (arg1 != NULL && ffebld_op (arg1) == FFEBLD_opANY)
3985 return error_mark_node;
3986 if ((list = ffebld_trail (list)) != NULL)
3988 arg2 = ffebld_head (list);
3989 if (arg2 != NULL && ffebld_op (arg2) == FFEBLD_opANY)
3990 return error_mark_node;
3991 if ((list = ffebld_trail (list)) != NULL)
3993 arg3 = ffebld_head (list);
3994 if (arg3 != NULL && ffebld_op (arg3) == FFEBLD_opANY)
3995 return error_mark_node;
4004 arg1 = arg2 = arg3 = NULL;
4006 /* <list> ends up at the opITEM of the 3rd arg, or NULL if there are < 3
4007 args. This is used by the MAX/MIN expansions. */
4010 arg1_type = ffecom_tree_type
4011 [ffeinfo_basictype (ffebld_info (arg1))]
4012 [ffeinfo_kindtype (ffebld_info (arg1))];
4014 arg1_type = NULL_TREE; /* Really not needed, but might catch bugs
4017 /* There are several ways for each of the cases in the following switch
4018 statements to exit (from simplest to use to most complicated):
4020 break; (when expr_tree == NULL)
4022 A standard call is made to the specific intrinsic just as if it had been
4023 passed in as a dummy procedure and called as any old procedure. This
4024 method can produce slower code but in some cases it's the easiest way for
4025 now. However, if a (presumably faster) direct call is available,
4026 that is used, so this is the easiest way in many more cases now.
4028 gfrt = FFECOM_gfrtWHATEVER;
4031 gfrt contains the gfrt index of a library function to call, passing the
4032 argument(s) by value rather than by reference. Used when a more
4033 careful choice of library function is needed than that provided
4034 by the vanilla `break;'.
4038 The expr_tree has been completely set up and is ready to be returned
4039 as is. No further actions are taken. Use this when the tree is not
4040 in the simple form for one of the arity_n labels. */
4042 /* For info on how the switch statement cases were written, see the files
4043 enclosed in comments below the switch statement. */
4045 codegen_imp = ffebld_symter_implementation (ffebld_left (expr));
4046 gfrt = ffeintrin_gfrt_direct (codegen_imp);
4047 if (gfrt == FFECOM_gfrt)
4048 gfrt = ffeintrin_gfrt_indirect (codegen_imp);
4050 switch (codegen_imp)
4052 case FFEINTRIN_impABS:
4053 case FFEINTRIN_impCABS:
4054 case FFEINTRIN_impCDABS:
4055 case FFEINTRIN_impDABS:
4056 case FFEINTRIN_impIABS:
4057 if (ffeinfo_basictype (ffebld_info (arg1))
4058 == FFEINFO_basictypeCOMPLEX)
4060 if (kt == FFEINFO_kindtypeREAL1)
4061 gfrt = FFECOM_gfrtCABS;
4062 else if (kt == FFEINFO_kindtypeREAL2)
4063 gfrt = FFECOM_gfrtCDABS;
4066 return ffecom_1 (ABS_EXPR, tree_type,
4067 convert (tree_type, ffecom_expr (arg1)));
4069 case FFEINTRIN_impACOS:
4070 case FFEINTRIN_impDACOS:
4073 case FFEINTRIN_impAIMAG:
4074 case FFEINTRIN_impDIMAG:
4075 case FFEINTRIN_impIMAGPART:
4076 if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
4077 arg1_type = TREE_TYPE (arg1_type);
4079 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
4083 ffecom_1 (IMAGPART_EXPR, arg1_type,
4084 ffecom_expr (arg1)));
4086 case FFEINTRIN_impAINT:
4087 case FFEINTRIN_impDINT:
4089 /* ~~Someday implement FIX_TRUNC_EXPR yielding same type as arg. */
4090 return ffecom_1 (FIX_TRUNC_EXPR, tree_type, ffecom_expr (arg1));
4091 #else /* in the meantime, must use floor to avoid range problems with ints */
4092 /* r__1 = r1 >= 0 ? floor(r1) : -floor(-r1); */
4093 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4096 ffecom_3 (COND_EXPR, double_type_node,
4098 (ffecom_2 (GE_EXPR, integer_type_node,
4101 ffecom_float_zero_))),
4102 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4103 build_tree_list (NULL_TREE,
4104 convert (double_type_node,
4107 ffecom_1 (NEGATE_EXPR, double_type_node,
4108 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4109 build_tree_list (NULL_TREE,
4110 convert (double_type_node,
4111 ffecom_1 (NEGATE_EXPR,
4119 case FFEINTRIN_impANINT:
4120 case FFEINTRIN_impDNINT:
4121 #if 0 /* This way of doing it won't handle real
4122 numbers of large magnitudes. */
4123 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4124 expr_tree = convert (tree_type,
4125 convert (integer_type_node,
4126 ffecom_3 (COND_EXPR, tree_type,
4131 ffecom_float_zero_)),
4132 ffecom_2 (PLUS_EXPR,
4135 ffecom_float_half_),
4136 ffecom_2 (MINUS_EXPR,
4139 ffecom_float_half_))));
4141 #else /* So we instead call floor. */
4142 /* r__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1) */
4143 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4146 ffecom_3 (COND_EXPR, double_type_node,
4148 (ffecom_2 (GE_EXPR, integer_type_node,
4151 ffecom_float_zero_))),
4152 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4153 build_tree_list (NULL_TREE,
4154 convert (double_type_node,
4155 ffecom_2 (PLUS_EXPR,
4159 ffecom_float_half_)))),
4161 ffecom_1 (NEGATE_EXPR, double_type_node,
4162 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4163 build_tree_list (NULL_TREE,
4164 convert (double_type_node,
4165 ffecom_2 (MINUS_EXPR,
4168 ffecom_float_half_),
4175 case FFEINTRIN_impASIN:
4176 case FFEINTRIN_impDASIN:
4177 case FFEINTRIN_impATAN:
4178 case FFEINTRIN_impDATAN:
4179 case FFEINTRIN_impATAN2:
4180 case FFEINTRIN_impDATAN2:
4183 case FFEINTRIN_impCHAR:
4184 case FFEINTRIN_impACHAR:
4186 tempvar = ffecom_make_tempvar (char_type_node, 1, -1);
4188 tempvar = ffebld_nonter_hook (expr);
4192 tree tmv = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (tempvar)));
4194 expr_tree = ffecom_modify (tmv,
4195 ffecom_2 (ARRAY_REF, tmv, tempvar,
4197 convert (tmv, ffecom_expr (arg1)));
4199 expr_tree = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar),
4202 expr_tree = ffecom_1 (ADDR_EXPR,
4203 build_pointer_type (TREE_TYPE (expr_tree)),
4207 case FFEINTRIN_impCMPLX:
4208 case FFEINTRIN_impDCMPLX:
4211 convert (tree_type, ffecom_expr (arg1));
4213 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
4215 ffecom_2 (COMPLEX_EXPR, tree_type,
4216 convert (real_type, ffecom_expr (arg1)),
4218 ffecom_expr (arg2)));
4220 case FFEINTRIN_impCOMPLEX:
4222 ffecom_2 (COMPLEX_EXPR, tree_type,
4224 ffecom_expr (arg2));
4226 case FFEINTRIN_impCONJG:
4227 case FFEINTRIN_impDCONJG:
4231 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
4232 arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4234 ffecom_2 (COMPLEX_EXPR, tree_type,
4235 ffecom_1 (REALPART_EXPR, real_type, arg1_tree),
4236 ffecom_1 (NEGATE_EXPR, real_type,
4237 ffecom_1 (IMAGPART_EXPR, real_type, arg1_tree)));
4240 case FFEINTRIN_impCOS:
4241 case FFEINTRIN_impCCOS:
4242 case FFEINTRIN_impCDCOS:
4243 case FFEINTRIN_impDCOS:
4244 if (bt == FFEINFO_basictypeCOMPLEX)
4246 if (kt == FFEINFO_kindtypeREAL1)
4247 gfrt = FFECOM_gfrtCCOS; /* Overlapping result okay. */
4248 else if (kt == FFEINFO_kindtypeREAL2)
4249 gfrt = FFECOM_gfrtCDCOS; /* Overlapping result okay. */
4253 case FFEINTRIN_impCOSH:
4254 case FFEINTRIN_impDCOSH:
4257 case FFEINTRIN_impDBLE:
4258 case FFEINTRIN_impDFLOAT:
4259 case FFEINTRIN_impDREAL:
4260 case FFEINTRIN_impFLOAT:
4261 case FFEINTRIN_impIDINT:
4262 case FFEINTRIN_impIFIX:
4263 case FFEINTRIN_impINT2:
4264 case FFEINTRIN_impINT8:
4265 case FFEINTRIN_impINT:
4266 case FFEINTRIN_impLONG:
4267 case FFEINTRIN_impREAL:
4268 case FFEINTRIN_impSHORT:
4269 case FFEINTRIN_impSNGL:
4270 return convert (tree_type, ffecom_expr (arg1));
4272 case FFEINTRIN_impDIM:
4273 case FFEINTRIN_impDDIM:
4274 case FFEINTRIN_impIDIM:
4275 saved_expr1 = ffecom_save_tree (convert (tree_type,
4276 ffecom_expr (arg1)));
4277 saved_expr2 = ffecom_save_tree (convert (tree_type,
4278 ffecom_expr (arg2)));
4280 ffecom_3 (COND_EXPR, tree_type,
4282 (ffecom_2 (GT_EXPR, integer_type_node,
4285 ffecom_2 (MINUS_EXPR, tree_type,
4288 convert (tree_type, ffecom_float_zero_));
4290 case FFEINTRIN_impDPROD:
4292 ffecom_2 (MULT_EXPR, tree_type,
4293 convert (tree_type, ffecom_expr (arg1)),
4294 convert (tree_type, ffecom_expr (arg2)));
4296 case FFEINTRIN_impEXP:
4297 case FFEINTRIN_impCDEXP:
4298 case FFEINTRIN_impCEXP:
4299 case FFEINTRIN_impDEXP:
4300 if (bt == FFEINFO_basictypeCOMPLEX)
4302 if (kt == FFEINFO_kindtypeREAL1)
4303 gfrt = FFECOM_gfrtCEXP; /* Overlapping result okay. */
4304 else if (kt == FFEINFO_kindtypeREAL2)
4305 gfrt = FFECOM_gfrtCDEXP; /* Overlapping result okay. */
4309 case FFEINTRIN_impICHAR:
4310 case FFEINTRIN_impIACHAR:
4311 #if 0 /* The simple approach. */
4312 ffecom_char_args_ (&expr_tree, &saved_expr1 /* Ignored */ , arg1);
4314 = ffecom_1 (INDIRECT_REF,
4315 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
4318 = ffecom_2 (ARRAY_REF,
4319 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
4322 return convert (tree_type, expr_tree);
4323 #else /* The more interesting (and more optimal) approach. */
4324 expr_tree = ffecom_intrinsic_ichar_ (tree_type, arg1, &saved_expr1);
4325 expr_tree = ffecom_3 (COND_EXPR, tree_type,
4328 convert (tree_type, integer_zero_node));
4332 case FFEINTRIN_impINDEX:
4335 case FFEINTRIN_impLEN:
4337 break; /* The simple approach. */
4339 return ffecom_intrinsic_len_ (arg1); /* The more optimal approach. */
4342 case FFEINTRIN_impLGE:
4343 case FFEINTRIN_impLGT:
4344 case FFEINTRIN_impLLE:
4345 case FFEINTRIN_impLLT:
4348 case FFEINTRIN_impLOG:
4349 case FFEINTRIN_impALOG:
4350 case FFEINTRIN_impCDLOG:
4351 case FFEINTRIN_impCLOG:
4352 case FFEINTRIN_impDLOG:
4353 if (bt == FFEINFO_basictypeCOMPLEX)
4355 if (kt == FFEINFO_kindtypeREAL1)
4356 gfrt = FFECOM_gfrtCLOG; /* Overlapping result okay. */
4357 else if (kt == FFEINFO_kindtypeREAL2)
4358 gfrt = FFECOM_gfrtCDLOG; /* Overlapping result okay. */
4362 case FFEINTRIN_impLOG10:
4363 case FFEINTRIN_impALOG10:
4364 case FFEINTRIN_impDLOG10:
4365 if (gfrt != FFECOM_gfrt)
4366 break; /* Already picked one, stick with it. */
4368 if (kt == FFEINFO_kindtypeREAL1)
4369 gfrt = FFECOM_gfrtALOG10;
4370 else if (kt == FFEINFO_kindtypeREAL2)
4371 gfrt = FFECOM_gfrtDLOG10;
4374 case FFEINTRIN_impMAX:
4375 case FFEINTRIN_impAMAX0:
4376 case FFEINTRIN_impAMAX1:
4377 case FFEINTRIN_impDMAX1:
4378 case FFEINTRIN_impMAX0:
4379 case FFEINTRIN_impMAX1:
4380 if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4381 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4383 arg1_type = tree_type;
4384 expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4385 convert (arg1_type, ffecom_expr (arg1)),
4386 convert (arg1_type, ffecom_expr (arg2)));
4387 for (; list != NULL; list = ffebld_trail (list))
4389 if ((ffebld_head (list) == NULL)
4390 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4392 expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4395 ffecom_expr (ffebld_head (list))));
4397 return convert (tree_type, expr_tree);
4399 case FFEINTRIN_impMIN:
4400 case FFEINTRIN_impAMIN0:
4401 case FFEINTRIN_impAMIN1:
4402 case FFEINTRIN_impDMIN1:
4403 case FFEINTRIN_impMIN0:
4404 case FFEINTRIN_impMIN1:
4405 if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4406 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4408 arg1_type = tree_type;
4409 expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4410 convert (arg1_type, ffecom_expr (arg1)),
4411 convert (arg1_type, ffecom_expr (arg2)));
4412 for (; list != NULL; list = ffebld_trail (list))
4414 if ((ffebld_head (list) == NULL)
4415 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4417 expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4420 ffecom_expr (ffebld_head (list))));
4422 return convert (tree_type, expr_tree);
4424 case FFEINTRIN_impMOD:
4425 case FFEINTRIN_impAMOD:
4426 case FFEINTRIN_impDMOD:
4427 if (bt != FFEINFO_basictypeREAL)
4428 return ffecom_2 (TRUNC_MOD_EXPR, tree_type,
4429 convert (tree_type, ffecom_expr (arg1)),
4430 convert (tree_type, ffecom_expr (arg2)));
4432 if (kt == FFEINFO_kindtypeREAL1)
4433 gfrt = FFECOM_gfrtAMOD;
4434 else if (kt == FFEINFO_kindtypeREAL2)
4435 gfrt = FFECOM_gfrtDMOD;
4438 case FFEINTRIN_impNINT:
4439 case FFEINTRIN_impIDNINT:
4441 /* ~~Ideally FIX_ROUND_EXPR would be implemented, but it ain't yet. */
4442 return ffecom_1 (FIX_ROUND_EXPR, tree_type, ffecom_expr (arg1));
4444 /* i__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1); */
4445 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4447 convert (ffecom_integer_type_node,
4448 ffecom_3 (COND_EXPR, arg1_type,
4450 (ffecom_2 (GE_EXPR, integer_type_node,
4453 ffecom_float_zero_))),
4454 ffecom_2 (PLUS_EXPR, arg1_type,
4457 ffecom_float_half_)),
4458 ffecom_2 (MINUS_EXPR, arg1_type,
4461 ffecom_float_half_))));
4464 case FFEINTRIN_impSIGN:
4465 case FFEINTRIN_impDSIGN:
4466 case FFEINTRIN_impISIGN:
4468 tree arg2_tree = ffecom_expr (arg2);
4472 (ffecom_1 (ABS_EXPR, tree_type,
4474 ffecom_expr (arg1))));
4476 = ffecom_3 (COND_EXPR, tree_type,
4478 (ffecom_2 (GE_EXPR, integer_type_node,
4480 convert (TREE_TYPE (arg2_tree),
4481 integer_zero_node))),
4483 ffecom_1 (NEGATE_EXPR, tree_type, saved_expr1));
4484 /* Make sure SAVE_EXPRs get referenced early enough. */
4486 = ffecom_2 (COMPOUND_EXPR, tree_type,
4487 convert (void_type_node, saved_expr1),
4492 case FFEINTRIN_impSIN:
4493 case FFEINTRIN_impCDSIN:
4494 case FFEINTRIN_impCSIN:
4495 case FFEINTRIN_impDSIN:
4496 if (bt == FFEINFO_basictypeCOMPLEX)
4498 if (kt == FFEINFO_kindtypeREAL1)
4499 gfrt = FFECOM_gfrtCSIN; /* Overlapping result okay. */
4500 else if (kt == FFEINFO_kindtypeREAL2)
4501 gfrt = FFECOM_gfrtCDSIN; /* Overlapping result okay. */
4505 case FFEINTRIN_impSINH:
4506 case FFEINTRIN_impDSINH:
4509 case FFEINTRIN_impSQRT:
4510 case FFEINTRIN_impCDSQRT:
4511 case FFEINTRIN_impCSQRT:
4512 case FFEINTRIN_impDSQRT:
4513 if (bt == FFEINFO_basictypeCOMPLEX)
4515 if (kt == FFEINFO_kindtypeREAL1)
4516 gfrt = FFECOM_gfrtCSQRT; /* Overlapping result okay. */
4517 else if (kt == FFEINFO_kindtypeREAL2)
4518 gfrt = FFECOM_gfrtCDSQRT; /* Overlapping result okay. */
4522 case FFEINTRIN_impTAN:
4523 case FFEINTRIN_impDTAN:
4524 case FFEINTRIN_impTANH:
4525 case FFEINTRIN_impDTANH:
4528 case FFEINTRIN_impREALPART:
4529 if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
4530 arg1_type = TREE_TYPE (arg1_type);
4532 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
4536 ffecom_1 (REALPART_EXPR, arg1_type,
4537 ffecom_expr (arg1)));
4539 case FFEINTRIN_impIAND:
4540 case FFEINTRIN_impAND:
4541 return ffecom_2 (BIT_AND_EXPR, tree_type,
4543 ffecom_expr (arg1)),
4545 ffecom_expr (arg2)));
4547 case FFEINTRIN_impIOR:
4548 case FFEINTRIN_impOR:
4549 return ffecom_2 (BIT_IOR_EXPR, tree_type,
4551 ffecom_expr (arg1)),
4553 ffecom_expr (arg2)));
4555 case FFEINTRIN_impIEOR:
4556 case FFEINTRIN_impXOR:
4557 return ffecom_2 (BIT_XOR_EXPR, tree_type,
4559 ffecom_expr (arg1)),
4561 ffecom_expr (arg2)));
4563 case FFEINTRIN_impLSHIFT:
4564 return ffecom_2 (LSHIFT_EXPR, tree_type,
4566 convert (integer_type_node,
4567 ffecom_expr (arg2)));
4569 case FFEINTRIN_impRSHIFT:
4570 return ffecom_2 (RSHIFT_EXPR, tree_type,
4572 convert (integer_type_node,
4573 ffecom_expr (arg2)));
4575 case FFEINTRIN_impNOT:
4576 return ffecom_1 (BIT_NOT_EXPR, tree_type, ffecom_expr (arg1));
4578 case FFEINTRIN_impBIT_SIZE:
4579 return convert (tree_type, TYPE_SIZE (arg1_type));
4581 case FFEINTRIN_impBTEST:
4583 ffetargetLogical1 true;
4584 ffetargetLogical1 false;
4588 ffetarget_logical1 (&true, TRUE);
4589 ffetarget_logical1 (&false, FALSE);
4591 true_tree = convert (tree_type, integer_one_node);
4593 true_tree = convert (tree_type, build_int_2 (true, 0));
4595 false_tree = convert (tree_type, integer_zero_node);
4597 false_tree = convert (tree_type, build_int_2 (false, 0));
4600 ffecom_3 (COND_EXPR, tree_type,
4602 (ffecom_2 (EQ_EXPR, integer_type_node,
4603 ffecom_2 (BIT_AND_EXPR, arg1_type,
4605 ffecom_2 (LSHIFT_EXPR, arg1_type,
4608 convert (integer_type_node,
4609 ffecom_expr (arg2)))),
4611 integer_zero_node))),
4616 case FFEINTRIN_impIBCLR:
4618 ffecom_2 (BIT_AND_EXPR, tree_type,
4620 ffecom_1 (BIT_NOT_EXPR, tree_type,
4621 ffecom_2 (LSHIFT_EXPR, tree_type,
4624 convert (integer_type_node,
4625 ffecom_expr (arg2)))));
4627 case FFEINTRIN_impIBITS:
4629 tree arg3_tree = ffecom_save_tree (convert (integer_type_node,
4630 ffecom_expr (arg3)));
4632 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4635 = ffecom_2 (BIT_AND_EXPR, tree_type,
4636 ffecom_2 (RSHIFT_EXPR, tree_type,
4638 convert (integer_type_node,
4639 ffecom_expr (arg2))),
4641 ffecom_2 (RSHIFT_EXPR, uns_type,
4642 ffecom_1 (BIT_NOT_EXPR,
4645 integer_zero_node)),
4646 ffecom_2 (MINUS_EXPR,
4648 TYPE_SIZE (uns_type),
4650 #if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4652 = ffecom_3 (COND_EXPR, tree_type,
4654 (ffecom_2 (NE_EXPR, integer_type_node,
4656 integer_zero_node)),
4658 convert (tree_type, integer_zero_node));
4663 case FFEINTRIN_impIBSET:
4665 ffecom_2 (BIT_IOR_EXPR, tree_type,
4667 ffecom_2 (LSHIFT_EXPR, tree_type,
4668 convert (tree_type, integer_one_node),
4669 convert (integer_type_node,
4670 ffecom_expr (arg2))));
4672 case FFEINTRIN_impISHFT:
4674 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4675 tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4676 ffecom_expr (arg2)));
4678 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4681 = ffecom_3 (COND_EXPR, tree_type,
4683 (ffecom_2 (GE_EXPR, integer_type_node,
4685 integer_zero_node)),
4686 ffecom_2 (LSHIFT_EXPR, tree_type,
4690 ffecom_2 (RSHIFT_EXPR, uns_type,
4691 convert (uns_type, arg1_tree),
4692 ffecom_1 (NEGATE_EXPR,
4695 #if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4697 = ffecom_3 (COND_EXPR, tree_type,
4699 (ffecom_2 (NE_EXPR, integer_type_node,
4701 TYPE_SIZE (uns_type))),
4703 convert (tree_type, integer_zero_node));
4705 /* Make sure SAVE_EXPRs get referenced early enough. */
4707 = ffecom_2 (COMPOUND_EXPR, tree_type,
4708 convert (void_type_node, arg1_tree),
4709 ffecom_2 (COMPOUND_EXPR, tree_type,
4710 convert (void_type_node, arg2_tree),
4715 case FFEINTRIN_impISHFTC:
4717 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4718 tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4719 ffecom_expr (arg2)));
4720 tree arg3_tree = (arg3 == NULL) ? TYPE_SIZE (tree_type)
4721 : ffecom_save_tree (convert (integer_type_node, ffecom_expr (arg3)));
4727 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4730 = ffecom_2 (LSHIFT_EXPR, tree_type,
4731 ffecom_1 (BIT_NOT_EXPR, tree_type,
4732 convert (tree_type, integer_zero_node)),
4734 #if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4736 = ffecom_3 (COND_EXPR, tree_type,
4738 (ffecom_2 (NE_EXPR, integer_type_node,
4740 TYPE_SIZE (uns_type))),
4742 convert (tree_type, integer_zero_node));
4744 mask_arg1 = ffecom_save_tree (mask_arg1);
4746 = ffecom_2 (BIT_AND_EXPR, tree_type,
4748 ffecom_1 (BIT_NOT_EXPR, tree_type,
4750 masked_arg1 = ffecom_save_tree (masked_arg1);
4752 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4754 ffecom_2 (RSHIFT_EXPR, uns_type,
4755 convert (uns_type, masked_arg1),
4756 ffecom_1 (NEGATE_EXPR,
4759 ffecom_2 (LSHIFT_EXPR, tree_type,
4761 ffecom_2 (PLUS_EXPR, integer_type_node,
4765 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4766 ffecom_2 (LSHIFT_EXPR, tree_type,
4770 ffecom_2 (RSHIFT_EXPR, uns_type,
4771 convert (uns_type, masked_arg1),
4772 ffecom_2 (MINUS_EXPR,
4777 = ffecom_3 (COND_EXPR, tree_type,
4779 (ffecom_2 (LT_EXPR, integer_type_node,
4781 integer_zero_node)),
4785 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4786 ffecom_2 (BIT_AND_EXPR, tree_type,
4789 ffecom_2 (BIT_AND_EXPR, tree_type,
4790 ffecom_1 (BIT_NOT_EXPR, tree_type,
4794 = ffecom_3 (COND_EXPR, tree_type,
4796 (ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
4797 ffecom_2 (EQ_EXPR, integer_type_node,
4802 ffecom_2 (EQ_EXPR, integer_type_node,
4804 integer_zero_node))),
4807 /* Make sure SAVE_EXPRs get referenced early enough. */
4809 = ffecom_2 (COMPOUND_EXPR, tree_type,
4810 convert (void_type_node, arg1_tree),
4811 ffecom_2 (COMPOUND_EXPR, tree_type,
4812 convert (void_type_node, arg2_tree),
4813 ffecom_2 (COMPOUND_EXPR, tree_type,
4814 convert (void_type_node,
4816 ffecom_2 (COMPOUND_EXPR, tree_type,
4817 convert (void_type_node,
4821 = ffecom_2 (COMPOUND_EXPR, tree_type,
4822 convert (void_type_node,
4828 case FFEINTRIN_impLOC:
4830 tree arg1_tree = ffecom_expr (arg1);
4833 = convert (tree_type,
4834 ffecom_1 (ADDR_EXPR,
4835 build_pointer_type (TREE_TYPE (arg1_tree)),
4840 case FFEINTRIN_impMVBITS:
4845 ffebld arg4 = ffebld_head (ffebld_trail (list));
4848 ffebld arg5 = ffebld_head (ffebld_trail (ffebld_trail (list)));
4852 tree arg5_plus_arg3;
4854 arg2_tree = convert (integer_type_node,
4855 ffecom_expr (arg2));
4856 arg3_tree = ffecom_save_tree (convert (integer_type_node,
4857 ffecom_expr (arg3)));
4858 arg4_tree = ffecom_expr_rw (NULL_TREE, arg4);
4859 arg4_type = TREE_TYPE (arg4_tree);
4861 arg1_tree = ffecom_save_tree (convert (arg4_type,
4862 ffecom_expr (arg1)));
4864 arg5_tree = ffecom_save_tree (convert (integer_type_node,
4865 ffecom_expr (arg5)));
4868 = ffecom_2 (LSHIFT_EXPR, arg4_type,
4869 ffecom_2 (BIT_AND_EXPR, arg4_type,
4870 ffecom_2 (RSHIFT_EXPR, arg4_type,
4873 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4874 ffecom_2 (LSHIFT_EXPR, arg4_type,
4875 ffecom_1 (BIT_NOT_EXPR,
4879 integer_zero_node)),
4883 = ffecom_save_tree (ffecom_2 (PLUS_EXPR, arg4_type,
4887 = ffecom_2 (LSHIFT_EXPR, arg4_type,
4888 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4890 integer_zero_node)),
4892 #if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4894 = ffecom_3 (COND_EXPR, arg4_type,
4896 (ffecom_2 (NE_EXPR, integer_type_node,
4898 convert (TREE_TYPE (arg5_plus_arg3),
4899 TYPE_SIZE (arg4_type)))),
4901 convert (arg4_type, integer_zero_node));
4904 = ffecom_2 (BIT_AND_EXPR, arg4_type,
4906 ffecom_2 (BIT_IOR_EXPR, arg4_type,
4908 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4909 ffecom_2 (LSHIFT_EXPR, arg4_type,
4910 ffecom_1 (BIT_NOT_EXPR,
4914 integer_zero_node)),
4917 = ffecom_2 (BIT_IOR_EXPR, arg4_type,
4920 #if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4922 = ffecom_3 (COND_EXPR, arg4_type,
4924 (ffecom_2 (NE_EXPR, integer_type_node,
4926 convert (TREE_TYPE (arg3_tree),
4927 integer_zero_node))),
4931 = ffecom_3 (COND_EXPR, arg4_type,
4933 (ffecom_2 (NE_EXPR, integer_type_node,
4935 convert (TREE_TYPE (arg3_tree),
4936 TYPE_SIZE (arg4_type)))),
4941 = ffecom_2s (MODIFY_EXPR, void_type_node,
4944 /* Make sure SAVE_EXPRs get referenced early enough. */
4946 = ffecom_2 (COMPOUND_EXPR, void_type_node,
4948 ffecom_2 (COMPOUND_EXPR, void_type_node,
4950 ffecom_2 (COMPOUND_EXPR, void_type_node,
4952 ffecom_2 (COMPOUND_EXPR, void_type_node,
4956 = ffecom_2 (COMPOUND_EXPR, void_type_node,
4963 case FFEINTRIN_impDERF:
4964 case FFEINTRIN_impERF:
4965 case FFEINTRIN_impDERFC:
4966 case FFEINTRIN_impERFC:
4969 case FFEINTRIN_impIARGC:
4970 /* extern int xargc; i__1 = xargc - 1; */
4971 expr_tree = ffecom_2 (MINUS_EXPR, TREE_TYPE (ffecom_tree_xargc_),
4973 convert (TREE_TYPE (ffecom_tree_xargc_),
4977 case FFEINTRIN_impSIGNAL_func:
4978 case FFEINTRIN_impSIGNAL_subr:
4984 arg1_tree = convert (ffecom_f2c_integer_type_node,
4985 ffecom_expr (arg1));
4986 arg1_tree = ffecom_1 (ADDR_EXPR,
4987 build_pointer_type (TREE_TYPE (arg1_tree)),
4990 /* Pass procedure as a pointer to it, anything else by value. */
4991 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
4992 arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
4994 arg2_tree = ffecom_ptr_to_expr (arg2);
4995 arg2_tree = convert (TREE_TYPE (null_pointer_node),
4999 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5001 arg3_tree = NULL_TREE;
5003 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5004 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5005 TREE_CHAIN (arg1_tree) = arg2_tree;
5008 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5009 ffecom_gfrt_kindtype (gfrt),
5011 ((codegen_imp == FFEINTRIN_impSIGNAL_subr) ?
5015 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5016 ffebld_nonter_hook (expr));
5018 if (arg3_tree != NULL_TREE)
5020 = ffecom_modify (NULL_TREE, arg3_tree,
5021 convert (TREE_TYPE (arg3_tree),
5026 case FFEINTRIN_impALARM:
5032 arg1_tree = convert (ffecom_f2c_integer_type_node,
5033 ffecom_expr (arg1));
5034 arg1_tree = ffecom_1 (ADDR_EXPR,
5035 build_pointer_type (TREE_TYPE (arg1_tree)),
5038 /* Pass procedure as a pointer to it, anything else by value. */
5039 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
5040 arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
5042 arg2_tree = ffecom_ptr_to_expr (arg2);
5043 arg2_tree = convert (TREE_TYPE (null_pointer_node),
5047 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5049 arg3_tree = NULL_TREE;
5051 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5052 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5053 TREE_CHAIN (arg1_tree) = arg2_tree;
5056 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5057 ffecom_gfrt_kindtype (gfrt),
5061 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5062 ffebld_nonter_hook (expr));
5064 if (arg3_tree != NULL_TREE)
5066 = ffecom_modify (NULL_TREE, arg3_tree,
5067 convert (TREE_TYPE (arg3_tree),
5072 case FFEINTRIN_impCHDIR_subr:
5073 case FFEINTRIN_impFDATE_subr:
5074 case FFEINTRIN_impFGET_subr:
5075 case FFEINTRIN_impFPUT_subr:
5076 case FFEINTRIN_impGETCWD_subr:
5077 case FFEINTRIN_impHOSTNM_subr:
5078 case FFEINTRIN_impSYSTEM_subr:
5079 case FFEINTRIN_impUNLINK_subr:
5081 tree arg1_len = integer_zero_node;
5085 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5088 arg2_tree = ffecom_expr_w (NULL_TREE, arg2);
5090 arg2_tree = NULL_TREE;
5092 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5093 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5094 TREE_CHAIN (arg1_tree) = arg1_len;
5097 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5098 ffecom_gfrt_kindtype (gfrt),
5102 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5103 ffebld_nonter_hook (expr));
5105 if (arg2_tree != NULL_TREE)
5107 = ffecom_modify (NULL_TREE, arg2_tree,
5108 convert (TREE_TYPE (arg2_tree),
5113 case FFEINTRIN_impEXIT:
5117 expr_tree = build_tree_list (NULL_TREE,
5118 ffecom_1 (ADDR_EXPR,
5120 (ffecom_integer_type_node),
5121 integer_zero_node));
5124 ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5125 ffecom_gfrt_kindtype (gfrt),
5129 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5130 ffebld_nonter_hook (expr));
5132 case FFEINTRIN_impFLUSH:
5134 gfrt = FFECOM_gfrtFLUSH;
5136 gfrt = FFECOM_gfrtFLUSH1;
5139 case FFEINTRIN_impCHMOD_subr:
5140 case FFEINTRIN_impLINK_subr:
5141 case FFEINTRIN_impRENAME_subr:
5142 case FFEINTRIN_impSYMLNK_subr:
5144 tree arg1_len = integer_zero_node;
5146 tree arg2_len = integer_zero_node;
5150 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5151 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
5153 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5155 arg3_tree = NULL_TREE;
5157 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5158 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5159 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5160 arg2_len = build_tree_list (NULL_TREE, arg2_len);
5161 TREE_CHAIN (arg1_tree) = arg2_tree;
5162 TREE_CHAIN (arg2_tree) = arg1_len;
5163 TREE_CHAIN (arg1_len) = arg2_len;
5164 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5165 ffecom_gfrt_kindtype (gfrt),
5169 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5170 ffebld_nonter_hook (expr));
5171 if (arg3_tree != NULL_TREE)
5172 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5173 convert (TREE_TYPE (arg3_tree),
5178 case FFEINTRIN_impLSTAT_subr:
5179 case FFEINTRIN_impSTAT_subr:
5181 tree arg1_len = integer_zero_node;
5186 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5188 arg2_tree = ffecom_ptr_to_expr (arg2);
5191 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5193 arg3_tree = NULL_TREE;
5195 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5196 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5197 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5198 TREE_CHAIN (arg1_tree) = arg2_tree;
5199 TREE_CHAIN (arg2_tree) = arg1_len;
5200 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5201 ffecom_gfrt_kindtype (gfrt),
5205 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5206 ffebld_nonter_hook (expr));
5207 if (arg3_tree != NULL_TREE)
5208 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5209 convert (TREE_TYPE (arg3_tree),
5214 case FFEINTRIN_impFGETC_subr:
5215 case FFEINTRIN_impFPUTC_subr:
5219 tree arg2_len = integer_zero_node;
5222 arg1_tree = convert (ffecom_f2c_integer_type_node,
5223 ffecom_expr (arg1));
5224 arg1_tree = ffecom_1 (ADDR_EXPR,
5225 build_pointer_type (TREE_TYPE (arg1_tree)),
5228 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
5229 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5231 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5232 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5233 arg2_len = build_tree_list (NULL_TREE, arg2_len);
5234 TREE_CHAIN (arg1_tree) = arg2_tree;
5235 TREE_CHAIN (arg2_tree) = arg2_len;
5237 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5238 ffecom_gfrt_kindtype (gfrt),
5242 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5243 ffebld_nonter_hook (expr));
5244 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5245 convert (TREE_TYPE (arg3_tree),
5250 case FFEINTRIN_impFSTAT_subr:
5256 arg1_tree = convert (ffecom_f2c_integer_type_node,
5257 ffecom_expr (arg1));
5258 arg1_tree = ffecom_1 (ADDR_EXPR,
5259 build_pointer_type (TREE_TYPE (arg1_tree)),
5262 arg2_tree = convert (ffecom_f2c_ptr_to_integer_type_node,
5263 ffecom_ptr_to_expr (arg2));
5266 arg3_tree = NULL_TREE;
5268 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5270 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5271 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5272 TREE_CHAIN (arg1_tree) = arg2_tree;
5273 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5274 ffecom_gfrt_kindtype (gfrt),
5278 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5279 ffebld_nonter_hook (expr));
5280 if (arg3_tree != NULL_TREE) {
5281 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5282 convert (TREE_TYPE (arg3_tree),
5288 case FFEINTRIN_impKILL_subr:
5294 arg1_tree = convert (ffecom_f2c_integer_type_node,
5295 ffecom_expr (arg1));
5296 arg1_tree = ffecom_1 (ADDR_EXPR,
5297 build_pointer_type (TREE_TYPE (arg1_tree)),
5300 arg2_tree = convert (ffecom_f2c_integer_type_node,
5301 ffecom_expr (arg2));
5302 arg2_tree = ffecom_1 (ADDR_EXPR,
5303 build_pointer_type (TREE_TYPE (arg2_tree)),
5307 arg3_tree = NULL_TREE;
5309 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5311 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5312 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5313 TREE_CHAIN (arg1_tree) = arg2_tree;
5314 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5315 ffecom_gfrt_kindtype (gfrt),
5319 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5320 ffebld_nonter_hook (expr));
5321 if (arg3_tree != NULL_TREE) {
5322 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5323 convert (TREE_TYPE (arg3_tree),
5329 case FFEINTRIN_impCTIME_subr:
5330 case FFEINTRIN_impTTYNAM_subr:
5332 tree arg1_len = integer_zero_node;
5336 arg1_tree = ffecom_arg_ptr_to_expr (arg2, &arg1_len);
5338 arg2_tree = convert (((codegen_imp == FFEINTRIN_impCTIME_subr) ?
5339 ffecom_f2c_longint_type_node :
5340 ffecom_f2c_integer_type_node),
5341 ffecom_expr (arg1));
5342 arg2_tree = ffecom_1 (ADDR_EXPR,
5343 build_pointer_type (TREE_TYPE (arg2_tree)),
5346 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5347 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5348 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5349 TREE_CHAIN (arg1_len) = arg2_tree;
5350 TREE_CHAIN (arg1_tree) = arg1_len;
5353 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5354 ffecom_gfrt_kindtype (gfrt),
5358 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5359 ffebld_nonter_hook (expr));
5360 TREE_SIDE_EFFECTS (expr_tree) = 1;
5364 case FFEINTRIN_impIRAND:
5365 case FFEINTRIN_impRAND:
5366 /* Arg defaults to 0 (normal random case) */
5371 arg1_tree = ffecom_integer_zero_node;
5373 arg1_tree = ffecom_expr (arg1);
5374 arg1_tree = convert (ffecom_f2c_integer_type_node,
5376 arg1_tree = ffecom_1 (ADDR_EXPR,
5377 build_pointer_type (TREE_TYPE (arg1_tree)),
5379 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5381 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5382 ffecom_gfrt_kindtype (gfrt),
5384 ((codegen_imp == FFEINTRIN_impIRAND) ?
5385 ffecom_f2c_integer_type_node :
5386 ffecom_f2c_real_type_node),
5388 dest_tree, dest, dest_used,
5390 ffebld_nonter_hook (expr));
5394 case FFEINTRIN_impFTELL_subr:
5395 case FFEINTRIN_impUMASK_subr:
5400 arg1_tree = convert (ffecom_f2c_integer_type_node,
5401 ffecom_expr (arg1));
5402 arg1_tree = ffecom_1 (ADDR_EXPR,
5403 build_pointer_type (TREE_TYPE (arg1_tree)),
5407 arg2_tree = NULL_TREE;
5409 arg2_tree = ffecom_expr_w (NULL_TREE, arg2);
5411 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5412 ffecom_gfrt_kindtype (gfrt),
5415 build_tree_list (NULL_TREE, arg1_tree),
5416 NULL_TREE, NULL, NULL, NULL_TREE,
5418 ffebld_nonter_hook (expr));
5419 if (arg2_tree != NULL_TREE) {
5420 expr_tree = ffecom_modify (NULL_TREE, arg2_tree,
5421 convert (TREE_TYPE (arg2_tree),
5427 case FFEINTRIN_impCPU_TIME:
5428 case FFEINTRIN_impSECOND_subr:
5432 arg1_tree = ffecom_expr_w (NULL_TREE, arg1);
5435 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5436 ffecom_gfrt_kindtype (gfrt),
5440 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5441 ffebld_nonter_hook (expr));
5444 = ffecom_modify (NULL_TREE, arg1_tree,
5445 convert (TREE_TYPE (arg1_tree),
5450 case FFEINTRIN_impDTIME_subr:
5451 case FFEINTRIN_impETIME_subr:
5456 result_tree = ffecom_expr_w (NULL_TREE, arg2);
5458 arg1_tree = ffecom_ptr_to_expr (arg1);
5460 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5461 ffecom_gfrt_kindtype (gfrt),
5464 build_tree_list (NULL_TREE, arg1_tree),
5465 NULL_TREE, NULL, NULL, NULL_TREE,
5467 ffebld_nonter_hook (expr));
5468 expr_tree = ffecom_modify (NULL_TREE, result_tree,
5469 convert (TREE_TYPE (result_tree),
5474 /* Straightforward calls of libf2c routines: */
5475 case FFEINTRIN_impABORT:
5476 case FFEINTRIN_impACCESS:
5477 case FFEINTRIN_impBESJ0:
5478 case FFEINTRIN_impBESJ1:
5479 case FFEINTRIN_impBESJN:
5480 case FFEINTRIN_impBESY0:
5481 case FFEINTRIN_impBESY1:
5482 case FFEINTRIN_impBESYN:
5483 case FFEINTRIN_impCHDIR_func:
5484 case FFEINTRIN_impCHMOD_func:
5485 case FFEINTRIN_impDATE:
5486 case FFEINTRIN_impDATE_AND_TIME:
5487 case FFEINTRIN_impDBESJ0:
5488 case FFEINTRIN_impDBESJ1:
5489 case FFEINTRIN_impDBESJN:
5490 case FFEINTRIN_impDBESY0:
5491 case FFEINTRIN_impDBESY1:
5492 case FFEINTRIN_impDBESYN:
5493 case FFEINTRIN_impDTIME_func:
5494 case FFEINTRIN_impETIME_func:
5495 case FFEINTRIN_impFGETC_func:
5496 case FFEINTRIN_impFGET_func:
5497 case FFEINTRIN_impFNUM:
5498 case FFEINTRIN_impFPUTC_func:
5499 case FFEINTRIN_impFPUT_func:
5500 case FFEINTRIN_impFSEEK:
5501 case FFEINTRIN_impFSTAT_func:
5502 case FFEINTRIN_impFTELL_func:
5503 case FFEINTRIN_impGERROR:
5504 case FFEINTRIN_impGETARG:
5505 case FFEINTRIN_impGETCWD_func:
5506 case FFEINTRIN_impGETENV:
5507 case FFEINTRIN_impGETGID:
5508 case FFEINTRIN_impGETLOG:
5509 case FFEINTRIN_impGETPID:
5510 case FFEINTRIN_impGETUID:
5511 case FFEINTRIN_impGMTIME:
5512 case FFEINTRIN_impHOSTNM_func:
5513 case FFEINTRIN_impIDATE_unix:
5514 case FFEINTRIN_impIDATE_vxt:
5515 case FFEINTRIN_impIERRNO:
5516 case FFEINTRIN_impISATTY:
5517 case FFEINTRIN_impITIME:
5518 case FFEINTRIN_impKILL_func:
5519 case FFEINTRIN_impLINK_func:
5520 case FFEINTRIN_impLNBLNK:
5521 case FFEINTRIN_impLSTAT_func:
5522 case FFEINTRIN_impLTIME:
5523 case FFEINTRIN_impMCLOCK8:
5524 case FFEINTRIN_impMCLOCK:
5525 case FFEINTRIN_impPERROR:
5526 case FFEINTRIN_impRENAME_func:
5527 case FFEINTRIN_impSECNDS:
5528 case FFEINTRIN_impSECOND_func:
5529 case FFEINTRIN_impSLEEP:
5530 case FFEINTRIN_impSRAND:
5531 case FFEINTRIN_impSTAT_func:
5532 case FFEINTRIN_impSYMLNK_func:
5533 case FFEINTRIN_impSYSTEM_CLOCK:
5534 case FFEINTRIN_impSYSTEM_func:
5535 case FFEINTRIN_impTIME8:
5536 case FFEINTRIN_impTIME_unix:
5537 case FFEINTRIN_impTIME_vxt:
5538 case FFEINTRIN_impUMASK_func:
5539 case FFEINTRIN_impUNLINK_func:
5542 case FFEINTRIN_impCTIME_func: /* CHARACTER functions not handled here. */
5543 case FFEINTRIN_impFDATE_func: /* CHARACTER functions not handled here. */
5544 case FFEINTRIN_impTTYNAM_func: /* CHARACTER functions not handled here. */
5545 case FFEINTRIN_impNONE:
5546 case FFEINTRIN_imp: /* Hush up gcc warning. */
5547 fprintf (stderr, "No %s implementation.\n",
5548 ffeintrin_name_implementation (ffebld_symter_implementation (ffebld_left (expr))));
5549 assert ("unimplemented intrinsic" == NULL);
5550 return error_mark_node;
5553 assert (gfrt != FFECOM_gfrt); /* Must have an implementation! */
5555 expr_tree = ffecom_arglist_expr_ (ffecom_gfrt_args_ (gfrt),
5556 ffebld_right (expr));
5558 return ffecom_call_ (ffecom_gfrt_tree_ (gfrt), ffecom_gfrt_kindtype (gfrt),
5559 (ffe_is_f2c_library () && ffecom_gfrt_complex_[gfrt]),
5561 expr_tree, dest_tree, dest, dest_used,
5563 ffebld_nonter_hook (expr));
5565 /* See bottom of this file for f2c transforms used to determine
5566 many of the above implementations. The info seems to confuse
5567 Emacs's C mode indentation, which is why it's been moved to
5568 the bottom of this source file. */
5572 /* For power (exponentiation) where right-hand operand is type INTEGER,
5573 generate in-line code to do it the fast way (which, if the operand
5574 is a constant, might just mean a series of multiplies). */
5576 #if FFECOM_targetCURRENT == FFECOM_targetGCC
5578 ffecom_expr_power_integer_ (ffebld expr)
5580 tree l = ffecom_expr (ffebld_left (expr));
5581 tree r = ffecom_expr (ffebld_right (expr));
5582 tree ltype = TREE_TYPE (l);
5583 tree rtype = TREE_TYPE (r);
5584 tree result = NULL_TREE;
5586 if (l == error_mark_node
5587 || r == error_mark_node)
5588 return error_mark_node;
5590 if (TREE_CODE (r) == INTEGER_CST)
5592 int sgn = tree_int_cst_sgn (r);
5595 return convert (ltype, integer_one_node);
5597 if ((TREE_CODE (ltype) == INTEGER_TYPE)
5600 /* Reciprocal of integer is either 0, -1, or 1, so after
5601 calculating that (which we leave to the back end to do
5602 or not do optimally), don't bother with any multiplying. */
5604 result = ffecom_tree_divide_ (ltype,
5605 convert (ltype, integer_one_node),
5607 NULL_TREE, NULL, NULL, NULL_TREE);
5608 r = ffecom_1 (NEGATE_EXPR,
5611 if ((TREE_INT_CST_LOW (r) & 1) == 0)
5612 result = ffecom_1 (ABS_EXPR, rtype,
5616 /* Generate appropriate series of multiplies, preceded
5617 by divide if the exponent is negative. */
5623 l = ffecom_tree_divide_ (ltype,
5624 convert (ltype, integer_one_node),
5626 NULL_TREE, NULL, NULL,
5627 ffebld_nonter_hook (expr));
5628 r = ffecom_1 (NEGATE_EXPR, rtype, r);
5629 assert (TREE_CODE (r) == INTEGER_CST);
5631 if (tree_int_cst_sgn (r) < 0)
5632 { /* The "most negative" number. */
5633 r = ffecom_1 (NEGATE_EXPR, rtype,
5634 ffecom_2 (RSHIFT_EXPR, rtype,
5638 l = ffecom_2 (MULT_EXPR, ltype,
5646 if (TREE_INT_CST_LOW (r) & 1)
5648 if (result == NULL_TREE)
5651 result = ffecom_2 (MULT_EXPR, ltype,
5656 r = ffecom_2 (RSHIFT_EXPR, rtype,
5659 if (integer_zerop (r))
5661 assert (TREE_CODE (r) == INTEGER_CST);
5664 l = ffecom_2 (MULT_EXPR, ltype,
5671 /* Though rhs isn't a constant, in-line code cannot be expanded
5672 while transforming dummies
5673 because the back end cannot be easily convinced to generate
5674 stores (MODIFY_EXPR), handle temporaries, and so on before
5675 all the appropriate rtx's have been generated for things like
5676 dummy args referenced in rhs -- which doesn't happen until
5677 store_parm_decls() is called (expand_function_start, I believe,
5678 does the actual rtx-stuffing of PARM_DECLs).
5680 So, in this case, let the caller generate the call to the
5681 run-time-library function to evaluate the power for us. */
5683 if (ffecom_transform_only_dummies_)
5686 /* Right-hand operand not a constant, expand in-line code to figure
5687 out how to do the multiplies, &c.
5689 The returned expression is expressed this way in GNU C, where l and
5692 ({ typeof (r) rtmp = r;
5693 typeof (l) ltmp = l;
5700 if ((basetypeof (l) == basetypeof (int))
5703 result = ((typeof (l)) 1) / ltmp;
5704 if ((ltmp < 0) && (((-rtmp) & 1) == 0))
5710 if ((basetypeof (l) != basetypeof (int))
5713 ltmp = ((typeof (l)) 1) / ltmp;
5717 rtmp = -(rtmp >> 1);
5725 if ((rtmp >>= 1) == 0)
5734 Note that some of the above is compile-time collapsable, such as
5735 the first part of the if statements that checks the base type of
5736 l against int. The if statements are phrased that way to suggest
5737 an easy way to generate the if/else constructs here, knowing that
5738 the back end should (and probably does) eliminate the resulting
5739 dead code (either the int case or the non-int case), something
5740 it couldn't do without the redundant phrasing, requiring explicit
5741 dead-code elimination here, which would be kind of difficult to
5748 tree basetypeof_l_is_int;
5753 = build_int_2 ((TREE_CODE (ltype) == INTEGER_TYPE), 0);
5755 se = expand_start_stmt_expr ();
5757 ffecom_start_compstmt ();
5760 rtmp = ffecom_make_tempvar ("power_r", rtype,
5761 FFETARGET_charactersizeNONE, -1);
5762 ltmp = ffecom_make_tempvar ("power_l", ltype,
5763 FFETARGET_charactersizeNONE, -1);
5764 result = ffecom_make_tempvar ("power_res", ltype,
5765 FFETARGET_charactersizeNONE, -1);
5766 if (TREE_CODE (ltype) == COMPLEX_TYPE
5767 || TREE_CODE (ltype) == RECORD_TYPE)
5768 divide = ffecom_make_tempvar ("power_div", ltype,
5769 FFETARGET_charactersizeNONE, -1);
5776 hook = ffebld_nonter_hook (expr);
5778 assert (TREE_CODE (hook) == TREE_VEC);
5779 assert (TREE_VEC_LENGTH (hook) == 4);
5780 rtmp = TREE_VEC_ELT (hook, 0);
5781 ltmp = TREE_VEC_ELT (hook, 1);
5782 result = TREE_VEC_ELT (hook, 2);
5783 divide = TREE_VEC_ELT (hook, 3);
5784 if (TREE_CODE (ltype) == COMPLEX_TYPE
5785 || TREE_CODE (ltype) == RECORD_TYPE)
5792 expand_expr_stmt (ffecom_modify (void_type_node,
5795 expand_expr_stmt (ffecom_modify (void_type_node,
5798 expand_start_cond (ffecom_truth_value
5799 (ffecom_2 (EQ_EXPR, integer_type_node,
5801 convert (rtype, integer_zero_node))),
5803 expand_expr_stmt (ffecom_modify (void_type_node,
5805 convert (ltype, integer_one_node)));
5806 expand_start_else ();
5807 if (! integer_zerop (basetypeof_l_is_int))
5809 expand_start_cond (ffecom_2 (LT_EXPR, integer_type_node,
5812 integer_zero_node)),
5814 expand_expr_stmt (ffecom_modify (void_type_node,
5818 convert (ltype, integer_one_node),
5820 NULL_TREE, NULL, NULL,
5822 expand_start_cond (ffecom_truth_value
5823 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
5824 ffecom_2 (LT_EXPR, integer_type_node,
5827 integer_zero_node)),
5828 ffecom_2 (EQ_EXPR, integer_type_node,
5829 ffecom_2 (BIT_AND_EXPR,
5831 ffecom_1 (NEGATE_EXPR,
5837 integer_zero_node)))),
5839 expand_expr_stmt (ffecom_modify (void_type_node,
5841 ffecom_1 (NEGATE_EXPR,
5845 expand_start_else ();
5847 expand_expr_stmt (ffecom_modify (void_type_node,
5849 convert (ltype, integer_one_node)));
5850 expand_start_cond (ffecom_truth_value
5851 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
5852 ffecom_truth_value_invert
5853 (basetypeof_l_is_int),
5854 ffecom_2 (LT_EXPR, integer_type_node,
5857 integer_zero_node)))),
5859 expand_expr_stmt (ffecom_modify (void_type_node,
5863 convert (ltype, integer_one_node),
5865 NULL_TREE, NULL, NULL,
5867 expand_expr_stmt (ffecom_modify (void_type_node,
5869 ffecom_1 (NEGATE_EXPR, rtype,
5871 expand_start_cond (ffecom_truth_value
5872 (ffecom_2 (LT_EXPR, integer_type_node,
5874 convert (rtype, integer_zero_node))),
5876 expand_expr_stmt (ffecom_modify (void_type_node,
5878 ffecom_1 (NEGATE_EXPR, rtype,
5879 ffecom_2 (RSHIFT_EXPR,
5882 integer_one_node))));
5883 expand_expr_stmt (ffecom_modify (void_type_node,
5885 ffecom_2 (MULT_EXPR, ltype,
5890 expand_start_loop (1);
5891 expand_start_cond (ffecom_truth_value
5892 (ffecom_2 (BIT_AND_EXPR, rtype,
5894 convert (rtype, integer_one_node))),
5896 expand_expr_stmt (ffecom_modify (void_type_node,
5898 ffecom_2 (MULT_EXPR, ltype,
5902 expand_exit_loop_if_false (NULL,
5904 (ffecom_modify (rtype,
5906 ffecom_2 (RSHIFT_EXPR,
5909 integer_one_node))));
5910 expand_expr_stmt (ffecom_modify (void_type_node,
5912 ffecom_2 (MULT_EXPR, ltype,
5917 if (!integer_zerop (basetypeof_l_is_int))
5919 expand_expr_stmt (result);
5921 t = ffecom_end_compstmt ();
5923 result = expand_end_stmt_expr (se);
5925 /* This code comes from c-parse.in, after its expand_end_stmt_expr. */
5927 if (TREE_CODE (t) == BLOCK)
5929 /* Make a BIND_EXPR for the BLOCK already made. */
5930 result = build (BIND_EXPR, TREE_TYPE (result),
5931 NULL_TREE, result, t);
5932 /* Remove the block from the tree at this point.
5933 It gets put back at the proper place
5934 when the BIND_EXPR is expanded. */
5945 /* ffecom_expr_transform_ -- Transform symbols in expr
5947 ffebld expr; // FFE expression.
5948 ffecom_expr_transform_ (expr);
5950 Recursive descent on expr while transforming any untransformed SYMTERs. */
5952 #if FFECOM_targetCURRENT == FFECOM_targetGCC
5954 ffecom_expr_transform_ (ffebld expr)
5959 tail_recurse: /* :::::::::::::::::::: */
5964 switch (ffebld_op (expr))
5966 case FFEBLD_opSYMTER:
5967 s = ffebld_symter (expr);
5968 t = ffesymbol_hook (s).decl_tree;
5969 if ((t == NULL_TREE)
5970 && ((ffesymbol_kind (s) != FFEINFO_kindNONE)
5971 || ((ffesymbol_where (s) != FFEINFO_whereNONE)
5972 && (ffesymbol_where (s) != FFEINFO_whereINTRINSIC))))
5974 s = ffecom_sym_transform_ (s);
5975 t = ffesymbol_hook (s).decl_tree; /* Sfunc expr non-dummy,
5978 break; /* Ok if (t == NULL) here. */
5981 ffecom_expr_transform_ (ffebld_head (expr));
5982 expr = ffebld_trail (expr);
5983 goto tail_recurse; /* :::::::::::::::::::: */
5989 switch (ffebld_arity (expr))
5992 ffecom_expr_transform_ (ffebld_left (expr));
5993 expr = ffebld_right (expr);
5994 goto tail_recurse; /* :::::::::::::::::::: */
5997 expr = ffebld_left (expr);
5998 goto tail_recurse; /* :::::::::::::::::::: */
6008 /* Make a type based on info in live f2c.h file. */
6010 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6012 ffecom_f2c_make_type_ (tree *type, int tcode, const char *name)
6016 case FFECOM_f2ccodeCHAR:
6017 *type = make_signed_type (CHAR_TYPE_SIZE);
6020 case FFECOM_f2ccodeSHORT:
6021 *type = make_signed_type (SHORT_TYPE_SIZE);
6024 case FFECOM_f2ccodeINT:
6025 *type = make_signed_type (INT_TYPE_SIZE);
6028 case FFECOM_f2ccodeLONG:
6029 *type = make_signed_type (LONG_TYPE_SIZE);
6032 case FFECOM_f2ccodeLONGLONG:
6033 *type = make_signed_type (LONG_LONG_TYPE_SIZE);
6036 case FFECOM_f2ccodeCHARPTR:
6037 *type = build_pointer_type (DEFAULT_SIGNED_CHAR
6038 ? signed_char_type_node
6039 : unsigned_char_type_node);
6042 case FFECOM_f2ccodeFLOAT:
6043 *type = make_node (REAL_TYPE);
6044 TYPE_PRECISION (*type) = FLOAT_TYPE_SIZE;
6045 layout_type (*type);
6048 case FFECOM_f2ccodeDOUBLE:
6049 *type = make_node (REAL_TYPE);
6050 TYPE_PRECISION (*type) = DOUBLE_TYPE_SIZE;
6051 layout_type (*type);
6054 case FFECOM_f2ccodeLONGDOUBLE:
6055 *type = make_node (REAL_TYPE);
6056 TYPE_PRECISION (*type) = LONG_DOUBLE_TYPE_SIZE;
6057 layout_type (*type);
6060 case FFECOM_f2ccodeTWOREALS:
6061 *type = ffecom_make_complex_type_ (ffecom_f2c_real_type_node);
6064 case FFECOM_f2ccodeTWODOUBLEREALS:
6065 *type = ffecom_make_complex_type_ (ffecom_f2c_doublereal_type_node);
6069 assert ("unexpected FFECOM_f2ccodeXYZZY!" == NULL);
6070 *type = error_mark_node;
6074 pushdecl (build_decl (TYPE_DECL,
6075 ffecom_get_invented_identifier ("__g77_f2c_%s",
6081 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6082 /* Set the f2c list-directed-I/O code for whatever (integral) type has the
6086 ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size,
6092 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
6093 if (((t = ffecom_tree_type[bt][j]) != NULL_TREE)
6094 && (TREE_INT_CST_LOW (TYPE_SIZE (t)) == size))
6096 assert (code != -1);
6097 ffecom_f2c_typecode_[bt][j] = code;
6103 /* Finish up globals after doing all program units in file
6105 Need to handle only uninitialized COMMON areas. */
6107 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6109 ffecom_finish_global_ (ffeglobal global)
6115 if (ffeglobal_type (global) != FFEGLOBAL_typeCOMMON)
6118 if (ffeglobal_common_init (global))
6121 cbt = ffeglobal_hook (global);
6122 if ((cbt == NULL_TREE)
6123 || !ffeglobal_common_have_size (global))
6124 return global; /* No need to make common, never ref'd. */
6126 suspend_momentary ();
6128 DECL_EXTERNAL (cbt) = 0;
6130 /* Give the array a size now. */
6132 size = build_int_2 ((ffeglobal_common_size (global)
6133 + ffeglobal_common_pad (global)) - 1,
6136 cbtype = TREE_TYPE (cbt);
6137 TYPE_DOMAIN (cbtype) = build_range_type (integer_type_node,
6140 if (!TREE_TYPE (size))
6141 TREE_TYPE (size) = TYPE_DOMAIN (cbtype);
6142 layout_type (cbtype);
6144 cbt = start_decl (cbt, FALSE);
6145 assert (cbt == ffeglobal_hook (global));
6147 finish_decl (cbt, NULL_TREE, FALSE);
6153 /* Finish up any untransformed symbols. */
6155 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6157 ffecom_finish_symbol_transform_ (ffesymbol s)
6159 if ((s == NULL) || (TREE_CODE (current_function_decl) == ERROR_MARK))
6162 /* It's easy to know to transform an untransformed symbol, to make sure
6163 we put out debugging info for it. But COMMON variables, unlike
6164 EQUIVALENCE ones, aren't given declarations in addition to the
6165 tree expressions that specify offsets, because COMMON variables
6166 can be referenced in the outer scope where only dummy arguments
6167 (PARM_DECLs) should really be seen. To be safe, just don't do any
6168 VAR_DECLs for COMMON variables when we transform them for real
6169 use, and therefore we do all the VAR_DECL creating here. */
6171 if (ffesymbol_hook (s).decl_tree == NULL_TREE)
6173 if (ffesymbol_kind (s) != FFEINFO_kindNONE
6174 || (ffesymbol_where (s) != FFEINFO_whereNONE
6175 && ffesymbol_where (s) != FFEINFO_whereINTRINSIC
6176 && ffesymbol_where (s) != FFEINFO_whereDUMMY))
6177 /* Not transformed, and not CHARACTER*(*), and not a dummy
6178 argument, which can happen only if the entry point names
6179 it "rides in on" are all invalidated for other reasons. */
6180 s = ffecom_sym_transform_ (s);
6183 if ((ffesymbol_where (s) == FFEINFO_whereCOMMON)
6184 && (ffesymbol_hook (s).decl_tree != error_mark_node))
6186 #ifdef SOMEONE_GETS_DEBUG_SUPPORT_WORKING
6187 int yes = suspend_momentary ();
6189 /* This isn't working, at least for dbxout. The .s file looks
6190 okay to me (burley), but in gdb 4.9 at least, the variables
6191 appear to reside somewhere outside of the common area, so
6192 it doesn't make sense to mislead anyone by generating the info
6193 on those variables until this is fixed. NOTE: Same problem
6194 with EQUIVALENCE, sadly...see similar #if later. */
6195 ffecom_member_phase2_ (ffesymbol_storage (ffesymbol_common (s)),
6196 ffesymbol_storage (s));
6198 resume_momentary (yes);
6206 /* Append underscore(s) to name before calling get_identifier. "us"
6207 is nonzero if the name already contains an underscore and thus
6208 needs two underscores appended. */
6210 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6212 ffecom_get_appended_identifier_ (char us, const char *name)
6218 newname = xmalloc ((i = strlen (name)) + 1
6219 + ffe_is_underscoring ()
6221 memcpy (newname, name, i);
6223 newname[i + us] = '_';
6224 newname[i + 1 + us] = '\0';
6225 id = get_identifier (newname);
6233 /* Decide whether to append underscore to name before calling
6236 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6238 ffecom_get_external_identifier_ (ffesymbol s)
6241 const char *name = ffesymbol_text (s);
6243 /* If name is a built-in name, just return it as is. */
6245 if (!ffe_is_underscoring ()
6246 || (strcmp (name, FFETARGET_nameBLANK_COMMON) == 0)
6247 #if FFETARGET_isENFORCED_MAIN_NAME
6248 || (strcmp (name, FFETARGET_nameENFORCED_NAME) == 0)
6250 || (strcmp (name, FFETARGET_nameUNNAMED_MAIN) == 0)
6252 || (strcmp (name, FFETARGET_nameUNNAMED_BLOCK_DATA) == 0))
6253 return get_identifier (name);
6255 us = ffe_is_second_underscore ()
6256 ? (strchr (name, '_') != NULL)
6259 return ffecom_get_appended_identifier_ (us, name);
6263 /* Decide whether to append underscore to internal name before calling
6266 This is for non-external, top-function-context names only. Transform
6267 identifier so it doesn't conflict with the transformed result
6268 of using a _different_ external name. E.g. if "CALL FOO" is
6269 transformed into "FOO_();", then the variable in "FOO_ = 3"
6270 must be transformed into something that does not conflict, since
6271 these two things should be independent.
6273 The transformation is as follows. If the name does not contain
6274 an underscore, there is no possible conflict, so just return.
6275 If the name does contain an underscore, then transform it just
6276 like we transform an external identifier. */
6278 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6280 ffecom_get_identifier_ (const char *name)
6282 /* If name does not contain an underscore, just return it as is. */
6284 if (!ffe_is_underscoring ()
6285 || (strchr (name, '_') == NULL))
6286 return get_identifier (name);
6288 return ffecom_get_appended_identifier_ (ffe_is_second_underscore (),
6293 /* ffecom_gen_sfuncdef_ -- Generate definition of statement function
6296 ffesymbol s; // kindFUNCTION, whereIMMEDIATE.
6297 t = ffecom_gen_sfuncdef_(s,ffesymbol_basictype(s),
6298 ffesymbol_kindtype(s));
6300 Call after setting up containing function and getting trees for all
6303 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6305 ffecom_gen_sfuncdef_ (ffesymbol s, ffeinfoBasictype bt, ffeinfoKindtype kt)
6307 ffebld expr = ffesymbol_sfexpr (s);
6311 bool charfunc = (bt == FFEINFO_basictypeCHARACTER);
6312 static bool recurse = FALSE;
6314 int old_lineno = lineno;
6315 char *old_input_filename = input_filename;
6317 ffecom_nested_entry_ = s;
6319 /* For now, we don't have a handy pointer to where the sfunc is actually
6320 defined, though that should be easy to add to an ffesymbol. (The
6321 token/where info available might well point to the place where the type
6322 of the sfunc is declared, especially if that precedes the place where
6323 the sfunc itself is defined, which is typically the case.) We should
6324 put out a null pointer rather than point somewhere wrong, but I want to
6325 see how it works at this point. */
6327 input_filename = ffesymbol_where_filename (s);
6328 lineno = ffesymbol_where_filelinenum (s);
6330 /* Pretransform the expression so any newly discovered things belong to the
6331 outer program unit, not to the statement function. */
6333 ffecom_expr_transform_ (expr);
6335 /* Make sure no recursive invocation of this fn (a specific case of failing
6336 to pretransform an sfunc's expression, i.e. where its expression
6337 references another untransformed sfunc) happens. */
6342 yes = suspend_momentary ();
6344 push_f_function_context ();
6347 type = void_type_node;
6350 type = ffecom_tree_type[bt][kt];
6351 if (type == NULL_TREE)
6352 type = integer_type_node; /* _sym_exec_transition reports
6356 start_function (ffecom_get_identifier_ (ffesymbol_text (s)),
6357 build_function_type (type, NULL_TREE),
6358 1, /* nested/inline */
6359 0); /* TREE_PUBLIC */
6361 /* We don't worry about COMPLEX return values here, because this is
6362 entirely internal to our code, and gcc has the ability to return COMPLEX
6363 directly as a value. */
6365 yes = suspend_momentary ();
6368 { /* Prepend arg for where result goes. */
6371 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
6373 result = ffecom_get_invented_identifier ("__g77_%s",
6376 ffecom_char_enhance_arg_ (&type, s); /* Ignore returned length. */
6378 type = build_pointer_type (type);
6379 result = build_decl (PARM_DECL, result, type);
6381 push_parm_decl (result);
6384 result = NULL_TREE; /* Not ref'd if !charfunc. */
6386 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (s), TRUE);
6388 resume_momentary (yes);
6390 store_parm_decls (0);
6392 ffecom_start_compstmt ();
6398 ffetargetCharacterSize sz = ffesymbol_size (s);
6401 result_length = build_int_2 (sz, 0);
6402 TREE_TYPE (result_length) = ffecom_f2c_ftnlen_type_node;
6404 ffecom_prepare_let_char_ (sz, expr);
6406 ffecom_prepare_end ();
6408 ffecom_let_char_ (result, result_length, sz, expr);
6409 expand_null_return ();
6413 ffecom_prepare_expr (expr);
6415 ffecom_prepare_end ();
6417 expand_return (ffecom_modify (NULL_TREE,
6418 DECL_RESULT (current_function_decl),
6419 ffecom_expr (expr)));
6425 ffecom_end_compstmt ();
6427 func = current_function_decl;
6428 finish_function (1);
6430 pop_f_function_context ();
6432 resume_momentary (yes);
6436 lineno = old_lineno;
6437 input_filename = old_input_filename;
6439 ffecom_nested_entry_ = NULL;
6446 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6448 ffecom_gfrt_args_ (ffecomGfrt ix)
6450 return ffecom_gfrt_argstring_[ix];
6454 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6456 ffecom_gfrt_tree_ (ffecomGfrt ix)
6458 if (ffecom_gfrt_[ix] == NULL_TREE)
6459 ffecom_make_gfrt_ (ix);
6461 return ffecom_1 (ADDR_EXPR,
6462 build_pointer_type (TREE_TYPE (ffecom_gfrt_[ix])),
6467 /* Return initialize-to-zero expression for this VAR_DECL. */
6469 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6471 ffecom_init_zero_ (tree decl)
6474 int incremental = TREE_STATIC (decl);
6475 tree type = TREE_TYPE (decl);
6479 int momentary = suspend_momentary ();
6480 push_obstacks_nochange ();
6481 if (TREE_PERMANENT (decl))
6482 end_temporary_allocation ();
6483 make_decl_rtl (decl, NULL, TREE_PUBLIC (decl) ? 1 : 0);
6484 assemble_variable (decl, TREE_PUBLIC (decl) ? 1 : 0, 0, 1);
6486 resume_momentary (momentary);
6491 if ((TREE_CODE (type) != ARRAY_TYPE)
6492 && (TREE_CODE (type) != RECORD_TYPE)
6493 && (TREE_CODE (type) != UNION_TYPE)
6495 init = convert (type, integer_zero_node);
6496 else if (!incremental)
6498 int momentary = suspend_momentary ();
6500 init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
6501 TREE_CONSTANT (init) = 1;
6502 TREE_STATIC (init) = 1;
6504 resume_momentary (momentary);
6508 int momentary = suspend_momentary ();
6510 assemble_zeros (int_size_in_bytes (type));
6511 init = error_mark_node;
6513 resume_momentary (momentary);
6516 pop_momentary_nofree ();
6522 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6524 ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg,
6530 switch (ffebld_op (arg))
6532 case FFEBLD_opCONTER: /* For F90, check 0-length. */
6533 if (ffetarget_length_character1
6534 (ffebld_constant_character1
6535 (ffebld_conter (arg))) == 0)
6537 *maybe_tree = integer_zero_node;
6538 return convert (tree_type, integer_zero_node);
6541 *maybe_tree = integer_one_node;
6542 expr_tree = build_int_2 (*ffetarget_text_character1
6543 (ffebld_constant_character1
6544 (ffebld_conter (arg))),
6546 TREE_TYPE (expr_tree) = tree_type;
6549 case FFEBLD_opSYMTER:
6550 case FFEBLD_opARRAYREF:
6551 case FFEBLD_opFUNCREF:
6552 case FFEBLD_opSUBSTR:
6553 ffecom_char_args_ (&expr_tree, &length_tree, arg);
6555 if ((expr_tree == error_mark_node)
6556 || (length_tree == error_mark_node))
6558 *maybe_tree = error_mark_node;
6559 return error_mark_node;
6562 if (integer_zerop (length_tree))
6564 *maybe_tree = integer_zero_node;
6565 return convert (tree_type, integer_zero_node);
6569 = ffecom_1 (INDIRECT_REF,
6570 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
6573 = ffecom_2 (ARRAY_REF,
6574 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
6577 expr_tree = convert (tree_type, expr_tree);
6579 if (TREE_CODE (length_tree) == INTEGER_CST)
6580 *maybe_tree = integer_one_node;
6581 else /* Must check length at run time. */
6583 = ffecom_truth_value
6584 (ffecom_2 (GT_EXPR, integer_type_node,
6586 ffecom_f2c_ftnlen_zero_node));
6589 case FFEBLD_opPAREN:
6590 case FFEBLD_opCONVERT:
6591 if (ffeinfo_size (ffebld_info (arg)) == 0)
6593 *maybe_tree = integer_zero_node;
6594 return convert (tree_type, integer_zero_node);
6596 return ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
6599 case FFEBLD_opCONCATENATE:
6606 expr_left = ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
6608 expr_right = ffecom_intrinsic_ichar_ (tree_type, ffebld_right (arg),
6610 *maybe_tree = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
6613 expr_tree = ffecom_3 (COND_EXPR, tree_type,
6621 assert ("bad op in ICHAR" == NULL);
6622 return error_mark_node;
6627 /* ffecom_intrinsic_len_ -- Return length info for char arg (LEN())
6631 length_arg = ffecom_intrinsic_len_ (expr);
6633 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
6634 subexpressions by constructing the appropriate tree for the
6635 length-of-character-text argument in a calling sequence. */
6637 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6639 ffecom_intrinsic_len_ (ffebld expr)
6641 ffetargetCharacter1 val;
6644 switch (ffebld_op (expr))
6646 case FFEBLD_opCONTER:
6647 val = ffebld_constant_character1 (ffebld_conter (expr));
6648 length = build_int_2 (ffetarget_length_character1 (val), 0);
6649 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6652 case FFEBLD_opSYMTER:
6654 ffesymbol s = ffebld_symter (expr);
6657 item = ffesymbol_hook (s).decl_tree;
6658 if (item == NULL_TREE)
6660 s = ffecom_sym_transform_ (s);
6661 item = ffesymbol_hook (s).decl_tree;
6663 if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
6665 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
6666 length = ffesymbol_hook (s).length_tree;
6669 length = build_int_2 (ffesymbol_size (s), 0);
6670 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6673 else if (item == error_mark_node)
6674 length = error_mark_node;
6675 else /* FFEINFO_kindFUNCTION: */
6680 case FFEBLD_opARRAYREF:
6681 length = ffecom_intrinsic_len_ (ffebld_left (expr));
6684 case FFEBLD_opSUBSTR:
6688 ffebld thing = ffebld_right (expr);
6692 assert (ffebld_op (thing) == FFEBLD_opITEM);
6693 start = ffebld_head (thing);
6694 thing = ffebld_trail (thing);
6695 assert (ffebld_trail (thing) == NULL);
6696 end = ffebld_head (thing);
6698 length = ffecom_intrinsic_len_ (ffebld_left (expr));
6700 if (length == error_mark_node)
6709 length = convert (ffecom_f2c_ftnlen_type_node,
6715 start_tree = convert (ffecom_f2c_ftnlen_type_node,
6716 ffecom_expr (start));
6718 if (start_tree == error_mark_node)
6720 length = error_mark_node;
6726 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6727 ffecom_f2c_ftnlen_one_node,
6728 ffecom_2 (MINUS_EXPR,
6729 ffecom_f2c_ftnlen_type_node,
6735 end_tree = convert (ffecom_f2c_ftnlen_type_node,
6738 if (end_tree == error_mark_node)
6740 length = error_mark_node;
6744 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6745 ffecom_f2c_ftnlen_one_node,
6746 ffecom_2 (MINUS_EXPR,
6747 ffecom_f2c_ftnlen_type_node,
6748 end_tree, start_tree));
6754 case FFEBLD_opCONCATENATE:
6756 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6757 ffecom_intrinsic_len_ (ffebld_left (expr)),
6758 ffecom_intrinsic_len_ (ffebld_right (expr)));
6761 case FFEBLD_opFUNCREF:
6762 case FFEBLD_opCONVERT:
6763 length = build_int_2 (ffebld_size (expr), 0);
6764 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6768 assert ("bad op for single char arg expr" == NULL);
6769 length = ffecom_f2c_ftnlen_zero_node;
6773 assert (length != NULL_TREE);
6779 /* Handle CHARACTER assignments.
6781 Generates code to do the assignment. Used by ordinary assignment
6782 statement handler ffecom_let_stmt and by statement-function
6783 handler to generate code for a statement function. */
6785 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6787 ffecom_let_char_ (tree dest_tree, tree dest_length,
6788 ffetargetCharacterSize dest_size, ffebld source)
6790 ffecomConcatList_ catlist;
6795 if ((dest_tree == error_mark_node)
6796 || (dest_length == error_mark_node))
6799 assert (dest_tree != NULL_TREE);
6800 assert (dest_length != NULL_TREE);
6802 /* Source might be an opCONVERT, which just means it is a different size
6803 than the destination. Since the underlying implementation here handles
6804 that (directly or via the s_copy or s_cat run-time-library functions),
6805 we don't need the "convenience" of an opCONVERT that tells us to
6806 truncate or blank-pad, particularly since the resulting implementation
6807 would probably be slower than otherwise. */
6809 while (ffebld_op (source) == FFEBLD_opCONVERT)
6810 source = ffebld_left (source);
6812 catlist = ffecom_concat_list_new_ (source, dest_size);
6813 switch (ffecom_concat_list_count_ (catlist))
6815 case 0: /* Shouldn't happen, but in case it does... */
6816 ffecom_concat_list_kill_ (catlist);
6817 source_tree = null_pointer_node;
6818 source_length = ffecom_f2c_ftnlen_zero_node;
6819 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6820 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
6821 TREE_CHAIN (TREE_CHAIN (expr_tree))
6822 = build_tree_list (NULL_TREE, dest_length);
6823 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6824 = build_tree_list (NULL_TREE, source_length);
6826 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree, NULL_TREE);
6827 TREE_SIDE_EFFECTS (expr_tree) = 1;
6829 expand_expr_stmt (expr_tree);
6833 case 1: /* The (fairly) easy case. */
6834 ffecom_char_args_ (&source_tree, &source_length,
6835 ffecom_concat_list_expr_ (catlist, 0));
6836 ffecom_concat_list_kill_ (catlist);
6837 assert (source_tree != NULL_TREE);
6838 assert (source_length != NULL_TREE);
6840 if ((source_tree == error_mark_node)
6841 || (source_length == error_mark_node))
6847 = ffecom_1 (INDIRECT_REF,
6848 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6852 = ffecom_2 (ARRAY_REF,
6853 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6858 = ffecom_1 (INDIRECT_REF,
6859 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6863 = ffecom_2 (ARRAY_REF,
6864 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6869 expr_tree = ffecom_modify (void_type_node, dest_tree, source_tree);
6871 expand_expr_stmt (expr_tree);
6876 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6877 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
6878 TREE_CHAIN (TREE_CHAIN (expr_tree))
6879 = build_tree_list (NULL_TREE, dest_length);
6880 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6881 = build_tree_list (NULL_TREE, source_length);
6883 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree, NULL_TREE);
6884 TREE_SIDE_EFFECTS (expr_tree) = 1;
6886 expand_expr_stmt (expr_tree);
6890 default: /* Must actually concatenate things. */
6894 /* Heavy-duty concatenation. */
6897 int count = ffecom_concat_list_count_ (catlist);
6909 = ffecom_push_tempvar (ffecom_f2c_ftnlen_type_node,
6910 FFETARGET_charactersizeNONE, count, TRUE);
6911 item_array = items = ffecom_push_tempvar (ffecom_f2c_address_type_node,
6912 FFETARGET_charactersizeNONE,
6918 hook = ffebld_nonter_hook (source);
6920 assert (TREE_CODE (hook) == TREE_VEC);
6921 assert (TREE_VEC_LENGTH (hook) == 2);
6922 length_array = lengths = TREE_VEC_ELT (hook, 0);
6923 item_array = items = TREE_VEC_ELT (hook, 1);
6927 for (i = 0; i < count; ++i)
6929 ffecom_char_args_ (&citem, &clength,
6930 ffecom_concat_list_expr_ (catlist, i));
6931 if ((citem == error_mark_node)
6932 || (clength == error_mark_node))
6934 ffecom_concat_list_kill_ (catlist);
6939 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
6940 ffecom_modify (void_type_node,
6941 ffecom_2 (ARRAY_REF,
6942 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
6944 build_int_2 (i, 0)),
6948 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
6949 ffecom_modify (void_type_node,
6950 ffecom_2 (ARRAY_REF,
6951 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
6953 build_int_2 (i, 0)),
6958 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6959 TREE_CHAIN (expr_tree)
6960 = build_tree_list (NULL_TREE,
6961 ffecom_1 (ADDR_EXPR,
6962 build_pointer_type (TREE_TYPE (items)),
6964 TREE_CHAIN (TREE_CHAIN (expr_tree))
6965 = build_tree_list (NULL_TREE,
6966 ffecom_1 (ADDR_EXPR,
6967 build_pointer_type (TREE_TYPE (lengths)),
6969 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6972 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
6973 convert (ffecom_f2c_ftnlen_type_node,
6974 build_int_2 (count, 0))));
6975 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree))))
6976 = build_tree_list (NULL_TREE, dest_length);
6978 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCAT, expr_tree, NULL_TREE);
6979 TREE_SIDE_EFFECTS (expr_tree) = 1;
6981 expand_expr_stmt (expr_tree);
6984 ffecom_concat_list_kill_ (catlist);
6988 /* ffecom_make_gfrt_ -- Make initial info for run-time routine
6991 ffecom_make_gfrt_(ix);
6993 Assumes gfrt_[ix] is NULL_TREE, and replaces it with the FUNCTION_DECL
6994 for the indicated run-time routine (ix). */
6996 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6998 ffecom_make_gfrt_ (ffecomGfrt ix)
7003 push_obstacks_nochange ();
7004 end_temporary_allocation ();
7006 switch (ffecom_gfrt_type_[ix])
7008 case FFECOM_rttypeVOID_:
7009 ttype = void_type_node;
7012 case FFECOM_rttypeVOIDSTAR_:
7013 ttype = TREE_TYPE (null_pointer_node); /* `void *'. */
7016 case FFECOM_rttypeFTNINT_:
7017 ttype = ffecom_f2c_ftnint_type_node;
7020 case FFECOM_rttypeINTEGER_:
7021 ttype = ffecom_f2c_integer_type_node;
7024 case FFECOM_rttypeLONGINT_:
7025 ttype = ffecom_f2c_longint_type_node;
7028 case FFECOM_rttypeLOGICAL_:
7029 ttype = ffecom_f2c_logical_type_node;
7032 case FFECOM_rttypeREAL_F2C_:
7033 ttype = double_type_node;
7036 case FFECOM_rttypeREAL_GNU_:
7037 ttype = float_type_node;
7040 case FFECOM_rttypeCOMPLEX_F2C_:
7041 ttype = void_type_node;
7044 case FFECOM_rttypeCOMPLEX_GNU_:
7045 ttype = ffecom_f2c_complex_type_node;
7048 case FFECOM_rttypeDOUBLE_:
7049 ttype = double_type_node;
7052 case FFECOM_rttypeDOUBLEREAL_:
7053 ttype = ffecom_f2c_doublereal_type_node;
7056 case FFECOM_rttypeDBLCMPLX_F2C_:
7057 ttype = void_type_node;
7060 case FFECOM_rttypeDBLCMPLX_GNU_:
7061 ttype = ffecom_f2c_doublecomplex_type_node;
7064 case FFECOM_rttypeCHARACTER_:
7065 ttype = void_type_node;
7070 assert ("bad rttype" == NULL);
7074 ttype = build_function_type (ttype, NULL_TREE);
7075 t = build_decl (FUNCTION_DECL,
7076 get_identifier (ffecom_gfrt_name_[ix]),
7078 DECL_EXTERNAL (t) = 1;
7079 TREE_PUBLIC (t) = 1;
7080 TREE_THIS_VOLATILE (t) = ffecom_gfrt_volatile_[ix] ? 1 : 0;
7082 t = start_decl (t, TRUE);
7084 finish_decl (t, NULL_TREE, TRUE);
7086 resume_temporary_allocation ();
7089 ffecom_gfrt_[ix] = t;
7093 /* Phase 1 pass over each member of a COMMON/EQUIVALENCE group. */
7095 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7097 ffecom_member_phase1_ (ffestorag mst UNUSED, ffestorag st)
7099 ffesymbol s = ffestorag_symbol (st);
7101 if (ffesymbol_namelisted (s))
7102 ffecom_member_namelisted_ = TRUE;
7106 /* Phase 2 pass over each member of a COMMON/EQUIVALENCE group. Declare
7107 the member so debugger will see it. Otherwise nobody should be
7108 referencing the member. */
7110 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7111 #ifdef SOMEONE_GETS_DEBUG_SUPPORT_WORKING
7113 ffecom_member_phase2_ (ffestorag mst, ffestorag st)
7121 || ((mt = ffestorag_hook (mst)) == NULL)
7122 || (mt == error_mark_node))
7126 || ((s = ffestorag_symbol (st)) == NULL))
7129 type = ffecom_type_localvar_ (s,
7130 ffesymbol_basictype (s),
7131 ffesymbol_kindtype (s));
7132 if (type == error_mark_node)
7135 t = build_decl (VAR_DECL,
7136 ffecom_get_identifier_ (ffesymbol_text (s)),
7139 TREE_STATIC (t) = TREE_STATIC (mt);
7140 DECL_INITIAL (t) = NULL_TREE;
7141 TREE_ASM_WRITTEN (t) = 1;
7144 = gen_rtx (MEM, TYPE_MODE (type),
7145 plus_constant (XEXP (DECL_RTL (mt), 0),
7146 ffestorag_modulo (mst)
7147 + ffestorag_offset (st)
7148 - ffestorag_offset (mst)));
7150 t = start_decl (t, FALSE);
7152 finish_decl (t, NULL_TREE, FALSE);
7157 /* Prepare source expression for assignment into a destination perhaps known
7158 to be of a specific size. */
7161 ffecom_prepare_let_char_ (ffetargetCharacterSize dest_size, ffebld source)
7163 ffecomConcatList_ catlist;
7168 tree tempvar = NULL_TREE;
7170 while (ffebld_op (source) == FFEBLD_opCONVERT)
7171 source = ffebld_left (source);
7173 catlist = ffecom_concat_list_new_ (source, dest_size);
7174 count = ffecom_concat_list_count_ (catlist);
7179 = ffecom_make_tempvar ("let_char_len", ffecom_f2c_ftnlen_type_node,
7180 FFETARGET_charactersizeNONE, count);
7182 = ffecom_make_tempvar ("let_char_item", ffecom_f2c_address_type_node,
7183 FFETARGET_charactersizeNONE, count);
7185 tempvar = make_tree_vec (2);
7186 TREE_VEC_ELT (tempvar, 0) = ltmp;
7187 TREE_VEC_ELT (tempvar, 1) = itmp;
7190 for (i = 0; i < count; ++i)
7191 ffecom_prepare_arg_ptr_to_expr (ffecom_concat_list_expr_ (catlist, i));
7193 ffecom_concat_list_kill_ (catlist);
7197 ffebld_nonter_set_hook (source, tempvar);
7198 current_binding_level->prep_state = 1;
7202 /* ffecom_push_dummy_decls_ -- Transform dummy args, push parm decls in order
7204 Ignores STAR (alternate-return) dummies. All other get exec-transitioned
7205 (which generates their trees) and then their trees get push_parm_decl'd.
7207 The second arg is TRUE if the dummies are for a statement function, in
7208 which case lengths are not pushed for character arguments (since they are
7209 always known by both the caller and the callee, though the code allows
7210 for someday permitting CHAR*(*) stmtfunc dummies). */
7212 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7214 ffecom_push_dummy_decls_ (ffebld dummy_list, bool stmtfunc)
7221 ffecom_transform_only_dummies_ = TRUE;
7223 /* First push the parms corresponding to actual dummy "contents". */
7225 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
7227 dummy = ffebld_head (dumlist);
7228 switch (ffebld_op (dummy))
7232 continue; /* Forget alternate returns. */
7237 assert (ffebld_op (dummy) == FFEBLD_opSYMTER);
7238 s = ffebld_symter (dummy);
7239 parm = ffesymbol_hook (s).decl_tree;
7240 if (parm == NULL_TREE)
7242 s = ffecom_sym_transform_ (s);
7243 parm = ffesymbol_hook (s).decl_tree;
7244 assert (parm != NULL_TREE);
7246 if (parm != error_mark_node)
7247 push_parm_decl (parm);
7250 /* Then, for CHARACTER dummies, push the parms giving their lengths. */
7252 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
7254 dummy = ffebld_head (dumlist);
7255 switch (ffebld_op (dummy))
7259 continue; /* Forget alternate returns, they mean
7265 s = ffebld_symter (dummy);
7266 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
7267 continue; /* Only looking for CHARACTER arguments. */
7268 if (stmtfunc && (ffesymbol_size (s) != FFETARGET_charactersizeNONE))
7269 continue; /* Stmtfunc arg with known size needs no
7271 if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
7272 continue; /* Only looking for variables and arrays. */
7273 parm = ffesymbol_hook (s).length_tree;
7274 assert (parm != NULL_TREE);
7275 if (parm != error_mark_node)
7276 push_parm_decl (parm);
7279 ffecom_transform_only_dummies_ = FALSE;
7283 /* ffecom_start_progunit_ -- Beginning of program unit
7285 Does GNU back end stuff necessary to teach it about the start of its
7286 equivalent of a Fortran program unit. */
7288 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7290 ffecom_start_progunit_ ()
7292 ffesymbol fn = ffecom_primary_entry_;
7294 tree id; /* Identifier (name) of function. */
7295 tree type; /* Type of function. */
7296 tree result; /* Result of function. */
7297 ffeinfoBasictype bt;
7301 ffeglobalType egt = FFEGLOBAL_type;
7304 bool altentries = (ffecom_num_entrypoints_ != 0);
7307 && (ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
7308 && (ffecom_master_bt_ == FFEINFO_basictypeNONE);
7309 bool main_program = FALSE;
7310 int old_lineno = lineno;
7311 char *old_input_filename = input_filename;
7314 assert (fn != NULL);
7315 assert (ffesymbol_hook (fn).decl_tree == NULL_TREE);
7317 input_filename = ffesymbol_where_filename (fn);
7318 lineno = ffesymbol_where_filelinenum (fn);
7320 /* c-parse.y indeed does call suspend_momentary and not only ignores the
7321 return value, but also never calls resume_momentary, when starting an
7322 outer function (see "fndef:", "setspecs:", and so on). So g77 does the
7323 same thing. It shouldn't be a problem since start_function calls
7324 temporary_allocation, but it might be necessary. If it causes a problem
7325 here, then maybe there's a bug lurking in gcc. NOTE: This identical
7326 comment appears twice in thist file. */
7328 suspend_momentary ();
7330 switch (ffecom_primary_entry_kind_)
7332 case FFEINFO_kindPROGRAM:
7333 main_program = TRUE;
7334 gt = FFEGLOBAL_typeMAIN;
7335 bt = FFEINFO_basictypeNONE;
7336 kt = FFEINFO_kindtypeNONE;
7337 type = ffecom_tree_fun_type_void;
7342 case FFEINFO_kindBLOCKDATA:
7343 gt = FFEGLOBAL_typeBDATA;
7344 bt = FFEINFO_basictypeNONE;
7345 kt = FFEINFO_kindtypeNONE;
7346 type = ffecom_tree_fun_type_void;
7351 case FFEINFO_kindFUNCTION:
7352 gt = FFEGLOBAL_typeFUNC;
7353 egt = FFEGLOBAL_typeEXT;
7354 bt = ffesymbol_basictype (fn);
7355 kt = ffesymbol_kindtype (fn);
7356 if (bt == FFEINFO_basictypeNONE)
7358 ffeimplic_establish_symbol (fn);
7359 if (ffesymbol_funcresult (fn) != NULL)
7360 ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
7361 bt = ffesymbol_basictype (fn);
7362 kt = ffesymbol_kindtype (fn);
7366 charfunc = cmplxfunc = FALSE;
7367 else if (bt == FFEINFO_basictypeCHARACTER)
7368 charfunc = TRUE, cmplxfunc = FALSE;
7369 else if ((bt == FFEINFO_basictypeCOMPLEX)
7370 && ffesymbol_is_f2c (fn)
7372 charfunc = FALSE, cmplxfunc = TRUE;
7374 charfunc = cmplxfunc = FALSE;
7376 if (multi || charfunc)
7377 type = ffecom_tree_fun_type_void;
7378 else if (ffesymbol_is_f2c (fn) && !altentries)
7379 type = ffecom_tree_fun_type[bt][kt];
7381 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
7383 if ((type == NULL_TREE)
7384 || (TREE_TYPE (type) == NULL_TREE))
7385 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */
7388 case FFEINFO_kindSUBROUTINE:
7389 gt = FFEGLOBAL_typeSUBR;
7390 egt = FFEGLOBAL_typeEXT;
7391 bt = FFEINFO_basictypeNONE;
7392 kt = FFEINFO_kindtypeNONE;
7393 if (ffecom_is_altreturning_)
7394 type = ffecom_tree_subr_type;
7396 type = ffecom_tree_fun_type_void;
7402 assert ("say what??" == NULL);
7404 case FFEINFO_kindANY:
7405 gt = FFEGLOBAL_typeANY;
7406 bt = FFEINFO_basictypeNONE;
7407 kt = FFEINFO_kindtypeNONE;
7408 type = error_mark_node;
7416 id = ffecom_get_invented_identifier ("__g77_masterfun_%s",
7417 ffesymbol_text (fn),
7420 #if FFETARGET_isENFORCED_MAIN
7421 else if (main_program)
7422 id = get_identifier (FFETARGET_nameENFORCED_MAIN_NAME);
7425 id = ffecom_get_external_identifier_ (fn);
7429 0, /* nested/inline */
7430 !altentries); /* TREE_PUBLIC */
7432 TREE_USED (current_function_decl) = 1; /* Avoid spurious warning if altentries. */
7435 && ((g = ffesymbol_global (fn)) != NULL)
7436 && ((ffeglobal_type (g) == gt)
7437 || (ffeglobal_type (g) == egt)))
7439 ffeglobal_set_hook (g, current_function_decl);
7442 yes = suspend_momentary ();
7444 /* Arg handling needs exec-transitioned ffesymbols to work with. But
7445 exec-transitioning needs current_function_decl to be filled in. So we
7446 do these things in two phases. */
7449 { /* 1st arg identifies which entrypoint. */
7450 ffecom_which_entrypoint_decl_
7451 = build_decl (PARM_DECL,
7452 ffecom_get_invented_identifier ("__g77_%s",
7456 push_parm_decl (ffecom_which_entrypoint_decl_);
7462 { /* Arg for result (return value). */
7467 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
7469 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
7471 type = ffecom_multi_type_node_;
7473 result = ffecom_get_invented_identifier ("__g77_%s",
7476 /* Make length arg _and_ enhance type info for CHAR arg itself. */
7479 length = ffecom_char_enhance_arg_ (&type, fn);
7481 length = NULL_TREE; /* Not ref'd if !charfunc. */
7483 type = build_pointer_type (type);
7484 result = build_decl (PARM_DECL, result, type);
7486 push_parm_decl (result);
7488 ffecom_multi_retval_ = result;
7490 ffecom_func_result_ = result;
7494 push_parm_decl (length);
7495 ffecom_func_length_ = length;
7499 if (ffecom_primary_entry_is_proc_)
7502 arglist = ffecom_master_arglist_;
7504 arglist = ffesymbol_dummyargs (fn);
7505 ffecom_push_dummy_decls_ (arglist, FALSE);
7508 resume_momentary (yes);
7510 if (TREE_CODE (current_function_decl) != ERROR_MARK)
7511 store_parm_decls (main_program ? 1 : 0);
7513 ffecom_start_compstmt ();
7514 /* Disallow temp vars at this level. */
7515 current_binding_level->prep_state = 2;
7517 lineno = old_lineno;
7518 input_filename = old_input_filename;
7520 /* This handles any symbols still untransformed, in case -g specified.
7521 This used to be done in ffecom_finish_progunit, but it turns out to
7522 be necessary to do it here so that statement functions are
7523 expanded before code. But don't bother for BLOCK DATA. */
7525 if (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
7526 ffesymbol_drive (ffecom_finish_symbol_transform_);
7530 /* ffecom_sym_transform_ -- Transform FFE sym into backend sym
7533 ffecom_sym_transform_(s);
7535 The ffesymbol_hook info for s is updated with appropriate backend info
7538 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7540 ffecom_sym_transform_ (ffesymbol s)
7542 tree t; /* Transformed thingy. */
7543 tree tlen; /* Length if CHAR*(*). */
7544 bool addr; /* Is t the address of the thingy? */
7545 ffeinfoBasictype bt;
7549 int old_lineno = lineno;
7550 char *old_input_filename = input_filename;
7552 /* Must ensure special ASSIGN variables are declared at top of outermost
7553 block, else they'll end up in the innermost block when their first
7554 ASSIGN is seen, which leaves them out of scope when they're the
7555 subject of a GOTO or I/O statement.
7557 We make this variable even if -fugly-assign. Just let it go unused,
7558 in case it turns out there are cases where we really want to use this
7559 variable anyway (e.g. ASSIGN to INTEGER*2 variable). */
7561 if (! ffecom_transform_only_dummies_
7562 && ffesymbol_assigned (s)
7563 && ! ffesymbol_hook (s).assign_tree)
7564 s = ffecom_sym_transform_assign_ (s);
7566 if (ffesymbol_sfdummyparent (s) == NULL)
7568 input_filename = ffesymbol_where_filename (s);
7569 lineno = ffesymbol_where_filelinenum (s);
7573 ffesymbol sf = ffesymbol_sfdummyparent (s);
7575 input_filename = ffesymbol_where_filename (sf);
7576 lineno = ffesymbol_where_filelinenum (sf);
7579 bt = ffeinfo_basictype (ffebld_info (s));
7580 kt = ffeinfo_kindtype (ffebld_info (s));
7586 switch (ffesymbol_kind (s))
7588 case FFEINFO_kindNONE:
7589 switch (ffesymbol_where (s))
7591 case FFEINFO_whereDUMMY: /* Subroutine or function. */
7592 assert (ffecom_transform_only_dummies_);
7594 /* Before 0.4, this could be ENTITY/DUMMY, but see
7595 ffestu_sym_end_transition -- no longer true (in particular, if
7596 it could be an ENTITY, it _will_ be made one, so that
7597 possibility won't come through here). So we never make length
7598 arg for CHARACTER type. */
7600 t = build_decl (PARM_DECL,
7601 ffecom_get_identifier_ (ffesymbol_text (s)),
7602 ffecom_tree_ptr_to_subr_type);
7604 DECL_ARTIFICIAL (t) = 1;
7609 case FFEINFO_whereGLOBAL: /* Subroutine or function. */
7610 assert (!ffecom_transform_only_dummies_);
7612 if (((g = ffesymbol_global (s)) != NULL)
7613 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
7614 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
7615 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
7616 && (ffeglobal_hook (g) != NULL_TREE)
7617 && ffe_is_globals ())
7619 t = ffeglobal_hook (g);
7623 push_obstacks_nochange ();
7624 end_temporary_allocation ();
7626 t = build_decl (FUNCTION_DECL,
7627 ffecom_get_external_identifier_ (s),
7628 ffecom_tree_subr_type); /* Assume subr. */
7629 DECL_EXTERNAL (t) = 1;
7630 TREE_PUBLIC (t) = 1;
7632 t = start_decl (t, FALSE);
7633 finish_decl (t, NULL_TREE, FALSE);
7636 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
7637 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
7638 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
7639 ffeglobal_set_hook (g, t);
7641 resume_temporary_allocation ();
7647 assert ("NONE where unexpected" == NULL);
7649 case FFEINFO_whereANY:
7654 case FFEINFO_kindENTITY:
7655 switch (ffeinfo_where (ffesymbol_info (s)))
7658 case FFEINFO_whereCONSTANT:
7659 /* ~~Debugging info needed? */
7660 assert (!ffecom_transform_only_dummies_);
7661 t = error_mark_node; /* Shouldn't ever see this in expr. */
7664 case FFEINFO_whereLOCAL:
7665 assert (!ffecom_transform_only_dummies_);
7668 ffestorag st = ffesymbol_storage (s);
7672 && (ffestorag_size (st) == 0))
7674 t = error_mark_node;
7678 yes = suspend_momentary ();
7679 type = ffecom_type_localvar_ (s, bt, kt);
7680 resume_momentary (yes);
7682 if (type == error_mark_node)
7684 t = error_mark_node;
7689 && (ffestorag_parent (st) != NULL))
7690 { /* Child of EQUIVALENCE parent. */
7694 ffetargetOffset offset;
7696 est = ffestorag_parent (st);
7697 ffecom_transform_equiv_ (est);
7699 et = ffestorag_hook (est);
7700 assert (et != NULL_TREE);
7702 if (! TREE_STATIC (et))
7703 put_var_into_stack (et);
7705 yes = suspend_momentary ();
7707 offset = ffestorag_modulo (est)
7708 + ffestorag_offset (ffesymbol_storage (s))
7709 - ffestorag_offset (est);
7711 ffecom_debug_kludge_ (et, "EQUIVALENCE", s, type, offset);
7713 /* (t_type *) (((char *) &et) + offset) */
7715 t = convert (string_type_node, /* (char *) */
7716 ffecom_1 (ADDR_EXPR,
7717 build_pointer_type (TREE_TYPE (et)),
7719 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
7721 build_int_2 (offset, 0));
7722 t = convert (build_pointer_type (type),
7724 TREE_CONSTANT (t) = staticp (et);
7728 resume_momentary (yes);
7733 bool init = ffesymbol_is_init (s);
7735 yes = suspend_momentary ();
7737 t = build_decl (VAR_DECL,
7738 ffecom_get_identifier_ (ffesymbol_text (s)),
7742 || ffesymbol_namelisted (s)
7743 #ifdef FFECOM_sizeMAXSTACKITEM
7745 && (ffestorag_size (st) > FFECOM_sizeMAXSTACKITEM))
7747 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
7748 && (ffecom_primary_entry_kind_
7749 != FFEINFO_kindBLOCKDATA)
7750 && (ffesymbol_is_save (s) || ffe_is_saveall ())))
7751 TREE_STATIC (t) = !ffesymbol_attr (s, FFESYMBOL_attrADJUSTABLE);
7753 TREE_STATIC (t) = 0; /* No need to make static. */
7755 if (init || ffe_is_init_local_zero ())
7756 DECL_INITIAL (t) = error_mark_node;
7758 /* Keep -Wunused from complaining about var if it
7759 is used as sfunc arg or DATA implied-DO. */
7760 if (ffesymbol_attrs (s) & FFESYMBOL_attrsSFARG)
7761 DECL_IN_SYSTEM_HEADER (t) = 1;
7763 t = start_decl (t, FALSE);
7767 if (ffesymbol_init (s) != NULL)
7768 initexpr = ffecom_expr (ffesymbol_init (s));
7770 initexpr = ffecom_init_zero_ (t);
7772 else if (ffe_is_init_local_zero ())
7773 initexpr = ffecom_init_zero_ (t);
7775 initexpr = NULL_TREE; /* Not ref'd if !init. */
7777 finish_decl (t, initexpr, FALSE);
7779 if ((st != NULL) && (DECL_SIZE (t) != error_mark_node))
7783 size_tree = size_binop (CEIL_DIV_EXPR,
7785 size_int (BITS_PER_UNIT));
7786 assert (TREE_INT_CST_HIGH (size_tree) == 0);
7787 assert (TREE_INT_CST_LOW (size_tree) == ffestorag_size (st));
7790 resume_momentary (yes);
7795 case FFEINFO_whereRESULT:
7796 assert (!ffecom_transform_only_dummies_);
7798 if (bt == FFEINFO_basictypeCHARACTER)
7799 { /* Result is already in list of dummies, use
7801 t = ffecom_func_result_;
7802 tlen = ffecom_func_length_;
7806 if ((ffecom_num_entrypoints_ == 0)
7807 && (bt == FFEINFO_basictypeCOMPLEX)
7808 && (ffesymbol_is_f2c (ffecom_primary_entry_)))
7809 { /* Result is already in list of dummies, use
7811 t = ffecom_func_result_;
7815 if (ffecom_func_result_ != NULL_TREE)
7817 t = ffecom_func_result_;
7820 if ((ffecom_num_entrypoints_ != 0)
7821 && (ffecom_master_bt_ == FFEINFO_basictypeNONE))
7823 yes = suspend_momentary ();
7825 assert (ffecom_multi_retval_ != NULL_TREE);
7826 t = ffecom_1 (INDIRECT_REF, ffecom_multi_type_node_,
7827 ffecom_multi_retval_);
7828 t = ffecom_2 (COMPONENT_REF, ffecom_tree_type[bt][kt],
7829 t, ffecom_multi_fields_[bt][kt]);
7831 resume_momentary (yes);
7835 yes = suspend_momentary ();
7837 t = build_decl (VAR_DECL,
7838 ffecom_get_identifier_ (ffesymbol_text (s)),
7839 ffecom_tree_type[bt][kt]);
7840 TREE_STATIC (t) = 0; /* Put result on stack. */
7841 t = start_decl (t, FALSE);
7842 finish_decl (t, NULL_TREE, FALSE);
7844 ffecom_func_result_ = t;
7846 resume_momentary (yes);
7849 case FFEINFO_whereDUMMY:
7857 bool adjustable = FALSE; /* Conditionally adjustable? */
7859 type = ffecom_tree_type[bt][kt];
7860 if (ffesymbol_sfdummyparent (s) != NULL)
7862 if (current_function_decl == ffecom_outer_function_decl_)
7863 { /* Exec transition before sfunc
7864 context; get it later. */
7867 t = ffecom_get_identifier_ (ffesymbol_text
7868 (ffesymbol_sfdummyparent (s)));
7871 t = ffecom_get_identifier_ (ffesymbol_text (s));
7873 assert (ffecom_transform_only_dummies_);
7875 old_sizes = get_pending_sizes ();
7876 put_pending_sizes (old_sizes);
7878 if (bt == FFEINFO_basictypeCHARACTER)
7879 tlen = ffecom_char_enhance_arg_ (&type, s);
7880 type = ffecom_check_size_overflow_ (s, type, TRUE);
7882 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
7884 if (type == error_mark_node)
7887 dim = ffebld_head (dl);
7888 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
7889 if ((ffebld_left (dim) == NULL) || ffecom_doing_entry_)
7890 low = ffecom_integer_one_node;
7892 low = ffecom_expr (ffebld_left (dim));
7893 assert (ffebld_right (dim) != NULL);
7894 if ((ffebld_op (ffebld_right (dim)) == FFEBLD_opSTAR)
7895 || ffecom_doing_entry_)
7897 /* Used to just do high=low. But for ffecom_tree_
7898 canonize_ref_, it probably is important to correctly
7899 assess the size. E.g. given COMPLEX C(*),CFUNC and
7900 C(2)=CFUNC(C), overlap can happen, while it can't
7901 for, say, C(1)=CFUNC(C(2)). */
7902 /* Even more recently used to set to INT_MAX, but that
7903 broke when some overflow checking went into the back
7904 end. Now we just leave the upper bound unspecified. */
7908 high = ffecom_expr (ffebld_right (dim));
7910 /* Determine whether array is conditionally adjustable,
7911 to decide whether back-end magic is needed.
7913 Normally the front end uses the back-end function
7914 variable_size to wrap SAVE_EXPR's around expressions
7915 affecting the size/shape of an array so that the
7916 size/shape info doesn't change during execution
7917 of the compiled code even though variables and
7918 functions referenced in those expressions might.
7920 variable_size also makes sure those saved expressions
7921 get evaluated immediately upon entry to the
7922 compiled procedure -- the front end normally doesn't
7923 have to worry about that.
7925 However, there is a problem with this that affects
7926 g77's implementation of entry points, and that is
7927 that it is _not_ true that each invocation of the
7928 compiled procedure is permitted to evaluate
7929 array size/shape info -- because it is possible
7930 that, for some invocations, that info is invalid (in
7931 which case it is "promised" -- i.e. a violation of
7932 the Fortran standard -- that the compiled code
7933 won't reference the array or its size/shape
7934 during that particular invocation).
7936 To phrase this in C terms, consider this gcc function:
7938 void foo (int *n, float (*a)[*n])
7940 // a is "pointer to array ...", fyi.
7943 Suppose that, for some invocations, it is permitted
7944 for a caller of foo to do this:
7948 Now the _written_ code for foo can take such a call
7949 into account by either testing explicitly for whether
7950 (a == NULL) || (n == NULL) -- presumably it is
7951 not permitted to reference *a in various fashions
7952 if (n == NULL) I suppose -- or it can avoid it by
7953 looking at other info (other arguments, static/global
7956 However, this won't work in gcc 2.5.8 because it'll
7957 automatically emit the code to save the "*n"
7958 expression, which'll yield a NULL dereference for
7959 the "foo (NULL, NULL)" call, something the code
7960 for foo cannot prevent.
7962 g77 definitely needs to avoid executing such
7963 code anytime the pointer to the adjustable array
7964 is NULL, because even if its bounds expressions
7965 don't have any references to possible "absent"
7966 variables like "*n" -- say all variable references
7967 are to COMMON variables, i.e. global (though in C,
7968 local static could actually make sense) -- the
7969 expressions could yield other run-time problems
7970 for allowably "dead" values in those variables.
7972 For example, let's consider a more complicated
7978 void foo (float (*a)[i/j])
7983 The above is (essentially) quite valid for Fortran
7984 but, again, for a call like "foo (NULL);", it is
7985 permitted for i and j to be undefined when the
7986 call is made. If j happened to be zero, for
7987 example, emitting the code to evaluate "i/j"
7988 could result in a run-time error.
7990 Offhand, though I don't have my F77 or F90
7991 standards handy, it might even be valid for a
7992 bounds expression to contain a function reference,
7993 in which case I doubt it is permitted for an
7994 implementation to invoke that function in the
7995 Fortran case involved here (invocation of an
7996 alternate ENTRY point that doesn't have the adjustable
7997 array as one of its arguments).
7999 So, the code that the compiler would normally emit
8000 to preevaluate the size/shape info for an
8001 adjustable array _must not_ be executed at run time
8002 in certain cases. Specifically, for Fortran,
8003 the case is when the pointer to the adjustable
8004 array == NULL. (For gnu-ish C, it might be nice
8005 for the source code itself to specify an expression
8006 that, if TRUE, inhibits execution of the code. Or
8007 reverse the sense for elegance.)
8009 (Note that g77 could use a different test than NULL,
8010 actually, since it happens to always pass an
8011 integer to the called function that specifies which
8012 entry point is being invoked. Hmm, this might
8013 solve the next problem.)
8015 One way a user could, I suppose, write "foo" so
8016 it works is to insert COND_EXPR's for the
8017 size/shape info so the dangerous stuff isn't
8018 actually done, as in:
8020 void foo (int *n, float (*a)[(a == NULL) ? 0 : *n])
8025 The next problem is that the front end needs to
8026 be able to tell the back end about the array's
8027 decl _before_ it tells it about the conditional
8028 expression to inhibit evaluation of size/shape info,
8031 To solve this, the front end needs to be able
8032 to give the back end the expression to inhibit
8033 generation of the preevaluation code _after_
8034 it makes the decl for the adjustable array.
8036 Until then, the above example using the COND_EXPR
8037 doesn't pass muster with gcc because the "(a == NULL)"
8038 part has a reference to "a", which is still
8039 undefined at that point.
8041 g77 will therefore use a different mechanism in the
8045 && ((TREE_CODE (low) != INTEGER_CST)
8046 || (high && TREE_CODE (high) != INTEGER_CST)))
8049 #if 0 /* Old approach -- see below. */
8050 if (TREE_CODE (low) != INTEGER_CST)
8051 low = ffecom_3 (COND_EXPR, integer_type_node,
8052 ffecom_adjarray_passed_ (s),
8054 ffecom_integer_zero_node);
8056 if (high && TREE_CODE (high) != INTEGER_CST)
8057 high = ffecom_3 (COND_EXPR, integer_type_node,
8058 ffecom_adjarray_passed_ (s),
8060 ffecom_integer_zero_node);
8063 /* ~~~gcc/stor-layout.c (layout_type) should do this,
8064 probably. Fixes 950302-1.f. */
8066 if (TREE_CODE (low) != INTEGER_CST)
8067 low = variable_size (low);
8069 /* ~~~Similarly, this fixes dumb0.f. The C front end
8070 does this, which is why dumb0.c would work. */
8072 if (high && TREE_CODE (high) != INTEGER_CST)
8073 high = variable_size (high);
8078 build_range_type (ffecom_integer_type_node,
8080 type = ffecom_check_size_overflow_ (s, type, TRUE);
8083 if (type == error_mark_node)
8085 t = error_mark_node;
8089 if ((ffesymbol_sfdummyparent (s) == NULL)
8090 || (ffesymbol_basictype (s) == FFEINFO_basictypeCHARACTER))
8092 type = build_pointer_type (type);
8096 t = build_decl (PARM_DECL, t, type);
8098 DECL_ARTIFICIAL (t) = 1;
8101 /* If this arg is present in every entry point's list of
8102 dummy args, then we're done. */
8104 if (ffesymbol_numentries (s)
8105 == (ffecom_num_entrypoints_ + 1))
8110 /* If variable_size in stor-layout has been called during
8111 the above, then get_pending_sizes should have the
8112 yet-to-be-evaluated saved expressions pending.
8113 Make the whole lot of them get emitted, conditionally
8114 on whether the array decl ("t" above) is not NULL. */
8117 tree sizes = get_pending_sizes ();
8122 tem = TREE_CHAIN (tem))
8124 tree temv = TREE_VALUE (tem);
8130 = ffecom_2 (COMPOUND_EXPR,
8139 = ffecom_3 (COND_EXPR,
8146 convert (TREE_TYPE (sizes),
8147 integer_zero_node));
8148 sizes = ffecom_save_tree (sizes);
8151 = tree_cons (NULL_TREE, sizes, tem);
8155 put_pending_sizes (sizes);
8161 && (ffesymbol_numentries (s)
8162 != ffecom_num_entrypoints_ + 1))
8164 = ffecom_2 (NE_EXPR, integer_type_node,
8170 && (ffesymbol_numentries (s)
8171 != ffecom_num_entrypoints_ + 1))
8173 ffebad_start (FFEBAD_MISSING_ADJARRAY_UNSUPPORTED);
8174 ffebad_here (0, ffesymbol_where_line (s),
8175 ffesymbol_where_column (s));
8176 ffebad_string (ffesymbol_text (s));
8185 case FFEINFO_whereCOMMON:
8190 ffestorag st = ffesymbol_storage (s);
8194 cs = ffesymbol_common (s); /* The COMMON area itself. */
8195 if (st != NULL) /* Else not laid out. */
8197 ffecom_transform_common_ (cs);
8198 st = ffesymbol_storage (s);
8201 yes = suspend_momentary ();
8203 type = ffecom_type_localvar_ (s, bt, kt);
8205 cg = ffesymbol_global (cs); /* The global COMMON info. */
8207 || (ffeglobal_type (cg) != FFEGLOBAL_typeCOMMON))
8210 ct = ffeglobal_hook (cg); /* The common area's tree. */
8212 if ((ct == NULL_TREE)
8214 || (type == error_mark_node))
8215 t = error_mark_node;
8218 ffetargetOffset offset;
8221 cst = ffestorag_parent (st);
8222 assert (cst == ffesymbol_storage (cs));
8224 offset = ffestorag_modulo (cst)
8225 + ffestorag_offset (st)
8226 - ffestorag_offset (cst);
8228 ffecom_debug_kludge_ (ct, "COMMON", s, type, offset);
8230 /* (t_type *) (((char *) &ct) + offset) */
8232 t = convert (string_type_node, /* (char *) */
8233 ffecom_1 (ADDR_EXPR,
8234 build_pointer_type (TREE_TYPE (ct)),
8236 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
8238 build_int_2 (offset, 0));
8239 t = convert (build_pointer_type (type),
8241 TREE_CONSTANT (t) = 1;
8246 resume_momentary (yes);
8250 case FFEINFO_whereIMMEDIATE:
8251 case FFEINFO_whereGLOBAL:
8252 case FFEINFO_whereFLEETING:
8253 case FFEINFO_whereFLEETING_CADDR:
8254 case FFEINFO_whereFLEETING_IADDR:
8255 case FFEINFO_whereINTRINSIC:
8256 case FFEINFO_whereCONSTANT_SUBOBJECT:
8258 assert ("ENTITY where unheard of" == NULL);
8260 case FFEINFO_whereANY:
8261 t = error_mark_node;
8266 case FFEINFO_kindFUNCTION:
8267 switch (ffeinfo_where (ffesymbol_info (s)))
8269 case FFEINFO_whereLOCAL: /* Me. */
8270 assert (!ffecom_transform_only_dummies_);
8271 t = current_function_decl;
8274 case FFEINFO_whereGLOBAL:
8275 assert (!ffecom_transform_only_dummies_);
8277 if (((g = ffesymbol_global (s)) != NULL)
8278 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8279 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8280 && (ffeglobal_hook (g) != NULL_TREE)
8281 && ffe_is_globals ())
8283 t = ffeglobal_hook (g);
8287 push_obstacks_nochange ();
8288 end_temporary_allocation ();
8290 if (ffesymbol_is_f2c (s)
8291 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
8292 t = ffecom_tree_fun_type[bt][kt];
8294 t = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
8296 t = build_decl (FUNCTION_DECL,
8297 ffecom_get_external_identifier_ (s),
8299 DECL_EXTERNAL (t) = 1;
8300 TREE_PUBLIC (t) = 1;
8302 t = start_decl (t, FALSE);
8303 finish_decl (t, NULL_TREE, FALSE);
8306 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8307 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8308 ffeglobal_set_hook (g, t);
8310 resume_temporary_allocation ();
8315 case FFEINFO_whereDUMMY:
8316 assert (ffecom_transform_only_dummies_);
8318 if (ffesymbol_is_f2c (s)
8319 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
8320 t = ffecom_tree_ptr_to_fun_type[bt][kt];
8322 t = build_pointer_type
8323 (build_function_type (ffecom_tree_type[bt][kt], NULL_TREE));
8325 t = build_decl (PARM_DECL,
8326 ffecom_get_identifier_ (ffesymbol_text (s)),
8329 DECL_ARTIFICIAL (t) = 1;
8334 case FFEINFO_whereCONSTANT: /* Statement function. */
8335 assert (!ffecom_transform_only_dummies_);
8336 t = ffecom_gen_sfuncdef_ (s, bt, kt);
8339 case FFEINFO_whereINTRINSIC:
8340 assert (!ffecom_transform_only_dummies_);
8341 break; /* Let actual references generate their
8345 assert ("FUNCTION where unheard of" == NULL);
8347 case FFEINFO_whereANY:
8348 t = error_mark_node;
8353 case FFEINFO_kindSUBROUTINE:
8354 switch (ffeinfo_where (ffesymbol_info (s)))
8356 case FFEINFO_whereLOCAL: /* Me. */
8357 assert (!ffecom_transform_only_dummies_);
8358 t = current_function_decl;
8361 case FFEINFO_whereGLOBAL:
8362 assert (!ffecom_transform_only_dummies_);
8364 if (((g = ffesymbol_global (s)) != NULL)
8365 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8366 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8367 && (ffeglobal_hook (g) != NULL_TREE)
8368 && ffe_is_globals ())
8370 t = ffeglobal_hook (g);
8374 push_obstacks_nochange ();
8375 end_temporary_allocation ();
8377 t = build_decl (FUNCTION_DECL,
8378 ffecom_get_external_identifier_ (s),
8379 ffecom_tree_subr_type);
8380 DECL_EXTERNAL (t) = 1;
8381 TREE_PUBLIC (t) = 1;
8383 t = start_decl (t, FALSE);
8384 finish_decl (t, NULL_TREE, FALSE);
8387 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8388 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8389 ffeglobal_set_hook (g, t);
8391 resume_temporary_allocation ();
8396 case FFEINFO_whereDUMMY:
8397 assert (ffecom_transform_only_dummies_);
8399 t = build_decl (PARM_DECL,
8400 ffecom_get_identifier_ (ffesymbol_text (s)),
8401 ffecom_tree_ptr_to_subr_type);
8403 DECL_ARTIFICIAL (t) = 1;
8408 case FFEINFO_whereINTRINSIC:
8409 assert (!ffecom_transform_only_dummies_);
8410 break; /* Let actual references generate their
8414 assert ("SUBROUTINE where unheard of" == NULL);
8416 case FFEINFO_whereANY:
8417 t = error_mark_node;
8422 case FFEINFO_kindPROGRAM:
8423 switch (ffeinfo_where (ffesymbol_info (s)))
8425 case FFEINFO_whereLOCAL: /* Me. */
8426 assert (!ffecom_transform_only_dummies_);
8427 t = current_function_decl;
8430 case FFEINFO_whereCOMMON:
8431 case FFEINFO_whereDUMMY:
8432 case FFEINFO_whereGLOBAL:
8433 case FFEINFO_whereRESULT:
8434 case FFEINFO_whereFLEETING:
8435 case FFEINFO_whereFLEETING_CADDR:
8436 case FFEINFO_whereFLEETING_IADDR:
8437 case FFEINFO_whereIMMEDIATE:
8438 case FFEINFO_whereINTRINSIC:
8439 case FFEINFO_whereCONSTANT:
8440 case FFEINFO_whereCONSTANT_SUBOBJECT:
8442 assert ("PROGRAM where unheard of" == NULL);
8444 case FFEINFO_whereANY:
8445 t = error_mark_node;
8450 case FFEINFO_kindBLOCKDATA:
8451 switch (ffeinfo_where (ffesymbol_info (s)))
8453 case FFEINFO_whereLOCAL: /* Me. */
8454 assert (!ffecom_transform_only_dummies_);
8455 t = current_function_decl;
8458 case FFEINFO_whereGLOBAL:
8459 assert (!ffecom_transform_only_dummies_);
8461 push_obstacks_nochange ();
8462 end_temporary_allocation ();
8464 t = build_decl (FUNCTION_DECL,
8465 ffecom_get_external_identifier_ (s),
8466 ffecom_tree_blockdata_type);
8467 DECL_EXTERNAL (t) = 1;
8468 TREE_PUBLIC (t) = 1;
8470 t = start_decl (t, FALSE);
8471 finish_decl (t, NULL_TREE, FALSE);
8473 resume_temporary_allocation ();
8478 case FFEINFO_whereCOMMON:
8479 case FFEINFO_whereDUMMY:
8480 case FFEINFO_whereRESULT:
8481 case FFEINFO_whereFLEETING:
8482 case FFEINFO_whereFLEETING_CADDR:
8483 case FFEINFO_whereFLEETING_IADDR:
8484 case FFEINFO_whereIMMEDIATE:
8485 case FFEINFO_whereINTRINSIC:
8486 case FFEINFO_whereCONSTANT:
8487 case FFEINFO_whereCONSTANT_SUBOBJECT:
8489 assert ("BLOCKDATA where unheard of" == NULL);
8491 case FFEINFO_whereANY:
8492 t = error_mark_node;
8497 case FFEINFO_kindCOMMON:
8498 switch (ffeinfo_where (ffesymbol_info (s)))
8500 case FFEINFO_whereLOCAL:
8501 assert (!ffecom_transform_only_dummies_);
8502 ffecom_transform_common_ (s);
8505 case FFEINFO_whereNONE:
8506 case FFEINFO_whereCOMMON:
8507 case FFEINFO_whereDUMMY:
8508 case FFEINFO_whereGLOBAL:
8509 case FFEINFO_whereRESULT:
8510 case FFEINFO_whereFLEETING:
8511 case FFEINFO_whereFLEETING_CADDR:
8512 case FFEINFO_whereFLEETING_IADDR:
8513 case FFEINFO_whereIMMEDIATE:
8514 case FFEINFO_whereINTRINSIC:
8515 case FFEINFO_whereCONSTANT:
8516 case FFEINFO_whereCONSTANT_SUBOBJECT:
8518 assert ("COMMON where unheard of" == NULL);
8520 case FFEINFO_whereANY:
8521 t = error_mark_node;
8526 case FFEINFO_kindCONSTRUCT:
8527 switch (ffeinfo_where (ffesymbol_info (s)))
8529 case FFEINFO_whereLOCAL:
8530 assert (!ffecom_transform_only_dummies_);
8533 case FFEINFO_whereNONE:
8534 case FFEINFO_whereCOMMON:
8535 case FFEINFO_whereDUMMY:
8536 case FFEINFO_whereGLOBAL:
8537 case FFEINFO_whereRESULT:
8538 case FFEINFO_whereFLEETING:
8539 case FFEINFO_whereFLEETING_CADDR:
8540 case FFEINFO_whereFLEETING_IADDR:
8541 case FFEINFO_whereIMMEDIATE:
8542 case FFEINFO_whereINTRINSIC:
8543 case FFEINFO_whereCONSTANT:
8544 case FFEINFO_whereCONSTANT_SUBOBJECT:
8546 assert ("CONSTRUCT where unheard of" == NULL);
8548 case FFEINFO_whereANY:
8549 t = error_mark_node;
8554 case FFEINFO_kindNAMELIST:
8555 switch (ffeinfo_where (ffesymbol_info (s)))
8557 case FFEINFO_whereLOCAL:
8558 assert (!ffecom_transform_only_dummies_);
8559 t = ffecom_transform_namelist_ (s);
8562 case FFEINFO_whereNONE:
8563 case FFEINFO_whereCOMMON:
8564 case FFEINFO_whereDUMMY:
8565 case FFEINFO_whereGLOBAL:
8566 case FFEINFO_whereRESULT:
8567 case FFEINFO_whereFLEETING:
8568 case FFEINFO_whereFLEETING_CADDR:
8569 case FFEINFO_whereFLEETING_IADDR:
8570 case FFEINFO_whereIMMEDIATE:
8571 case FFEINFO_whereINTRINSIC:
8572 case FFEINFO_whereCONSTANT:
8573 case FFEINFO_whereCONSTANT_SUBOBJECT:
8575 assert ("NAMELIST where unheard of" == NULL);
8577 case FFEINFO_whereANY:
8578 t = error_mark_node;
8584 assert ("kind unheard of" == NULL);
8586 case FFEINFO_kindANY:
8587 t = error_mark_node;
8591 ffesymbol_hook (s).decl_tree = t;
8592 ffesymbol_hook (s).length_tree = tlen;
8593 ffesymbol_hook (s).addr = addr;
8595 lineno = old_lineno;
8596 input_filename = old_input_filename;
8602 /* Transform into ASSIGNable symbol.
8604 Symbol has already been transformed, but for whatever reason, the
8605 resulting decl_tree has been deemed not usable for an ASSIGN target.
8606 (E.g. it isn't wide enough to hold a pointer.) So, here we invent
8607 another local symbol of type void * and stuff that in the assign_tree
8608 argument. The F77/F90 standards allow this implementation. */
8610 #if FFECOM_targetCURRENT == FFECOM_targetGCC
8612 ffecom_sym_transform_assign_ (ffesymbol s)
8614 tree t; /* Transformed thingy. */
8616 int old_lineno = lineno;
8617 char *old_input_filename = input_filename;
8619 if (ffesymbol_sfdummyparent (s) == NULL)
8621 input_filename = ffesymbol_where_filename (s);
8622 lineno = ffesymbol_where_filelinenum (s);
8626 ffesymbol sf = ffesymbol_sfdummyparent (s);
8628 input_filename = ffesymbol_where_filename (sf);
8629 lineno = ffesymbol_where_filelinenum (sf);
8632 assert (!ffecom_transform_only_dummies_);
8634 yes = suspend_momentary ();
8636 t = build_decl (VAR_DECL,
8637 ffecom_get_invented_identifier ("__g77_ASSIGN_%s",
8640 TREE_TYPE (null_pointer_node));
8642 switch (ffesymbol_where (s))
8644 case FFEINFO_whereLOCAL:
8645 /* Unlike for regular vars, SAVE status is easy to determine for
8646 ASSIGNed vars, since there's no initialization, there's no
8647 effective storage association (so "SAVE J" does not apply to
8648 K even given "EQUIVALENCE (J,K)"), there's no size issue
8649 to worry about, etc. */
8650 if ((ffesymbol_is_save (s) || ffe_is_saveall ())
8651 && (ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
8652 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA))
8653 TREE_STATIC (t) = 1; /* SAVEd in proc, make static. */
8655 TREE_STATIC (t) = 0; /* No need to make static. */
8658 case FFEINFO_whereCOMMON:
8659 TREE_STATIC (t) = 1; /* Assume COMMONs always SAVEd. */
8662 case FFEINFO_whereDUMMY:
8663 /* Note that twinning a DUMMY means the caller won't see
8664 the ASSIGNed value. But both F77 and F90 allow implementations
8665 to do this, i.e. disallow Fortran code that would try and
8666 take advantage of actually putting a label into a variable
8667 via a dummy argument (or any other storage association, for
8669 TREE_STATIC (t) = 0;
8673 TREE_STATIC (t) = 0;
8677 t = start_decl (t, FALSE);
8678 finish_decl (t, NULL_TREE, FALSE);
8680 resume_momentary (yes);
8682 ffesymbol_hook (s).assign_tree = t;
8684 lineno = old_lineno;
8685 input_filename = old_input_filename;
8691 /* Implement COMMON area in back end.
8693 Because COMMON-based variables can be referenced in the dimension
8694 expressions of dummy (adjustable) arrays, and because dummies
8695 (in the gcc back end) need to be put in the outer binding level
8696 of a function (which has two binding levels, the outer holding
8697 the dummies and the inner holding the other vars), special care
8698 must be taken to handle COMMON areas.
8700 The current strategy is basically to always tell the back end about
8701 the COMMON area as a top-level external reference to just a block
8702 of storage of the master type of that area (e.g. integer, real,
8703 character, whatever -- not a structure). As a distinct action,
8704 if initial values are provided, tell the back end about the area
8705 as a top-level non-external (initialized) area and remember not to
8706 allow further initialization or expansion of the area. Meanwhile,
8707 if no initialization happens at all, tell the back end about
8708 the largest size we've seen declared so the space does get reserved.
8709 (This function doesn't handle all that stuff, but it does some
8710 of the important things.)
8712 Meanwhile, for COMMON variables themselves, just keep creating
8713 references like *((float *) (&common_area + offset)) each time
8714 we reference the variable. In other words, don't make a VAR_DECL
8715 or any kind of component reference (like we used to do before 0.4),
8716 though we might do that as well just for debugging purposes (and
8717 stuff the rtl with the appropriate offset expression). */
8719 #if FFECOM_targetCURRENT == FFECOM_targetGCC
8721 ffecom_transform_common_ (ffesymbol s)
8723 ffestorag st = ffesymbol_storage (s);
8724 ffeglobal g = ffesymbol_global (s);
8729 bool is_init = ffestorag_is_init (st);
8731 assert (st != NULL);
8734 || (ffeglobal_type (g) != FFEGLOBAL_typeCOMMON))
8737 /* First update the size of the area in global terms. */
8739 ffeglobal_size_common (s, ffestorag_size (st));
8741 if (!ffeglobal_common_init (g))
8742 is_init = FALSE; /* No explicit init, don't let erroneous joins init. */
8744 cbt = ffeglobal_hook (g);
8746 /* If we already have declared this common block for a previous program
8747 unit, and either we already initialized it or we don't have new
8748 initialization for it, just return what we have without changing it. */
8750 if ((cbt != NULL_TREE)
8752 || !DECL_EXTERNAL (cbt)))
8755 /* Process inits. */
8759 if (ffestorag_init (st) != NULL)
8763 /* Set the padding for the expression, so ffecom_expr
8764 knows to insert that many zeros. */
8765 switch (ffebld_op (sexp = ffestorag_init (st)))
8767 case FFEBLD_opCONTER:
8768 ffebld_conter_set_pad (sexp, ffestorag_modulo (st));
8771 case FFEBLD_opARRTER:
8772 ffebld_arrter_set_pad (sexp, ffestorag_modulo (st));
8775 case FFEBLD_opACCTER:
8776 ffebld_accter_set_pad (sexp, ffestorag_modulo (st));
8780 assert ("bad op for cmn init (pad)" == NULL);
8784 init = ffecom_expr (sexp);
8785 if (init == error_mark_node)
8786 { /* Hopefully the back end complained! */
8788 if (cbt != NULL_TREE)
8793 init = error_mark_node;
8798 push_obstacks_nochange ();
8799 end_temporary_allocation ();
8801 /* cbtype must be permanently allocated! */
8803 /* Allocate the MAX of the areas so far, seen filewide. */
8804 high = build_int_2 ((ffeglobal_common_size (g)
8805 + ffeglobal_common_pad (g)) - 1, 0);
8806 TREE_TYPE (high) = ffecom_integer_type_node;
8809 cbtype = build_array_type (char_type_node,
8810 build_range_type (integer_type_node,
8814 cbtype = build_array_type (char_type_node, NULL_TREE);
8816 if (cbt == NULL_TREE)
8819 = build_decl (VAR_DECL,
8820 ffecom_get_external_identifier_ (s),
8822 TREE_STATIC (cbt) = 1;
8823 TREE_PUBLIC (cbt) = 1;
8828 TREE_TYPE (cbt) = cbtype;
8830 DECL_EXTERNAL (cbt) = init ? 0 : 1;
8831 DECL_INITIAL (cbt) = init ? error_mark_node : NULL_TREE;
8833 cbt = start_decl (cbt, TRUE);
8834 if (ffeglobal_hook (g) != NULL)
8835 assert (cbt == ffeglobal_hook (g));
8837 assert (!init || !DECL_EXTERNAL (cbt));
8839 /* Make sure that any type can live in COMMON and be referenced
8840 without getting a bus error. We could pick the most restrictive
8841 alignment of all entities actually placed in the COMMON, but
8842 this seems easy enough. */
8844 DECL_ALIGN (cbt) = BIGGEST_ALIGNMENT;
8846 if (is_init && (ffestorag_init (st) == NULL))
8847 init = ffecom_init_zero_ (cbt);
8849 finish_decl (cbt, init, TRUE);
8852 ffestorag_set_init (st, ffebld_new_any ());
8858 assert (DECL_SIZE (cbt) != NULL_TREE);
8859 assert (TREE_CODE (DECL_SIZE (cbt)) == INTEGER_CST);
8860 size_tree = size_binop (CEIL_DIV_EXPR,
8862 size_int (BITS_PER_UNIT));
8863 assert (TREE_INT_CST_HIGH (size_tree) == 0);
8864 assert (TREE_INT_CST_LOW (size_tree)
8865 == ffeglobal_common_size (g) + ffeglobal_common_pad (g));
8868 ffeglobal_set_hook (g, cbt);
8870 ffestorag_set_hook (st, cbt);
8872 resume_temporary_allocation ();
8877 /* Make master area for local EQUIVALENCE. */
8879 #if FFECOM_targetCURRENT == FFECOM_targetGCC
8881 ffecom_transform_equiv_ (ffestorag eqst)
8887 bool is_init = ffestorag_is_init (eqst);
8890 assert (eqst != NULL);
8892 eqt = ffestorag_hook (eqst);
8894 if (eqt != NULL_TREE)
8897 /* Process inits. */
8901 if (ffestorag_init (eqst) != NULL)
8905 /* Set the padding for the expression, so ffecom_expr
8906 knows to insert that many zeros. */
8907 switch (ffebld_op (sexp = ffestorag_init (eqst)))
8909 case FFEBLD_opCONTER:
8910 ffebld_conter_set_pad (sexp, ffestorag_modulo (eqst));
8913 case FFEBLD_opARRTER:
8914 ffebld_arrter_set_pad (sexp, ffestorag_modulo (eqst));
8917 case FFEBLD_opACCTER:
8918 ffebld_accter_set_pad (sexp, ffestorag_modulo (eqst));
8922 assert ("bad op for eqv init (pad)" == NULL);
8926 init = ffecom_expr (sexp);
8927 if (init == error_mark_node)
8928 init = NULL_TREE; /* Hopefully the back end complained! */
8931 init = error_mark_node;
8933 else if (ffe_is_init_local_zero ())
8934 init = error_mark_node;
8938 ffecom_member_namelisted_ = FALSE;
8939 ffestorag_drive (ffestorag_list_equivs (eqst),
8940 &ffecom_member_phase1_,
8943 yes = suspend_momentary ();
8945 high = build_int_2 ((ffestorag_size (eqst)
8946 + ffestorag_modulo (eqst)) - 1, 0);
8947 TREE_TYPE (high) = ffecom_integer_type_node;
8949 eqtype = build_array_type (char_type_node,
8950 build_range_type (ffecom_integer_type_node,
8951 ffecom_integer_zero_node,
8954 eqt = build_decl (VAR_DECL,
8955 ffecom_get_invented_identifier ("__g77_equiv_%s",
8961 DECL_EXTERNAL (eqt) = 0;
8963 || ffecom_member_namelisted_
8964 #ifdef FFECOM_sizeMAXSTACKITEM
8965 || (ffestorag_size (eqst) > FFECOM_sizeMAXSTACKITEM)
8967 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
8968 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
8969 && (ffestorag_is_save (eqst) || ffe_is_saveall ())))
8970 TREE_STATIC (eqt) = 1;
8972 TREE_STATIC (eqt) = 0;
8973 TREE_PUBLIC (eqt) = 0;
8974 DECL_CONTEXT (eqt) = current_function_decl;
8976 DECL_INITIAL (eqt) = error_mark_node;
8978 DECL_INITIAL (eqt) = NULL_TREE;
8980 eqt = start_decl (eqt, FALSE);
8982 /* Make sure that any type can live in EQUIVALENCE and be referenced
8983 without getting a bus error. We could pick the most restrictive
8984 alignment of all entities actually placed in the EQUIVALENCE, but
8985 this seems easy enough. */
8987 DECL_ALIGN (eqt) = BIGGEST_ALIGNMENT;
8989 if ((!is_init && ffe_is_init_local_zero ())
8990 || (is_init && (ffestorag_init (eqst) == NULL)))
8991 init = ffecom_init_zero_ (eqt);
8993 finish_decl (eqt, init, FALSE);
8996 ffestorag_set_init (eqst, ffebld_new_any ());
9001 size_tree = size_binop (CEIL_DIV_EXPR,
9003 size_int (BITS_PER_UNIT));
9004 assert (TREE_INT_CST_HIGH (size_tree) == 0);
9005 assert (TREE_INT_CST_LOW (size_tree)
9006 == ffestorag_size (eqst) + ffestorag_modulo (eqst));
9009 ffestorag_set_hook (eqst, eqt);
9011 #ifdef SOMEONE_GETS_DEBUG_SUPPORT_WORKING
9012 ffestorag_drive (ffestorag_list_equivs (eqst),
9013 &ffecom_member_phase2_,
9017 resume_momentary (yes);
9021 /* Implement NAMELIST in back end. See f2c/format.c for more info. */
9023 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9025 ffecom_transform_namelist_ (ffesymbol s)
9028 tree nmltype = ffecom_type_namelist_ ();
9037 static int mynumber = 0;
9039 yes = suspend_momentary ();
9041 nmlt = build_decl (VAR_DECL,
9042 ffecom_get_invented_identifier ("__g77_namelist_%d",
9045 TREE_STATIC (nmlt) = 1;
9046 DECL_INITIAL (nmlt) = error_mark_node;
9048 nmlt = start_decl (nmlt, FALSE);
9050 /* Process inits. */
9052 i = strlen (ffesymbol_text (s));
9054 high = build_int_2 (i, 0);
9055 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
9057 nameinit = ffecom_build_f2c_string_ (i + 1,
9058 ffesymbol_text (s));
9059 TREE_TYPE (nameinit)
9060 = build_type_variant
9063 build_range_type (ffecom_f2c_ftnlen_type_node,
9064 ffecom_f2c_ftnlen_one_node,
9067 TREE_CONSTANT (nameinit) = 1;
9068 TREE_STATIC (nameinit) = 1;
9069 nameinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (nameinit)),
9072 varsinit = ffecom_vardesc_array_ (s);
9073 varsinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (varsinit)),
9075 TREE_CONSTANT (varsinit) = 1;
9076 TREE_STATIC (varsinit) = 1;
9081 for (i = 0, b = ffesymbol_namelist (s); b != NULL; b = ffebld_trail (b))
9084 nvarsinit = build_int_2 (i, 0);
9085 TREE_TYPE (nvarsinit) = integer_type_node;
9086 TREE_CONSTANT (nvarsinit) = 1;
9087 TREE_STATIC (nvarsinit) = 1;
9089 nmlinits = build_tree_list ((field = TYPE_FIELDS (nmltype)), nameinit);
9090 TREE_CHAIN (nmlinits) = build_tree_list ((field = TREE_CHAIN (field)),
9092 TREE_CHAIN (TREE_CHAIN (nmlinits))
9093 = build_tree_list ((field = TREE_CHAIN (field)), nvarsinit);
9095 nmlinits = build (CONSTRUCTOR, nmltype, NULL_TREE, nmlinits);
9096 TREE_CONSTANT (nmlinits) = 1;
9097 TREE_STATIC (nmlinits) = 1;
9099 finish_decl (nmlt, nmlinits, FALSE);
9101 nmlt = ffecom_1 (ADDR_EXPR, build_pointer_type (nmltype), nmlt);
9103 resume_momentary (yes);
9110 /* A subroutine of ffecom_tree_canonize_ref_. The incoming tree is
9111 analyzed on the assumption it is calculating a pointer to be
9112 indirected through. It must return the proper decl and offset,
9113 taking into account different units of measurements for offsets. */
9115 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9117 ffecom_tree_canonize_ptr_ (tree *decl, tree *offset,
9120 switch (TREE_CODE (t))
9124 case NON_LVALUE_EXPR:
9125 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
9129 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
9130 if ((*decl == NULL_TREE)
9131 || (*decl == error_mark_node))
9134 if (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST)
9136 /* An offset into COMMON. */
9137 *offset = size_binop (PLUS_EXPR,
9139 TREE_OPERAND (t, 1));
9140 /* Convert offset (presumably in bytes) into canonical units
9141 (presumably bits). */
9142 *offset = size_binop (MULT_EXPR,
9143 TYPE_SIZE (TREE_TYPE (TREE_TYPE (t))),
9147 /* Not a COMMON reference, so an unrecognized pattern. */
9148 *decl = error_mark_node;
9153 *offset = bitsize_int (0L, 0L);
9157 if (TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL)
9159 /* A reference to COMMON. */
9160 *decl = TREE_OPERAND (t, 0);
9161 *offset = bitsize_int (0L, 0L);
9166 /* Not a COMMON reference, so an unrecognized pattern. */
9167 *decl = error_mark_node;
9173 /* Given a tree that is possibly intended for use as an lvalue, return
9174 information representing a canonical view of that tree as a decl, an
9175 offset into that decl, and a size for the lvalue.
9177 If there's no applicable decl, NULL_TREE is returned for the decl,
9178 and the other fields are left undefined.
9180 If the tree doesn't fit the recognizable forms, an ERROR_MARK node
9181 is returned for the decl, and the other fields are left undefined.
9183 Otherwise, the decl returned currently is either a VAR_DECL or a
9186 The offset returned is always valid, but of course not necessarily
9187 a constant, and not necessarily converted into the appropriate
9188 type, leaving that up to the caller (so as to avoid that overhead
9189 if the decls being looked at are different anyway).
9191 If the size cannot be determined (e.g. an adjustable array),
9192 an ERROR_MARK node is returned for the size. Otherwise, the
9193 size returned is valid, not necessarily a constant, and not
9194 necessarily converted into the appropriate type as with the
9197 Note that the offset and size expressions are expressed in the
9198 base storage units (usually bits) rather than in the units of
9199 the type of the decl, because two decls with different types
9200 might overlap but with apparently non-overlapping array offsets,
9201 whereas converting the array offsets to consistant offsets will
9202 reveal the overlap. */
9204 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9206 ffecom_tree_canonize_ref_ (tree *decl, tree *offset,
9209 /* The default path is to report a nonexistant decl. */
9215 switch (TREE_CODE (t))
9218 case IDENTIFIER_NODE:
9227 case TRUNC_DIV_EXPR:
9229 case FLOOR_DIV_EXPR:
9230 case ROUND_DIV_EXPR:
9231 case TRUNC_MOD_EXPR:
9233 case FLOOR_MOD_EXPR:
9234 case ROUND_MOD_EXPR:
9236 case EXACT_DIV_EXPR:
9237 case FIX_TRUNC_EXPR:
9239 case FIX_FLOOR_EXPR:
9240 case FIX_ROUND_EXPR:
9255 case BIT_ANDTC_EXPR:
9257 case TRUTH_ANDIF_EXPR:
9258 case TRUTH_ORIF_EXPR:
9259 case TRUTH_AND_EXPR:
9261 case TRUTH_XOR_EXPR:
9262 case TRUTH_NOT_EXPR:
9282 *offset = bitsize_int (0L, 0L);
9283 *size = TYPE_SIZE (TREE_TYPE (t));
9288 tree array = TREE_OPERAND (t, 0);
9289 tree element = TREE_OPERAND (t, 1);
9292 if ((array == NULL_TREE)
9293 || (element == NULL_TREE))
9295 *decl = error_mark_node;
9299 ffecom_tree_canonize_ref_ (decl, &init_offset, size,
9301 if ((*decl == NULL_TREE)
9302 || (*decl == error_mark_node))
9305 *offset = size_binop (MULT_EXPR,
9306 TYPE_SIZE (TREE_TYPE (TREE_TYPE (array))),
9307 size_binop (MINUS_EXPR,
9311 (TREE_TYPE (array)))));
9313 *offset = size_binop (PLUS_EXPR,
9317 *size = TYPE_SIZE (TREE_TYPE (t));
9323 /* Most of this code is to handle references to COMMON. And so
9324 far that is useful only for calling library functions, since
9325 external (user) functions might reference common areas. But
9326 even calling an external function, it's worthwhile to decode
9327 COMMON references because if not storing into COMMON, we don't
9328 want COMMON-based arguments to gratuitously force use of a
9331 *size = TYPE_SIZE (TREE_TYPE (t));
9333 ffecom_tree_canonize_ptr_ (decl, offset,
9334 TREE_OPERAND (t, 0));
9341 case NON_LVALUE_EXPR:
9344 case COND_EXPR: /* More cases than we can handle. */
9346 case REFERENCE_EXPR:
9347 case PREDECREMENT_EXPR:
9348 case PREINCREMENT_EXPR:
9349 case POSTDECREMENT_EXPR:
9350 case POSTINCREMENT_EXPR:
9353 *decl = error_mark_node;
9359 /* Do divide operation appropriate to type of operands. */
9361 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9363 ffecom_tree_divide_ (tree tree_type, tree left, tree right,
9364 tree dest_tree, ffebld dest, bool *dest_used,
9367 if ((left == error_mark_node)
9368 || (right == error_mark_node))
9369 return error_mark_node;
9371 switch (TREE_CODE (tree_type))
9374 return ffecom_2 (TRUNC_DIV_EXPR, tree_type,
9379 if (! optimize_size)
9380 return ffecom_2 (RDIV_EXPR, tree_type,
9386 if (TREE_TYPE (tree_type)
9387 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9388 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */
9390 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */
9392 left = ffecom_1 (ADDR_EXPR,
9393 build_pointer_type (TREE_TYPE (left)),
9395 left = build_tree_list (NULL_TREE, left);
9396 right = ffecom_1 (ADDR_EXPR,
9397 build_pointer_type (TREE_TYPE (right)),
9399 right = build_tree_list (NULL_TREE, right);
9400 TREE_CHAIN (left) = right;
9402 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9403 ffecom_gfrt_kindtype (ix),
9404 ffe_is_f2c_library (),
9407 dest_tree, dest, dest_used,
9408 NULL_TREE, TRUE, hook);
9416 if (TREE_TYPE (TYPE_FIELDS (tree_type))
9417 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9418 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */
9420 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */
9422 left = ffecom_1 (ADDR_EXPR,
9423 build_pointer_type (TREE_TYPE (left)),
9425 left = build_tree_list (NULL_TREE, left);
9426 right = ffecom_1 (ADDR_EXPR,
9427 build_pointer_type (TREE_TYPE (right)),
9429 right = build_tree_list (NULL_TREE, right);
9430 TREE_CHAIN (left) = right;
9432 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9433 ffecom_gfrt_kindtype (ix),
9434 ffe_is_f2c_library (),
9437 dest_tree, dest, dest_used,
9438 NULL_TREE, TRUE, hook);
9443 return ffecom_2 (RDIV_EXPR, tree_type,
9450 /* Build type info for non-dummy variable. */
9452 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9454 ffecom_type_localvar_ (ffesymbol s, ffeinfoBasictype bt,
9463 type = ffecom_tree_type[bt][kt];
9464 if (bt == FFEINFO_basictypeCHARACTER)
9466 hight = build_int_2 (ffesymbol_size (s), 0);
9467 TREE_TYPE (hight) = ffecom_f2c_ftnlen_type_node;
9472 build_range_type (ffecom_f2c_ftnlen_type_node,
9473 ffecom_f2c_ftnlen_one_node,
9475 type = ffecom_check_size_overflow_ (s, type, FALSE);
9478 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
9480 if (type == error_mark_node)
9483 dim = ffebld_head (dl);
9484 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
9486 if (ffebld_left (dim) == NULL)
9487 lowt = integer_one_node;
9489 lowt = ffecom_expr (ffebld_left (dim));
9491 if (TREE_CODE (lowt) != INTEGER_CST)
9492 lowt = variable_size (lowt);
9494 assert (ffebld_right (dim) != NULL);
9495 hight = ffecom_expr (ffebld_right (dim));
9497 if (TREE_CODE (hight) != INTEGER_CST)
9498 hight = variable_size (hight);
9500 type = build_array_type (type,
9501 build_range_type (ffecom_integer_type_node,
9503 type = ffecom_check_size_overflow_ (s, type, FALSE);
9510 /* Build Namelist type. */
9512 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9514 ffecom_type_namelist_ ()
9516 static tree type = NULL_TREE;
9518 if (type == NULL_TREE)
9520 static tree namefield, varsfield, nvarsfield;
9523 vardesctype = ffecom_type_vardesc_ ();
9525 push_obstacks_nochange ();
9526 end_temporary_allocation ();
9528 type = make_node (RECORD_TYPE);
9530 vardesctype = build_pointer_type (build_pointer_type (vardesctype));
9532 namefield = ffecom_decl_field (type, NULL_TREE, "name",
9534 varsfield = ffecom_decl_field (type, namefield, "vars", vardesctype);
9535 nvarsfield = ffecom_decl_field (type, varsfield, "nvars",
9538 TYPE_FIELDS (type) = namefield;
9541 resume_temporary_allocation ();
9550 /* Make a copy of a type, assuming caller has switched to the permanent
9551 obstacks and that the type is for an aggregate (array) initializer. */
9553 #if FFECOM_targetCURRENT == FFECOM_targetGCC && 0 /* Not used now. */
9555 ffecom_type_permanent_copy_ (tree t)
9560 assert (TREE_TYPE (t) != NULL_TREE);
9562 domain = TYPE_DOMAIN (t);
9564 assert (TREE_CODE (t) == ARRAY_TYPE);
9565 assert (TREE_PERMANENT (TREE_TYPE (t)));
9566 assert (TREE_PERMANENT (TREE_TYPE (domain)));
9567 assert (TREE_PERMANENT (TYPE_MIN_VALUE (domain)));
9569 max = TYPE_MAX_VALUE (domain);
9570 if (!TREE_PERMANENT (max))
9572 assert (TREE_CODE (max) == INTEGER_CST);
9574 max = build_int_2 (TREE_INT_CST_LOW (max), TREE_INT_CST_HIGH (max));
9575 TREE_TYPE (max) = TREE_TYPE (TYPE_MIN_VALUE (domain));
9578 return build_array_type (TREE_TYPE (t),
9579 build_range_type (TREE_TYPE (domain),
9580 TYPE_MIN_VALUE (domain),
9585 /* Build Vardesc type. */
9587 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9589 ffecom_type_vardesc_ ()
9591 static tree type = NULL_TREE;
9592 static tree namefield, addrfield, dimsfield, typefield;
9594 if (type == NULL_TREE)
9596 push_obstacks_nochange ();
9597 end_temporary_allocation ();
9599 type = make_node (RECORD_TYPE);
9601 namefield = ffecom_decl_field (type, NULL_TREE, "name",
9603 addrfield = ffecom_decl_field (type, namefield, "addr",
9605 dimsfield = ffecom_decl_field (type, addrfield, "dims",
9606 ffecom_f2c_ptr_to_ftnlen_type_node);
9607 typefield = ffecom_decl_field (type, dimsfield, "type",
9610 TYPE_FIELDS (type) = namefield;
9613 resume_temporary_allocation ();
9622 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9624 ffecom_vardesc_ (ffebld expr)
9628 assert (ffebld_op (expr) == FFEBLD_opSYMTER);
9629 s = ffebld_symter (expr);
9631 if (ffesymbol_hook (s).vardesc_tree == NULL_TREE)
9634 tree vardesctype = ffecom_type_vardesc_ ();
9643 static int mynumber = 0;
9645 yes = suspend_momentary ();
9647 var = build_decl (VAR_DECL,
9648 ffecom_get_invented_identifier ("__g77_vardesc_%d",
9651 TREE_STATIC (var) = 1;
9652 DECL_INITIAL (var) = error_mark_node;
9654 var = start_decl (var, FALSE);
9656 /* Process inits. */
9658 nameinit = ffecom_build_f2c_string_ ((i = strlen (ffesymbol_text (s)))
9660 ffesymbol_text (s));
9661 TREE_TYPE (nameinit)
9662 = build_type_variant
9665 build_range_type (integer_type_node,
9667 build_int_2 (i, 0))),
9669 TREE_CONSTANT (nameinit) = 1;
9670 TREE_STATIC (nameinit) = 1;
9671 nameinit = ffecom_1 (ADDR_EXPR,
9672 build_pointer_type (TREE_TYPE (nameinit)),
9675 addrinit = ffecom_arg_ptr_to_expr (expr, &typeinit);
9677 dimsinit = ffecom_vardesc_dims_ (s);
9679 if (typeinit == NULL_TREE)
9681 ffeinfoBasictype bt = ffesymbol_basictype (s);
9682 ffeinfoKindtype kt = ffesymbol_kindtype (s);
9683 int tc = ffecom_f2c_typecode (bt, kt);
9686 typeinit = build_int_2 (tc, (tc < 0) ? -1 : 0);
9689 typeinit = ffecom_1 (NEGATE_EXPR, TREE_TYPE (typeinit), typeinit);
9691 varinits = build_tree_list ((field = TYPE_FIELDS (vardesctype)),
9693 TREE_CHAIN (varinits) = build_tree_list ((field = TREE_CHAIN (field)),
9695 TREE_CHAIN (TREE_CHAIN (varinits))
9696 = build_tree_list ((field = TREE_CHAIN (field)), dimsinit);
9697 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (varinits)))
9698 = build_tree_list ((field = TREE_CHAIN (field)), typeinit);
9700 varinits = build (CONSTRUCTOR, vardesctype, NULL_TREE, varinits);
9701 TREE_CONSTANT (varinits) = 1;
9702 TREE_STATIC (varinits) = 1;
9704 finish_decl (var, varinits, FALSE);
9706 var = ffecom_1 (ADDR_EXPR, build_pointer_type (vardesctype), var);
9708 resume_momentary (yes);
9710 ffesymbol_hook (s).vardesc_tree = var;
9713 return ffesymbol_hook (s).vardesc_tree;
9717 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9719 ffecom_vardesc_array_ (ffesymbol s)
9723 tree item = NULL_TREE;
9727 static int mynumber = 0;
9729 for (i = 0, list = NULL_TREE, b = ffesymbol_namelist (s);
9731 b = ffebld_trail (b), ++i)
9735 t = ffecom_vardesc_ (ffebld_head (b));
9737 if (list == NULL_TREE)
9738 list = item = build_tree_list (NULL_TREE, t);
9741 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
9742 item = TREE_CHAIN (item);
9746 yes = suspend_momentary ();
9748 item = build_array_type (build_pointer_type (ffecom_type_vardesc_ ()),
9749 build_range_type (integer_type_node,
9751 build_int_2 (i, 0)));
9752 list = build (CONSTRUCTOR, item, NULL_TREE, list);
9753 TREE_CONSTANT (list) = 1;
9754 TREE_STATIC (list) = 1;
9756 var = ffecom_get_invented_identifier ("__g77_vardesc_array_%d", NULL,
9758 var = build_decl (VAR_DECL, var, item);
9759 TREE_STATIC (var) = 1;
9760 DECL_INITIAL (var) = error_mark_node;
9761 var = start_decl (var, FALSE);
9762 finish_decl (var, list, FALSE);
9764 resume_momentary (yes);
9770 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9772 ffecom_vardesc_dims_ (ffesymbol s)
9774 if (ffesymbol_dims (s) == NULL)
9775 return convert (ffecom_f2c_ptr_to_ftnlen_type_node,
9783 tree item = NULL_TREE;
9788 tree baseoff = NULL_TREE;
9789 static int mynumber = 0;
9791 numdim = build_int_2 ((int) ffesymbol_rank (s), 0);
9792 TREE_TYPE (numdim) = ffecom_f2c_ftnlen_type_node;
9794 numelem = ffecom_expr (ffesymbol_arraysize (s));
9795 TREE_TYPE (numelem) = ffecom_f2c_ftnlen_type_node;
9798 backlist = NULL_TREE;
9799 for (b = ffesymbol_dims (s), e = ffesymbol_extents (s);
9801 b = ffebld_trail (b), e = ffebld_trail (e))
9807 if (ffebld_trail (b) == NULL)
9811 t = convert (ffecom_f2c_ftnlen_type_node,
9812 ffecom_expr (ffebld_head (e)));
9814 if (list == NULL_TREE)
9815 list = item = build_tree_list (NULL_TREE, t);
9818 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
9819 item = TREE_CHAIN (item);
9823 if (ffebld_left (ffebld_head (b)) == NULL)
9824 low = ffecom_integer_one_node;
9826 low = ffecom_expr (ffebld_left (ffebld_head (b)));
9827 low = convert (ffecom_f2c_ftnlen_type_node, low);
9829 back = build_tree_list (low, t);
9830 TREE_CHAIN (back) = backlist;
9834 for (item = backlist; item != NULL_TREE; item = TREE_CHAIN (item))
9836 if (TREE_VALUE (item) == NULL_TREE)
9837 baseoff = TREE_PURPOSE (item);
9839 baseoff = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
9840 TREE_PURPOSE (item),
9841 ffecom_2 (MULT_EXPR,
9842 ffecom_f2c_ftnlen_type_node,
9847 /* backlist now dead, along with all TREE_PURPOSEs on it. */
9849 baseoff = build_tree_list (NULL_TREE, baseoff);
9850 TREE_CHAIN (baseoff) = list;
9852 numelem = build_tree_list (NULL_TREE, numelem);
9853 TREE_CHAIN (numelem) = baseoff;
9855 numdim = build_tree_list (NULL_TREE, numdim);
9856 TREE_CHAIN (numdim) = numelem;
9858 yes = suspend_momentary ();
9860 item = build_array_type (ffecom_f2c_ftnlen_type_node,
9861 build_range_type (integer_type_node,
9864 ((int) ffesymbol_rank (s)
9866 list = build (CONSTRUCTOR, item, NULL_TREE, numdim);
9867 TREE_CONSTANT (list) = 1;
9868 TREE_STATIC (list) = 1;
9870 var = ffecom_get_invented_identifier ("__g77_dims_%d", NULL,
9872 var = build_decl (VAR_DECL, var, item);
9873 TREE_STATIC (var) = 1;
9874 DECL_INITIAL (var) = error_mark_node;
9875 var = start_decl (var, FALSE);
9876 finish_decl (var, list, FALSE);
9878 var = ffecom_1 (ADDR_EXPR, build_pointer_type (item), var);
9880 resume_momentary (yes);
9887 /* Essentially does a "fold (build1 (code, type, node))" while checking
9888 for certain housekeeping things.
9890 NOTE: for building an ADDR_EXPR around a FUNCTION_DECL, use
9891 ffecom_1_fn instead. */
9893 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9895 ffecom_1 (enum tree_code code, tree type, tree node)
9899 if ((node == error_mark_node)
9900 || (type == error_mark_node))
9901 return error_mark_node;
9903 if (code == ADDR_EXPR)
9905 if (!mark_addressable (node))
9906 assert ("can't mark_addressable this node!" == NULL);
9909 switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
9914 item = build (COMPONENT_REF, type, node, TYPE_FIELDS (TREE_TYPE (node)));
9918 item = build (COMPONENT_REF, type, node, TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (node))));
9923 if (TREE_CODE (type) != RECORD_TYPE)
9925 item = build1 (code, type, node);
9928 node = ffecom_stabilize_aggregate_ (node);
9929 realtype = TREE_TYPE (TYPE_FIELDS (type));
9931 ffecom_2 (COMPLEX_EXPR, type,
9932 ffecom_1 (NEGATE_EXPR, realtype,
9933 ffecom_1 (REALPART_EXPR, realtype,
9935 ffecom_1 (NEGATE_EXPR, realtype,
9936 ffecom_1 (IMAGPART_EXPR, realtype,
9941 item = build1 (code, type, node);
9945 if (TREE_SIDE_EFFECTS (node))
9946 TREE_SIDE_EFFECTS (item) = 1;
9947 if ((code == ADDR_EXPR) && staticp (node))
9948 TREE_CONSTANT (item) = 1;
9953 /* Like ffecom_1 (ADDR_EXPR, TREE_TYPE (node), node), except
9954 handles TREE_CODE (node) == FUNCTION_DECL. In particular,
9955 does not set TREE_ADDRESSABLE (because calling an inline
9956 function does not mean the function needs to be separately
9959 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9961 ffecom_1_fn (tree node)
9966 if (node == error_mark_node)
9967 return error_mark_node;
9969 type = build_type_variant (TREE_TYPE (node),
9970 TREE_READONLY (node),
9971 TREE_THIS_VOLATILE (node));
9972 item = build1 (ADDR_EXPR,
9973 build_pointer_type (type), node);
9974 if (TREE_SIDE_EFFECTS (node))
9975 TREE_SIDE_EFFECTS (item) = 1;
9977 TREE_CONSTANT (item) = 1;
9982 /* Essentially does a "fold (build (code, type, node1, node2))" while
9983 checking for certain housekeeping things. */
9985 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9987 ffecom_2 (enum tree_code code, tree type, tree node1,
9992 if ((node1 == error_mark_node)
9993 || (node2 == error_mark_node)
9994 || (type == error_mark_node))
9995 return error_mark_node;
9997 switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
9999 tree a, b, c, d, realtype;
10002 assert ("no CONJ_EXPR support yet" == NULL);
10003 return error_mark_node;
10006 item = build_tree_list (TYPE_FIELDS (type), node1);
10007 TREE_CHAIN (item) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), node2);
10008 item = build (CONSTRUCTOR, type, NULL_TREE, item);
10012 if (TREE_CODE (type) != RECORD_TYPE)
10014 item = build (code, type, node1, node2);
10017 node1 = ffecom_stabilize_aggregate_ (node1);
10018 node2 = ffecom_stabilize_aggregate_ (node2);
10019 realtype = TREE_TYPE (TYPE_FIELDS (type));
10021 ffecom_2 (COMPLEX_EXPR, type,
10022 ffecom_2 (PLUS_EXPR, realtype,
10023 ffecom_1 (REALPART_EXPR, realtype,
10025 ffecom_1 (REALPART_EXPR, realtype,
10027 ffecom_2 (PLUS_EXPR, realtype,
10028 ffecom_1 (IMAGPART_EXPR, realtype,
10030 ffecom_1 (IMAGPART_EXPR, realtype,
10035 if (TREE_CODE (type) != RECORD_TYPE)
10037 item = build (code, type, node1, node2);
10040 node1 = ffecom_stabilize_aggregate_ (node1);
10041 node2 = ffecom_stabilize_aggregate_ (node2);
10042 realtype = TREE_TYPE (TYPE_FIELDS (type));
10044 ffecom_2 (COMPLEX_EXPR, type,
10045 ffecom_2 (MINUS_EXPR, realtype,
10046 ffecom_1 (REALPART_EXPR, realtype,
10048 ffecom_1 (REALPART_EXPR, realtype,
10050 ffecom_2 (MINUS_EXPR, realtype,
10051 ffecom_1 (IMAGPART_EXPR, realtype,
10053 ffecom_1 (IMAGPART_EXPR, realtype,
10058 if (TREE_CODE (type) != RECORD_TYPE)
10060 item = build (code, type, node1, node2);
10063 node1 = ffecom_stabilize_aggregate_ (node1);
10064 node2 = ffecom_stabilize_aggregate_ (node2);
10065 realtype = TREE_TYPE (TYPE_FIELDS (type));
10066 a = save_expr (ffecom_1 (REALPART_EXPR, realtype,
10068 b = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
10070 c = save_expr (ffecom_1 (REALPART_EXPR, realtype,
10072 d = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
10075 ffecom_2 (COMPLEX_EXPR, type,
10076 ffecom_2 (MINUS_EXPR, realtype,
10077 ffecom_2 (MULT_EXPR, realtype,
10080 ffecom_2 (MULT_EXPR, realtype,
10083 ffecom_2 (PLUS_EXPR, realtype,
10084 ffecom_2 (MULT_EXPR, realtype,
10087 ffecom_2 (MULT_EXPR, realtype,
10093 if ((TREE_CODE (node1) != RECORD_TYPE)
10094 && (TREE_CODE (node2) != RECORD_TYPE))
10096 item = build (code, type, node1, node2);
10099 assert (TREE_CODE (node1) == RECORD_TYPE);
10100 assert (TREE_CODE (node2) == RECORD_TYPE);
10101 node1 = ffecom_stabilize_aggregate_ (node1);
10102 node2 = ffecom_stabilize_aggregate_ (node2);
10103 realtype = TREE_TYPE (TYPE_FIELDS (type));
10105 ffecom_2 (TRUTH_ANDIF_EXPR, type,
10106 ffecom_2 (code, type,
10107 ffecom_1 (REALPART_EXPR, realtype,
10109 ffecom_1 (REALPART_EXPR, realtype,
10111 ffecom_2 (code, type,
10112 ffecom_1 (IMAGPART_EXPR, realtype,
10114 ffecom_1 (IMAGPART_EXPR, realtype,
10119 if ((TREE_CODE (node1) != RECORD_TYPE)
10120 && (TREE_CODE (node2) != RECORD_TYPE))
10122 item = build (code, type, node1, node2);
10125 assert (TREE_CODE (node1) == RECORD_TYPE);
10126 assert (TREE_CODE (node2) == RECORD_TYPE);
10127 node1 = ffecom_stabilize_aggregate_ (node1);
10128 node2 = ffecom_stabilize_aggregate_ (node2);
10129 realtype = TREE_TYPE (TYPE_FIELDS (type));
10131 ffecom_2 (TRUTH_ORIF_EXPR, type,
10132 ffecom_2 (code, type,
10133 ffecom_1 (REALPART_EXPR, realtype,
10135 ffecom_1 (REALPART_EXPR, realtype,
10137 ffecom_2 (code, type,
10138 ffecom_1 (IMAGPART_EXPR, realtype,
10140 ffecom_1 (IMAGPART_EXPR, realtype,
10145 item = build (code, type, node1, node2);
10149 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2))
10150 TREE_SIDE_EFFECTS (item) = 1;
10151 return fold (item);
10155 /* ffecom_2pass_advise_entrypoint -- Advise that there's this entrypoint
10157 ffesymbol s; // the ENTRY point itself
10158 if (ffecom_2pass_advise_entrypoint(s))
10159 // the ENTRY point has been accepted
10161 Does whatever compiler needs to do when it learns about the entrypoint,
10162 like determine the return type of the master function, count the
10163 number of entrypoints, etc. Returns FALSE if the return type is
10164 not compatible with the return type(s) of other entrypoint(s).
10166 NOTE: for every call to this fn that returns TRUE, _do_entrypoint must
10167 later (after _finish_progunit) be called with the same entrypoint(s)
10168 as passed to this fn for which TRUE was returned.
10171 Return FALSE if the return type conflicts with previous entrypoints. */
10173 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10175 ffecom_2pass_advise_entrypoint (ffesymbol entry)
10177 ffebld list; /* opITEM. */
10178 ffebld mlist; /* opITEM. */
10179 ffebld plist; /* opITEM. */
10180 ffebld arg; /* ffebld_head(opITEM). */
10181 ffebld item; /* opITEM. */
10182 ffesymbol s; /* ffebld_symter(arg). */
10183 ffeinfoBasictype bt = ffesymbol_basictype (entry);
10184 ffeinfoKindtype kt = ffesymbol_kindtype (entry);
10185 ffetargetCharacterSize size = ffesymbol_size (entry);
10188 if (ffecom_num_entrypoints_ == 0)
10189 { /* First entrypoint, make list of main
10190 arglist's dummies. */
10191 assert (ffecom_primary_entry_ != NULL);
10193 ffecom_master_bt_ = ffesymbol_basictype (ffecom_primary_entry_);
10194 ffecom_master_kt_ = ffesymbol_kindtype (ffecom_primary_entry_);
10195 ffecom_master_size_ = ffesymbol_size (ffecom_primary_entry_);
10197 for (plist = NULL, list = ffesymbol_dummyargs (ffecom_primary_entry_);
10199 list = ffebld_trail (list))
10201 arg = ffebld_head (list);
10202 if (ffebld_op (arg) != FFEBLD_opSYMTER)
10203 continue; /* Alternate return or some such thing. */
10204 item = ffebld_new_item (arg, NULL);
10206 ffecom_master_arglist_ = item;
10208 ffebld_set_trail (plist, item);
10213 /* If necessary, scan entry arglist for alternate returns. Do this scan
10214 apparently redundantly (it's done below to UNIONize the arglists) so
10215 that we don't complain about RETURN 1 if an offending ENTRY is the only
10216 one with an alternate return. */
10218 if (!ffecom_is_altreturning_)
10220 for (list = ffesymbol_dummyargs (entry);
10222 list = ffebld_trail (list))
10224 arg = ffebld_head (list);
10225 if (ffebld_op (arg) == FFEBLD_opSTAR)
10227 ffecom_is_altreturning_ = TRUE;
10233 /* Now check type compatibility. */
10235 switch (ffecom_master_bt_)
10237 case FFEINFO_basictypeNONE:
10238 ok = (bt != FFEINFO_basictypeCHARACTER);
10241 case FFEINFO_basictypeCHARACTER:
10243 = (bt == FFEINFO_basictypeCHARACTER)
10244 && (kt == ffecom_master_kt_)
10245 && (size == ffecom_master_size_);
10248 case FFEINFO_basictypeANY:
10249 return FALSE; /* Just don't bother. */
10252 if (bt == FFEINFO_basictypeCHARACTER)
10258 if ((bt != ffecom_master_bt_) || (kt != ffecom_master_kt_))
10260 ffecom_master_bt_ = FFEINFO_basictypeNONE;
10261 ffecom_master_kt_ = FFEINFO_kindtypeNONE;
10268 ffebad_start (FFEBAD_ENTRY_CONFLICTS);
10269 ffest_ffebad_here_current_stmt (0);
10271 return FALSE; /* Can't handle entrypoint. */
10274 /* Entrypoint type compatible with previous types. */
10276 ++ffecom_num_entrypoints_;
10278 /* Master-arg-list = UNION(Master-arg-list,entry-arg-list). */
10280 for (list = ffesymbol_dummyargs (entry);
10282 list = ffebld_trail (list))
10284 arg = ffebld_head (list);
10285 if (ffebld_op (arg) != FFEBLD_opSYMTER)
10286 continue; /* Alternate return or some such thing. */
10287 s = ffebld_symter (arg);
10288 for (plist = NULL, mlist = ffecom_master_arglist_;
10290 plist = mlist, mlist = ffebld_trail (mlist))
10291 { /* plist points to previous item for easy
10292 appending of arg. */
10293 if (ffebld_symter (ffebld_head (mlist)) == s)
10294 break; /* Already have this arg in the master list. */
10297 continue; /* Already have this arg in the master list. */
10299 /* Append this arg to the master list. */
10301 item = ffebld_new_item (arg, NULL);
10303 ffecom_master_arglist_ = item;
10305 ffebld_set_trail (plist, item);
10312 /* ffecom_2pass_do_entrypoint -- Do compilation of entrypoint
10314 ffesymbol s; // the ENTRY point itself
10315 ffecom_2pass_do_entrypoint(s);
10317 Does whatever compiler needs to do to make the entrypoint actually
10318 happen. Must be called for each entrypoint after
10319 ffecom_finish_progunit is called. */
10321 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10323 ffecom_2pass_do_entrypoint (ffesymbol entry)
10325 static int mfn_num = 0;
10326 static int ent_num;
10328 if (mfn_num != ffecom_num_fns_)
10329 { /* First entrypoint for this program unit. */
10331 mfn_num = ffecom_num_fns_;
10332 ffecom_do_entry_ (ffecom_primary_entry_, 0);
10337 --ffecom_num_entrypoints_;
10339 ffecom_do_entry_ (entry, ent_num);
10344 /* Essentially does a "fold (build (code, type, node1, node2))" while
10345 checking for certain housekeeping things. Always sets
10346 TREE_SIDE_EFFECTS. */
10348 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10350 ffecom_2s (enum tree_code code, tree type, tree node1,
10355 if ((node1 == error_mark_node)
10356 || (node2 == error_mark_node)
10357 || (type == error_mark_node))
10358 return error_mark_node;
10360 item = build (code, type, node1, node2);
10361 TREE_SIDE_EFFECTS (item) = 1;
10362 return fold (item);
10366 /* Essentially does a "fold (build (code, type, node1, node2, node3))" while
10367 checking for certain housekeeping things. */
10369 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10371 ffecom_3 (enum tree_code code, tree type, tree node1,
10372 tree node2, tree node3)
10376 if ((node1 == error_mark_node)
10377 || (node2 == error_mark_node)
10378 || (node3 == error_mark_node)
10379 || (type == error_mark_node))
10380 return error_mark_node;
10382 item = build (code, type, node1, node2, node3);
10383 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2)
10384 || (node3 != NULL_TREE && TREE_SIDE_EFFECTS (node3)))
10385 TREE_SIDE_EFFECTS (item) = 1;
10386 return fold (item);
10390 /* Essentially does a "fold (build (code, type, node1, node2, node3))" while
10391 checking for certain housekeeping things. Always sets
10392 TREE_SIDE_EFFECTS. */
10394 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10396 ffecom_3s (enum tree_code code, tree type, tree node1,
10397 tree node2, tree node3)
10401 if ((node1 == error_mark_node)
10402 || (node2 == error_mark_node)
10403 || (node3 == error_mark_node)
10404 || (type == error_mark_node))
10405 return error_mark_node;
10407 item = build (code, type, node1, node2, node3);
10408 TREE_SIDE_EFFECTS (item) = 1;
10409 return fold (item);
10414 /* ffecom_arg_expr -- Transform argument expr into gcc tree
10416 See use by ffecom_list_expr.
10418 If expression is NULL, returns an integer zero tree. If it is not
10419 a CHARACTER expression, returns whatever ffecom_expr
10420 returns and sets the length return value to NULL_TREE. Otherwise
10421 generates code to evaluate the character expression, returns the proper
10422 pointer to the result, but does NOT set the length return value to a tree
10423 that specifies the length of the result. (In other words, the length
10424 variable is always set to NULL_TREE, because a length is never passed.)
10427 Don't set returned length, since nobody needs it (yet; someday if
10428 we allow CHARACTER*(*) dummies to statement functions, we'll need
10431 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10433 ffecom_arg_expr (ffebld expr, tree *length)
10437 *length = NULL_TREE;
10440 return integer_zero_node;
10442 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10443 return ffecom_expr (expr);
10445 return ffecom_arg_ptr_to_expr (expr, &ign);
10449 /* Transform expression into constant argument-pointer-to-expression tree.
10451 If the expression can be transformed into a argument-pointer-to-expression
10452 tree that is constant, that is done, and the tree returned. Else
10453 NULL_TREE is returned.
10455 That way, a caller can attempt to provide compile-time initialization
10456 of a variable and, if that fails, *then* choose to start a new block
10457 and resort to using temporaries, as appropriate. */
10460 ffecom_arg_ptr_to_const_expr (ffebld expr, tree *length)
10463 return integer_zero_node;
10465 if (ffebld_op (expr) == FFEBLD_opANY)
10468 *length = error_mark_node;
10469 return error_mark_node;
10472 if (ffebld_arity (expr) == 0
10473 && (ffebld_op (expr) != FFEBLD_opSYMTER
10474 || ffebld_where (expr) == FFEINFO_whereCOMMON
10475 || ffebld_where (expr) == FFEINFO_whereGLOBAL
10476 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
10480 t = ffecom_arg_ptr_to_expr (expr, length);
10481 assert (TREE_CONSTANT (t));
10482 assert (! length || TREE_CONSTANT (*length));
10487 && ffebld_size (expr) != FFETARGET_charactersizeNONE)
10488 *length = build_int_2 (ffebld_size (expr), 0);
10490 *length = NULL_TREE;
10494 /* ffecom_arg_ptr_to_expr -- Transform argument expr into gcc tree
10496 See use by ffecom_list_ptr_to_expr.
10498 If expression is NULL, returns an integer zero tree. If it is not
10499 a CHARACTER expression, returns whatever ffecom_ptr_to_expr
10500 returns and sets the length return value to NULL_TREE. Otherwise
10501 generates code to evaluate the character expression, returns the proper
10502 pointer to the result, AND sets the length return value to a tree that
10503 specifies the length of the result.
10505 If the length argument is NULL, this is a slightly special
10506 case of building a FORMAT expression, that is, an expression that
10507 will be used at run time without regard to length. For the current
10508 implementation, which uses the libf2c library, this means it is nice
10509 to append a null byte to the end of the expression, where feasible,
10510 to make sure any diagnostic about the FORMAT string terminates at
10513 For now, treat %REF(char-expr) as the same as char-expr with a NULL
10514 length argument. This might even be seen as a feature, if a null
10515 byte can always be appended. */
10517 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10519 ffecom_arg_ptr_to_expr (ffebld expr, tree *length)
10523 ffecomConcatList_ catlist;
10525 if (length != NULL)
10526 *length = NULL_TREE;
10529 return integer_zero_node;
10531 switch (ffebld_op (expr))
10533 case FFEBLD_opPERCENT_VAL:
10534 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10535 return ffecom_expr (ffebld_left (expr));
10540 temp_exp = ffecom_arg_ptr_to_expr (ffebld_left (expr), &temp_length);
10541 if (temp_exp == error_mark_node)
10542 return error_mark_node;
10544 return ffecom_1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (temp_exp)),
10548 case FFEBLD_opPERCENT_REF:
10549 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10550 return ffecom_ptr_to_expr (ffebld_left (expr));
10551 if (length != NULL)
10553 ign_length = NULL_TREE;
10554 length = &ign_length;
10556 expr = ffebld_left (expr);
10559 case FFEBLD_opPERCENT_DESCR:
10560 switch (ffeinfo_basictype (ffebld_info (expr)))
10562 #ifdef PASS_HOLLERITH_BY_DESCRIPTOR
10563 case FFEINFO_basictypeHOLLERITH:
10565 case FFEINFO_basictypeCHARACTER:
10566 break; /* Passed by descriptor anyway. */
10569 item = ffecom_ptr_to_expr (expr);
10570 if (item != error_mark_node)
10571 *length = TYPE_SIZE (TREE_TYPE (TREE_TYPE (item)));
10580 #ifdef PASS_HOLLERITH_BY_DESCRIPTOR
10581 if ((ffeinfo_basictype (ffebld_info (expr)) == FFEINFO_basictypeHOLLERITH)
10582 && (length != NULL))
10583 { /* Pass Hollerith by descriptor. */
10584 ffetargetHollerith h;
10586 assert (ffebld_op (expr) == FFEBLD_opCONTER);
10587 h = ffebld_cu_val_hollerith (ffebld_constant_union
10588 (ffebld_conter (expr)));
10590 = build_int_2 (h.length, 0);
10591 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
10595 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10596 return ffecom_ptr_to_expr (expr);
10598 assert (ffeinfo_kindtype (ffebld_info (expr))
10599 == FFEINFO_kindtypeCHARACTER1);
10601 while (ffebld_op (expr) == FFEBLD_opPAREN)
10602 expr = ffebld_left (expr);
10604 catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
10605 switch (ffecom_concat_list_count_ (catlist))
10607 case 0: /* Shouldn't happen, but in case it does... */
10608 if (length != NULL)
10610 *length = ffecom_f2c_ftnlen_zero_node;
10611 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
10613 ffecom_concat_list_kill_ (catlist);
10614 return null_pointer_node;
10616 case 1: /* The (fairly) easy case. */
10617 if (length == NULL)
10618 ffecom_char_args_with_null_ (&item, &ign_length,
10619 ffecom_concat_list_expr_ (catlist, 0));
10621 ffecom_char_args_ (&item, length,
10622 ffecom_concat_list_expr_ (catlist, 0));
10623 ffecom_concat_list_kill_ (catlist);
10624 assert (item != NULL_TREE);
10627 default: /* Must actually concatenate things. */
10632 int count = ffecom_concat_list_count_ (catlist);
10643 ffetargetCharacterSize sz;
10645 sz = ffecom_concat_list_maxlen_ (catlist);
10647 assert (sz != FFETARGET_charactersizeNONE);
10652 = ffecom_push_tempvar (ffecom_f2c_ftnlen_type_node,
10653 FFETARGET_charactersizeNONE, count, TRUE);
10656 = ffecom_push_tempvar (ffecom_f2c_address_type_node,
10657 FFETARGET_charactersizeNONE, count, TRUE);
10658 temporary = ffecom_push_tempvar (char_type_node,
10664 hook = ffebld_nonter_hook (expr);
10666 assert (TREE_CODE (hook) == TREE_VEC);
10667 assert (TREE_VEC_LENGTH (hook) == 3);
10668 length_array = lengths = TREE_VEC_ELT (hook, 0);
10669 item_array = items = TREE_VEC_ELT (hook, 1);
10670 temporary = TREE_VEC_ELT (hook, 2);
10674 known_length = ffecom_f2c_ftnlen_zero_node;
10676 for (i = 0; i < count; ++i)
10679 && (length == NULL))
10680 ffecom_char_args_with_null_ (&citem, &clength,
10681 ffecom_concat_list_expr_ (catlist, i));
10683 ffecom_char_args_ (&citem, &clength,
10684 ffecom_concat_list_expr_ (catlist, i));
10685 if ((citem == error_mark_node)
10686 || (clength == error_mark_node))
10688 ffecom_concat_list_kill_ (catlist);
10689 *length = error_mark_node;
10690 return error_mark_node;
10694 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
10695 ffecom_modify (void_type_node,
10696 ffecom_2 (ARRAY_REF,
10697 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
10699 build_int_2 (i, 0)),
10702 clength = ffecom_save_tree (clength);
10703 if (length != NULL)
10705 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
10709 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
10710 ffecom_modify (void_type_node,
10711 ffecom_2 (ARRAY_REF,
10712 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
10714 build_int_2 (i, 0)),
10719 temporary = ffecom_1 (ADDR_EXPR,
10720 build_pointer_type (TREE_TYPE (temporary)),
10723 item = build_tree_list (NULL_TREE, temporary);
10725 = build_tree_list (NULL_TREE,
10726 ffecom_1 (ADDR_EXPR,
10727 build_pointer_type (TREE_TYPE (items)),
10729 TREE_CHAIN (TREE_CHAIN (item))
10730 = build_tree_list (NULL_TREE,
10731 ffecom_1 (ADDR_EXPR,
10732 build_pointer_type (TREE_TYPE (lengths)),
10734 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
10737 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
10738 convert (ffecom_f2c_ftnlen_type_node,
10739 build_int_2 (count, 0))));
10740 num = build_int_2 (sz, 0);
10741 TREE_TYPE (num) = ffecom_f2c_ftnlen_type_node;
10742 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item))))
10743 = build_tree_list (NULL_TREE, num);
10745 item = ffecom_call_gfrt (FFECOM_gfrtCAT, item, NULL_TREE);
10746 TREE_SIDE_EFFECTS (item) = 1;
10747 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (temporary),
10751 if (length != NULL)
10752 *length = known_length;
10755 ffecom_concat_list_kill_ (catlist);
10756 assert (item != NULL_TREE);
10761 /* Generate call to run-time function.
10763 The first arg is the GNU Fortran Run-Time function index, the second
10764 arg is the list of arguments to pass to it. Returned is the expression
10765 (WITHOUT TREE_SIDE_EFFECTS set!) that makes the call and returns the
10766 result (which may be void). */
10768 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10770 ffecom_call_gfrt (ffecomGfrt ix, tree args, tree hook)
10772 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
10773 ffecom_gfrt_kindtype (ix),
10774 ffe_is_f2c_library () && ffecom_gfrt_complex_[ix],
10775 NULL_TREE, args, NULL_TREE, NULL,
10776 NULL, NULL_TREE, TRUE, hook);
10780 /* Transform constant-union to tree. */
10782 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10784 ffecom_constantunion (ffebldConstantUnion *cu, ffeinfoBasictype bt,
10785 ffeinfoKindtype kt, tree tree_type)
10791 case FFEINFO_basictypeINTEGER:
10797 #if FFETARGET_okINTEGER1
10798 case FFEINFO_kindtypeINTEGER1:
10799 val = ffebld_cu_val_integer1 (*cu);
10803 #if FFETARGET_okINTEGER2
10804 case FFEINFO_kindtypeINTEGER2:
10805 val = ffebld_cu_val_integer2 (*cu);
10809 #if FFETARGET_okINTEGER3
10810 case FFEINFO_kindtypeINTEGER3:
10811 val = ffebld_cu_val_integer3 (*cu);
10815 #if FFETARGET_okINTEGER4
10816 case FFEINFO_kindtypeINTEGER4:
10817 val = ffebld_cu_val_integer4 (*cu);
10822 assert ("bad INTEGER constant kind type" == NULL);
10823 /* Fall through. */
10824 case FFEINFO_kindtypeANY:
10825 return error_mark_node;
10827 item = build_int_2 (val, (val < 0) ? -1 : 0);
10828 TREE_TYPE (item) = tree_type;
10832 case FFEINFO_basictypeLOGICAL:
10838 #if FFETARGET_okLOGICAL1
10839 case FFEINFO_kindtypeLOGICAL1:
10840 val = ffebld_cu_val_logical1 (*cu);
10844 #if FFETARGET_okLOGICAL2
10845 case FFEINFO_kindtypeLOGICAL2:
10846 val = ffebld_cu_val_logical2 (*cu);
10850 #if FFETARGET_okLOGICAL3
10851 case FFEINFO_kindtypeLOGICAL3:
10852 val = ffebld_cu_val_logical3 (*cu);
10856 #if FFETARGET_okLOGICAL4
10857 case FFEINFO_kindtypeLOGICAL4:
10858 val = ffebld_cu_val_logical4 (*cu);
10863 assert ("bad LOGICAL constant kind type" == NULL);
10864 /* Fall through. */
10865 case FFEINFO_kindtypeANY:
10866 return error_mark_node;
10868 item = build_int_2 (val, (val < 0) ? -1 : 0);
10869 TREE_TYPE (item) = tree_type;
10873 case FFEINFO_basictypeREAL:
10875 REAL_VALUE_TYPE val;
10879 #if FFETARGET_okREAL1
10880 case FFEINFO_kindtypeREAL1:
10881 val = ffetarget_value_real1 (ffebld_cu_val_real1 (*cu));
10885 #if FFETARGET_okREAL2
10886 case FFEINFO_kindtypeREAL2:
10887 val = ffetarget_value_real2 (ffebld_cu_val_real2 (*cu));
10891 #if FFETARGET_okREAL3
10892 case FFEINFO_kindtypeREAL3:
10893 val = ffetarget_value_real3 (ffebld_cu_val_real3 (*cu));
10897 #if FFETARGET_okREAL4
10898 case FFEINFO_kindtypeREAL4:
10899 val = ffetarget_value_real4 (ffebld_cu_val_real4 (*cu));
10904 assert ("bad REAL constant kind type" == NULL);
10905 /* Fall through. */
10906 case FFEINFO_kindtypeANY:
10907 return error_mark_node;
10909 item = build_real (tree_type, val);
10913 case FFEINFO_basictypeCOMPLEX:
10915 REAL_VALUE_TYPE real;
10916 REAL_VALUE_TYPE imag;
10917 tree el_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
10921 #if FFETARGET_okCOMPLEX1
10922 case FFEINFO_kindtypeREAL1:
10923 real = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).real);
10924 imag = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).imaginary);
10928 #if FFETARGET_okCOMPLEX2
10929 case FFEINFO_kindtypeREAL2:
10930 real = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).real);
10931 imag = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).imaginary);
10935 #if FFETARGET_okCOMPLEX3
10936 case FFEINFO_kindtypeREAL3:
10937 real = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).real);
10938 imag = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).imaginary);
10942 #if FFETARGET_okCOMPLEX4
10943 case FFEINFO_kindtypeREAL4:
10944 real = ffetarget_value_real4 (ffebld_cu_val_complex4 (*cu).real);
10945 imag = ffetarget_value_real4 (ffebld_cu_val_complex4 (*cu).imaginary);
10950 assert ("bad REAL constant kind type" == NULL);
10951 /* Fall through. */
10952 case FFEINFO_kindtypeANY:
10953 return error_mark_node;
10955 item = ffecom_build_complex_constant_ (tree_type,
10956 build_real (el_type, real),
10957 build_real (el_type, imag));
10961 case FFEINFO_basictypeCHARACTER:
10962 { /* Happens only in DATA and similar contexts. */
10963 ffetargetCharacter1 val;
10967 #if FFETARGET_okCHARACTER1
10968 case FFEINFO_kindtypeLOGICAL1:
10969 val = ffebld_cu_val_character1 (*cu);
10974 assert ("bad CHARACTER constant kind type" == NULL);
10975 /* Fall through. */
10976 case FFEINFO_kindtypeANY:
10977 return error_mark_node;
10979 item = build_string (ffetarget_length_character1 (val),
10980 ffetarget_text_character1 (val));
10982 = build_type_variant (build_array_type (char_type_node,
10984 (integer_type_node,
10987 (ffetarget_length_character1
10993 case FFEINFO_basictypeHOLLERITH:
10995 ffetargetHollerith h;
10997 h = ffebld_cu_val_hollerith (*cu);
10999 /* If not at least as wide as default INTEGER, widen it. */
11000 if (h.length >= FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE)
11001 item = build_string (h.length, h.text);
11004 char str[FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE];
11006 memcpy (str, h.text, h.length);
11007 memset (&str[h.length], ' ',
11008 FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE
11010 item = build_string (FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE,
11014 = build_type_variant (build_array_type (char_type_node,
11016 (integer_type_node,
11024 case FFEINFO_basictypeTYPELESS:
11026 ffetargetInteger1 ival;
11027 ffetargetTypeless tless;
11030 tless = ffebld_cu_val_typeless (*cu);
11031 error = ffetarget_convert_integer1_typeless (&ival, tless);
11032 assert (error == FFEBAD);
11034 item = build_int_2 ((int) ival, 0);
11039 assert ("not yet on constant type" == NULL);
11040 /* Fall through. */
11041 case FFEINFO_basictypeANY:
11042 return error_mark_node;
11045 TREE_CONSTANT (item) = 1;
11052 /* Transform expression into constant tree.
11054 If the expression can be transformed into a tree that is constant,
11055 that is done, and the tree returned. Else NULL_TREE is returned.
11057 That way, a caller can attempt to provide compile-time initialization
11058 of a variable and, if that fails, *then* choose to start a new block
11059 and resort to using temporaries, as appropriate. */
11062 ffecom_const_expr (ffebld expr)
11065 return integer_zero_node;
11067 if (ffebld_op (expr) == FFEBLD_opANY)
11068 return error_mark_node;
11070 if (ffebld_arity (expr) == 0
11071 && (ffebld_op (expr) != FFEBLD_opSYMTER
11073 /* ~~Enable once common/equivalence is handled properly? */
11074 || ffebld_where (expr) == FFEINFO_whereCOMMON
11076 || ffebld_where (expr) == FFEINFO_whereGLOBAL
11077 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
11081 t = ffecom_expr (expr);
11082 assert (TREE_CONSTANT (t));
11089 /* Handy way to make a field in a struct/union. */
11091 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11093 ffecom_decl_field (tree context, tree prevfield,
11094 const char *name, tree type)
11098 field = build_decl (FIELD_DECL, get_identifier (name), type);
11099 DECL_CONTEXT (field) = context;
11100 DECL_FRAME_SIZE (field) = 0;
11101 if (prevfield != NULL_TREE)
11102 TREE_CHAIN (prevfield) = field;
11110 ffecom_close_include (FILE *f)
11112 #if FFECOM_GCC_INCLUDE
11113 ffecom_close_include_ (f);
11118 ffecom_decode_include_option (char *spec)
11120 #if FFECOM_GCC_INCLUDE
11121 return ffecom_decode_include_option_ (spec);
11127 /* End a compound statement (block). */
11129 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11131 ffecom_end_compstmt (void)
11133 return bison_rule_compstmt_ ();
11135 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
11137 /* ffecom_end_transition -- Perform end transition on all symbols
11139 ffecom_end_transition();
11141 Calls ffecom_sym_end_transition for each global and local symbol. */
11144 ffecom_end_transition ()
11146 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11150 if (ffe_is_ffedebug ())
11151 fprintf (dmpout, "; end_stmt_transition\n");
11153 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11154 ffecom_list_blockdata_ = NULL;
11155 ffecom_list_common_ = NULL;
11158 ffesymbol_drive (ffecom_sym_end_transition);
11159 if (ffe_is_ffedebug ())
11161 ffestorag_report ();
11162 #if FFECOM_targetCURRENT == FFECOM_targetFFE
11163 ffesymbol_report_all ();
11167 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11168 ffecom_start_progunit_ ();
11170 for (item = ffecom_list_blockdata_;
11172 item = ffebld_trail (item))
11180 static int number = 0;
11182 callee = ffebld_head (item);
11183 s = ffebld_symter (callee);
11184 t = ffesymbol_hook (s).decl_tree;
11185 if (t == NULL_TREE)
11187 s = ffecom_sym_transform_ (s);
11188 t = ffesymbol_hook (s).decl_tree;
11191 yes = suspend_momentary ();
11193 dt = build_pointer_type (TREE_TYPE (t));
11195 var = build_decl (VAR_DECL,
11196 ffecom_get_invented_identifier ("__g77_forceload_%d",
11199 DECL_EXTERNAL (var) = 0;
11200 TREE_STATIC (var) = 1;
11201 TREE_PUBLIC (var) = 0;
11202 DECL_INITIAL (var) = error_mark_node;
11203 TREE_USED (var) = 1;
11205 var = start_decl (var, FALSE);
11207 t = ffecom_1 (ADDR_EXPR, dt, t);
11209 finish_decl (var, t, FALSE);
11211 resume_momentary (yes);
11214 /* This handles any COMMON areas that weren't referenced but have, for
11215 example, important initial data. */
11217 for (item = ffecom_list_common_;
11219 item = ffebld_trail (item))
11220 ffecom_transform_common_ (ffebld_symter (ffebld_head (item)));
11222 ffecom_list_common_ = NULL;
11226 /* ffecom_exec_transition -- Perform exec transition on all symbols
11228 ffecom_exec_transition();
11230 Calls ffecom_sym_exec_transition for each global and local symbol.
11231 Make sure error updating not inhibited. */
11234 ffecom_exec_transition ()
11238 if (ffe_is_ffedebug ())
11239 fprintf (dmpout, "; exec_stmt_transition\n");
11241 inhibited = ffebad_inhibit ();
11242 ffebad_set_inhibit (FALSE);
11244 ffesymbol_drive (ffecom_sym_exec_transition); /* Don't retract! */
11245 ffeequiv_exec_transition (); /* Handle all pending EQUIVALENCEs. */
11246 if (ffe_is_ffedebug ())
11248 ffestorag_report ();
11249 #if FFECOM_targetCURRENT == FFECOM_targetFFE
11250 ffesymbol_report_all ();
11255 ffebad_set_inhibit (TRUE);
11258 /* Handle assignment statement.
11260 Convert dest and source using ffecom_expr, then join them
11261 with an ASSIGN op and pass the whole thing to expand_expr_stmt. */
11263 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11265 ffecom_expand_let_stmt (ffebld dest, ffebld source)
11272 if (ffeinfo_basictype (ffebld_info (dest)) != FFEINFO_basictypeCHARACTER)
11277 /* This attempts to replicate the test below, but must not be
11278 true when the test below is false. (Always err on the side
11279 of creating unused temporaries, to avoid ICEs.) */
11280 if (ffebld_op (dest) != FFEBLD_opSYMTER
11281 || ((dest_tree = ffesymbol_hook (ffebld_symter (dest)).decl_tree)
11282 && (TREE_CODE (dest_tree) != VAR_DECL
11283 || TREE_ADDRESSABLE (dest_tree))))
11285 ffecom_prepare_expr_ (source, dest);
11290 ffecom_prepare_expr_ (source, NULL);
11294 ffecom_prepare_expr_w (NULL_TREE, dest);
11296 /* For COMPLEX assignment like C1=C2, if partial overlap is possible,
11297 create a temporary through which the assignment is to take place,
11298 since MODIFY_EXPR doesn't handle partial overlap properly. */
11299 if (ffebld_basictype (dest) == FFEINFO_basictypeCOMPLEX
11300 && ffecom_possible_partial_overlap_ (dest, source))
11302 assign_temp = ffecom_make_tempvar ("complex_let",
11304 [ffebld_basictype (dest)]
11305 [ffebld_kindtype (dest)],
11306 FFETARGET_charactersizeNONE,
11310 assign_temp = NULL_TREE;
11312 ffecom_prepare_end ();
11314 dest_tree = ffecom_expr_w (NULL_TREE, dest);
11315 if (dest_tree == error_mark_node)
11318 if ((TREE_CODE (dest_tree) != VAR_DECL)
11319 || TREE_ADDRESSABLE (dest_tree))
11320 source_tree = ffecom_expr_ (source, dest_tree, dest, &dest_used,
11324 assert (! dest_used);
11326 source_tree = ffecom_expr (source);
11328 if (source_tree == error_mark_node)
11332 expr_tree = source_tree;
11333 else if (assign_temp)
11336 /* The back end understands a conceptual move (evaluate source;
11337 store into dest), so use that, in case it can determine
11338 that it is going to use, say, two registers as temporaries
11339 anyway. So don't use the temp (and someday avoid generating
11340 it, once this code starts triggering regularly). */
11341 expr_tree = ffecom_2s (MOVE_EXPR, void_type_node,
11345 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11348 expand_expr_stmt (expr_tree);
11349 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11355 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11359 expand_expr_stmt (expr_tree);
11363 ffecom_prepare_let_char_ (ffebld_size_known (dest), source);
11364 ffecom_prepare_expr_w (NULL_TREE, dest);
11366 ffecom_prepare_end ();
11368 ffecom_char_args_ (&dest_tree, &dest_length, dest);
11369 ffecom_let_char_ (dest_tree, dest_length, ffebld_size_known (dest),
11374 /* ffecom_expr -- Transform expr into gcc tree
11377 ffebld expr; // FFE expression.
11378 tree = ffecom_expr(expr);
11380 Recursive descent on expr while making corresponding tree nodes and
11381 attaching type info and such. */
11383 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11385 ffecom_expr (ffebld expr)
11387 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, FALSE, FALSE);
11391 /* Like ffecom_expr, but return tree usable for assigned GOTO or FORMAT. */
11393 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11395 ffecom_expr_assign (ffebld expr)
11397 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE);
11401 /* Like ffecom_expr_rw, but return tree usable for ASSIGN. */
11403 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11405 ffecom_expr_assign_w (ffebld expr)
11407 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE);
11411 /* Transform expr for use as into read/write tree and stabilize the
11412 reference. Not for use on CHARACTER expressions.
11414 Recursive descent on expr while making corresponding tree nodes and
11415 attaching type info and such. */
11417 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11419 ffecom_expr_rw (tree type, ffebld expr)
11421 assert (expr != NULL);
11422 /* Different target types not yet supported. */
11423 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
11425 return stabilize_reference (ffecom_expr (expr));
11429 /* Transform expr for use as into write tree and stabilize the
11430 reference. Not for use on CHARACTER expressions.
11432 Recursive descent on expr while making corresponding tree nodes and
11433 attaching type info and such. */
11435 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11437 ffecom_expr_w (tree type, ffebld expr)
11439 assert (expr != NULL);
11440 /* Different target types not yet supported. */
11441 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
11443 return stabilize_reference (ffecom_expr (expr));
11447 /* Do global stuff. */
11449 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11451 ffecom_finish_compile ()
11453 assert (ffecom_outer_function_decl_ == NULL_TREE);
11454 assert (current_function_decl == NULL_TREE);
11456 ffeglobal_drive (ffecom_finish_global_);
11460 /* Public entry point for front end to access finish_decl. */
11462 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11464 ffecom_finish_decl (tree decl, tree init, bool is_top_level)
11466 assert (!is_top_level);
11467 finish_decl (decl, init, FALSE);
11471 /* Finish a program unit. */
11473 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11475 ffecom_finish_progunit ()
11477 ffecom_end_compstmt ();
11479 ffecom_previous_function_decl_ = current_function_decl;
11480 ffecom_which_entrypoint_decl_ = NULL_TREE;
11482 finish_function (0);
11486 /* Wrapper for get_identifier. pattern is sprintf-like, assumed to contain
11487 one %s if text is not NULL, assumed to contain one %d if number is
11488 not -1. If both are assumed, the %s is assumed to precede the %d. */
11490 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11492 ffecom_get_invented_identifier (const char *pattern, const char *text,
11502 lenlen += strlen (text);
11505 if (text || number != -1)
11507 lenlen += strlen (pattern);
11508 if (lenlen > ARRAY_SIZE (space))
11509 nam = malloc_new_ks (malloc_pool_image (), pattern, lenlen);
11516 nam = (char *) pattern;
11522 sprintf (&nam[0], pattern, number);
11527 sprintf (&nam[0], pattern, text);
11529 sprintf (&nam[0], pattern, text, number);
11532 decl = get_identifier (nam);
11534 if (lenlen > ARRAY_SIZE (space))
11535 malloc_kill_ks (malloc_pool_image (), nam, lenlen);
11537 IDENTIFIER_INVENTED (decl) = 1;
11543 ffecom_gfrt_basictype (ffecomGfrt gfrt)
11545 assert (gfrt < FFECOM_gfrt);
11547 switch (ffecom_gfrt_type_[gfrt])
11549 case FFECOM_rttypeVOID_:
11550 case FFECOM_rttypeVOIDSTAR_:
11551 return FFEINFO_basictypeNONE;
11553 case FFECOM_rttypeFTNINT_:
11554 return FFEINFO_basictypeINTEGER;
11556 case FFECOM_rttypeINTEGER_:
11557 return FFEINFO_basictypeINTEGER;
11559 case FFECOM_rttypeLONGINT_:
11560 return FFEINFO_basictypeINTEGER;
11562 case FFECOM_rttypeLOGICAL_:
11563 return FFEINFO_basictypeLOGICAL;
11565 case FFECOM_rttypeREAL_F2C_:
11566 case FFECOM_rttypeREAL_GNU_:
11567 return FFEINFO_basictypeREAL;
11569 case FFECOM_rttypeCOMPLEX_F2C_:
11570 case FFECOM_rttypeCOMPLEX_GNU_:
11571 return FFEINFO_basictypeCOMPLEX;
11573 case FFECOM_rttypeDOUBLE_:
11574 case FFECOM_rttypeDOUBLEREAL_:
11575 return FFEINFO_basictypeREAL;
11577 case FFECOM_rttypeDBLCMPLX_F2C_:
11578 case FFECOM_rttypeDBLCMPLX_GNU_:
11579 return FFEINFO_basictypeCOMPLEX;
11581 case FFECOM_rttypeCHARACTER_:
11582 return FFEINFO_basictypeCHARACTER;
11585 return FFEINFO_basictypeANY;
11590 ffecom_gfrt_kindtype (ffecomGfrt gfrt)
11592 assert (gfrt < FFECOM_gfrt);
11594 switch (ffecom_gfrt_type_[gfrt])
11596 case FFECOM_rttypeVOID_:
11597 case FFECOM_rttypeVOIDSTAR_:
11598 return FFEINFO_kindtypeNONE;
11600 case FFECOM_rttypeFTNINT_:
11601 return FFEINFO_kindtypeINTEGER1;
11603 case FFECOM_rttypeINTEGER_:
11604 return FFEINFO_kindtypeINTEGER1;
11606 case FFECOM_rttypeLONGINT_:
11607 return FFEINFO_kindtypeINTEGER4;
11609 case FFECOM_rttypeLOGICAL_:
11610 return FFEINFO_kindtypeLOGICAL1;
11612 case FFECOM_rttypeREAL_F2C_:
11613 case FFECOM_rttypeREAL_GNU_:
11614 return FFEINFO_kindtypeREAL1;
11616 case FFECOM_rttypeCOMPLEX_F2C_:
11617 case FFECOM_rttypeCOMPLEX_GNU_:
11618 return FFEINFO_kindtypeREAL1;
11620 case FFECOM_rttypeDOUBLE_:
11621 case FFECOM_rttypeDOUBLEREAL_:
11622 return FFEINFO_kindtypeREAL2;
11624 case FFECOM_rttypeDBLCMPLX_F2C_:
11625 case FFECOM_rttypeDBLCMPLX_GNU_:
11626 return FFEINFO_kindtypeREAL2;
11628 case FFECOM_rttypeCHARACTER_:
11629 return FFEINFO_kindtypeCHARACTER1;
11632 return FFEINFO_kindtypeANY;
11647 /* This block of code comes from the now-obsolete cktyps.c. It checks
11648 whether the compiler environment is buggy in known ways, some of which
11649 would, if not explicitly checked here, result in subtle bugs in g77. */
11651 if (ffe_is_do_internal_checks ())
11653 static char names[][12]
11655 {"bar", "bletch", "foo", "foobar"};
11660 name = bsearch ("foo", &names[0], ARRAY_SIZE (names), sizeof (names[0]),
11661 (int (*)()) strcmp);
11662 if (name != (char *) &names[2])
11664 assert ("bsearch doesn't work, #define FFEPROJ_BSEARCH 0 in proj.h"
11669 ul = strtoul ("123456789", NULL, 10);
11670 if (ul != 123456789L)
11672 assert ("strtoul doesn't have enough range, #define FFEPROJ_STRTOUL 0\
11673 in proj.h" == NULL);
11677 fl = atof ("56.789");
11678 if ((fl < 56.788) || (fl > 56.79))
11680 assert ("atof not type double, fix your #include <stdio.h>"
11686 #if FFECOM_GCC_INCLUDE
11687 ffecom_initialize_char_syntax_ ();
11690 ffecom_outer_function_decl_ = NULL_TREE;
11691 current_function_decl = NULL_TREE;
11692 named_labels = NULL_TREE;
11693 current_binding_level = NULL_BINDING_LEVEL;
11694 free_binding_level = NULL_BINDING_LEVEL;
11695 /* Make the binding_level structure for global names. */
11697 global_binding_level = current_binding_level;
11698 current_binding_level->prep_state = 2;
11700 /* Define `int' and `char' first so that dbx will output them first. */
11702 integer_type_node = make_signed_type (INT_TYPE_SIZE);
11703 pushdecl (build_decl (TYPE_DECL, get_identifier ("int"),
11704 integer_type_node));
11706 char_type_node = make_unsigned_type (CHAR_TYPE_SIZE);
11707 pushdecl (build_decl (TYPE_DECL, get_identifier ("char"),
11710 long_integer_type_node = make_signed_type (LONG_TYPE_SIZE);
11711 pushdecl (build_decl (TYPE_DECL, get_identifier ("long int"),
11712 long_integer_type_node));
11714 unsigned_type_node = make_unsigned_type (INT_TYPE_SIZE);
11715 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned int"),
11716 unsigned_type_node));
11718 long_unsigned_type_node = make_unsigned_type (LONG_TYPE_SIZE);
11719 pushdecl (build_decl (TYPE_DECL, get_identifier ("long unsigned int"),
11720 long_unsigned_type_node));
11722 long_long_integer_type_node = make_signed_type (LONG_LONG_TYPE_SIZE);
11723 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long int"),
11724 long_long_integer_type_node));
11726 long_long_unsigned_type_node = make_unsigned_type (LONG_LONG_TYPE_SIZE);
11727 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long unsigned int"),
11728 long_long_unsigned_type_node));
11730 short_integer_type_node = make_signed_type (SHORT_TYPE_SIZE);
11731 pushdecl (build_decl (TYPE_DECL, get_identifier ("short int"),
11732 short_integer_type_node));
11734 short_unsigned_type_node = make_unsigned_type (SHORT_TYPE_SIZE);
11735 pushdecl (build_decl (TYPE_DECL, get_identifier ("short unsigned int"),
11736 short_unsigned_type_node));
11738 /* Set the sizetype before we make other types. This *should* be the
11739 first type we create. */
11742 (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE))));
11743 ffecom_typesize_pointer_
11744 = TREE_INT_CST_LOW (TYPE_SIZE (sizetype)) / BITS_PER_UNIT;
11746 error_mark_node = make_node (ERROR_MARK);
11747 TREE_TYPE (error_mark_node) = error_mark_node;
11749 /* Define both `signed char' and `unsigned char'. */
11750 signed_char_type_node = make_signed_type (CHAR_TYPE_SIZE);
11751 pushdecl (build_decl (TYPE_DECL, get_identifier ("signed char"),
11752 signed_char_type_node));
11754 unsigned_char_type_node = make_unsigned_type (CHAR_TYPE_SIZE);
11755 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned char"),
11756 unsigned_char_type_node));
11758 float_type_node = make_node (REAL_TYPE);
11759 TYPE_PRECISION (float_type_node) = FLOAT_TYPE_SIZE;
11760 layout_type (float_type_node);
11761 pushdecl (build_decl (TYPE_DECL, get_identifier ("float"),
11764 double_type_node = make_node (REAL_TYPE);
11765 TYPE_PRECISION (double_type_node) = DOUBLE_TYPE_SIZE;
11766 layout_type (double_type_node);
11767 pushdecl (build_decl (TYPE_DECL, get_identifier ("double"),
11768 double_type_node));
11770 long_double_type_node = make_node (REAL_TYPE);
11771 TYPE_PRECISION (long_double_type_node) = LONG_DOUBLE_TYPE_SIZE;
11772 layout_type (long_double_type_node);
11773 pushdecl (build_decl (TYPE_DECL, get_identifier ("long double"),
11774 long_double_type_node));
11776 complex_integer_type_node = ffecom_make_complex_type_ (integer_type_node);
11777 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex int"),
11778 complex_integer_type_node));
11780 complex_float_type_node = ffecom_make_complex_type_ (float_type_node);
11781 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex float"),
11782 complex_float_type_node));
11784 complex_double_type_node = ffecom_make_complex_type_ (double_type_node);
11785 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex double"),
11786 complex_double_type_node));
11788 complex_long_double_type_node = ffecom_make_complex_type_ (long_double_type_node);
11789 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex long double"),
11790 complex_long_double_type_node));
11792 integer_zero_node = build_int_2 (0, 0);
11793 TREE_TYPE (integer_zero_node) = integer_type_node;
11794 integer_one_node = build_int_2 (1, 0);
11795 TREE_TYPE (integer_one_node) = integer_type_node;
11797 size_zero_node = build_int_2 (0, 0);
11798 TREE_TYPE (size_zero_node) = sizetype;
11799 size_one_node = build_int_2 (1, 0);
11800 TREE_TYPE (size_one_node) = sizetype;
11802 void_type_node = make_node (VOID_TYPE);
11803 pushdecl (build_decl (TYPE_DECL, get_identifier ("void"),
11805 layout_type (void_type_node); /* Uses integer_zero_node */
11806 /* We are not going to have real types in C with less than byte alignment,
11807 so we might as well not have any types that claim to have it. */
11808 TYPE_ALIGN (void_type_node) = BITS_PER_UNIT;
11810 null_pointer_node = build_int_2 (0, 0);
11811 TREE_TYPE (null_pointer_node) = build_pointer_type (void_type_node);
11812 layout_type (TREE_TYPE (null_pointer_node));
11814 string_type_node = build_pointer_type (char_type_node);
11816 ffecom_tree_fun_type_void
11817 = build_function_type (void_type_node, NULL_TREE);
11819 ffecom_tree_ptr_to_fun_type_void
11820 = build_pointer_type (ffecom_tree_fun_type_void);
11822 endlink = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
11825 = build_function_type (float_type_node,
11826 tree_cons (NULL_TREE, float_type_node, endlink));
11828 double_ftype_double
11829 = build_function_type (double_type_node,
11830 tree_cons (NULL_TREE, double_type_node, endlink));
11832 ldouble_ftype_ldouble
11833 = build_function_type (long_double_type_node,
11834 tree_cons (NULL_TREE, long_double_type_node,
11837 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11838 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11840 ffecom_tree_type[i][j] = NULL_TREE;
11841 ffecom_tree_fun_type[i][j] = NULL_TREE;
11842 ffecom_tree_ptr_to_fun_type[i][j] = NULL_TREE;
11843 ffecom_f2c_typecode_[i][j] = -1;
11846 /* Set up standard g77 types. Note that INTEGER and LOGICAL are set
11847 to size FLOAT_TYPE_SIZE because they have to be the same size as
11848 REAL, which also is FLOAT_TYPE_SIZE, according to the standard.
11849 Compiler options and other such stuff that change the ways these
11850 types are set should not affect this particular setup. */
11852 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1]
11853 = t = make_signed_type (FLOAT_TYPE_SIZE);
11854 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer"),
11856 type = ffetype_new ();
11858 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER1,
11860 ffetype_set_ams (type,
11861 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11862 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11863 ffetype_set_star (base_type,
11864 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11866 ffetype_set_kind (base_type, 1, type);
11867 ffecom_typesize_integer1_ = ffetype_size (type);
11868 assert (ffetype_size (type) == sizeof (ffetargetInteger1));
11870 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER1]
11871 = t = make_unsigned_type (FLOAT_TYPE_SIZE); /* HOLLERITH means unsigned. */
11872 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned"),
11875 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER2]
11876 = t = make_signed_type (CHAR_TYPE_SIZE);
11877 pushdecl (build_decl (TYPE_DECL, get_identifier ("byte"),
11879 type = ffetype_new ();
11880 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER2,
11882 ffetype_set_ams (type,
11883 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11884 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11885 ffetype_set_star (base_type,
11886 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11888 ffetype_set_kind (base_type, 3, type);
11889 assert (ffetype_size (type) == sizeof (ffetargetInteger2));
11891 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER2]
11892 = t = make_unsigned_type (CHAR_TYPE_SIZE);
11893 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned byte"),
11896 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER3]
11897 = t = make_signed_type (CHAR_TYPE_SIZE * 2);
11898 pushdecl (build_decl (TYPE_DECL, get_identifier ("word"),
11900 type = ffetype_new ();
11901 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER3,
11903 ffetype_set_ams (type,
11904 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11905 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11906 ffetype_set_star (base_type,
11907 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11909 ffetype_set_kind (base_type, 6, type);
11910 assert (ffetype_size (type) == sizeof (ffetargetInteger3));
11912 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER3]
11913 = t = make_unsigned_type (CHAR_TYPE_SIZE * 2);
11914 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned word"),
11917 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER4]
11918 = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
11919 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer4"),
11921 type = ffetype_new ();
11922 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER4,
11924 ffetype_set_ams (type,
11925 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11926 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11927 ffetype_set_star (base_type,
11928 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11930 ffetype_set_kind (base_type, 2, type);
11931 assert (ffetype_size (type) == sizeof (ffetargetInteger4));
11933 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER4]
11934 = t = make_unsigned_type (FLOAT_TYPE_SIZE * 2);
11935 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned4"),
11939 if (ffe_is_do_internal_checks ()
11940 && LONG_TYPE_SIZE != FLOAT_TYPE_SIZE
11941 && LONG_TYPE_SIZE != CHAR_TYPE_SIZE
11942 && LONG_TYPE_SIZE != SHORT_TYPE_SIZE
11943 && LONG_TYPE_SIZE != LONG_LONG_TYPE_SIZE)
11945 fprintf (stderr, "Sorry, no g77 support for LONG_TYPE_SIZE (%d bits) yet.\n",
11950 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL1]
11951 = t = make_signed_type (FLOAT_TYPE_SIZE);
11952 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical"),
11954 type = ffetype_new ();
11956 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL1,
11958 ffetype_set_ams (type,
11959 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11960 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11961 ffetype_set_star (base_type,
11962 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11964 ffetype_set_kind (base_type, 1, type);
11965 assert (ffetype_size (type) == sizeof (ffetargetLogical1));
11967 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL2]
11968 = t = make_signed_type (CHAR_TYPE_SIZE);
11969 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical2"),
11971 type = ffetype_new ();
11972 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL2,
11974 ffetype_set_ams (type,
11975 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11976 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11977 ffetype_set_star (base_type,
11978 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11980 ffetype_set_kind (base_type, 3, type);
11981 assert (ffetype_size (type) == sizeof (ffetargetLogical2));
11983 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL3]
11984 = t = make_signed_type (CHAR_TYPE_SIZE * 2);
11985 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical3"),
11987 type = ffetype_new ();
11988 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL3,
11990 ffetype_set_ams (type,
11991 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11992 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11993 ffetype_set_star (base_type,
11994 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11996 ffetype_set_kind (base_type, 6, type);
11997 assert (ffetype_size (type) == sizeof (ffetargetLogical3));
11999 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL4]
12000 = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
12001 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical4"),
12003 type = ffetype_new ();
12004 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL4,
12006 ffetype_set_ams (type,
12007 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12008 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12009 ffetype_set_star (base_type,
12010 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12012 ffetype_set_kind (base_type, 2, type);
12013 assert (ffetype_size (type) == sizeof (ffetargetLogical4));
12015 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
12016 = t = make_node (REAL_TYPE);
12017 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE;
12018 pushdecl (build_decl (TYPE_DECL, get_identifier ("real"),
12021 type = ffetype_new ();
12023 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREAL1,
12025 ffetype_set_ams (type,
12026 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12027 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12028 ffetype_set_star (base_type,
12029 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12031 ffetype_set_kind (base_type, 1, type);
12032 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
12033 = FFETARGET_f2cTYREAL;
12034 assert (ffetype_size (type) == sizeof (ffetargetReal1));
12036 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREALDOUBLE]
12037 = t = make_node (REAL_TYPE);
12038 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE * 2; /* Always twice REAL. */
12039 pushdecl (build_decl (TYPE_DECL, get_identifier ("double precision"),
12042 type = ffetype_new ();
12043 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREALDOUBLE,
12045 ffetype_set_ams (type,
12046 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12047 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12048 ffetype_set_star (base_type,
12049 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12051 ffetype_set_kind (base_type, 2, type);
12052 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]
12053 = FFETARGET_f2cTYDREAL;
12054 assert (ffetype_size (type) == sizeof (ffetargetReal2));
12056 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
12057 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]);
12058 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex"),
12060 type = ffetype_new ();
12062 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREAL1,
12064 ffetype_set_ams (type,
12065 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12066 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12067 ffetype_set_star (base_type,
12068 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12070 ffetype_set_kind (base_type, 1, type);
12071 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
12072 = FFETARGET_f2cTYCOMPLEX;
12073 assert (ffetype_size (type) == sizeof (ffetargetComplex1));
12075 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREALDOUBLE]
12076 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]);
12077 pushdecl (build_decl (TYPE_DECL, get_identifier ("double complex"),
12079 type = ffetype_new ();
12080 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREALDOUBLE,
12082 ffetype_set_ams (type,
12083 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12084 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12085 ffetype_set_star (base_type,
12086 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12088 ffetype_set_kind (base_type, 2,
12090 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL2]
12091 = FFETARGET_f2cTYDCOMPLEX;
12092 assert (ffetype_size (type) == sizeof (ffetargetComplex2));
12094 /* Make function and ptr-to-function types for non-CHARACTER types. */
12096 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
12097 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
12099 if ((t = ffecom_tree_type[i][j]) != NULL_TREE)
12101 if (i == FFEINFO_basictypeINTEGER)
12103 /* Figure out the smallest INTEGER type that can hold
12104 a pointer on this machine. */
12105 if (GET_MODE_SIZE (TYPE_MODE (t))
12106 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
12108 if ((ffecom_pointer_kind_ == FFEINFO_kindtypeNONE)
12109 || (GET_MODE_SIZE (TYPE_MODE (ffecom_tree_type[i][ffecom_pointer_kind_]))
12110 > GET_MODE_SIZE (TYPE_MODE (t))))
12111 ffecom_pointer_kind_ = j;
12114 else if (i == FFEINFO_basictypeCOMPLEX)
12115 t = void_type_node;
12116 /* For f2c compatibility, REAL functions are really
12117 implemented as DOUBLE PRECISION. */
12118 else if ((i == FFEINFO_basictypeREAL)
12119 && (j == FFEINFO_kindtypeREAL1))
12120 t = ffecom_tree_type
12121 [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2];
12123 t = ffecom_tree_fun_type[i][j] = build_function_type (t,
12125 ffecom_tree_ptr_to_fun_type[i][j] = build_pointer_type (t);
12129 /* Set up pointer types. */
12131 if (ffecom_pointer_kind_ == FFEINFO_basictypeNONE)
12132 fatal ("no INTEGER type can hold a pointer on this configuration");
12133 else if (0 && ffe_is_do_internal_checks ())
12134 fprintf (stderr, "Pointer type kt=%d\n", ffecom_pointer_kind_);
12135 ffetype_set_kind (ffeinfo_type (FFEINFO_basictypeINTEGER,
12136 FFEINFO_kindtypeINTEGERDEFAULT),
12138 ffeinfo_type (FFEINFO_basictypeINTEGER,
12139 ffecom_pointer_kind_));
12141 if (ffe_is_ugly_assign ())
12142 ffecom_label_kind_ = ffecom_pointer_kind_; /* Require ASSIGN etc to this. */
12144 ffecom_label_kind_ = FFEINFO_kindtypeINTEGERDEFAULT;
12145 if (0 && ffe_is_do_internal_checks ())
12146 fprintf (stderr, "Label type kt=%d\n", ffecom_label_kind_);
12148 ffecom_integer_type_node
12149 = ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1];
12150 ffecom_integer_zero_node = convert (ffecom_integer_type_node,
12151 integer_zero_node);
12152 ffecom_integer_one_node = convert (ffecom_integer_type_node,
12155 /* Yes, the "FLOAT_TYPE_SIZE" references below are intentional.
12156 Turns out that by TYLONG, runtime/libI77/lio.h really means
12157 "whatever size an ftnint is". For consistency and sanity,
12158 com.h and runtime/f2c.h.in agree that flag, ftnint, and ftlen
12159 all are INTEGER, which we also make out of whatever back-end
12160 integer type is FLOAT_TYPE_SIZE bits wide. This change, from
12161 LONG_TYPE_SIZE, for TYLONG and TYLOGICAL, was necessary to
12162 accommodate machines like the Alpha. Note that this suggests
12163 f2c and libf2c are missing a distinction perhaps needed on
12164 some machines between "int" and "long int". -- burley 0.5.5 950215 */
12166 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, FLOAT_TYPE_SIZE,
12167 FFETARGET_f2cTYLONG);
12168 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, SHORT_TYPE_SIZE,
12169 FFETARGET_f2cTYSHORT);
12170 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, CHAR_TYPE_SIZE,
12171 FFETARGET_f2cTYINT1);
12172 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, LONG_LONG_TYPE_SIZE,
12173 FFETARGET_f2cTYQUAD);
12174 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, FLOAT_TYPE_SIZE,
12175 FFETARGET_f2cTYLOGICAL);
12176 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, SHORT_TYPE_SIZE,
12177 FFETARGET_f2cTYLOGICAL2);
12178 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, CHAR_TYPE_SIZE,
12179 FFETARGET_f2cTYLOGICAL1);
12180 /* ~~~Not really such a type in libf2c, e.g. I/O support? */
12181 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, LONG_LONG_TYPE_SIZE,
12182 FFETARGET_f2cTYQUAD);
12184 /* CHARACTER stuff is all special-cased, so it is not handled in the above
12185 loop. CHARACTER items are built as arrays of unsigned char. */
12187 ffecom_tree_type[FFEINFO_basictypeCHARACTER]
12188 [FFEINFO_kindtypeCHARACTER1] = t = char_type_node;
12189 type = ffetype_new ();
12191 ffeinfo_set_type (FFEINFO_basictypeCHARACTER,
12192 FFEINFO_kindtypeCHARACTER1,
12194 ffetype_set_ams (type,
12195 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12196 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12197 ffetype_set_kind (base_type, 1, type);
12198 assert (ffetype_size (type)
12199 == sizeof (((ffetargetCharacter1) { 0, NULL }).text[0]));
12201 ffecom_tree_fun_type[FFEINFO_basictypeCHARACTER]
12202 [FFEINFO_kindtypeCHARACTER1] = ffecom_tree_fun_type_void;
12203 ffecom_tree_ptr_to_fun_type[FFEINFO_basictypeCHARACTER]
12204 [FFEINFO_kindtypeCHARACTER1]
12205 = ffecom_tree_ptr_to_fun_type_void;
12206 ffecom_f2c_typecode_[FFEINFO_basictypeCHARACTER][FFEINFO_kindtypeCHARACTER1]
12207 = FFETARGET_f2cTYCHAR;
12209 ffecom_f2c_typecode_[FFEINFO_basictypeANY][FFEINFO_kindtypeANY]
12212 /* Make multi-return-value type and fields. */
12214 ffecom_multi_type_node_ = make_node (UNION_TYPE);
12218 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
12219 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
12223 if (ffecom_tree_type[i][j] == NULL_TREE)
12224 continue; /* Not supported. */
12225 sprintf (&name[0], "bt_%s_kt_%s",
12226 ffeinfo_basictype_string ((ffeinfoBasictype) i),
12227 ffeinfo_kindtype_string ((ffeinfoKindtype) j));
12228 ffecom_multi_fields_[i][j] = build_decl (FIELD_DECL,
12229 get_identifier (name),
12230 ffecom_tree_type[i][j]);
12231 DECL_CONTEXT (ffecom_multi_fields_[i][j])
12232 = ffecom_multi_type_node_;
12233 DECL_FRAME_SIZE (ffecom_multi_fields_[i][j]) = 0;
12234 TREE_CHAIN (ffecom_multi_fields_[i][j]) = field;
12235 field = ffecom_multi_fields_[i][j];
12238 TYPE_FIELDS (ffecom_multi_type_node_) = field;
12239 layout_type (ffecom_multi_type_node_);
12241 /* Subroutines usually return integer because they might have alternate
12244 ffecom_tree_subr_type
12245 = build_function_type (integer_type_node, NULL_TREE);
12246 ffecom_tree_ptr_to_subr_type
12247 = build_pointer_type (ffecom_tree_subr_type);
12248 ffecom_tree_blockdata_type
12249 = build_function_type (void_type_node, NULL_TREE);
12251 builtin_function ("__builtin_sqrtf", float_ftype_float,
12252 BUILT_IN_FSQRT, "sqrtf");
12253 builtin_function ("__builtin_fsqrt", double_ftype_double,
12254 BUILT_IN_FSQRT, "sqrt");
12255 builtin_function ("__builtin_sqrtl", ldouble_ftype_ldouble,
12256 BUILT_IN_FSQRT, "sqrtl");
12257 builtin_function ("__builtin_sinf", float_ftype_float,
12258 BUILT_IN_SIN, "sinf");
12259 builtin_function ("__builtin_sin", double_ftype_double,
12260 BUILT_IN_SIN, "sin");
12261 builtin_function ("__builtin_sinl", ldouble_ftype_ldouble,
12262 BUILT_IN_SIN, "sinl");
12263 builtin_function ("__builtin_cosf", float_ftype_float,
12264 BUILT_IN_COS, "cosf");
12265 builtin_function ("__builtin_cos", double_ftype_double,
12266 BUILT_IN_COS, "cos");
12267 builtin_function ("__builtin_cosl", ldouble_ftype_ldouble,
12268 BUILT_IN_COS, "cosl");
12271 pedantic_lvalues = FALSE;
12274 ffecom_f2c_make_type_ (&ffecom_f2c_integer_type_node,
12277 ffecom_f2c_make_type_ (&ffecom_f2c_address_type_node,
12280 ffecom_f2c_make_type_ (&ffecom_f2c_real_type_node,
12283 ffecom_f2c_make_type_ (&ffecom_f2c_doublereal_type_node,
12284 FFECOM_f2cDOUBLEREAL,
12286 ffecom_f2c_make_type_ (&ffecom_f2c_complex_type_node,
12289 ffecom_f2c_make_type_ (&ffecom_f2c_doublecomplex_type_node,
12290 FFECOM_f2cDOUBLECOMPLEX,
12292 ffecom_f2c_make_type_ (&ffecom_f2c_longint_type_node,
12295 ffecom_f2c_make_type_ (&ffecom_f2c_logical_type_node,
12298 ffecom_f2c_make_type_ (&ffecom_f2c_flag_type_node,
12301 ffecom_f2c_make_type_ (&ffecom_f2c_ftnlen_type_node,
12304 ffecom_f2c_make_type_ (&ffecom_f2c_ftnint_type_node,
12308 ffecom_f2c_ftnlen_zero_node
12309 = convert (ffecom_f2c_ftnlen_type_node, integer_zero_node);
12311 ffecom_f2c_ftnlen_one_node
12312 = convert (ffecom_f2c_ftnlen_type_node, integer_one_node);
12314 ffecom_f2c_ftnlen_two_node = build_int_2 (2, 0);
12315 TREE_TYPE (ffecom_f2c_ftnlen_two_node) = ffecom_integer_type_node;
12317 ffecom_f2c_ptr_to_ftnlen_type_node
12318 = build_pointer_type (ffecom_f2c_ftnlen_type_node);
12320 ffecom_f2c_ptr_to_ftnint_type_node
12321 = build_pointer_type (ffecom_f2c_ftnint_type_node);
12323 ffecom_f2c_ptr_to_integer_type_node
12324 = build_pointer_type (ffecom_f2c_integer_type_node);
12326 ffecom_f2c_ptr_to_real_type_node
12327 = build_pointer_type (ffecom_f2c_real_type_node);
12329 ffecom_float_zero_ = build_real (float_type_node, dconst0);
12330 ffecom_double_zero_ = build_real (double_type_node, dconst0);
12332 REAL_VALUE_TYPE point_5;
12334 #ifdef REAL_ARITHMETIC
12335 REAL_ARITHMETIC (point_5, RDIV_EXPR, dconst1, dconst2);
12339 ffecom_float_half_ = build_real (float_type_node, point_5);
12340 ffecom_double_half_ = build_real (double_type_node, point_5);
12343 /* Do "extern int xargc;". */
12345 ffecom_tree_xargc_ = build_decl (VAR_DECL,
12346 get_identifier ("f__xargc"),
12347 integer_type_node);
12348 DECL_EXTERNAL (ffecom_tree_xargc_) = 1;
12349 TREE_STATIC (ffecom_tree_xargc_) = 1;
12350 TREE_PUBLIC (ffecom_tree_xargc_) = 1;
12351 ffecom_tree_xargc_ = start_decl (ffecom_tree_xargc_, FALSE);
12352 finish_decl (ffecom_tree_xargc_, NULL_TREE, FALSE);
12354 #if 0 /* This is being fixed, and seems to be working now. */
12355 if ((FLOAT_TYPE_SIZE != 32)
12356 || (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))) != 32))
12358 warning ("configuration: REAL, INTEGER, and LOGICAL are %d bits wide,",
12359 (int) FLOAT_TYPE_SIZE);
12360 warning ("and pointers are %d bits wide, but g77 doesn't yet work",
12361 (int) TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))));
12362 warning ("properly unless they all are 32 bits wide.");
12363 warning ("Please keep this in mind before you report bugs. g77 should");
12364 warning ("support non-32-bit machines better as of version 0.6.");
12368 #if 0 /* Code in ste.c that would crash has been commented out. */
12369 if (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)
12370 < TYPE_PRECISION (string_type_node))
12371 /* I/O will probably crash. */
12372 warning ("configuration: char * holds %d bits, but ftnlen only %d",
12373 TYPE_PRECISION (string_type_node),
12374 TYPE_PRECISION (ffecom_f2c_ftnlen_type_node));
12377 #if 0 /* ASSIGN-related stuff has been changed to accommodate this. */
12378 if (TYPE_PRECISION (ffecom_integer_type_node)
12379 < TYPE_PRECISION (string_type_node))
12380 /* ASSIGN 10 TO I will crash. */
12381 warning ("configuration: char * holds %d bits, but INTEGER only %d --\n\
12382 ASSIGN statement might fail",
12383 TYPE_PRECISION (string_type_node),
12384 TYPE_PRECISION (ffecom_integer_type_node));
12389 /* ffecom_init_2 -- Initialize
12391 ffecom_init_2(); */
12393 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12397 assert (ffecom_outer_function_decl_ == NULL_TREE);
12398 assert (current_function_decl == NULL_TREE);
12399 assert (ffecom_which_entrypoint_decl_ == NULL_TREE);
12401 ffecom_master_arglist_ = NULL;
12403 ffecom_primary_entry_ = NULL;
12404 ffecom_is_altreturning_ = FALSE;
12405 ffecom_func_result_ = NULL_TREE;
12406 ffecom_multi_retval_ = NULL_TREE;
12410 /* ffecom_list_expr -- Transform list of exprs into gcc tree
12413 ffebld expr; // FFE opITEM list.
12414 tree = ffecom_list_expr(expr);
12416 List of actual args is transformed into corresponding gcc backend list. */
12418 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12420 ffecom_list_expr (ffebld expr)
12423 tree *plist = &list;
12424 tree trail = NULL_TREE; /* Append char length args here. */
12425 tree *ptrail = &trail;
12428 while (expr != NULL)
12430 tree texpr = ffecom_arg_expr (ffebld_head (expr), &length);
12432 if (texpr == error_mark_node)
12433 return error_mark_node;
12435 *plist = build_tree_list (NULL_TREE, texpr);
12436 plist = &TREE_CHAIN (*plist);
12437 expr = ffebld_trail (expr);
12438 if (length != NULL_TREE)
12440 *ptrail = build_tree_list (NULL_TREE, length);
12441 ptrail = &TREE_CHAIN (*ptrail);
12451 /* ffecom_list_ptr_to_expr -- Transform list of exprs into gcc tree
12454 ffebld expr; // FFE opITEM list.
12455 tree = ffecom_list_ptr_to_expr(expr);
12457 List of actual args is transformed into corresponding gcc backend list for
12458 use in calling an external procedure (vs. a statement function). */
12460 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12462 ffecom_list_ptr_to_expr (ffebld expr)
12465 tree *plist = &list;
12466 tree trail = NULL_TREE; /* Append char length args here. */
12467 tree *ptrail = &trail;
12470 while (expr != NULL)
12472 tree texpr = ffecom_arg_ptr_to_expr (ffebld_head (expr), &length);
12474 if (texpr == error_mark_node)
12475 return error_mark_node;
12477 *plist = build_tree_list (NULL_TREE, texpr);
12478 plist = &TREE_CHAIN (*plist);
12479 expr = ffebld_trail (expr);
12480 if (length != NULL_TREE)
12482 *ptrail = build_tree_list (NULL_TREE, length);
12483 ptrail = &TREE_CHAIN (*ptrail);
12493 /* Obtain gcc's LABEL_DECL tree for label. */
12495 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12497 ffecom_lookup_label (ffelab label)
12501 if (ffelab_hook (label) == NULL_TREE)
12503 char labelname[16];
12505 switch (ffelab_type (label))
12507 case FFELAB_typeLOOPEND:
12508 case FFELAB_typeNOTLOOP:
12509 case FFELAB_typeENDIF:
12510 sprintf (labelname, "%" ffelabValue_f "u", ffelab_value (label));
12511 glabel = build_decl (LABEL_DECL, get_identifier (labelname),
12513 DECL_CONTEXT (glabel) = current_function_decl;
12514 DECL_MODE (glabel) = VOIDmode;
12517 case FFELAB_typeFORMAT:
12518 push_obstacks_nochange ();
12519 end_temporary_allocation ();
12521 glabel = build_decl (VAR_DECL,
12522 ffecom_get_invented_identifier
12523 ("__g77_format_%d", NULL,
12524 (int) ffelab_value (label)),
12525 build_type_variant (build_array_type
12529 TREE_CONSTANT (glabel) = 1;
12530 TREE_STATIC (glabel) = 1;
12531 DECL_CONTEXT (glabel) = 0;
12532 DECL_INITIAL (glabel) = NULL;
12533 make_decl_rtl (glabel, NULL, 0);
12534 expand_decl (glabel);
12536 resume_temporary_allocation ();
12541 case FFELAB_typeANY:
12542 glabel = error_mark_node;
12546 assert ("bad label type" == NULL);
12550 ffelab_set_hook (label, glabel);
12554 glabel = ffelab_hook (label);
12561 /* Stabilizes the arguments. Don't use this if the lhs and rhs come from
12562 a single source specification (as in the fourth argument of MVBITS).
12563 If the type is NULL_TREE, the type of lhs is used to make the type of
12564 the MODIFY_EXPR. */
12566 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12568 ffecom_modify (tree newtype, tree lhs,
12571 if (lhs == error_mark_node || rhs == error_mark_node)
12572 return error_mark_node;
12574 if (newtype == NULL_TREE)
12575 newtype = TREE_TYPE (lhs);
12577 if (TREE_SIDE_EFFECTS (lhs))
12578 lhs = stabilize_reference (lhs);
12580 return ffecom_2s (MODIFY_EXPR, newtype, lhs, rhs);
12585 /* Register source file name. */
12588 ffecom_file (char *name)
12590 #if FFECOM_GCC_INCLUDE
12591 ffecom_file_ (name);
12595 /* ffecom_notify_init_storage -- An aggregate storage is now fully init'ed
12598 ffecom_notify_init_storage(st);
12600 Gets called when all possible units in an aggregate storage area (a LOCAL
12601 with equivalences or a COMMON) have been initialized. The initialization
12602 info either is in ffestorag_init or, if that is NULL,
12603 ffestorag_accretion:
12605 ffestorag_init may contain an opCONTER or opARRTER. opCONTER may occur
12606 even for an array if the array is one element in length!
12608 ffestorag_accretion will contain an opACCTER. It is much like an
12609 opARRTER except it has an ffebit object in it instead of just a size.
12610 The back end can use the info in the ffebit object, if it wants, to
12611 reduce the amount of actual initialization, but in any case it should
12612 kill the ffebit object when done. Also, set accretion to NULL but
12613 init to a non-NULL value.
12615 After performing initialization, DO NOT set init to NULL, because that'll
12616 tell the front end it is ok for more initialization to happen. Instead,
12617 set init to an opANY expression or some such thing that you can use to
12618 tell that you've already initialized the object.
12621 Support two-pass FFE. */
12624 ffecom_notify_init_storage (ffestorag st)
12626 ffebld init; /* The initialization expression. */
12627 #if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12628 ffetargetOffset size; /* The size of the entity. */
12629 ffetargetAlign pad; /* Its initial padding. */
12632 if (ffestorag_init (st) == NULL)
12634 init = ffestorag_accretion (st);
12635 assert (init != NULL);
12636 ffestorag_set_accretion (st, NULL);
12637 ffestorag_set_accretes (st, 0);
12639 #if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12640 /* For GNU backend, just turn ACCTER into ARRTER and proceed. */
12641 size = ffebld_accter_size (init);
12642 pad = ffebld_accter_pad (init);
12643 ffebit_kill (ffebld_accter_bits (init));
12644 ffebld_set_op (init, FFEBLD_opARRTER);
12645 ffebld_set_arrter (init, ffebld_accter (init));
12646 ffebld_arrter_set_size (init, size);
12647 ffebld_arrter_set_pad (init, size);
12651 ffestorag_set_init (st, init);
12656 init = ffestorag_init (st);
12659 #if FFECOM_ONEPASS /* Process the inits, wipe 'em out. */
12660 ffestorag_set_init (st, ffebld_new_any ());
12662 if (ffebld_op (init) == FFEBLD_opANY)
12663 return; /* Oh, we already did this! */
12665 #if FFECOM_targetCURRENT == FFECOM_targetFFE
12669 if (ffestorag_symbol (st) != NULL)
12670 s = ffestorag_symbol (st);
12672 s = ffestorag_typesymbol (st);
12674 fprintf (dmpout, "= initialize_storage \"%s\" ",
12675 (s != NULL) ? ffesymbol_text (s) : "(unnamed)");
12676 ffebld_dump (init);
12677 fputc ('\n', dmpout);
12681 #endif /* if FFECOM_ONEPASS */
12684 /* ffecom_notify_init_symbol -- A symbol is now fully init'ed
12687 ffecom_notify_init_symbol(s);
12689 Gets called when all possible units in a symbol (not placed in COMMON
12690 or involved in EQUIVALENCE, unless it as yet has no ffestorag object)
12691 have been initialized. The initialization info either is in
12692 ffesymbol_init or, if that is NULL, ffesymbol_accretion:
12694 ffesymbol_init may contain an opCONTER or opARRTER. opCONTER may occur
12695 even for an array if the array is one element in length!
12697 ffesymbol_accretion will contain an opACCTER. It is much like an
12698 opARRTER except it has an ffebit object in it instead of just a size.
12699 The back end can use the info in the ffebit object, if it wants, to
12700 reduce the amount of actual initialization, but in any case it should
12701 kill the ffebit object when done. Also, set accretion to NULL but
12702 init to a non-NULL value.
12704 After performing initialization, DO NOT set init to NULL, because that'll
12705 tell the front end it is ok for more initialization to happen. Instead,
12706 set init to an opANY expression or some such thing that you can use to
12707 tell that you've already initialized the object.
12710 Support two-pass FFE. */
12713 ffecom_notify_init_symbol (ffesymbol s)
12715 ffebld init; /* The initialization expression. */
12716 #if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12717 ffetargetOffset size; /* The size of the entity. */
12718 ffetargetAlign pad; /* Its initial padding. */
12721 if (ffesymbol_storage (s) == NULL)
12722 return; /* Do nothing until COMMON/EQUIVALENCE
12723 possibilities checked. */
12725 if ((ffesymbol_init (s) == NULL)
12726 && ((init = ffesymbol_accretion (s)) != NULL))
12728 ffesymbol_set_accretion (s, NULL);
12729 ffesymbol_set_accretes (s, 0);
12731 #if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12732 /* For GNU backend, just turn ACCTER into ARRTER and proceed. */
12733 size = ffebld_accter_size (init);
12734 pad = ffebld_accter_pad (init);
12735 ffebit_kill (ffebld_accter_bits (init));
12736 ffebld_set_op (init, FFEBLD_opARRTER);
12737 ffebld_set_arrter (init, ffebld_accter (init));
12738 ffebld_arrter_set_size (init, size);
12739 ffebld_arrter_set_pad (init, size);
12743 ffesymbol_set_init (s, init);
12748 init = ffesymbol_init (s);
12752 ffesymbol_set_init (s, ffebld_new_any ());
12754 if (ffebld_op (init) == FFEBLD_opANY)
12755 return; /* Oh, we already did this! */
12757 #if FFECOM_targetCURRENT == FFECOM_targetFFE
12758 fprintf (dmpout, "= initialize_symbol \"%s\" ", ffesymbol_text (s));
12759 ffebld_dump (init);
12760 fputc ('\n', dmpout);
12763 #endif /* if FFECOM_ONEPASS */
12766 /* ffecom_notify_primary_entry -- Learn which is the primary entry point
12769 ffecom_notify_primary_entry(s);
12771 Gets called when implicit or explicit PROGRAM statement seen or when
12772 FUNCTION, SUBROUTINE, or BLOCK DATA statement seen, with the primary
12773 global symbol that serves as the entry point. */
12776 ffecom_notify_primary_entry (ffesymbol s)
12778 ffecom_primary_entry_ = s;
12779 ffecom_primary_entry_kind_ = ffesymbol_kind (s);
12781 if ((ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
12782 || (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE))
12783 ffecom_primary_entry_is_proc_ = TRUE;
12785 ffecom_primary_entry_is_proc_ = FALSE;
12787 if (!ffe_is_silent ())
12789 if (ffecom_primary_entry_kind_ == FFEINFO_kindPROGRAM)
12790 fprintf (stderr, "%s:\n", ffesymbol_text (s));
12792 fprintf (stderr, " %s:\n", ffesymbol_text (s));
12795 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12796 if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
12801 for (list = ffesymbol_dummyargs (s);
12803 list = ffebld_trail (list))
12805 arg = ffebld_head (list);
12806 if (ffebld_op (arg) == FFEBLD_opSTAR)
12808 ffecom_is_altreturning_ = TRUE;
12817 ffecom_open_include (char *name, ffewhereLine l, ffewhereColumn c)
12819 #if FFECOM_GCC_INCLUDE
12820 return ffecom_open_include_ (name, l, c);
12822 return fopen (name, "r");
12826 /* ffecom_ptr_to_expr -- Transform expr into gcc tree with & in front
12829 ffebld expr; // FFE expression.
12830 tree = ffecom_ptr_to_expr(expr);
12832 Like ffecom_expr, but sticks address-of in front of most things. */
12834 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12836 ffecom_ptr_to_expr (ffebld expr)
12839 ffeinfoBasictype bt;
12840 ffeinfoKindtype kt;
12843 assert (expr != NULL);
12845 switch (ffebld_op (expr))
12847 case FFEBLD_opSYMTER:
12848 s = ffebld_symter (expr);
12849 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
12853 ix = ffeintrin_gfrt_indirect (ffebld_symter_implementation (expr));
12854 assert (ix != FFECOM_gfrt);
12855 if ((item = ffecom_gfrt_[ix]) == NULL_TREE)
12857 ffecom_make_gfrt_ (ix);
12858 item = ffecom_gfrt_[ix];
12863 item = ffesymbol_hook (s).decl_tree;
12864 if (item == NULL_TREE)
12866 s = ffecom_sym_transform_ (s);
12867 item = ffesymbol_hook (s).decl_tree;
12870 assert (item != NULL);
12871 if (item == error_mark_node)
12873 if (!ffesymbol_hook (s).addr)
12874 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12878 case FFEBLD_opARRAYREF:
12879 return ffecom_arrayref_ (NULL_TREE, expr, 1);
12881 case FFEBLD_opCONTER:
12883 bt = ffeinfo_basictype (ffebld_info (expr));
12884 kt = ffeinfo_kindtype (ffebld_info (expr));
12886 item = ffecom_constantunion (&ffebld_constant_union
12887 (ffebld_conter (expr)), bt, kt,
12888 ffecom_tree_type[bt][kt]);
12889 if (item == error_mark_node)
12890 return error_mark_node;
12891 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12896 return error_mark_node;
12899 bt = ffeinfo_basictype (ffebld_info (expr));
12900 kt = ffeinfo_kindtype (ffebld_info (expr));
12902 item = ffecom_expr (expr);
12903 if (item == error_mark_node)
12904 return error_mark_node;
12906 /* The back end currently optimizes a bit too zealously for us, in that
12907 we fail JCB001 if the following block of code is omitted. It checks
12908 to see if the transformed expression is a symbol or array reference,
12909 and encloses it in a SAVE_EXPR if that is the case. */
12912 if ((TREE_CODE (item) == VAR_DECL)
12913 || (TREE_CODE (item) == PARM_DECL)
12914 || (TREE_CODE (item) == RESULT_DECL)
12915 || (TREE_CODE (item) == INDIRECT_REF)
12916 || (TREE_CODE (item) == ARRAY_REF)
12917 || (TREE_CODE (item) == COMPONENT_REF)
12919 || (TREE_CODE (item) == OFFSET_REF)
12921 || (TREE_CODE (item) == BUFFER_REF)
12922 || (TREE_CODE (item) == REALPART_EXPR)
12923 || (TREE_CODE (item) == IMAGPART_EXPR))
12925 item = ffecom_save_tree (item);
12928 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12933 assert ("fall-through error" == NULL);
12934 return error_mark_node;
12938 /* Obtain a temp var with given data type.
12940 size is FFETARGET_charactersizeNONE for a non-CHARACTER type
12941 or >= 0 for a CHARACTER type.
12943 elements is -1 for a scalar or > 0 for an array of type. */
12945 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12947 ffecom_make_tempvar (const char *commentary, tree type,
12948 ffetargetCharacterSize size, int elements)
12952 static int mynumber;
12954 assert (current_binding_level->prep_state < 2);
12956 if (type == error_mark_node)
12957 return error_mark_node;
12959 yes = suspend_momentary ();
12961 if (size != FFETARGET_charactersizeNONE)
12962 type = build_array_type (type,
12963 build_range_type (ffecom_f2c_ftnlen_type_node,
12964 ffecom_f2c_ftnlen_one_node,
12965 build_int_2 (size, 0)));
12966 if (elements != -1)
12967 type = build_array_type (type,
12968 build_range_type (integer_type_node,
12970 build_int_2 (elements - 1,
12972 t = build_decl (VAR_DECL,
12973 ffecom_get_invented_identifier ("__g77_%s_%d",
12978 t = start_decl (t, FALSE);
12979 finish_decl (t, NULL_TREE, FALSE);
12981 resume_momentary (yes);
12987 /* Prepare argument pointer to expression.
12989 Like ffecom_prepare_expr, except for expressions to be evaluated
12990 via ffecom_arg_ptr_to_expr. */
12993 ffecom_prepare_arg_ptr_to_expr (ffebld expr)
12995 /* ~~For now, it seems to be the same thing. */
12996 ffecom_prepare_expr (expr);
13000 /* End of preparations. */
13003 ffecom_prepare_end (void)
13005 int prep_state = current_binding_level->prep_state;
13007 assert (prep_state < 2);
13008 current_binding_level->prep_state = 2;
13010 return (prep_state == 1) ? TRUE : FALSE;
13013 /* Prepare expression.
13015 This is called before any code is generated for the current block.
13016 It scans the expression, declares any temporaries that might be needed
13017 during evaluation of the expression, and stores those temporaries in
13018 the appropriate "hook" fields of the expression. `dest', if not NULL,
13019 specifies the destination that ffecom_expr_ will see, in case that
13020 helps avoid generating unused temporaries.
13022 ~~Improve to avoid allocating unused temporaries by taking `dest'
13023 into account vis-a-vis aliasing requirements of complex/character
13027 ffecom_prepare_expr_ (ffebld expr, ffebld dest UNUSED)
13029 ffeinfoBasictype bt;
13030 ffeinfoKindtype kt;
13031 ffetargetCharacterSize sz;
13032 tree tempvar = NULL_TREE;
13034 assert (current_binding_level->prep_state < 2);
13039 bt = ffeinfo_basictype (ffebld_info (expr));
13040 kt = ffeinfo_kindtype (ffebld_info (expr));
13041 sz = ffeinfo_size (ffebld_info (expr));
13043 /* Generate whatever temporaries are needed to represent the result
13044 of the expression. */
13046 if (bt == FFEINFO_basictypeCHARACTER)
13048 while (ffebld_op (expr) == FFEBLD_opPAREN)
13049 expr = ffebld_left (expr);
13052 switch (ffebld_op (expr))
13055 /* Don't make temps for SYMTER, CONTER, etc. */
13056 if (ffebld_arity (expr) == 0)
13061 case FFEINFO_basictypeCOMPLEX:
13062 if (ffebld_op (expr) == FFEBLD_opFUNCREF)
13066 if (ffebld_op (ffebld_left (expr)) != FFEBLD_opSYMTER)
13069 s = ffebld_symter (ffebld_left (expr));
13070 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT
13071 || (ffesymbol_where (s) != FFEINFO_whereINTRINSIC
13072 && ! ffesymbol_is_f2c (s))
13073 || (ffesymbol_where (s) == FFEINFO_whereINTRINSIC
13074 && ! ffe_is_f2c_library ()))
13077 else if (ffebld_op (expr) == FFEBLD_opPOWER)
13079 /* Requires special treatment. There's no POW_CC function
13080 in libg2c, so POW_ZZ is used, which means we always
13081 need a double-complex temp, not a single-complex. */
13082 kt = FFEINFO_kindtypeREAL2;
13084 else if (ffebld_op (expr) != FFEBLD_opDIVIDE)
13085 /* The other ops don't need temps for complex operands. */
13088 /* ~~~Avoid making temps for some intrinsics, such as AIMAG(C),
13089 REAL(C). See 19990325-0.f, routine `check', for cases. */
13090 tempvar = ffecom_make_tempvar ("complex",
13092 [FFEINFO_basictypeCOMPLEX][kt],
13093 FFETARGET_charactersizeNONE,
13097 case FFEINFO_basictypeCHARACTER:
13098 if (ffebld_op (expr) != FFEBLD_opFUNCREF)
13101 if (sz == FFETARGET_charactersizeNONE)
13102 /* ~~Kludge alert! This should someday be fixed. */
13105 tempvar = ffecom_make_tempvar ("char", char_type_node, sz, -1);
13114 case FFEBLD_opPOWER:
13117 tree rtmp, ltmp, result;
13119 ltype = ffecom_type_expr (ffebld_left (expr));
13120 rtype = ffecom_type_expr (ffebld_right (expr));
13122 rtmp = ffecom_make_tempvar (rtype, FFETARGET_charactersizeNONE, -1);
13123 ltmp = ffecom_make_tempvar (ltype, FFETARGET_charactersizeNONE, -1);
13124 result = ffecom_make_tempvar (ltype, FFETARGET_charactersizeNONE, -1);
13126 tempvar = make_tree_vec (3);
13127 TREE_VEC_ELT (tempvar, 0) = rtmp;
13128 TREE_VEC_ELT (tempvar, 1) = ltmp;
13129 TREE_VEC_ELT (tempvar, 2) = result;
13134 case FFEBLD_opCONCATENATE:
13136 /* This gets special handling, because only one set of temps
13137 is needed for a tree of these -- the tree is treated as
13138 a flattened list of concatenations when generating code. */
13140 ffecomConcatList_ catlist;
13141 tree ltmp, itmp, result;
13145 catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
13146 count = ffecom_concat_list_count_ (catlist);
13151 = ffecom_make_tempvar ("concat_len",
13152 ffecom_f2c_ftnlen_type_node,
13153 FFETARGET_charactersizeNONE, count);
13155 = ffecom_make_tempvar ("concat_item",
13156 ffecom_f2c_address_type_node,
13157 FFETARGET_charactersizeNONE, count);
13159 = ffecom_make_tempvar ("concat_res",
13161 ffecom_concat_list_maxlen_ (catlist),
13164 tempvar = make_tree_vec (3);
13165 TREE_VEC_ELT (tempvar, 0) = ltmp;
13166 TREE_VEC_ELT (tempvar, 1) = itmp;
13167 TREE_VEC_ELT (tempvar, 2) = result;
13170 for (i = 0; i < count; ++i)
13171 ffecom_prepare_arg_ptr_to_expr (ffecom_concat_list_expr_ (catlist,
13174 ffecom_concat_list_kill_ (catlist);
13178 ffebld_nonter_set_hook (expr, tempvar);
13179 current_binding_level->prep_state = 1;
13184 case FFEBLD_opCONVERT:
13185 if (bt == FFEINFO_basictypeCHARACTER
13186 && ((ffebld_size_known (ffebld_left (expr))
13187 == FFETARGET_charactersizeNONE)
13188 || (ffebld_size_known (ffebld_left (expr)) >= sz)))
13189 tempvar = ffecom_make_tempvar ("convert", char_type_node, sz, -1);
13195 ffebld_nonter_set_hook (expr, tempvar);
13196 current_binding_level->prep_state = 1;
13199 /* Prepare subexpressions for this expr. */
13201 switch (ffebld_op (expr))
13203 case FFEBLD_opPERCENT_LOC:
13204 ffecom_prepare_ptr_to_expr (ffebld_left (expr));
13207 case FFEBLD_opPERCENT_VAL:
13208 case FFEBLD_opPERCENT_REF:
13209 ffecom_prepare_expr (ffebld_left (expr));
13212 case FFEBLD_opPERCENT_DESCR:
13213 ffecom_prepare_arg_ptr_to_expr (ffebld_left (expr));
13216 case FFEBLD_opITEM:
13222 item = ffebld_trail (item))
13223 if (ffebld_head (item) != NULL)
13224 ffecom_prepare_expr (ffebld_head (item));
13229 /* Need to handle character conversion specially. */
13230 switch (ffebld_arity (expr))
13233 ffecom_prepare_expr (ffebld_left (expr));
13234 ffecom_prepare_expr (ffebld_right (expr));
13238 ffecom_prepare_expr (ffebld_left (expr));
13249 /* Prepare expression for reading and writing.
13251 Like ffecom_prepare_expr, except for expressions to be evaluated
13252 via ffecom_expr_rw. */
13255 ffecom_prepare_expr_rw (tree type, ffebld expr)
13257 /* This is all we support for now. */
13258 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
13260 /* ~~For now, it seems to be the same thing. */
13261 ffecom_prepare_expr (expr);
13265 /* Prepare expression for writing.
13267 Like ffecom_prepare_expr, except for expressions to be evaluated
13268 via ffecom_expr_w. */
13271 ffecom_prepare_expr_w (tree type, ffebld expr)
13273 /* This is all we support for now. */
13274 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
13276 /* ~~For now, it seems to be the same thing. */
13277 ffecom_prepare_expr (expr);
13281 /* Prepare expression for returning.
13283 Like ffecom_prepare_expr, except for expressions to be evaluated
13284 via ffecom_return_expr. */
13287 ffecom_prepare_return_expr (ffebld expr)
13289 assert (current_binding_level->prep_state < 2);
13291 if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE
13292 && ffecom_is_altreturning_
13294 ffecom_prepare_expr (expr);
13297 /* Prepare pointer to expression.
13299 Like ffecom_prepare_expr, except for expressions to be evaluated
13300 via ffecom_ptr_to_expr. */
13303 ffecom_prepare_ptr_to_expr (ffebld expr)
13305 /* ~~For now, it seems to be the same thing. */
13306 ffecom_prepare_expr (expr);
13310 /* Transform expression into constant pointer-to-expression tree.
13312 If the expression can be transformed into a pointer-to-expression tree
13313 that is constant, that is done, and the tree returned. Else NULL_TREE
13316 That way, a caller can attempt to provide compile-time initialization
13317 of a variable and, if that fails, *then* choose to start a new block
13318 and resort to using temporaries, as appropriate. */
13321 ffecom_ptr_to_const_expr (ffebld expr)
13324 return integer_zero_node;
13326 if (ffebld_op (expr) == FFEBLD_opANY)
13327 return error_mark_node;
13329 if (ffebld_arity (expr) == 0
13330 && (ffebld_op (expr) != FFEBLD_opSYMTER
13331 || ffebld_where (expr) == FFEINFO_whereCOMMON
13332 || ffebld_where (expr) == FFEINFO_whereGLOBAL
13333 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
13337 t = ffecom_ptr_to_expr (expr);
13338 assert (TREE_CONSTANT (t));
13345 /* ffecom_return_expr -- Returns return-value expr given alt return expr
13347 tree rtn; // NULL_TREE means use expand_null_return()
13348 ffebld expr; // NULL if no alt return expr to RETURN stmt
13349 rtn = ffecom_return_expr(expr);
13351 Based on the program unit type and other info (like return function
13352 type, return master function type when alternate ENTRY points,
13353 whether subroutine has any alternate RETURN points, etc), returns the
13354 appropriate expression to be returned to the caller, or NULL_TREE
13355 meaning no return value or the caller expects it to be returned somewhere
13356 else (which is handled by other parts of this module). */
13358 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13360 ffecom_return_expr (ffebld expr)
13364 switch (ffecom_primary_entry_kind_)
13366 case FFEINFO_kindPROGRAM:
13367 case FFEINFO_kindBLOCKDATA:
13371 case FFEINFO_kindSUBROUTINE:
13372 if (!ffecom_is_altreturning_)
13373 rtn = NULL_TREE; /* No alt returns, never an expr. */
13374 else if (expr == NULL)
13375 rtn = integer_zero_node;
13377 rtn = ffecom_expr (expr);
13380 case FFEINFO_kindFUNCTION:
13381 if ((ffecom_multi_retval_ != NULL_TREE)
13382 || (ffesymbol_basictype (ffecom_primary_entry_)
13383 == FFEINFO_basictypeCHARACTER)
13384 || ((ffesymbol_basictype (ffecom_primary_entry_)
13385 == FFEINFO_basictypeCOMPLEX)
13386 && (ffecom_num_entrypoints_ == 0)
13387 && ffesymbol_is_f2c (ffecom_primary_entry_)))
13388 { /* Value is returned by direct assignment
13389 into (implicit) dummy. */
13393 rtn = ffecom_func_result_;
13395 /* Spurious error if RETURN happens before first reference! So elide
13396 this code. In particular, for debugging registry, rtn should always
13397 be non-null after all, but TREE_USED won't be set until we encounter
13398 a reference in the code. Perfectly okay (but weird) code that,
13399 e.g., has "GOTO 20;10 RETURN;20 RTN=0;GOTO 10", would result in
13400 this diagnostic for no reason. Have people use -O -Wuninitialized
13401 and leave it to the back end to find obviously weird cases. */
13403 /* Used to "assert(rtn != NULL_TREE);" here, but it's kind of a valid
13404 situation; if the return value has never been referenced, it won't
13405 have a tree under 2pass mode. */
13406 if ((rtn == NULL_TREE)
13407 || !TREE_USED (rtn))
13409 ffebad_start (FFEBAD_RETURN_VALUE_UNSET);
13410 ffebad_here (0, ffesymbol_where_line (ffecom_primary_entry_),
13411 ffesymbol_where_column (ffecom_primary_entry_));
13412 ffebad_string (ffesymbol_text (ffesymbol_funcresult
13413 (ffecom_primary_entry_)));
13420 assert ("bad unit kind" == NULL);
13421 case FFEINFO_kindANY:
13422 rtn = error_mark_node;
13430 /* Do save_expr only if tree is not error_mark_node. */
13432 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13434 ffecom_save_tree (tree t)
13436 return save_expr (t);
13440 /* Start a compound statement (block). */
13442 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13444 ffecom_start_compstmt (void)
13446 bison_rule_pushlevel_ ();
13448 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
13450 /* Public entry point for front end to access start_decl. */
13452 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13454 ffecom_start_decl (tree decl, bool is_initialized)
13456 DECL_INITIAL (decl) = is_initialized ? error_mark_node : NULL_TREE;
13457 return start_decl (decl, FALSE);
13461 /* ffecom_sym_commit -- Symbol's state being committed to reality
13464 ffecom_sym_commit(s);
13466 Does whatever the backend needs when a symbol is committed after having
13467 been backtrackable for a period of time. */
13469 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13471 ffecom_sym_commit (ffesymbol s UNUSED)
13473 assert (!ffesymbol_retractable ());
13477 /* ffecom_sym_end_transition -- Perform end transition on all symbols
13479 ffecom_sym_end_transition();
13481 Does backend-specific stuff and also calls ffest_sym_end_transition
13482 to do the necessary FFE stuff.
13484 Backtracking is never enabled when this fn is called, so don't worry
13488 ffecom_sym_end_transition (ffesymbol s)
13492 assert (!ffesymbol_retractable ());
13494 s = ffest_sym_end_transition (s);
13496 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13497 if ((ffesymbol_kind (s) == FFEINFO_kindBLOCKDATA)
13498 && (ffesymbol_where (s) == FFEINFO_whereGLOBAL))
13500 ffecom_list_blockdata_
13501 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
13502 FFEINTRIN_specNONE,
13503 FFEINTRIN_impNONE),
13504 ffecom_list_blockdata_);
13508 /* This is where we finally notice that a symbol has partial initialization
13509 and finalize it. */
13511 if (ffesymbol_accretion (s) != NULL)
13513 assert (ffesymbol_init (s) == NULL);
13514 ffecom_notify_init_symbol (s);
13516 else if (((st = ffesymbol_storage (s)) != NULL)
13517 && ((st = ffestorag_parent (st)) != NULL)
13518 && (ffestorag_accretion (st) != NULL))
13520 assert (ffestorag_init (st) == NULL);
13521 ffecom_notify_init_storage (st);
13524 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13525 if ((ffesymbol_kind (s) == FFEINFO_kindCOMMON)
13526 && (ffesymbol_where (s) == FFEINFO_whereLOCAL)
13527 && (ffesymbol_storage (s) != NULL))
13529 ffecom_list_common_
13530 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
13531 FFEINTRIN_specNONE,
13532 FFEINTRIN_impNONE),
13533 ffecom_list_common_);
13540 /* ffecom_sym_exec_transition -- Perform exec transition on all symbols
13542 ffecom_sym_exec_transition();
13544 Does backend-specific stuff and also calls ffest_sym_exec_transition
13545 to do the necessary FFE stuff.
13547 See the long-winded description in ffecom_sym_learned for info
13548 on handling the situation where backtracking is inhibited. */
13551 ffecom_sym_exec_transition (ffesymbol s)
13553 s = ffest_sym_exec_transition (s);
13558 /* ffecom_sym_learned -- Initial or more info gained on symbol after exec
13561 s = ffecom_sym_learned(s);
13563 Called when a new symbol is seen after the exec transition or when more
13564 info (perhaps) is gained for an UNCERTAIN symbol. The symbol state when
13565 it arrives here is that all its latest info is updated already, so its
13566 state may be UNCERTAIN or UNDERSTOOD, it might already have the hook
13567 field filled in if its gone through here or exec_transition first, and
13570 The backend probably wants to check ffesymbol_retractable() to see if
13571 backtracking is in effect. If so, the FFE's changes to the symbol may
13572 be retracted (undone) or committed (ratified), at which time the
13573 appropriate ffecom_sym_retract or _commit function will be called
13576 If the backend has its own backtracking mechanism, great, use it so that
13577 committal is a simple operation. Though it doesn't make much difference,
13578 I suppose: the reason for tentative symbol evolution in the FFE is to
13579 enable error detection in weird incorrect statements early and to disable
13580 incorrect error detection on a correct statement. The backend is not
13581 likely to introduce any information that'll get involved in these
13582 considerations, so it is probably just fine that the implementation
13583 model for this fn and for _exec_transition is to not do anything
13584 (besides the required FFE stuff) if ffesymbol_retractable() returns TRUE
13585 and instead wait until ffecom_sym_commit is called (which it never
13586 will be as long as we're using ambiguity-detecting statement analysis in
13587 the FFE, which we are initially to shake out the code, but don't depend
13588 on this), otherwise go ahead and do whatever is needed.
13590 In essence, then, when this fn and _exec_transition get called while
13591 backtracking is enabled, a general mechanism would be to flag which (or
13592 both) of these were called (and in what order? neat question as to what
13593 might happen that I'm too lame to think through right now) and then when
13594 _commit is called reproduce the original calling sequence, if any, for
13595 the two fns (at which point backtracking will, of course, be disabled). */
13598 ffecom_sym_learned (ffesymbol s)
13600 ffestorag_exec_layout (s);
13605 /* ffecom_sym_retract -- Symbol's state being retracted from reality
13608 ffecom_sym_retract(s);
13610 Does whatever the backend needs when a symbol is retracted after having
13611 been backtrackable for a period of time. */
13613 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13615 ffecom_sym_retract (ffesymbol s UNUSED)
13617 assert (!ffesymbol_retractable ());
13619 #if 0 /* GCC doesn't commit any backtrackable sins,
13620 so nothing needed here. */
13621 switch (ffesymbol_hook (s).state)
13623 case 0: /* nothing happened yet. */
13626 case 1: /* exec transition happened. */
13629 case 2: /* learned happened. */
13632 case 3: /* learned then exec. */
13635 case 4: /* exec then learned. */
13639 assert ("bad hook state" == NULL);
13646 /* Create temporary gcc label. */
13648 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13650 ffecom_temp_label ()
13653 static int mynumber = 0;
13655 glabel = build_decl (LABEL_DECL,
13656 ffecom_get_invented_identifier ("__g77_label_%d",
13660 DECL_CONTEXT (glabel) = current_function_decl;
13661 DECL_MODE (glabel) = VOIDmode;
13667 /* Return an expression that is usable as an arg in a conditional context
13668 (IF, DO WHILE, .NOT., and so on).
13670 Use the one provided for the back end as of >2.6.0. */
13672 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13674 ffecom_truth_value (tree expr)
13676 return truthvalue_conversion (expr);
13680 /* Return the inversion of a truth value (the inversion of what
13681 ffecom_truth_value builds).
13683 Apparently invert_truthvalue, which is properly in the back end, is
13684 enough for now, so just use it. */
13686 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13688 ffecom_truth_value_invert (tree expr)
13690 return invert_truthvalue (ffecom_truth_value (expr));
13695 /* Return the tree that is the type of the expression, as would be
13696 returned in TREE_TYPE(ffecom_expr(expr)), without otherwise
13697 transforming the expression, generating temporaries, etc. */
13700 ffecom_type_expr (ffebld expr)
13702 ffeinfoBasictype bt;
13703 ffeinfoKindtype kt;
13706 assert (expr != NULL);
13708 bt = ffeinfo_basictype (ffebld_info (expr));
13709 kt = ffeinfo_kindtype (ffebld_info (expr));
13710 tree_type = ffecom_tree_type[bt][kt];
13712 switch (ffebld_op (expr))
13714 case FFEBLD_opCONTER:
13715 case FFEBLD_opSYMTER:
13716 case FFEBLD_opARRAYREF:
13717 case FFEBLD_opUPLUS:
13718 case FFEBLD_opPAREN:
13719 case FFEBLD_opUMINUS:
13721 case FFEBLD_opSUBTRACT:
13722 case FFEBLD_opMULTIPLY:
13723 case FFEBLD_opDIVIDE:
13724 case FFEBLD_opPOWER:
13726 case FFEBLD_opFUNCREF:
13727 case FFEBLD_opSUBRREF:
13731 case FFEBLD_opNEQV:
13733 case FFEBLD_opCONVERT:
13740 case FFEBLD_opPERCENT_LOC:
13743 case FFEBLD_opACCTER:
13744 case FFEBLD_opARRTER:
13745 case FFEBLD_opITEM:
13746 case FFEBLD_opSTAR:
13747 case FFEBLD_opBOUNDS:
13748 case FFEBLD_opREPEAT:
13749 case FFEBLD_opLABTER:
13750 case FFEBLD_opLABTOK:
13751 case FFEBLD_opIMPDO:
13752 case FFEBLD_opCONCATENATE:
13753 case FFEBLD_opSUBSTR:
13755 assert ("bad op for ffecom_type_expr" == NULL);
13756 /* Fall through. */
13758 return error_mark_node;
13762 /* Return PARM_DECL for arg#1 of master fn containing alternate ENTRY points
13764 If the PARM_DECL already exists, return it, else create it. It's an
13765 integer_type_node argument for the master function that implements a
13766 subroutine or function with more than one entrypoint and is bound at
13767 run time with the entrypoint number (0 for SUBROUTINE/FUNCTION, 1 for
13768 first ENTRY statement, and so on). */
13770 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13772 ffecom_which_entrypoint_decl ()
13774 assert (ffecom_which_entrypoint_decl_ != NULL_TREE);
13776 return ffecom_which_entrypoint_decl_;
13781 /* The following sections consists of private and public functions
13782 that have the same names and perform roughly the same functions
13783 as counterparts in the C front end. Changes in the C front end
13784 might affect how things should be done here. Only functions
13785 needed by the back end should be public here; the rest should
13786 be private (static in the C sense). Functions needed by other
13787 g77 front-end modules should be accessed by them via public
13788 ffecom_* names, which should themselves call private versions
13789 in this section so the private versions are easy to recognize
13790 when upgrading to a new gcc and finding interesting changes
13793 Functions named after rule "foo:" in c-parse.y are named
13794 "bison_rule_foo_" so they are easy to find. */
13796 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13799 bison_rule_pushlevel_ ()
13801 emit_line_note (input_filename, lineno);
13803 clear_last_expr ();
13805 expand_start_bindings (0);
13809 bison_rule_compstmt_ ()
13812 int keep = kept_level_p ();
13814 /* Make the temps go away. */
13816 current_binding_level->names = NULL_TREE;
13818 emit_line_note (input_filename, lineno);
13819 expand_end_bindings (getdecls (), keep, 0);
13820 t = poplevel (keep, 1, 0);
13826 /* Return a definition for a builtin function named NAME and whose data type
13827 is TYPE. TYPE should be a function type with argument types.
13828 FUNCTION_CODE tells later passes how to compile calls to this function.
13829 See tree.h for its possible values.
13831 If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME,
13832 the name to be called if we can't opencode the function. */
13835 builtin_function (const char *name, tree type,
13836 enum built_in_function function_code,
13837 const char *library_name)
13839 tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
13840 DECL_EXTERNAL (decl) = 1;
13841 TREE_PUBLIC (decl) = 1;
13843 DECL_ASSEMBLER_NAME (decl) = get_identifier (library_name);
13844 make_decl_rtl (decl, NULL_PTR, 1);
13846 if (function_code != NOT_BUILT_IN)
13848 DECL_BUILT_IN (decl) = 1;
13849 DECL_FUNCTION_CODE (decl) = function_code;
13855 /* Handle when a new declaration NEWDECL
13856 has the same name as an old one OLDDECL
13857 in the same binding contour.
13858 Prints an error message if appropriate.
13860 If safely possible, alter OLDDECL to look like NEWDECL, and return 1.
13861 Otherwise, return 0. */
13864 duplicate_decls (tree newdecl, tree olddecl)
13866 int types_match = 1;
13867 int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
13868 && DECL_INITIAL (newdecl) != 0);
13869 tree oldtype = TREE_TYPE (olddecl);
13870 tree newtype = TREE_TYPE (newdecl);
13872 if (olddecl == newdecl)
13875 if (TREE_CODE (newtype) == ERROR_MARK
13876 || TREE_CODE (oldtype) == ERROR_MARK)
13879 /* New decl is completely inconsistent with the old one =>
13880 tell caller to replace the old one.
13881 This is always an error except in the case of shadowing a builtin. */
13882 if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
13885 /* For real parm decl following a forward decl,
13886 return 1 so old decl will be reused. */
13887 if (types_match && TREE_CODE (newdecl) == PARM_DECL
13888 && TREE_ASM_WRITTEN (olddecl) && ! TREE_ASM_WRITTEN (newdecl))
13891 /* The new declaration is the same kind of object as the old one.
13892 The declarations may partially match. Print warnings if they don't
13893 match enough. Ultimately, copy most of the information from the new
13894 decl to the old one, and keep using the old one. */
13896 if (TREE_CODE (olddecl) == FUNCTION_DECL
13897 && DECL_BUILT_IN (olddecl))
13899 /* A function declaration for a built-in function. */
13900 if (!TREE_PUBLIC (newdecl))
13902 else if (!types_match)
13904 /* Accept the return type of the new declaration if same modes. */
13905 tree oldreturntype = TREE_TYPE (TREE_TYPE (olddecl));
13906 tree newreturntype = TREE_TYPE (TREE_TYPE (newdecl));
13908 /* Make sure we put the new type in the same obstack as the old ones.
13909 If the old types are not both in the same obstack, use the
13911 if (TYPE_OBSTACK (oldtype) == TYPE_OBSTACK (newtype))
13912 push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype));
13915 push_obstacks_nochange ();
13916 end_temporary_allocation ();
13919 if (TYPE_MODE (oldreturntype) == TYPE_MODE (newreturntype))
13921 /* Function types may be shared, so we can't just modify
13922 the return type of olddecl's function type. */
13924 = build_function_type (newreturntype,
13925 TYPE_ARG_TYPES (TREE_TYPE (olddecl)));
13929 TREE_TYPE (olddecl) = newtype;
13937 else if (TREE_CODE (olddecl) == FUNCTION_DECL
13938 && DECL_SOURCE_LINE (olddecl) == 0)
13940 /* A function declaration for a predeclared function
13941 that isn't actually built in. */
13942 if (!TREE_PUBLIC (newdecl))
13944 else if (!types_match)
13946 /* If the types don't match, preserve volatility indication.
13947 Later on, we will discard everything else about the
13948 default declaration. */
13949 TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
13953 /* Copy all the DECL_... slots specified in the new decl
13954 except for any that we copy here from the old type.
13956 Past this point, we don't change OLDTYPE and NEWTYPE
13957 even if we change the types of NEWDECL and OLDDECL. */
13961 /* Make sure we put the new type in the same obstack as the old ones.
13962 If the old types are not both in the same obstack, use the permanent
13964 if (TYPE_OBSTACK (oldtype) == TYPE_OBSTACK (newtype))
13965 push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype));
13968 push_obstacks_nochange ();
13969 end_temporary_allocation ();
13972 /* Merge the data types specified in the two decls. */
13973 if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl))
13974 TREE_TYPE (newdecl)
13975 = TREE_TYPE (olddecl)
13976 = TREE_TYPE (newdecl);
13978 /* Lay the type out, unless already done. */
13979 if (oldtype != TREE_TYPE (newdecl))
13981 if (TREE_TYPE (newdecl) != error_mark_node)
13982 layout_type (TREE_TYPE (newdecl));
13983 if (TREE_CODE (newdecl) != FUNCTION_DECL
13984 && TREE_CODE (newdecl) != TYPE_DECL
13985 && TREE_CODE (newdecl) != CONST_DECL)
13986 layout_decl (newdecl, 0);
13990 /* Since the type is OLDDECL's, make OLDDECL's size go with. */
13991 DECL_SIZE (newdecl) = DECL_SIZE (olddecl);
13992 if (TREE_CODE (olddecl) != FUNCTION_DECL)
13993 if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
13994 DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
13997 /* Keep the old rtl since we can safely use it. */
13998 DECL_RTL (newdecl) = DECL_RTL (olddecl);
14000 /* Merge the type qualifiers. */
14001 if (DECL_BUILT_IN_NONANSI (olddecl) && TREE_THIS_VOLATILE (olddecl)
14002 && !TREE_THIS_VOLATILE (newdecl))
14003 TREE_THIS_VOLATILE (olddecl) = 0;
14004 if (TREE_READONLY (newdecl))
14005 TREE_READONLY (olddecl) = 1;
14006 if (TREE_THIS_VOLATILE (newdecl))
14008 TREE_THIS_VOLATILE (olddecl) = 1;
14009 if (TREE_CODE (newdecl) == VAR_DECL)
14010 make_var_volatile (newdecl);
14013 /* Keep source location of definition rather than declaration.
14014 Likewise, keep decl at outer scope. */
14015 if ((DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0)
14016 || (DECL_CONTEXT (newdecl) != 0 && DECL_CONTEXT (olddecl) == 0))
14018 DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl);
14019 DECL_SOURCE_FILE (newdecl) = DECL_SOURCE_FILE (olddecl);
14021 if (DECL_CONTEXT (olddecl) == 0
14022 && TREE_CODE (newdecl) != FUNCTION_DECL)
14023 DECL_CONTEXT (newdecl) = 0;
14026 /* Merge the unused-warning information. */
14027 if (DECL_IN_SYSTEM_HEADER (olddecl))
14028 DECL_IN_SYSTEM_HEADER (newdecl) = 1;
14029 else if (DECL_IN_SYSTEM_HEADER (newdecl))
14030 DECL_IN_SYSTEM_HEADER (olddecl) = 1;
14032 /* Merge the initialization information. */
14033 if (DECL_INITIAL (newdecl) == 0)
14034 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
14036 /* Merge the section attribute.
14037 We want to issue an error if the sections conflict but that must be
14038 done later in decl_attributes since we are called before attributes
14040 if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
14041 DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
14044 if (TREE_CODE (newdecl) == FUNCTION_DECL)
14046 DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
14047 DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
14053 /* If cannot merge, then use the new type and qualifiers,
14054 and don't preserve the old rtl. */
14057 TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
14058 TREE_READONLY (olddecl) = TREE_READONLY (newdecl);
14059 TREE_THIS_VOLATILE (olddecl) = TREE_THIS_VOLATILE (newdecl);
14060 TREE_SIDE_EFFECTS (olddecl) = TREE_SIDE_EFFECTS (newdecl);
14063 /* Merge the storage class information. */
14064 /* For functions, static overrides non-static. */
14065 if (TREE_CODE (newdecl) == FUNCTION_DECL)
14067 TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl);
14068 /* This is since we don't automatically
14069 copy the attributes of NEWDECL into OLDDECL. */
14070 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
14071 /* If this clears `static', clear it in the identifier too. */
14072 if (! TREE_PUBLIC (olddecl))
14073 TREE_PUBLIC (DECL_NAME (olddecl)) = 0;
14075 if (DECL_EXTERNAL (newdecl))
14077 TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
14078 DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
14079 /* An extern decl does not override previous storage class. */
14080 TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
14084 TREE_STATIC (olddecl) = TREE_STATIC (newdecl);
14085 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
14088 /* If either decl says `inline', this fn is inline,
14089 unless its definition was passed already. */
14090 if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == 0)
14091 DECL_INLINE (olddecl) = 1;
14092 DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
14094 /* Get rid of any built-in function if new arg types don't match it
14095 or if we have a function definition. */
14096 if (TREE_CODE (newdecl) == FUNCTION_DECL
14097 && DECL_BUILT_IN (olddecl)
14098 && (!types_match || new_is_definition))
14100 TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
14101 DECL_BUILT_IN (olddecl) = 0;
14104 /* If redeclaring a builtin function, and not a definition,
14106 Also preserve various other info from the definition. */
14107 if (TREE_CODE (newdecl) == FUNCTION_DECL && !new_is_definition)
14109 if (DECL_BUILT_IN (olddecl))
14111 DECL_BUILT_IN (newdecl) = 1;
14112 DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
14115 DECL_FRAME_SIZE (newdecl) = DECL_FRAME_SIZE (olddecl);
14117 DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
14118 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
14119 DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
14120 DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
14123 /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
14124 But preserve olddecl's DECL_UID. */
14126 register unsigned olddecl_uid = DECL_UID (olddecl);
14128 memcpy ((char *) olddecl + sizeof (struct tree_common),
14129 (char *) newdecl + sizeof (struct tree_common),
14130 sizeof (struct tree_decl) - sizeof (struct tree_common));
14131 DECL_UID (olddecl) = olddecl_uid;
14137 /* Finish processing of a declaration;
14138 install its initial value.
14139 If the length of an array type is not known before,
14140 it must be determined now, from the initial value, or it is an error. */
14143 finish_decl (tree decl, tree init, bool is_top_level)
14145 register tree type = TREE_TYPE (decl);
14146 int was_incomplete = (DECL_SIZE (decl) == 0);
14147 int temporary = allocation_temporary_p ();
14148 bool at_top_level = (current_binding_level == global_binding_level);
14149 bool top_level = is_top_level || at_top_level;
14151 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
14153 assert (!is_top_level || !at_top_level);
14155 if (TREE_CODE (decl) == PARM_DECL)
14156 assert (init == NULL_TREE);
14157 /* Remember that PARM_DECL doesn't have a DECL_INITIAL field per se -- it
14158 overlaps DECL_ARG_TYPE. */
14159 else if (init == NULL_TREE)
14160 assert (DECL_INITIAL (decl) == NULL_TREE);
14162 assert (DECL_INITIAL (decl) == error_mark_node);
14164 if (init != NULL_TREE)
14166 if (TREE_CODE (decl) != TYPE_DECL)
14167 DECL_INITIAL (decl) = init;
14170 /* typedef foo = bar; store the type of bar as the type of foo. */
14171 TREE_TYPE (decl) = TREE_TYPE (init);
14172 DECL_INITIAL (decl) = init = 0;
14176 /* Pop back to the obstack that is current for this binding level. This is
14177 because MAXINDEX, rtl, etc. to be made below must go in the permanent
14178 obstack. But don't discard the temporary data yet. */
14181 /* Deduce size of array from initialization, if not already known */
14183 if (TREE_CODE (type) == ARRAY_TYPE
14184 && TYPE_DOMAIN (type) == 0
14185 && TREE_CODE (decl) != TYPE_DECL)
14187 assert (top_level);
14188 assert (was_incomplete);
14190 layout_decl (decl, 0);
14193 if (TREE_CODE (decl) == VAR_DECL)
14195 if (DECL_SIZE (decl) == NULL_TREE
14196 && TYPE_SIZE (TREE_TYPE (decl)) != NULL_TREE)
14197 layout_decl (decl, 0);
14199 if (DECL_SIZE (decl) == NULL_TREE
14200 && (TREE_STATIC (decl)
14202 /* A static variable with an incomplete type is an error if it is
14203 initialized. Also if it is not file scope. Otherwise, let it
14204 through, but if it is not `extern' then it may cause an error
14206 (DECL_INITIAL (decl) != 0 || DECL_CONTEXT (decl) != 0)
14208 /* An automatic variable with an incomplete type is an error. */
14209 !DECL_EXTERNAL (decl)))
14211 assert ("storage size not known" == NULL);
14215 if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
14216 && (DECL_SIZE (decl) != 0)
14217 && (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST))
14219 assert ("storage size not constant" == NULL);
14224 /* Output the assembler code and/or RTL code for variables and functions,
14225 unless the type is an undefined structure or union. If not, it will get
14226 done when the type is completed. */
14228 if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
14230 rest_of_decl_compilation (decl, NULL,
14231 DECL_CONTEXT (decl) == 0,
14234 if (DECL_CONTEXT (decl) != 0)
14236 /* Recompute the RTL of a local array now if it used to be an
14237 incomplete type. */
14239 && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
14241 /* If we used it already as memory, it must stay in memory. */
14242 TREE_ADDRESSABLE (decl) = TREE_USED (decl);
14243 /* If it's still incomplete now, no init will save it. */
14244 if (DECL_SIZE (decl) == 0)
14245 DECL_INITIAL (decl) = 0;
14246 expand_decl (decl);
14248 /* Compute and store the initial value. */
14249 if (TREE_CODE (decl) != FUNCTION_DECL)
14250 expand_decl_init (decl);
14253 else if (TREE_CODE (decl) == TYPE_DECL)
14255 rest_of_decl_compilation (decl, NULL_PTR,
14256 DECL_CONTEXT (decl) == 0,
14260 /* This test used to include TREE_PERMANENT, however, we have the same
14261 problem with initializers at the function level. Such initializers get
14262 saved until the end of the function on the momentary_obstack. */
14263 if (!(TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl))
14265 /* DECL_INITIAL is not defined in PARM_DECLs, since it shares space with
14267 && TREE_CODE (decl) != PARM_DECL)
14269 /* We need to remember that this array HAD an initialization, but
14270 discard the actual temporary nodes, since we can't have a permanent
14271 node keep pointing to them. */
14272 /* We make an exception for inline functions, since it's normal for a
14273 local extern redeclaration of an inline function to have a copy of
14274 the top-level decl's DECL_INLINE. */
14275 if ((DECL_INITIAL (decl) != 0)
14276 && (DECL_INITIAL (decl) != error_mark_node))
14278 /* If this is a const variable, then preserve the
14279 initializer instead of discarding it so that we can optimize
14280 references to it. */
14281 /* This test used to include TREE_STATIC, but this won't be set
14282 for function level initializers. */
14283 if (TREE_READONLY (decl))
14285 preserve_initializer ();
14286 /* Hack? Set the permanent bit for something that is
14287 permanent, but not on the permenent obstack, so as to
14288 convince output_constant_def to make its rtl on the
14289 permanent obstack. */
14290 TREE_PERMANENT (DECL_INITIAL (decl)) = 1;
14292 /* The initializer and DECL must have the same (or equivalent
14293 types), but if the initializer is a STRING_CST, its type
14294 might not be on the right obstack, so copy the type
14296 TREE_TYPE (DECL_INITIAL (decl)) = type;
14299 DECL_INITIAL (decl) = error_mark_node;
14303 /* If requested, warn about definitions of large data objects. */
14305 if (warn_larger_than
14306 && (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
14307 && !DECL_EXTERNAL (decl))
14309 register tree decl_size = DECL_SIZE (decl);
14311 if (decl_size && TREE_CODE (decl_size) == INTEGER_CST)
14313 unsigned units = TREE_INT_CST_LOW (decl_size) / BITS_PER_UNIT;
14315 if (units > larger_than_size)
14316 warning_with_decl (decl, "size of `%s' is %u bytes", units);
14320 /* If we have gone back from temporary to permanent allocation, actually
14321 free the temporary space that we no longer need. */
14322 if (temporary && !allocation_temporary_p ())
14323 permanent_allocation (0);
14325 /* At the end of a declaration, throw away any variable type sizes of types
14326 defined inside that declaration. There is no use computing them in the
14327 following function definition. */
14328 if (current_binding_level == global_binding_level)
14329 get_pending_sizes ();
14332 /* Finish up a function declaration and compile that function
14333 all the way to assembler language output. The free the storage
14334 for the function definition.
14336 This is called after parsing the body of the function definition.
14338 NESTED is nonzero if the function being finished is nested in another. */
14341 finish_function (int nested)
14343 register tree fndecl = current_function_decl;
14345 assert (fndecl != NULL_TREE);
14346 if (TREE_CODE (fndecl) != ERROR_MARK)
14349 assert (DECL_CONTEXT (fndecl) != NULL_TREE);
14351 assert (DECL_CONTEXT (fndecl) == NULL_TREE);
14354 /* TREE_READONLY (fndecl) = 1;
14355 This caused &foo to be of type ptr-to-const-function
14356 which then got a warning when stored in a ptr-to-function variable. */
14358 poplevel (1, 0, 1);
14360 if (TREE_CODE (fndecl) != ERROR_MARK)
14362 BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
14364 /* Must mark the RESULT_DECL as being in this function. */
14366 DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
14368 /* Obey `register' declarations if `setjmp' is called in this fn. */
14369 /* Generate rtl for function exit. */
14370 expand_function_end (input_filename, lineno, 0);
14372 /* So we can tell if jump_optimize sets it to 1. */
14375 /* Run the optimizers and output the assembler code for this function. */
14376 rest_of_compilation (fndecl);
14379 /* Free all the tree nodes making up this function. */
14380 /* Switch back to allocating nodes permanently until we start another
14383 permanent_allocation (1);
14385 if (TREE_CODE (fndecl) != ERROR_MARK
14387 && DECL_SAVED_INSNS (fndecl) == 0)
14389 /* Stop pointing to the local nodes about to be freed. */
14390 /* But DECL_INITIAL must remain nonzero so we know this was an actual
14391 function definition. */
14392 /* For a nested function, this is done in pop_f_function_context. */
14393 /* If rest_of_compilation set this to 0, leave it 0. */
14394 if (DECL_INITIAL (fndecl) != 0)
14395 DECL_INITIAL (fndecl) = error_mark_node;
14396 DECL_ARGUMENTS (fndecl) = 0;
14401 /* Let the error reporting routines know that we're outside a function.
14402 For a nested function, this value is used in pop_c_function_context
14403 and then reset via pop_function_context. */
14404 ffecom_outer_function_decl_ = current_function_decl = NULL;
14408 /* Plug-in replacement for identifying the name of a decl and, for a
14409 function, what we call it in diagnostics. For now, "program unit"
14410 should suffice, since it's a bit of a hassle to figure out which
14411 of several kinds of things it is. Note that it could conceivably
14412 be a statement function, which probably isn't really a program unit
14413 per se, but if that comes up, it should be easy to check (being a
14414 nested function and all). */
14417 lang_printable_name (tree decl, int v)
14419 /* Just to keep GCC quiet about the unused variable.
14420 In theory, differing values of V should produce different
14425 if (TREE_CODE (decl) == ERROR_MARK)
14426 return "erroneous code";
14427 return IDENTIFIER_POINTER (DECL_NAME (decl));
14431 /* g77's function to print out name of current function that caused
14436 lang_print_error_function (file)
14439 static ffeglobal last_g = NULL;
14440 static ffesymbol last_s = NULL;
14445 if ((ffecom_primary_entry_ == NULL)
14446 || (ffesymbol_global (ffecom_primary_entry_) == NULL))
14454 g = ffesymbol_global (ffecom_primary_entry_);
14455 if (ffecom_nested_entry_ == NULL)
14457 s = ffecom_primary_entry_;
14458 switch (ffesymbol_kind (s))
14460 case FFEINFO_kindFUNCTION:
14464 case FFEINFO_kindSUBROUTINE:
14465 kind = "subroutine";
14468 case FFEINFO_kindPROGRAM:
14472 case FFEINFO_kindBLOCKDATA:
14473 kind = "block-data";
14477 kind = ffeinfo_kind_message (ffesymbol_kind (s));
14483 s = ffecom_nested_entry_;
14484 kind = "statement function";
14488 if ((last_g != g) || (last_s != s))
14491 fprintf (stderr, "%s: ", file);
14494 fprintf (stderr, "Outside of any program unit:\n");
14497 const char *name = ffesymbol_text (s);
14499 fprintf (stderr, "In %s `%s':\n", kind, name);
14508 /* Similar to `lookup_name' but look only at current binding level. */
14511 lookup_name_current_level (tree name)
14515 if (current_binding_level == global_binding_level)
14516 return IDENTIFIER_GLOBAL_VALUE (name);
14518 if (IDENTIFIER_LOCAL_VALUE (name) == 0)
14521 for (t = current_binding_level->names; t; t = TREE_CHAIN (t))
14522 if (DECL_NAME (t) == name)
14528 /* Create a new `struct binding_level'. */
14530 static struct binding_level *
14531 make_binding_level ()
14534 return (struct binding_level *) xmalloc (sizeof (struct binding_level));
14537 /* Save and restore the variables in this file and elsewhere
14538 that keep track of the progress of compilation of the current function.
14539 Used for nested functions. */
14543 struct f_function *next;
14545 tree shadowed_labels;
14546 struct binding_level *binding_level;
14549 struct f_function *f_function_chain;
14551 /* Restore the variables used during compilation of a C function. */
14554 pop_f_function_context ()
14556 struct f_function *p = f_function_chain;
14559 /* Bring back all the labels that were shadowed. */
14560 for (link = shadowed_labels; link; link = TREE_CHAIN (link))
14561 if (DECL_NAME (TREE_VALUE (link)) != 0)
14562 IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)))
14563 = TREE_VALUE (link);
14565 if (current_function_decl != error_mark_node
14566 && DECL_SAVED_INSNS (current_function_decl) == 0)
14568 /* Stop pointing to the local nodes about to be freed. */
14569 /* But DECL_INITIAL must remain nonzero so we know this was an actual
14570 function definition. */
14571 DECL_INITIAL (current_function_decl) = error_mark_node;
14572 DECL_ARGUMENTS (current_function_decl) = 0;
14575 pop_function_context ();
14577 f_function_chain = p->next;
14579 named_labels = p->named_labels;
14580 shadowed_labels = p->shadowed_labels;
14581 current_binding_level = p->binding_level;
14586 /* Save and reinitialize the variables
14587 used during compilation of a C function. */
14590 push_f_function_context ()
14592 struct f_function *p
14593 = (struct f_function *) xmalloc (sizeof (struct f_function));
14595 push_function_context ();
14597 p->next = f_function_chain;
14598 f_function_chain = p;
14600 p->named_labels = named_labels;
14601 p->shadowed_labels = shadowed_labels;
14602 p->binding_level = current_binding_level;
14606 push_parm_decl (tree parm)
14608 int old_immediate_size_expand = immediate_size_expand;
14610 /* Don't try computing parm sizes now -- wait till fn is called. */
14612 immediate_size_expand = 0;
14614 push_obstacks_nochange ();
14616 /* Fill in arg stuff. */
14618 DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
14619 DECL_ARG_TYPE_AS_WRITTEN (parm) = TREE_TYPE (parm);
14620 TREE_READONLY (parm) = 1; /* All implementation args are read-only. */
14622 parm = pushdecl (parm);
14624 immediate_size_expand = old_immediate_size_expand;
14626 finish_decl (parm, NULL_TREE, FALSE);
14629 /* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL, if appropriate. */
14632 pushdecl_top_level (x)
14636 register struct binding_level *b = current_binding_level;
14637 register tree f = current_function_decl;
14639 current_binding_level = global_binding_level;
14640 current_function_decl = NULL_TREE;
14642 current_binding_level = b;
14643 current_function_decl = f;
14647 /* Store the list of declarations of the current level.
14648 This is done for the parameter declarations of a function being defined,
14649 after they are modified in the light of any missing parameters. */
14655 return current_binding_level->names = decls;
14658 /* Store the parameter declarations into the current function declaration.
14659 This is called after parsing the parameter declarations, before
14660 digesting the body of the function.
14662 For an old-style definition, modify the function's type
14663 to specify at least the number of arguments. */
14666 store_parm_decls (int is_main_program UNUSED)
14668 register tree fndecl = current_function_decl;
14670 if (fndecl == error_mark_node)
14673 /* This is a chain of PARM_DECLs from old-style parm declarations. */
14674 DECL_ARGUMENTS (fndecl) = storedecls (nreverse (getdecls ()));
14676 /* Initialize the RTL code for the function. */
14678 init_function_start (fndecl, input_filename, lineno);
14680 /* Set up parameters and prepare for return, for the function. */
14682 expand_function_start (fndecl, 0);
14686 start_decl (tree decl, bool is_top_level)
14689 bool at_top_level = (current_binding_level == global_binding_level);
14690 bool top_level = is_top_level || at_top_level;
14692 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
14694 assert (!is_top_level || !at_top_level);
14696 /* The corresponding pop_obstacks is in finish_decl. */
14697 push_obstacks_nochange ();
14699 if (DECL_INITIAL (decl) != NULL_TREE)
14701 assert (DECL_INITIAL (decl) == error_mark_node);
14702 assert (!DECL_EXTERNAL (decl));
14704 else if (top_level)
14705 assert ((TREE_STATIC (decl) == 1) || DECL_EXTERNAL (decl) == 1);
14707 /* For Fortran, we by default put things in .common when possible. */
14708 DECL_COMMON (decl) = 1;
14710 /* Add this decl to the current binding level. TEM may equal DECL or it may
14711 be a previous decl of the same name. */
14713 tem = pushdecl_top_level (decl);
14715 tem = pushdecl (decl);
14717 /* For a local variable, define the RTL now. */
14719 /* But not if this is a duplicate decl and we preserved the rtl from the
14720 previous one (which may or may not happen). */
14721 && DECL_RTL (tem) == 0)
14723 if (TYPE_SIZE (TREE_TYPE (tem)) != 0)
14725 else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
14726 && DECL_INITIAL (tem) != 0)
14730 if (DECL_INITIAL (tem) != NULL_TREE)
14732 /* When parsing and digesting the initializer, use temporary storage.
14733 Do this even if we will ignore the value. */
14735 temporary_allocation ();
14741 /* Create the FUNCTION_DECL for a function definition.
14742 DECLSPECS and DECLARATOR are the parts of the declaration;
14743 they describe the function's name and the type it returns,
14744 but twisted together in a fashion that parallels the syntax of C.
14746 This function creates a binding context for the function body
14747 as well as setting up the FUNCTION_DECL in current_function_decl.
14749 Returns 1 on success. If the DECLARATOR is not suitable for a function
14750 (it defines a datum instead), we return 0, which tells
14751 yyparse to report a parse error.
14753 NESTED is nonzero for a function nested within another function. */
14756 start_function (tree name, tree type, int nested, int public)
14760 int old_immediate_size_expand = immediate_size_expand;
14763 shadowed_labels = 0;
14765 /* Don't expand any sizes in the return type of the function. */
14766 immediate_size_expand = 0;
14771 assert (current_function_decl != NULL_TREE);
14772 assert (DECL_CONTEXT (current_function_decl) == NULL_TREE);
14776 assert (current_function_decl == NULL_TREE);
14779 if (TREE_CODE (type) == ERROR_MARK)
14780 decl1 = current_function_decl = error_mark_node;
14783 decl1 = build_decl (FUNCTION_DECL,
14786 TREE_PUBLIC (decl1) = public ? 1 : 0;
14788 DECL_INLINE (decl1) = 1;
14789 TREE_STATIC (decl1) = 1;
14790 DECL_EXTERNAL (decl1) = 0;
14792 announce_function (decl1);
14794 /* Make the init_value nonzero so pushdecl knows this is not tentative.
14795 error_mark_node is replaced below (in poplevel) with the BLOCK. */
14796 DECL_INITIAL (decl1) = error_mark_node;
14798 /* Record the decl so that the function name is defined. If we already have
14799 a decl for this name, and it is a FUNCTION_DECL, use the old decl. */
14801 current_function_decl = pushdecl (decl1);
14805 ffecom_outer_function_decl_ = current_function_decl;
14808 current_binding_level->prep_state = 2;
14810 if (TREE_CODE (current_function_decl) != ERROR_MARK)
14812 make_function_rtl (current_function_decl);
14814 restype = TREE_TYPE (TREE_TYPE (current_function_decl));
14815 DECL_RESULT (current_function_decl)
14816 = build_decl (RESULT_DECL, NULL_TREE, restype);
14820 /* Allocate further tree nodes temporarily during compilation of this
14822 temporary_allocation ();
14824 if (!nested && (TREE_CODE (current_function_decl) != ERROR_MARK))
14825 TREE_ADDRESSABLE (current_function_decl) = 1;
14827 immediate_size_expand = old_immediate_size_expand;
14830 /* Here are the public functions the GNU back end needs. */
14833 convert (type, expr)
14836 register tree e = expr;
14837 register enum tree_code code = TREE_CODE (type);
14839 if (type == TREE_TYPE (e)
14840 || TREE_CODE (e) == ERROR_MARK)
14842 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
14843 return fold (build1 (NOP_EXPR, type, e));
14844 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
14845 || code == ERROR_MARK)
14846 return error_mark_node;
14847 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
14849 assert ("void value not ignored as it ought to be" == NULL);
14850 return error_mark_node;
14852 if (code == VOID_TYPE)
14853 return build1 (CONVERT_EXPR, type, e);
14854 if ((code != RECORD_TYPE)
14855 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
14856 e = ffecom_1 (REALPART_EXPR, TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e))),
14858 if (code == INTEGER_TYPE || code == ENUMERAL_TYPE)
14859 return fold (convert_to_integer (type, e));
14860 if (code == POINTER_TYPE)
14861 return fold (convert_to_pointer (type, e));
14862 if (code == REAL_TYPE)
14863 return fold (convert_to_real (type, e));
14864 if (code == COMPLEX_TYPE)
14865 return fold (convert_to_complex (type, e));
14866 if (code == RECORD_TYPE)
14867 return fold (ffecom_convert_to_complex_ (type, e));
14869 assert ("conversion to non-scalar type requested" == NULL);
14870 return error_mark_node;
14873 /* integrate_decl_tree calls this function, but since we don't use the
14874 DECL_LANG_SPECIFIC field, this is a no-op. */
14877 copy_lang_decl (node)
14882 /* Return the list of declarations of the current level.
14883 Note that this list is in reverse order unless/until
14884 you nreverse it; and when you do nreverse it, you must
14885 store the result back using `storedecls' or you will lose. */
14890 return current_binding_level->names;
14893 /* Nonzero if we are currently in the global binding level. */
14896 global_bindings_p ()
14898 return current_binding_level == global_binding_level;
14901 /* Print an error message for invalid use of an incomplete type.
14902 VALUE is the expression that was used (or 0 if that isn't known)
14903 and TYPE is the type that was invalid. */
14906 incomplete_type_error (value, type)
14910 if (TREE_CODE (type) == ERROR_MARK)
14913 assert ("incomplete type?!?" == NULL);
14917 init_decl_processing ()
14924 init_parse (filename)
14928 extern void (*print_error_function) (char *);
14931 /* Open input file. */
14932 if (filename == 0 || !strcmp (filename, "-"))
14935 filename = "stdin";
14938 finput = fopen (filename, "r");
14940 pfatal_with_name (filename);
14942 #ifdef IO_BUFFER_SIZE
14943 setvbuf (finput, (char *) xmalloc (IO_BUFFER_SIZE), _IOFBF, IO_BUFFER_SIZE);
14946 /* Make identifier nodes long enough for the language-specific slots. */
14947 set_identifier_size (sizeof (struct lang_identifier));
14948 decl_printable_name = lang_printable_name;
14950 print_error_function = lang_print_error_function;
14962 /* Delete the node BLOCK from the current binding level.
14963 This is used for the block inside a stmt expr ({...})
14964 so that the block can be reinserted where appropriate. */
14967 delete_block (block)
14971 if (current_binding_level->blocks == block)
14972 current_binding_level->blocks = TREE_CHAIN (block);
14973 for (t = current_binding_level->blocks; t;)
14975 if (TREE_CHAIN (t) == block)
14976 TREE_CHAIN (t) = TREE_CHAIN (block);
14978 t = TREE_CHAIN (t);
14980 TREE_CHAIN (block) = NULL;
14981 /* Clear TREE_USED which is always set by poplevel.
14982 The flag is set again if insert_block is called. */
14983 TREE_USED (block) = 0;
14987 insert_block (block)
14990 TREE_USED (block) = 1;
14991 current_binding_level->blocks
14992 = chainon (current_binding_level->blocks, block);
14996 lang_decode_option (argc, argv)
15000 return ffe_decode_option (argc, argv);
15003 /* used by print-tree.c */
15006 lang_print_xnode (file, node, indent)
15016 ffe_terminate_0 ();
15018 if (ffe_is_ffedebug ())
15019 malloc_pool_display (malloc_pool_image ());
15029 lang_init_options ()
15031 /* Set default options for Fortran. */
15032 flag_move_all_movables = 1;
15033 flag_reduce_all_givs = 1;
15034 flag_argument_noalias = 2;
15035 flag_errno_math = 0;
15036 flag_complex_divide_method = 1;
15042 /* If the file is output from cpp, it should contain a first line
15043 `# 1 "real-filename"', and the current design of gcc (toplev.c
15044 in particular and the way it sets up information relied on by
15045 INCLUDE) requires that we read this now, and store the
15046 "real-filename" info in master_input_filename. Ask the lexer
15047 to try doing this. */
15048 ffelex_hash_kludge (finput);
15052 mark_addressable (exp)
15055 register tree x = exp;
15057 switch (TREE_CODE (x))
15060 case COMPONENT_REF:
15062 x = TREE_OPERAND (x, 0);
15066 TREE_ADDRESSABLE (x) = 1;
15073 if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x)
15074 && DECL_NONLOCAL (x))
15076 if (TREE_PUBLIC (x))
15078 assert ("address of global register var requested" == NULL);
15081 assert ("address of register variable requested" == NULL);
15083 else if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x))
15085 if (TREE_PUBLIC (x))
15087 assert ("address of global register var requested" == NULL);
15090 assert ("address of register var requested" == NULL);
15092 put_var_into_stack (x);
15095 case FUNCTION_DECL:
15096 TREE_ADDRESSABLE (x) = 1;
15097 #if 0 /* poplevel deals with this now. */
15098 if (DECL_CONTEXT (x) == 0)
15099 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;
15107 /* If DECL has a cleanup, build and return that cleanup here.
15108 This is a callback called by expand_expr. */
15111 maybe_build_cleanup (decl)
15114 /* There are no cleanups in Fortran. */
15118 /* Exit a binding level.
15119 Pop the level off, and restore the state of the identifier-decl mappings
15120 that were in effect when this level was entered.
15122 If KEEP is nonzero, this level had explicit declarations, so
15123 and create a "block" (a BLOCK node) for the level
15124 to record its declarations and subblocks for symbol table output.
15126 If FUNCTIONBODY is nonzero, this level is the body of a function,
15127 so create a block as if KEEP were set and also clear out all
15130 If REVERSE is nonzero, reverse the order of decls before putting
15131 them into the BLOCK. */
15134 poplevel (keep, reverse, functionbody)
15139 register tree link;
15140 /* The chain of decls was accumulated in reverse order.
15141 Put it into forward order, just for cleanliness. */
15143 tree subblocks = current_binding_level->blocks;
15146 int block_previously_created;
15148 /* Get the decls in the order they were written.
15149 Usually current_binding_level->names is in reverse order.
15150 But parameter decls were previously put in forward order. */
15153 current_binding_level->names
15154 = decls = nreverse (current_binding_level->names);
15156 decls = current_binding_level->names;
15158 /* Output any nested inline functions within this block
15159 if they weren't already output. */
15161 for (decl = decls; decl; decl = TREE_CHAIN (decl))
15162 if (TREE_CODE (decl) == FUNCTION_DECL
15163 && ! TREE_ASM_WRITTEN (decl)
15164 && DECL_INITIAL (decl) != 0
15165 && TREE_ADDRESSABLE (decl))
15167 /* If this decl was copied from a file-scope decl
15168 on account of a block-scope extern decl,
15169 propagate TREE_ADDRESSABLE to the file-scope decl.
15171 DECL_ABSTRACT_ORIGIN can be set to itself if warn_return_type is
15172 true, since then the decl goes through save_for_inline_copying. */
15173 if (DECL_ABSTRACT_ORIGIN (decl) != 0
15174 && DECL_ABSTRACT_ORIGIN (decl) != decl)
15175 TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
15176 else if (DECL_SAVED_INSNS (decl) != 0)
15178 push_function_context ();
15179 output_inline_function (decl);
15180 pop_function_context ();
15184 /* If there were any declarations or structure tags in that level,
15185 or if this level is a function body,
15186 create a BLOCK to record them for the life of this function. */
15189 block_previously_created = (current_binding_level->this_block != 0);
15190 if (block_previously_created)
15191 block = current_binding_level->this_block;
15192 else if (keep || functionbody)
15193 block = make_node (BLOCK);
15196 BLOCK_VARS (block) = decls;
15197 BLOCK_SUBBLOCKS (block) = subblocks;
15198 remember_end_note (block);
15201 /* In each subblock, record that this is its superior. */
15203 for (link = subblocks; link; link = TREE_CHAIN (link))
15204 BLOCK_SUPERCONTEXT (link) = block;
15206 /* Clear out the meanings of the local variables of this level. */
15208 for (link = decls; link; link = TREE_CHAIN (link))
15210 if (DECL_NAME (link) != 0)
15212 /* If the ident. was used or addressed via a local extern decl,
15213 don't forget that fact. */
15214 if (DECL_EXTERNAL (link))
15216 if (TREE_USED (link))
15217 TREE_USED (DECL_NAME (link)) = 1;
15218 if (TREE_ADDRESSABLE (link))
15219 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1;
15221 IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = 0;
15225 /* If the level being exited is the top level of a function,
15226 check over all the labels, and clear out the current
15227 (function local) meanings of their names. */
15231 /* If this is the top level block of a function,
15232 the vars are the function's parameters.
15233 Don't leave them in the BLOCK because they are
15234 found in the FUNCTION_DECL instead. */
15236 BLOCK_VARS (block) = 0;
15239 /* Pop the current level, and free the structure for reuse. */
15242 register struct binding_level *level = current_binding_level;
15243 current_binding_level = current_binding_level->level_chain;
15245 level->level_chain = free_binding_level;
15246 free_binding_level = level;
15249 /* Dispose of the block that we just made inside some higher level. */
15251 && current_function_decl != error_mark_node)
15252 DECL_INITIAL (current_function_decl) = block;
15255 if (!block_previously_created)
15256 current_binding_level->blocks
15257 = chainon (current_binding_level->blocks, block);
15259 /* If we did not make a block for the level just exited,
15260 any blocks made for inner levels
15261 (since they cannot be recorded as subblocks in that level)
15262 must be carried forward so they will later become subblocks
15263 of something else. */
15264 else if (subblocks)
15265 current_binding_level->blocks
15266 = chainon (current_binding_level->blocks, subblocks);
15269 TREE_USED (block) = 1;
15274 print_lang_decl (file, node, indent)
15282 print_lang_identifier (file, node, indent)
15287 print_node (file, "global", IDENTIFIER_GLOBAL_VALUE (node), indent + 4);
15288 print_node (file, "local", IDENTIFIER_LOCAL_VALUE (node), indent + 4);
15292 print_lang_statistics ()
15297 print_lang_type (file, node, indent)
15304 /* Record a decl-node X as belonging to the current lexical scope.
15305 Check for errors (such as an incompatible declaration for the same
15306 name already seen in the same scope).
15308 Returns either X or an old decl for the same name.
15309 If an old decl is returned, it may have been smashed
15310 to agree with what X says. */
15317 register tree name = DECL_NAME (x);
15318 register struct binding_level *b = current_binding_level;
15320 if ((TREE_CODE (x) == FUNCTION_DECL)
15321 && (DECL_INITIAL (x) == 0)
15322 && DECL_EXTERNAL (x))
15323 DECL_CONTEXT (x) = NULL_TREE;
15325 DECL_CONTEXT (x) = current_function_decl;
15329 if (IDENTIFIER_INVENTED (name))
15332 DECL_ARTIFICIAL (x) = 1;
15334 DECL_IN_SYSTEM_HEADER (x) = 1;
15337 t = lookup_name_current_level (name);
15339 assert ((t == NULL_TREE) || (DECL_CONTEXT (x) == NULL_TREE));
15341 /* Don't push non-parms onto list for parms until we understand
15342 why we're doing this and whether it works. */
15344 assert ((b == global_binding_level)
15345 || !ffecom_transform_only_dummies_
15346 || TREE_CODE (x) == PARM_DECL);
15348 if ((t != NULL_TREE) && duplicate_decls (x, t))
15351 /* If we are processing a typedef statement, generate a whole new
15352 ..._TYPE node (which will be just an variant of the existing
15353 ..._TYPE node with identical properties) and then install the
15354 TYPE_DECL node generated to represent the typedef name as the
15355 TYPE_NAME of this brand new (duplicate) ..._TYPE node.
15357 The whole point here is to end up with a situation where each and every
15358 ..._TYPE node the compiler creates will be uniquely associated with
15359 AT MOST one node representing a typedef name. This way, even though
15360 the compiler substitutes corresponding ..._TYPE nodes for TYPE_DECL
15361 (i.e. "typedef name") nodes very early on, later parts of the
15362 compiler can always do the reverse translation and get back the
15363 corresponding typedef name. For example, given:
15365 typedef struct S MY_TYPE; MY_TYPE object;
15367 Later parts of the compiler might only know that `object' was of type
15368 `struct S' if it were not for code just below. With this code
15369 however, later parts of the compiler see something like:
15371 struct S' == struct S typedef struct S' MY_TYPE; struct S' object;
15373 And they can then deduce (from the node for type struct S') that the
15374 original object declaration was:
15378 Being able to do this is important for proper support of protoize, and
15379 also for generating precise symbolic debugging information which
15380 takes full account of the programmer's (typedef) vocabulary.
15382 Obviously, we don't want to generate a duplicate ..._TYPE node if the
15383 TYPE_DECL node that we are now processing really represents a
15384 standard built-in type.
15386 Since all standard types are effectively declared at line zero in the
15387 source file, we can easily check to see if we are working on a
15388 standard type by checking the current value of lineno. */
15390 if (TREE_CODE (x) == TYPE_DECL)
15392 if (DECL_SOURCE_LINE (x) == 0)
15394 if (TYPE_NAME (TREE_TYPE (x)) == 0)
15395 TYPE_NAME (TREE_TYPE (x)) = x;
15397 else if (TREE_TYPE (x) != error_mark_node)
15399 tree tt = TREE_TYPE (x);
15401 tt = build_type_copy (tt);
15402 TYPE_NAME (tt) = x;
15403 TREE_TYPE (x) = tt;
15407 /* This name is new in its binding level. Install the new declaration
15409 if (b == global_binding_level)
15410 IDENTIFIER_GLOBAL_VALUE (name) = x;
15412 IDENTIFIER_LOCAL_VALUE (name) = x;
15415 /* Put decls on list in reverse order. We will reverse them later if
15417 TREE_CHAIN (x) = b->names;
15423 /* Nonzero if the current level needs to have a BLOCK made. */
15430 for (decl = current_binding_level->names;
15432 decl = TREE_CHAIN (decl))
15434 if (TREE_USED (decl) || TREE_CODE (decl) != VAR_DECL
15435 || (DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl)))
15436 /* Currently, there aren't supposed to be non-artificial names
15437 at other than the top block for a function -- they're
15438 believed to always be temps. But it's wise to check anyway. */
15444 /* Enter a new binding level.
15445 If TAG_TRANSPARENT is nonzero, do so only for the name space of variables,
15446 not for that of tags. */
15449 pushlevel (tag_transparent)
15450 int tag_transparent;
15452 register struct binding_level *newlevel = NULL_BINDING_LEVEL;
15454 assert (! tag_transparent);
15456 if (current_binding_level == global_binding_level)
15461 /* Reuse or create a struct for this binding level. */
15463 if (free_binding_level)
15465 newlevel = free_binding_level;
15466 free_binding_level = free_binding_level->level_chain;
15470 newlevel = make_binding_level ();
15473 /* Add this level to the front of the chain (stack) of levels that
15476 *newlevel = clear_binding_level;
15477 newlevel->level_chain = current_binding_level;
15478 current_binding_level = newlevel;
15481 /* Set the BLOCK node for the innermost scope
15482 (the one we are currently in). */
15486 register tree block;
15488 current_binding_level->this_block = block;
15491 /* ~~gcc/tree.h *should* declare this, because toplev.c references it. */
15493 /* Can't 'yydebug' a front end not generated by yacc/bison! */
15496 set_yydebug (value)
15500 fprintf (stderr, "warning: no yacc/bison-generated output to debug!\n");
15504 signed_or_unsigned_type (unsignedp, type)
15510 if (! INTEGRAL_TYPE_P (type))
15512 if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node))
15513 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15514 if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
15515 return unsignedp ? unsigned_type_node : integer_type_node;
15516 if (TYPE_PRECISION (type) == TYPE_PRECISION (short_integer_type_node))
15517 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15518 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_integer_type_node))
15519 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15520 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_long_integer_type_node))
15521 return (unsignedp ? long_long_unsigned_type_node
15522 : long_long_integer_type_node);
15524 type2 = type_for_size (TYPE_PRECISION (type), unsignedp);
15525 if (type2 == NULL_TREE)
15535 tree type1 = TYPE_MAIN_VARIANT (type);
15536 ffeinfoKindtype kt;
15539 if (type1 == unsigned_char_type_node || type1 == char_type_node)
15540 return signed_char_type_node;
15541 if (type1 == unsigned_type_node)
15542 return integer_type_node;
15543 if (type1 == short_unsigned_type_node)
15544 return short_integer_type_node;
15545 if (type1 == long_unsigned_type_node)
15546 return long_integer_type_node;
15547 if (type1 == long_long_unsigned_type_node)
15548 return long_long_integer_type_node;
15549 #if 0 /* gcc/c-* files only */
15550 if (type1 == unsigned_intDI_type_node)
15551 return intDI_type_node;
15552 if (type1 == unsigned_intSI_type_node)
15553 return intSI_type_node;
15554 if (type1 == unsigned_intHI_type_node)
15555 return intHI_type_node;
15556 if (type1 == unsigned_intQI_type_node)
15557 return intQI_type_node;
15560 type2 = type_for_size (TYPE_PRECISION (type1), 0);
15561 if (type2 != NULL_TREE)
15564 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15566 type2 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
15568 if (type1 == type2)
15569 return ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15575 /* Prepare expr to be an argument of a TRUTH_NOT_EXPR,
15576 or validate its data type for an `if' or `while' statement or ?..: exp.
15578 This preparation consists of taking the ordinary
15579 representation of an expression expr and producing a valid tree
15580 boolean expression describing whether expr is nonzero. We could
15581 simply always do build_binary_op (NE_EXPR, expr, integer_zero_node, 1),
15582 but we optimize comparisons, &&, ||, and !.
15584 The resulting type should always be `integer_type_node'. */
15587 truthvalue_conversion (expr)
15590 if (TREE_CODE (expr) == ERROR_MARK)
15593 #if 0 /* This appears to be wrong for C++. */
15594 /* These really should return error_mark_node after 2.4 is stable.
15595 But not all callers handle ERROR_MARK properly. */
15596 switch (TREE_CODE (TREE_TYPE (expr)))
15599 error ("struct type value used where scalar is required");
15600 return integer_zero_node;
15603 error ("union type value used where scalar is required");
15604 return integer_zero_node;
15607 error ("array type value used where scalar is required");
15608 return integer_zero_node;
15615 switch (TREE_CODE (expr))
15617 /* It is simpler and generates better code to have only TRUTH_*_EXPR
15618 or comparison expressions as truth values at this level. */
15620 case COMPONENT_REF:
15621 /* A one-bit unsigned bit-field is already acceptable. */
15622 if (1 == TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (expr, 1)))
15623 && TREE_UNSIGNED (TREE_OPERAND (expr, 1)))
15629 /* It is simpler and generates better code to have only TRUTH_*_EXPR
15630 or comparison expressions as truth values at this level. */
15632 if (integer_zerop (TREE_OPERAND (expr, 1)))
15633 return build_unary_op (TRUTH_NOT_EXPR, TREE_OPERAND (expr, 0), 0);
15635 case NE_EXPR: case LE_EXPR: case GE_EXPR: case LT_EXPR: case GT_EXPR:
15636 case TRUTH_ANDIF_EXPR:
15637 case TRUTH_ORIF_EXPR:
15638 case TRUTH_AND_EXPR:
15639 case TRUTH_OR_EXPR:
15640 case TRUTH_XOR_EXPR:
15641 TREE_TYPE (expr) = integer_type_node;
15648 return integer_zerop (expr) ? integer_zero_node : integer_one_node;
15651 return real_zerop (expr) ? integer_zero_node : integer_one_node;
15654 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 0)))
15655 return build (COMPOUND_EXPR, integer_type_node,
15656 TREE_OPERAND (expr, 0), integer_one_node);
15658 return integer_one_node;
15661 return ffecom_2 ((TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
15662 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
15664 truthvalue_conversion (TREE_OPERAND (expr, 0)),
15665 truthvalue_conversion (TREE_OPERAND (expr, 1)));
15671 /* These don't change whether an object is non-zero or zero. */
15672 return truthvalue_conversion (TREE_OPERAND (expr, 0));
15676 /* These don't change whether an object is zero or non-zero, but
15677 we can't ignore them if their second arg has side-effects. */
15678 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
15679 return build (COMPOUND_EXPR, integer_type_node, TREE_OPERAND (expr, 1),
15680 truthvalue_conversion (TREE_OPERAND (expr, 0)));
15682 return truthvalue_conversion (TREE_OPERAND (expr, 0));
15685 /* Distribute the conversion into the arms of a COND_EXPR. */
15686 return fold (build (COND_EXPR, integer_type_node, TREE_OPERAND (expr, 0),
15687 truthvalue_conversion (TREE_OPERAND (expr, 1)),
15688 truthvalue_conversion (TREE_OPERAND (expr, 2))));
15691 /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
15692 since that affects how `default_conversion' will behave. */
15693 if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE
15694 || TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE)
15696 /* fall through... */
15698 /* If this is widening the argument, we can ignore it. */
15699 if (TYPE_PRECISION (TREE_TYPE (expr))
15700 >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))
15701 return truthvalue_conversion (TREE_OPERAND (expr, 0));
15705 /* With IEEE arithmetic, x - x may not equal 0, so we can't optimize
15707 if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
15708 && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE)
15710 /* fall through... */
15712 /* This and MINUS_EXPR can be changed into a comparison of the
15714 if (TREE_TYPE (TREE_OPERAND (expr, 0))
15715 == TREE_TYPE (TREE_OPERAND (expr, 1)))
15716 return ffecom_2 (NE_EXPR, integer_type_node,
15717 TREE_OPERAND (expr, 0),
15718 TREE_OPERAND (expr, 1));
15719 return ffecom_2 (NE_EXPR, integer_type_node,
15720 TREE_OPERAND (expr, 0),
15721 fold (build1 (NOP_EXPR,
15722 TREE_TYPE (TREE_OPERAND (expr, 0)),
15723 TREE_OPERAND (expr, 1))));
15726 if (integer_onep (TREE_OPERAND (expr, 1)))
15731 #if 0 /* No such thing in Fortran. */
15732 if (warn_parentheses && C_EXP_ORIGINAL_CODE (expr) == MODIFY_EXPR)
15733 warning ("suggest parentheses around assignment used as truth value");
15741 if (TREE_CODE (TREE_TYPE (expr)) == COMPLEX_TYPE)
15743 ((TREE_SIDE_EFFECTS (expr)
15744 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
15746 truthvalue_conversion (ffecom_1 (REALPART_EXPR,
15747 TREE_TYPE (TREE_TYPE (expr)),
15749 truthvalue_conversion (ffecom_1 (IMAGPART_EXPR,
15750 TREE_TYPE (TREE_TYPE (expr)),
15753 return ffecom_2 (NE_EXPR, integer_type_node,
15755 convert (TREE_TYPE (expr), integer_zero_node));
15759 type_for_mode (mode, unsignedp)
15760 enum machine_mode mode;
15767 if (mode == TYPE_MODE (integer_type_node))
15768 return unsignedp ? unsigned_type_node : integer_type_node;
15770 if (mode == TYPE_MODE (signed_char_type_node))
15771 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15773 if (mode == TYPE_MODE (short_integer_type_node))
15774 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15776 if (mode == TYPE_MODE (long_integer_type_node))
15777 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15779 if (mode == TYPE_MODE (long_long_integer_type_node))
15780 return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
15782 if (mode == TYPE_MODE (float_type_node))
15783 return float_type_node;
15785 if (mode == TYPE_MODE (double_type_node))
15786 return double_type_node;
15788 if (mode == TYPE_MODE (build_pointer_type (char_type_node)))
15789 return build_pointer_type (char_type_node);
15791 if (mode == TYPE_MODE (build_pointer_type (integer_type_node)))
15792 return build_pointer_type (integer_type_node);
15794 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
15795 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
15797 if (((t = ffecom_tree_type[i][j]) != NULL_TREE)
15798 && (mode == TYPE_MODE (t)))
15800 if ((i == FFEINFO_basictypeINTEGER) && unsignedp)
15801 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][j];
15811 type_for_size (bits, unsignedp)
15815 ffeinfoKindtype kt;
15818 if (bits == TYPE_PRECISION (integer_type_node))
15819 return unsignedp ? unsigned_type_node : integer_type_node;
15821 if (bits == TYPE_PRECISION (signed_char_type_node))
15822 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15824 if (bits == TYPE_PRECISION (short_integer_type_node))
15825 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15827 if (bits == TYPE_PRECISION (long_integer_type_node))
15828 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15830 if (bits == TYPE_PRECISION (long_long_integer_type_node))
15831 return (unsignedp ? long_long_unsigned_type_node
15832 : long_long_integer_type_node);
15834 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15836 type_node = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15838 if ((type_node != NULL_TREE) && (bits == TYPE_PRECISION (type_node)))
15839 return unsignedp ? ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt]
15847 unsigned_type (type)
15850 tree type1 = TYPE_MAIN_VARIANT (type);
15851 ffeinfoKindtype kt;
15854 if (type1 == signed_char_type_node || type1 == char_type_node)
15855 return unsigned_char_type_node;
15856 if (type1 == integer_type_node)
15857 return unsigned_type_node;
15858 if (type1 == short_integer_type_node)
15859 return short_unsigned_type_node;
15860 if (type1 == long_integer_type_node)
15861 return long_unsigned_type_node;
15862 if (type1 == long_long_integer_type_node)
15863 return long_long_unsigned_type_node;
15864 #if 0 /* gcc/c-* files only */
15865 if (type1 == intDI_type_node)
15866 return unsigned_intDI_type_node;
15867 if (type1 == intSI_type_node)
15868 return unsigned_intSI_type_node;
15869 if (type1 == intHI_type_node)
15870 return unsigned_intHI_type_node;
15871 if (type1 == intQI_type_node)
15872 return unsigned_intQI_type_node;
15875 type2 = type_for_size (TYPE_PRECISION (type1), 1);
15876 if (type2 != NULL_TREE)
15879 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15881 type2 = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15883 if (type1 == type2)
15884 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
15890 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
15892 #if FFECOM_GCC_INCLUDE
15894 /* From gcc/cccp.c, the code to handle -I. */
15896 /* Skip leading "./" from a directory name.
15897 This may yield the empty string, which represents the current directory. */
15899 static const char *
15900 skip_redundant_dir_prefix (const char *dir)
15902 while (dir[0] == '.' && dir[1] == '/')
15903 for (dir += 2; *dir == '/'; dir++)
15905 if (dir[0] == '.' && !dir[1])
15910 /* The file_name_map structure holds a mapping of file names for a
15911 particular directory. This mapping is read from the file named
15912 FILE_NAME_MAP_FILE in that directory. Such a file can be used to
15913 map filenames on a file system with severe filename restrictions,
15914 such as DOS. The format of the file name map file is just a series
15915 of lines with two tokens on each line. The first token is the name
15916 to map, and the second token is the actual name to use. */
15918 struct file_name_map
15920 struct file_name_map *map_next;
15925 #define FILE_NAME_MAP_FILE "header.gcc"
15927 /* Current maximum length of directory names in the search path
15928 for include files. (Altered as we get more of them.) */
15930 static int max_include_len = 0;
15932 struct file_name_list
15934 struct file_name_list *next;
15936 /* Mapping of file names for this directory. */
15937 struct file_name_map *name_map;
15938 /* Non-zero if name_map is valid. */
15942 static struct file_name_list *include = NULL; /* First dir to search */
15943 static struct file_name_list *last_include = NULL; /* Last in chain */
15945 /* I/O buffer structure.
15946 The `fname' field is nonzero for source files and #include files
15947 and for the dummy text used for -D and -U.
15948 It is zero for rescanning results of macro expansion
15949 and for expanding macro arguments. */
15950 #define INPUT_STACK_MAX 400
15951 static struct file_buf {
15953 /* Filename specified with #line command. */
15954 char *nominal_fname;
15955 /* Record where in the search path this file was found.
15956 For #include_next. */
15957 struct file_name_list *dir;
15959 ffewhereColumn column;
15960 } instack[INPUT_STACK_MAX];
15962 static int last_error_tick = 0; /* Incremented each time we print it. */
15963 static int input_file_stack_tick = 0; /* Incremented when status changes. */
15965 /* Current nesting level of input sources.
15966 `instack[indepth]' is the level currently being read. */
15967 static int indepth = -1;
15969 typedef struct file_buf FILE_BUF;
15971 typedef unsigned char U_CHAR;
15973 /* table to tell if char can be part of a C identifier. */
15974 U_CHAR is_idchar[256];
15975 /* table to tell if char can be first char of a c identifier. */
15976 U_CHAR is_idstart[256];
15977 /* table to tell if c is horizontal space. */
15978 U_CHAR is_hor_space[256];
15979 /* table to tell if c is horizontal or vertical space. */
15980 static U_CHAR is_space[256];
15982 #define SKIP_WHITE_SPACE(p) do { while (is_hor_space[*p]) p++; } while (0)
15983 #define SKIP_ALL_WHITE_SPACE(p) do { while (is_space[*p]) p++; } while (0)
15985 /* Nonzero means -I- has been seen,
15986 so don't look for #include "foo" the source-file directory. */
15987 static int ignore_srcdir;
15989 #ifndef INCLUDE_LEN_FUDGE
15990 #define INCLUDE_LEN_FUDGE 0
15993 static void append_include_chain (struct file_name_list *first,
15994 struct file_name_list *last);
15995 static FILE *open_include_file (char *filename,
15996 struct file_name_list *searchptr);
15997 static void print_containing_files (ffebadSeverity sev);
15998 static const char *skip_redundant_dir_prefix (const char *);
15999 static char *read_filename_string (int ch, FILE *f);
16000 static struct file_name_map *read_name_map (const char *dirname);
16002 /* Append a chain of `struct file_name_list's
16003 to the end of the main include chain.
16004 FIRST is the beginning of the chain to append, and LAST is the end. */
16007 append_include_chain (first, last)
16008 struct file_name_list *first, *last;
16010 struct file_name_list *dir;
16012 if (!first || !last)
16018 last_include->next = first;
16020 for (dir = first; ; dir = dir->next) {
16021 int len = strlen (dir->fname) + INCLUDE_LEN_FUDGE;
16022 if (len > max_include_len)
16023 max_include_len = len;
16029 last_include = last;
16032 /* Try to open include file FILENAME. SEARCHPTR is the directory
16033 being tried from the include file search path. This function maps
16034 filenames on file systems based on information read by
16038 open_include_file (filename, searchptr)
16040 struct file_name_list *searchptr;
16042 register struct file_name_map *map;
16043 register char *from;
16046 if (searchptr && ! searchptr->got_name_map)
16048 searchptr->name_map = read_name_map (searchptr->fname
16049 ? searchptr->fname : ".");
16050 searchptr->got_name_map = 1;
16053 /* First check the mapping for the directory we are using. */
16054 if (searchptr && searchptr->name_map)
16057 if (searchptr->fname)
16058 from += strlen (searchptr->fname) + 1;
16059 for (map = searchptr->name_map; map; map = map->map_next)
16061 if (! strcmp (map->map_from, from))
16063 /* Found a match. */
16064 return fopen (map->map_to, "r");
16069 /* Try to find a mapping file for the particular directory we are
16070 looking in. Thus #include <sys/types.h> will look up sys/types.h
16071 in /usr/include/header.gcc and look up types.h in
16072 /usr/include/sys/header.gcc. */
16073 p = rindex (filename, '/');
16074 #ifdef DIR_SEPARATOR
16075 if (! p) p = rindex (filename, DIR_SEPARATOR);
16077 char *tmp = rindex (filename, DIR_SEPARATOR);
16078 if (tmp != NULL && tmp > p) p = tmp;
16084 && searchptr->fname
16085 && strlen (searchptr->fname) == (size_t) (p - filename)
16086 && ! strncmp (searchptr->fname, filename, (int) (p - filename)))
16088 /* FILENAME is in SEARCHPTR, which we've already checked. */
16089 return fopen (filename, "r");
16095 map = read_name_map (".");
16099 dir = (char *) xmalloc (p - filename + 1);
16100 memcpy (dir, filename, p - filename);
16101 dir[p - filename] = '\0';
16103 map = read_name_map (dir);
16106 for (; map; map = map->map_next)
16107 if (! strcmp (map->map_from, from))
16108 return fopen (map->map_to, "r");
16110 return fopen (filename, "r");
16113 /* Print the file names and line numbers of the #include
16114 commands which led to the current file. */
16117 print_containing_files (ffebadSeverity sev)
16119 FILE_BUF *ip = NULL;
16125 /* If stack of files hasn't changed since we last printed
16126 this info, don't repeat it. */
16127 if (last_error_tick == input_file_stack_tick)
16130 for (i = indepth; i >= 0; i--)
16131 if (instack[i].fname != NULL) {
16136 /* Give up if we don't find a source file. */
16140 /* Find the other, outer source files. */
16141 for (i--; i >= 0; i--)
16142 if (instack[i].fname != NULL)
16148 str1 = "In file included";
16160 ffebad_start_msg ("%A from %B at %0%C", sev);
16161 ffebad_here (0, ip->line, ip->column);
16162 ffebad_string (str1);
16163 ffebad_string (ip->nominal_fname);
16164 ffebad_string (str2);
16168 /* Record we have printed the status as of this time. */
16169 last_error_tick = input_file_stack_tick;
16172 /* Read a space delimited string of unlimited length from a stdio
16176 read_filename_string (ch, f)
16184 set = alloc = xmalloc (len + 1);
16185 if (! is_space[ch])
16188 while ((ch = getc (f)) != EOF && ! is_space[ch])
16190 if (set - alloc == len)
16193 alloc = xrealloc (alloc, len + 1);
16194 set = alloc + len / 2;
16204 /* Read the file name map file for DIRNAME. */
16206 static struct file_name_map *
16207 read_name_map (dirname)
16208 const char *dirname;
16210 /* This structure holds a linked list of file name maps, one per
16212 struct file_name_map_list
16214 struct file_name_map_list *map_list_next;
16215 char *map_list_name;
16216 struct file_name_map *map_list_map;
16218 static struct file_name_map_list *map_list;
16219 register struct file_name_map_list *map_list_ptr;
16223 int separator_needed;
16225 dirname = skip_redundant_dir_prefix (dirname);
16227 for (map_list_ptr = map_list; map_list_ptr;
16228 map_list_ptr = map_list_ptr->map_list_next)
16229 if (! strcmp (map_list_ptr->map_list_name, dirname))
16230 return map_list_ptr->map_list_map;
16232 map_list_ptr = ((struct file_name_map_list *)
16233 xmalloc (sizeof (struct file_name_map_list)));
16234 map_list_ptr->map_list_name = xstrdup (dirname);
16235 map_list_ptr->map_list_map = NULL;
16237 dirlen = strlen (dirname);
16238 separator_needed = dirlen != 0 && dirname[dirlen - 1] != '/';
16239 name = (char *) xmalloc (dirlen + strlen (FILE_NAME_MAP_FILE) + 2);
16240 strcpy (name, dirname);
16241 name[dirlen] = '/';
16242 strcpy (name + dirlen + separator_needed, FILE_NAME_MAP_FILE);
16243 f = fopen (name, "r");
16246 map_list_ptr->map_list_map = NULL;
16251 while ((ch = getc (f)) != EOF)
16254 struct file_name_map *ptr;
16258 from = read_filename_string (ch, f);
16259 while ((ch = getc (f)) != EOF && is_hor_space[ch])
16261 to = read_filename_string (ch, f);
16263 ptr = ((struct file_name_map *)
16264 xmalloc (sizeof (struct file_name_map)));
16265 ptr->map_from = from;
16267 /* Make the real filename absolute. */
16272 ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
16273 strcpy (ptr->map_to, dirname);
16274 ptr->map_to[dirlen] = '/';
16275 strcpy (ptr->map_to + dirlen + separator_needed, to);
16279 ptr->map_next = map_list_ptr->map_list_map;
16280 map_list_ptr->map_list_map = ptr;
16282 while ((ch = getc (f)) != '\n')
16289 map_list_ptr->map_list_next = map_list;
16290 map_list = map_list_ptr;
16292 return map_list_ptr->map_list_map;
16296 ffecom_file_ (char *name)
16300 /* Do partial setup of input buffer for the sake of generating
16301 early #line directives (when -g is in effect). */
16303 fp = &instack[++indepth];
16304 memset ((char *) fp, 0, sizeof (FILE_BUF));
16307 fp->nominal_fname = fp->fname = name;
16310 /* Initialize syntactic classifications of characters. */
16313 ffecom_initialize_char_syntax_ ()
16318 * Set up is_idchar and is_idstart tables. These should be
16319 * faster than saying (is_alpha (c) || c == '_'), etc.
16320 * Set up these things before calling any routines tthat
16323 for (i = 'a'; i <= 'z'; i++) {
16324 is_idchar[i - 'a' + 'A'] = 1;
16326 is_idstart[i - 'a' + 'A'] = 1;
16329 for (i = '0'; i <= '9'; i++)
16331 is_idchar['_'] = 1;
16332 is_idstart['_'] = 1;
16334 /* horizontal space table */
16335 is_hor_space[' '] = 1;
16336 is_hor_space['\t'] = 1;
16337 is_hor_space['\v'] = 1;
16338 is_hor_space['\f'] = 1;
16339 is_hor_space['\r'] = 1;
16342 is_space['\t'] = 1;
16343 is_space['\v'] = 1;
16344 is_space['\f'] = 1;
16345 is_space['\n'] = 1;
16346 is_space['\r'] = 1;
16350 ffecom_close_include_ (FILE *f)
16355 input_file_stack_tick++;
16357 ffewhere_line_kill (instack[indepth].line);
16358 ffewhere_column_kill (instack[indepth].column);
16362 ffecom_decode_include_option_ (char *spec)
16364 struct file_name_list *dirtmp;
16366 if (! ignore_srcdir && !strcmp (spec, "-"))
16370 dirtmp = (struct file_name_list *)
16371 xmalloc (sizeof (struct file_name_list));
16372 dirtmp->next = 0; /* New one goes on the end */
16374 dirtmp->fname = spec;
16376 fatal ("Directory name must immediately follow -I option with no intervening spaces, as in `-Idir', not `-I dir'");
16377 dirtmp->got_name_map = 0;
16378 append_include_chain (dirtmp, dirtmp);
16383 /* Open INCLUDEd file. */
16386 ffecom_open_include_ (char *name, ffewhereLine l, ffewhereColumn c)
16389 size_t flen = strlen (fbeg);
16390 struct file_name_list *search_start = include; /* Chain of dirs to search */
16391 struct file_name_list dsp[1]; /* First in chain, if #include "..." */
16392 struct file_name_list *searchptr = 0;
16393 char *fname; /* Dynamically allocated fname buffer */
16400 dsp[0].fname = NULL;
16402 /* If -I- was specified, don't search current dir, only spec'd ones. */
16403 if (!ignore_srcdir)
16405 for (fp = &instack[indepth]; fp >= instack; fp--)
16411 if ((nam = fp->nominal_fname) != NULL)
16413 /* Found a named file. Figure out dir of the file,
16414 and put it in front of the search list. */
16415 dsp[0].next = search_start;
16416 search_start = dsp;
16418 ep = rindex (nam, '/');
16419 #ifdef DIR_SEPARATOR
16420 if (ep == NULL) ep = rindex (nam, DIR_SEPARATOR);
16422 char *tmp = rindex (nam, DIR_SEPARATOR);
16423 if (tmp != NULL && tmp > ep) ep = tmp;
16427 ep = rindex (nam, ']');
16428 if (ep == NULL) ep = rindex (nam, '>');
16429 if (ep == NULL) ep = rindex (nam, ':');
16430 if (ep != NULL) ep++;
16435 dsp[0].fname = (char *) xmalloc (n + 1);
16436 strncpy (dsp[0].fname, nam, n);
16437 dsp[0].fname[n] = '\0';
16438 if (n + INCLUDE_LEN_FUDGE > max_include_len)
16439 max_include_len = n + INCLUDE_LEN_FUDGE;
16442 dsp[0].fname = NULL; /* Current directory */
16443 dsp[0].got_name_map = 0;
16449 /* Allocate this permanently, because it gets stored in the definitions
16451 fname = xmalloc (max_include_len + flen + 4);
16452 /* + 2 above for slash and terminating null. */
16453 /* + 2 added for '.h' on VMS (to support '#include filename') (NOT USED
16456 /* If specified file name is absolute, just open it. */
16459 #ifdef DIR_SEPARATOR
16460 || *fbeg == DIR_SEPARATOR
16464 strncpy (fname, (char *) fbeg, flen);
16466 f = open_include_file (fname, NULL_PTR);
16472 /* Search directory path, trying to open the file.
16473 Copy each filename tried into FNAME. */
16475 for (searchptr = search_start; searchptr; searchptr = searchptr->next)
16477 if (searchptr->fname)
16479 /* The empty string in a search path is ignored.
16480 This makes it possible to turn off entirely
16481 a standard piece of the list. */
16482 if (searchptr->fname[0] == 0)
16484 strcpy (fname, skip_redundant_dir_prefix (searchptr->fname));
16485 if (fname[0] && fname[strlen (fname) - 1] != '/')
16486 strcat (fname, "/");
16487 fname[strlen (fname) + flen] = 0;
16492 strncat (fname, fbeg, flen);
16494 /* Change this 1/2 Unix 1/2 VMS file specification into a
16495 full VMS file specification */
16496 if (searchptr->fname && (searchptr->fname[0] != 0))
16498 /* Fix up the filename */
16499 hack_vms_include_specification (fname);
16503 /* This is a normal VMS filespec, so use it unchanged. */
16504 strncpy (fname, (char *) fbeg, flen);
16506 #if 0 /* Not for g77. */
16507 /* if it's '#include filename', add the missing .h */
16508 if (index (fname, '.') == NULL)
16509 strcat (fname, ".h");
16513 f = open_include_file (fname, searchptr);
16515 if (f == NULL && errno == EACCES)
16517 print_containing_files (FFEBAD_severityWARNING);
16518 ffebad_start_msg ("At %0, INCLUDE file %A exists, but is not readable",
16519 FFEBAD_severityWARNING);
16520 ffebad_string (fname);
16521 ffebad_here (0, l, c);
16532 /* A file that was not found. */
16534 strncpy (fname, (char *) fbeg, flen);
16536 print_containing_files (ffebad_severity (FFEBAD_OPEN_INCLUDE));
16537 ffebad_start (FFEBAD_OPEN_INCLUDE);
16538 ffebad_here (0, l, c);
16539 ffebad_string (fname);
16543 if (dsp[0].fname != NULL)
16544 free (dsp[0].fname);
16549 if (indepth >= (INPUT_STACK_MAX - 1))
16551 print_containing_files (FFEBAD_severityFATAL);
16552 ffebad_start_msg ("At %0, INCLUDE nesting too deep",
16553 FFEBAD_severityFATAL);
16554 ffebad_string (fname);
16555 ffebad_here (0, l, c);
16560 instack[indepth].line = ffewhere_line_use (l);
16561 instack[indepth].column = ffewhere_column_use (c);
16563 fp = &instack[indepth + 1];
16564 memset ((char *) fp, 0, sizeof (FILE_BUF));
16565 fp->nominal_fname = fp->fname = fname;
16566 fp->dir = searchptr;
16569 input_file_stack_tick++;
16573 #endif /* FFECOM_GCC_INCLUDE */
16575 /**INDENT* (Do not reformat this comment even with -fca option.)
16576 Data-gathering files: Given the source file listed below, compiled with
16577 f2c I obtained the output file listed after that, and from the output
16578 file I derived the above code.
16580 -------- (begin input file to f2c)
16586 double precision D1,D2
16588 call getem(A1,A2,C1,C2,I1,I2,R1,R2,D1,D2)
16615 c FFEINTRIN_impACOS
16616 call fooR(ACOS(R1))
16617 c FFEINTRIN_impAIMAG
16618 call fooR(AIMAG(C1))
16619 c FFEINTRIN_impAINT
16620 call fooR(AINT(R1))
16621 c FFEINTRIN_impALOG
16622 call fooR(ALOG(R1))
16623 c FFEINTRIN_impALOG10
16624 call fooR(ALOG10(R1))
16625 c FFEINTRIN_impAMAX0
16626 call fooR(AMAX0(I1,I2))
16627 c FFEINTRIN_impAMAX1
16628 call fooR(AMAX1(R1,R2))
16629 c FFEINTRIN_impAMIN0
16630 call fooR(AMIN0(I1,I2))
16631 c FFEINTRIN_impAMIN1
16632 call fooR(AMIN1(R1,R2))
16633 c FFEINTRIN_impAMOD
16634 call fooR(AMOD(R1,R2))
16635 c FFEINTRIN_impANINT
16636 call fooR(ANINT(R1))
16637 c FFEINTRIN_impASIN
16638 call fooR(ASIN(R1))
16639 c FFEINTRIN_impATAN
16640 call fooR(ATAN(R1))
16641 c FFEINTRIN_impATAN2
16642 call fooR(ATAN2(R1,R2))
16643 c FFEINTRIN_impCABS
16644 call fooR(CABS(C1))
16645 c FFEINTRIN_impCCOS
16646 call fooC(CCOS(C1))
16647 c FFEINTRIN_impCEXP
16648 call fooC(CEXP(C1))
16649 c FFEINTRIN_impCHAR
16650 call fooA(CHAR(I1))
16651 c FFEINTRIN_impCLOG
16652 call fooC(CLOG(C1))
16653 c FFEINTRIN_impCONJG
16654 call fooC(CONJG(C1))
16657 c FFEINTRIN_impCOSH
16658 call fooR(COSH(R1))
16659 c FFEINTRIN_impCSIN
16660 call fooC(CSIN(C1))
16661 c FFEINTRIN_impCSQRT
16662 call fooC(CSQRT(C1))
16663 c FFEINTRIN_impDABS
16664 call fooD(DABS(D1))
16665 c FFEINTRIN_impDACOS
16666 call fooD(DACOS(D1))
16667 c FFEINTRIN_impDASIN
16668 call fooD(DASIN(D1))
16669 c FFEINTRIN_impDATAN
16670 call fooD(DATAN(D1))
16671 c FFEINTRIN_impDATAN2
16672 call fooD(DATAN2(D1,D2))
16673 c FFEINTRIN_impDCOS
16674 call fooD(DCOS(D1))
16675 c FFEINTRIN_impDCOSH
16676 call fooD(DCOSH(D1))
16677 c FFEINTRIN_impDDIM
16678 call fooD(DDIM(D1,D2))
16679 c FFEINTRIN_impDEXP
16680 call fooD(DEXP(D1))
16682 call fooR(DIM(R1,R2))
16683 c FFEINTRIN_impDINT
16684 call fooD(DINT(D1))
16685 c FFEINTRIN_impDLOG
16686 call fooD(DLOG(D1))
16687 c FFEINTRIN_impDLOG10
16688 call fooD(DLOG10(D1))
16689 c FFEINTRIN_impDMAX1
16690 call fooD(DMAX1(D1,D2))
16691 c FFEINTRIN_impDMIN1
16692 call fooD(DMIN1(D1,D2))
16693 c FFEINTRIN_impDMOD
16694 call fooD(DMOD(D1,D2))
16695 c FFEINTRIN_impDNINT
16696 call fooD(DNINT(D1))
16697 c FFEINTRIN_impDPROD
16698 call fooD(DPROD(R1,R2))
16699 c FFEINTRIN_impDSIGN
16700 call fooD(DSIGN(D1,D2))
16701 c FFEINTRIN_impDSIN
16702 call fooD(DSIN(D1))
16703 c FFEINTRIN_impDSINH
16704 call fooD(DSINH(D1))
16705 c FFEINTRIN_impDSQRT
16706 call fooD(DSQRT(D1))
16707 c FFEINTRIN_impDTAN
16708 call fooD(DTAN(D1))
16709 c FFEINTRIN_impDTANH
16710 call fooD(DTANH(D1))
16713 c FFEINTRIN_impIABS
16714 call fooI(IABS(I1))
16715 c FFEINTRIN_impICHAR
16716 call fooI(ICHAR(A1))
16717 c FFEINTRIN_impIDIM
16718 call fooI(IDIM(I1,I2))
16719 c FFEINTRIN_impIDNINT
16720 call fooI(IDNINT(D1))
16721 c FFEINTRIN_impINDEX
16722 call fooI(INDEX(A1,A2))
16723 c FFEINTRIN_impISIGN
16724 call fooI(ISIGN(I1,I2))
16728 call fooL(LGE(A1,A2))
16730 call fooL(LGT(A1,A2))
16732 call fooL(LLE(A1,A2))
16734 call fooL(LLT(A1,A2))
16735 c FFEINTRIN_impMAX0
16736 call fooI(MAX0(I1,I2))
16737 c FFEINTRIN_impMAX1
16738 call fooI(MAX1(R1,R2))
16739 c FFEINTRIN_impMIN0
16740 call fooI(MIN0(I1,I2))
16741 c FFEINTRIN_impMIN1
16742 call fooI(MIN1(R1,R2))
16744 call fooI(MOD(I1,I2))
16745 c FFEINTRIN_impNINT
16746 call fooI(NINT(R1))
16747 c FFEINTRIN_impSIGN
16748 call fooR(SIGN(R1,R2))
16751 c FFEINTRIN_impSINH
16752 call fooR(SINH(R1))
16753 c FFEINTRIN_impSQRT
16754 call fooR(SQRT(R1))
16757 c FFEINTRIN_impTANH
16758 call fooR(TANH(R1))
16759 c FFEINTRIN_imp_CMPLX_C
16760 call fooC(cmplx(C1,C2))
16761 c FFEINTRIN_imp_CMPLX_D
16762 call fooZ(cmplx(D1,D2))
16763 c FFEINTRIN_imp_CMPLX_I
16764 call fooC(cmplx(I1,I2))
16765 c FFEINTRIN_imp_CMPLX_R
16766 call fooC(cmplx(R1,R2))
16767 c FFEINTRIN_imp_DBLE_C
16768 call fooD(dble(C1))
16769 c FFEINTRIN_imp_DBLE_D
16770 call fooD(dble(D1))
16771 c FFEINTRIN_imp_DBLE_I
16772 call fooD(dble(I1))
16773 c FFEINTRIN_imp_DBLE_R
16774 call fooD(dble(R1))
16775 c FFEINTRIN_imp_INT_C
16777 c FFEINTRIN_imp_INT_D
16779 c FFEINTRIN_imp_INT_I
16781 c FFEINTRIN_imp_INT_R
16783 c FFEINTRIN_imp_REAL_C
16784 call fooR(real(C1))
16785 c FFEINTRIN_imp_REAL_D
16786 call fooR(real(D1))
16787 c FFEINTRIN_imp_REAL_I
16788 call fooR(real(I1))
16789 c FFEINTRIN_imp_REAL_R
16790 call fooR(real(R1))
16792 c FFEINTRIN_imp_INT_D:
16794 c FFEINTRIN_specIDINT
16795 call fooI(IDINT(D1))
16797 c FFEINTRIN_imp_INT_R:
16799 c FFEINTRIN_specIFIX
16800 call fooI(IFIX(R1))
16801 c FFEINTRIN_specINT
16804 c FFEINTRIN_imp_REAL_D:
16806 c FFEINTRIN_specSNGL
16807 call fooR(SNGL(D1))
16809 c FFEINTRIN_imp_REAL_I:
16811 c FFEINTRIN_specFLOAT
16812 call fooR(FLOAT(I1))
16813 c FFEINTRIN_specREAL
16814 call fooR(REAL(I1))
16817 -------- (end input file to f2c)
16819 -------- (begin output from providing above input file as input to:
16820 -------- `f2c | gcc -E -C - | sed -e "s:/[*]*://:g" -e "s:[*]*[/]://:g" \
16821 -------- -e "s:^#.*$::g"')
16823 // -- translated by f2c (version 19950223).
16824 You must link the resulting object file with the libraries:
16825 -lf2c -lm (in that order)
16829 // f2c.h -- Standard Fortran to C header file //
16831 /// barf [ba:rf] 2. "He suggested using FORTRAN, and everybody barfed."
16833 - From The Shogakukan DICTIONARY OF NEW ENGLISH (Second edition) //
16838 // F2C_INTEGER will normally be `int' but would be `long' on 16-bit systems //
16839 // we assume short, float are OK //
16840 typedef long int // long int // integer;
16841 typedef char *address;
16842 typedef short int shortint;
16843 typedef float real;
16844 typedef double doublereal;
16845 typedef struct { real r, i; } complex;
16846 typedef struct { doublereal r, i; } doublecomplex;
16847 typedef long int // long int // logical;
16848 typedef short int shortlogical;
16849 typedef char logical1;
16850 typedef char integer1;
16851 // typedef long long longint; // // system-dependent //
16856 // Extern is for use with -E //
16870 typedef long int // int or long int // flag;
16871 typedef long int // int or long int // ftnlen;
16872 typedef long int // int or long int // ftnint;
16875 //external read, write//
16884 //internal read, write//
16914 //rewind, backspace, endfile//
16926 ftnint *inex; //parameters in standard's order//
16952 union Multitype { // for multiple entry points //
16963 typedef union Multitype Multitype;
16965 typedef long Long; // No longer used; formerly in Namelist //
16967 struct Vardesc { // for Namelist //
16973 typedef struct Vardesc Vardesc;
16980 typedef struct Namelist Namelist;
16989 // procedure parameter types for -A and -C++ //
16994 typedef int // Unknown procedure type // (*U_fp)();
16995 typedef shortint (*J_fp)();
16996 typedef integer (*I_fp)();
16997 typedef real (*R_fp)();
16998 typedef doublereal (*D_fp)(), (*E_fp)();
16999 typedef // Complex // void (*C_fp)();
17000 typedef // Double Complex // void (*Z_fp)();
17001 typedef logical (*L_fp)();
17002 typedef shortlogical (*K_fp)();
17003 typedef // Character // void (*H_fp)();
17004 typedef // Subroutine // int (*S_fp)();
17006 // E_fp is for real functions when -R is not specified //
17007 typedef void C_f; // complex function //
17008 typedef void H_f; // character function //
17009 typedef void Z_f; // double complex function //
17010 typedef doublereal E_f; // real function with -R not specified //
17012 // undef any lower-case symbols that your C compiler predefines, e.g.: //
17015 // (No such symbols should be defined in a strict ANSI C compiler.
17016 We can avoid trouble with f2c-translated code by using
17017 gcc -ansi [-traditional].) //
17041 // Main program // MAIN__()
17043 // System generated locals //
17046 doublereal d__1, d__2;
17048 doublecomplex z__1, z__2, z__3;
17052 // Builtin functions //
17055 double pow_ri(), pow_di();
17059 double acos(), r_imag(), r_int(), log(), r_lg10(), r_mod(), r_nint(),
17060 asin(), atan(), atan2(), c_abs();
17061 void c_cos(), c_exp(), c_log(), r_cnjg();
17062 double cos(), cosh();
17063 void c_sin(), c_sqrt();
17064 double d_dim(), exp(), r_dim(), d_int(), d_lg10(), d_mod(), d_nint(),
17065 d_sign(), sin(), sinh(), sqrt(), tan(), tanh();
17066 integer i_dim(), i_dnnt(), i_indx(), i_sign(), i_len();
17067 logical l_ge(), l_gt(), l_le(), l_lt();
17071 // Local variables //
17072 extern // Subroutine // int fooa_(), fooc_(), food_(), fooi_(), foor_(),
17073 fool_(), fooz_(), getem_();
17074 static char a1[10], a2[10];
17075 static complex c1, c2;
17076 static doublereal d1, d2;
17077 static integer i1, i2;
17078 static real r1, r2;
17081 getem_(a1, a2, &c1, &c2, &i1, &i2, &r1, &r2, &d1, &d2, 10L, 10L);
17089 d__1 = (doublereal) i1;
17090 q__1.r = c1.r / d__1, q__1.i = c1.i / d__1;
17100 c_div(&q__1, &c1, &c2);
17102 q__1.r = c1.r / r1, q__1.i = c1.i / r1;
17104 z__1.r = c1.r / d1, z__1.i = c1.i / d1;
17107 i__1 = pow_ii(&i1, &i2);
17109 r__1 = pow_ri(&r1, &i1);
17111 d__1 = pow_di(&d1, &i1);
17113 pow_ci(&q__1, &c1, &i1);
17115 d__1 = (doublereal) r1;
17116 d__2 = (doublereal) r2;
17117 r__1 = pow_dd(&d__1, &d__2);
17119 d__2 = (doublereal) r1;
17120 d__1 = pow_dd(&d__2, &d1);
17122 d__1 = pow_dd(&d1, &d2);
17124 d__2 = (doublereal) r1;
17125 d__1 = pow_dd(&d1, &d__2);
17127 z__2.r = c1.r, z__2.i = c1.i;
17128 z__3.r = c2.r, z__3.i = c2.i;
17129 pow_zz(&z__1, &z__2, &z__3);
17130 q__1.r = z__1.r, q__1.i = z__1.i;
17132 z__2.r = c1.r, z__2.i = c1.i;
17133 z__3.r = r1, z__3.i = 0.;
17134 pow_zz(&z__1, &z__2, &z__3);
17135 q__1.r = z__1.r, q__1.i = z__1.i;
17137 z__2.r = c1.r, z__2.i = c1.i;
17138 z__3.r = d1, z__3.i = 0.;
17139 pow_zz(&z__1, &z__2, &z__3);
17141 // FFEINTRIN_impABS //
17142 r__1 = (doublereal)(( r1 ) >= 0 ? ( r1 ) : -( r1 )) ;
17144 // FFEINTRIN_impACOS //
17147 // FFEINTRIN_impAIMAG //
17148 r__1 = r_imag(&c1);
17150 // FFEINTRIN_impAINT //
17153 // FFEINTRIN_impALOG //
17156 // FFEINTRIN_impALOG10 //
17157 r__1 = r_lg10(&r1);
17159 // FFEINTRIN_impAMAX0 //
17160 r__1 = (real) (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
17162 // FFEINTRIN_impAMAX1 //
17163 r__1 = (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
17165 // FFEINTRIN_impAMIN0 //
17166 r__1 = (real) (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
17168 // FFEINTRIN_impAMIN1 //
17169 r__1 = (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
17171 // FFEINTRIN_impAMOD //
17172 r__1 = r_mod(&r1, &r2);
17174 // FFEINTRIN_impANINT //
17175 r__1 = r_nint(&r1);
17177 // FFEINTRIN_impASIN //
17180 // FFEINTRIN_impATAN //
17183 // FFEINTRIN_impATAN2 //
17184 r__1 = atan2(r1, r2);
17186 // FFEINTRIN_impCABS //
17189 // FFEINTRIN_impCCOS //
17192 // FFEINTRIN_impCEXP //
17195 // FFEINTRIN_impCHAR //
17196 *(unsigned char *)&ch__1[0] = i1;
17198 // FFEINTRIN_impCLOG //
17201 // FFEINTRIN_impCONJG //
17202 r_cnjg(&q__1, &c1);
17204 // FFEINTRIN_impCOS //
17207 // FFEINTRIN_impCOSH //
17210 // FFEINTRIN_impCSIN //
17213 // FFEINTRIN_impCSQRT //
17214 c_sqrt(&q__1, &c1);
17216 // FFEINTRIN_impDABS //
17217 d__1 = (( d1 ) >= 0 ? ( d1 ) : -( d1 )) ;
17219 // FFEINTRIN_impDACOS //
17222 // FFEINTRIN_impDASIN //
17225 // FFEINTRIN_impDATAN //
17228 // FFEINTRIN_impDATAN2 //
17229 d__1 = atan2(d1, d2);
17231 // FFEINTRIN_impDCOS //
17234 // FFEINTRIN_impDCOSH //
17237 // FFEINTRIN_impDDIM //
17238 d__1 = d_dim(&d1, &d2);
17240 // FFEINTRIN_impDEXP //
17243 // FFEINTRIN_impDIM //
17244 r__1 = r_dim(&r1, &r2);
17246 // FFEINTRIN_impDINT //
17249 // FFEINTRIN_impDLOG //
17252 // FFEINTRIN_impDLOG10 //
17253 d__1 = d_lg10(&d1);
17255 // FFEINTRIN_impDMAX1 //
17256 d__1 = (( d1 ) >= ( d2 ) ? ( d1 ) : ( d2 )) ;
17258 // FFEINTRIN_impDMIN1 //
17259 d__1 = (( d1 ) <= ( d2 ) ? ( d1 ) : ( d2 )) ;
17261 // FFEINTRIN_impDMOD //
17262 d__1 = d_mod(&d1, &d2);
17264 // FFEINTRIN_impDNINT //
17265 d__1 = d_nint(&d1);
17267 // FFEINTRIN_impDPROD //
17268 d__1 = (doublereal) r1 * r2;
17270 // FFEINTRIN_impDSIGN //
17271 d__1 = d_sign(&d1, &d2);
17273 // FFEINTRIN_impDSIN //
17276 // FFEINTRIN_impDSINH //
17279 // FFEINTRIN_impDSQRT //
17282 // FFEINTRIN_impDTAN //
17285 // FFEINTRIN_impDTANH //
17288 // FFEINTRIN_impEXP //
17291 // FFEINTRIN_impIABS //
17292 i__1 = (( i1 ) >= 0 ? ( i1 ) : -( i1 )) ;
17294 // FFEINTRIN_impICHAR //
17295 i__1 = *(unsigned char *)a1;
17297 // FFEINTRIN_impIDIM //
17298 i__1 = i_dim(&i1, &i2);
17300 // FFEINTRIN_impIDNINT //
17301 i__1 = i_dnnt(&d1);
17303 // FFEINTRIN_impINDEX //
17304 i__1 = i_indx(a1, a2, 10L, 10L);
17306 // FFEINTRIN_impISIGN //
17307 i__1 = i_sign(&i1, &i2);
17309 // FFEINTRIN_impLEN //
17310 i__1 = i_len(a1, 10L);
17312 // FFEINTRIN_impLGE //
17313 L__1 = l_ge(a1, a2, 10L, 10L);
17315 // FFEINTRIN_impLGT //
17316 L__1 = l_gt(a1, a2, 10L, 10L);
17318 // FFEINTRIN_impLLE //
17319 L__1 = l_le(a1, a2, 10L, 10L);
17321 // FFEINTRIN_impLLT //
17322 L__1 = l_lt(a1, a2, 10L, 10L);
17324 // FFEINTRIN_impMAX0 //
17325 i__1 = (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
17327 // FFEINTRIN_impMAX1 //
17328 i__1 = (integer) (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
17330 // FFEINTRIN_impMIN0 //
17331 i__1 = (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
17333 // FFEINTRIN_impMIN1 //
17334 i__1 = (integer) (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
17336 // FFEINTRIN_impMOD //
17339 // FFEINTRIN_impNINT //
17340 i__1 = i_nint(&r1);
17342 // FFEINTRIN_impSIGN //
17343 r__1 = r_sign(&r1, &r2);
17345 // FFEINTRIN_impSIN //
17348 // FFEINTRIN_impSINH //
17351 // FFEINTRIN_impSQRT //
17354 // FFEINTRIN_impTAN //
17357 // FFEINTRIN_impTANH //
17360 // FFEINTRIN_imp_CMPLX_C //
17363 q__1.r = r__1, q__1.i = r__2;
17365 // FFEINTRIN_imp_CMPLX_D //
17366 z__1.r = d1, z__1.i = d2;
17368 // FFEINTRIN_imp_CMPLX_I //
17371 q__1.r = r__1, q__1.i = r__2;
17373 // FFEINTRIN_imp_CMPLX_R //
17374 q__1.r = r1, q__1.i = r2;
17376 // FFEINTRIN_imp_DBLE_C //
17377 d__1 = (doublereal) c1.r;
17379 // FFEINTRIN_imp_DBLE_D //
17382 // FFEINTRIN_imp_DBLE_I //
17383 d__1 = (doublereal) i1;
17385 // FFEINTRIN_imp_DBLE_R //
17386 d__1 = (doublereal) r1;
17388 // FFEINTRIN_imp_INT_C //
17389 i__1 = (integer) c1.r;
17391 // FFEINTRIN_imp_INT_D //
17392 i__1 = (integer) d1;
17394 // FFEINTRIN_imp_INT_I //
17397 // FFEINTRIN_imp_INT_R //
17398 i__1 = (integer) r1;
17400 // FFEINTRIN_imp_REAL_C //
17403 // FFEINTRIN_imp_REAL_D //
17406 // FFEINTRIN_imp_REAL_I //
17409 // FFEINTRIN_imp_REAL_R //
17413 // FFEINTRIN_imp_INT_D: //
17415 // FFEINTRIN_specIDINT //
17416 i__1 = (integer) d1;
17419 // FFEINTRIN_imp_INT_R: //
17421 // FFEINTRIN_specIFIX //
17422 i__1 = (integer) r1;
17424 // FFEINTRIN_specINT //
17425 i__1 = (integer) r1;
17428 // FFEINTRIN_imp_REAL_D: //
17430 // FFEINTRIN_specSNGL //
17434 // FFEINTRIN_imp_REAL_I: //
17436 // FFEINTRIN_specFLOAT //
17439 // FFEINTRIN_specREAL //
17445 -------- (end output file from f2c)