1 /* com.c -- Implementation File (module.c template V1.0)
2 Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001
3 Free Software Foundation, Inc.
4 Contributed by James Craig Burley.
6 This file is part of GNU Fortran.
8 GNU Fortran is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 GNU Fortran is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Fortran; see the file COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
27 Contains compiler-specific functions.
32 /* Understanding this module means understanding the interface between
33 the g77 front end and the gcc back end (or, perhaps, some other
34 back end). In here are the functions called by the front end proper
35 to notify whatever back end is in place about certain things, and
36 also the back-end-specific functions. It's a bear to deal with, so
37 lately I've been trying to simplify things, especially with regard
38 to the gcc-back-end-specific stuff.
40 Building expressions generally seems quite easy, but building decls
41 has been challenging and is undergoing revision. gcc has several
44 TYPE_DECL -- a type (int, float, struct, function, etc.)
45 CONST_DECL -- a constant of some type other than function
46 LABEL_DECL -- a variable or a constant?
47 PARM_DECL -- an argument to a function (a variable that is a dummy)
48 RESULT_DECL -- the return value of a function (a variable)
49 VAR_DECL -- other variable (can hold a ptr-to-function, struct, int, etc.)
50 FUNCTION_DECL -- a function (either the actual function or an extern ref)
51 FIELD_DECL -- a field in a struct or union (goes into types)
53 g77 has a set of functions that somewhat parallels the gcc front end
54 when it comes to building decls:
56 Internal Function (one we define, not just declare as extern):
57 if (is_nested) push_f_function_context ();
58 start_function (get_identifier ("function_name"), function_type,
59 is_nested, is_public);
60 // for each arg, build PARM_DECL and call push_parm_decl (decl) with it;
61 store_parm_decls (is_main_program);
62 ffecom_start_compstmt ();
63 // for stmts and decls inside function, do appropriate things;
64 ffecom_end_compstmt ();
65 finish_function (is_nested);
66 if (is_nested) pop_f_function_context ();
71 // fill in external, public, static, &c for decl, and
72 // set DECL_INITIAL to error_mark_node if going to initialize
73 // set is_top_level TRUE only if not at top level and decl
74 // must go in top level (i.e. not within current function decl context)
75 d = start_decl (decl, is_top_level);
76 init = ...; // if have initializer
77 finish_decl (d, init, is_top_level);
84 #if FFECOM_targetCURRENT == FFECOM_targetGCC
89 #include "output.h" /* Must follow tree.h so TREE_CODE is defined! */
93 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
95 #define FFECOM_GCC_INCLUDE 1 /* Enable -I. */
97 /* BEGIN stuff from gcc/cccp.c. */
99 /* The following symbols should be autoconfigured:
106 In the mean time, we'll get by with approximations based
107 on existing GCC configuration symbols. */
110 # ifndef HAVE_STDLIB_H
111 # define HAVE_STDLIB_H 1
113 # ifndef HAVE_UNISTD_H
114 # define HAVE_UNISTD_H 1
116 # ifndef STDC_HEADERS
117 # define STDC_HEADERS 1
119 #endif /* defined (POSIX) */
121 #if defined (POSIX) || (defined (USG) && !defined (VMS))
122 # ifndef HAVE_FCNTL_H
123 # define HAVE_FCNTL_H 1
128 # include <sys/resource.h>
135 /* This defines "errno" properly for VMS, and gives us EACCES. */
148 /* VMS-specific definitions */
151 #define O_RDONLY 0 /* Open arg for Read/Only */
152 #define O_WRONLY 1 /* Open arg for Write/Only */
153 #define read(fd,buf,size) VMS_read (fd,buf,size)
154 #define write(fd,buf,size) VMS_write (fd,buf,size)
155 #define open(fname,mode,prot) VMS_open (fname,mode,prot)
156 #define fopen(fname,mode) VMS_fopen (fname,mode)
157 #define freopen(fname,mode,ofile) VMS_freopen (fname,mode,ofile)
158 #define strncat(dst,src,cnt) VMS_strncat (dst,src,cnt)
159 #define fstat(fd,stbuf) VMS_fstat (fd,stbuf)
160 static int VMS_fstat (), VMS_stat ();
161 static char * VMS_strncat ();
162 static int VMS_read ();
163 static int VMS_write ();
164 static int VMS_open ();
165 static FILE * VMS_fopen ();
166 static FILE * VMS_freopen ();
167 static void hack_vms_include_specification ();
168 typedef struct { unsigned :16, :16, :16; } vms_ino_t;
169 #define ino_t vms_ino_t
170 #define INCLUDE_LEN_FUDGE 10 /* leave room for VMS syntax conversion */
177 /* END stuff from gcc/cccp.c. */
179 #define FFECOM_DETERMINE_TYPES 1 /* for com.h */
196 /* Externals defined here. */
198 #if FFECOM_targetCURRENT == FFECOM_targetGCC
200 /* ~~gcc/tree.h *should* declare this, because toplev.c and dwarfout.c
203 const char * const language_string = "GNU F77";
205 /* Stream for reading from the input file. */
208 /* These definitions parallel those in c-decl.c so that code from that
209 module can be used pretty much as is. Much of these defs aren't
210 otherwise used, i.e. by g77 code per se, except some of them are used
211 to build some of them that are. The ones that are global (i.e. not
212 "static") are those that ste.c and such might use (directly
213 or by using com macros that reference them in their definitions). */
215 tree string_type_node;
217 /* The rest of these are inventions for g77, though there might be
218 similar things in the C front end. As they are found, these
219 inventions should be renamed to be canonical. Note that only
220 the ones currently required to be global are so. */
222 static tree ffecom_tree_fun_type_void;
224 tree ffecom_integer_type_node; /* Abbrev for _tree_type[blah][blah]. */
225 tree ffecom_integer_zero_node; /* Like *_*_* with g77's integer type. */
226 tree ffecom_integer_one_node; /* " */
227 tree ffecom_tree_type[FFEINFO_basictype][FFEINFO_kindtype];
229 /* _fun_type things are the f2c-specific versions. For -fno-f2c,
230 just use build_function_type and build_pointer_type on the
231 appropriate _tree_type array element. */
233 static tree ffecom_tree_fun_type[FFEINFO_basictype][FFEINFO_kindtype];
234 static tree ffecom_tree_ptr_to_fun_type[FFEINFO_basictype][FFEINFO_kindtype];
235 static tree ffecom_tree_subr_type;
236 static tree ffecom_tree_ptr_to_subr_type;
237 static tree ffecom_tree_blockdata_type;
239 static tree ffecom_tree_xargc_;
241 ffecomSymbol ffecom_symbol_null_
250 ffeinfoKindtype ffecom_pointer_kind_ = FFEINFO_basictypeNONE;
251 ffeinfoKindtype ffecom_label_kind_ = FFEINFO_basictypeNONE;
253 int ffecom_f2c_typecode_[FFEINFO_basictype][FFEINFO_kindtype];
254 tree ffecom_f2c_integer_type_node;
255 tree ffecom_f2c_ptr_to_integer_type_node;
256 tree ffecom_f2c_address_type_node;
257 tree ffecom_f2c_real_type_node;
258 tree ffecom_f2c_ptr_to_real_type_node;
259 tree ffecom_f2c_doublereal_type_node;
260 tree ffecom_f2c_complex_type_node;
261 tree ffecom_f2c_doublecomplex_type_node;
262 tree ffecom_f2c_longint_type_node;
263 tree ffecom_f2c_logical_type_node;
264 tree ffecom_f2c_flag_type_node;
265 tree ffecom_f2c_ftnlen_type_node;
266 tree ffecom_f2c_ftnlen_zero_node;
267 tree ffecom_f2c_ftnlen_one_node;
268 tree ffecom_f2c_ftnlen_two_node;
269 tree ffecom_f2c_ptr_to_ftnlen_type_node;
270 tree ffecom_f2c_ftnint_type_node;
271 tree ffecom_f2c_ptr_to_ftnint_type_node;
272 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
274 /* Simple definitions and enumerations. */
276 #ifndef FFECOM_sizeMAXSTACKITEM
277 #define FFECOM_sizeMAXSTACKITEM 32*1024 /* Keep user-declared things
278 larger than this # bytes
279 off stack if possible. */
282 /* For systems that have large enough stacks, they should define
283 this to 0, and here, for ease of use later on, we just undefine
286 #if FFECOM_sizeMAXSTACKITEM == 0
287 #undef FFECOM_sizeMAXSTACKITEM
293 FFECOM_rttypeVOIDSTAR_, /* C's `void *' type. */
294 FFECOM_rttypeFTNINT_, /* f2c's `ftnint' type. */
295 FFECOM_rttypeINTEGER_, /* f2c's `integer' type. */
296 FFECOM_rttypeLONGINT_, /* f2c's `longint' type. */
297 FFECOM_rttypeLOGICAL_, /* f2c's `logical' type. */
298 FFECOM_rttypeREAL_F2C_, /* f2c's `real' returned as `double'. */
299 FFECOM_rttypeREAL_GNU_, /* `real' returned as such. */
300 FFECOM_rttypeCOMPLEX_F2C_, /* f2c's `complex' returned via 1st arg. */
301 FFECOM_rttypeCOMPLEX_GNU_, /* f2c's `complex' returned directly. */
302 FFECOM_rttypeDOUBLE_, /* C's `double' type. */
303 FFECOM_rttypeDOUBLEREAL_, /* f2c's `doublereal' type. */
304 FFECOM_rttypeDBLCMPLX_F2C_, /* f2c's `doublecomplex' returned via 1st arg. */
305 FFECOM_rttypeDBLCMPLX_GNU_, /* f2c's `doublecomplex' returned directly. */
306 FFECOM_rttypeCHARACTER_, /* f2c `char *'/`ftnlen' pair. */
310 /* Internal typedefs. */
312 #if FFECOM_targetCURRENT == FFECOM_targetGCC
313 typedef struct _ffecom_concat_list_ ffecomConcatList_;
314 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
316 /* Private include files. */
319 /* Internal structure definitions. */
321 #if FFECOM_targetCURRENT == FFECOM_targetGCC
322 struct _ffecom_concat_list_
327 ffetargetCharacterSize minlen;
328 ffetargetCharacterSize maxlen;
330 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
332 /* Static functions (internal). */
334 #if FFECOM_targetCURRENT == FFECOM_targetGCC
335 static tree ffecom_arglist_expr_ (const char *argstring, ffebld args);
336 static tree ffecom_widest_expr_type_ (ffebld list);
337 static bool ffecom_overlap_ (tree dest_decl, tree dest_offset,
338 tree dest_size, tree source_tree,
339 ffebld source, bool scalar_arg);
340 static bool ffecom_args_overlapping_ (tree dest_tree, ffebld dest,
341 tree args, tree callee_commons,
343 static tree ffecom_build_f2c_string_ (int i, const char *s);
344 static tree ffecom_call_ (tree fn, ffeinfoKindtype kt,
345 bool is_f2c_complex, tree type,
346 tree args, tree dest_tree,
347 ffebld dest, bool *dest_used,
348 tree callee_commons, bool scalar_args, tree hook);
349 static tree ffecom_call_binop_ (tree fn, ffeinfoKindtype kt,
350 bool is_f2c_complex, tree type,
351 ffebld left, ffebld right,
352 tree dest_tree, ffebld dest,
353 bool *dest_used, tree callee_commons,
354 bool scalar_args, bool ref, tree hook);
355 static void ffecom_char_args_x_ (tree *xitem, tree *length,
356 ffebld expr, bool with_null);
357 static tree ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy);
358 static tree ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s);
359 static ffecomConcatList_
360 ffecom_concat_list_gather_ (ffecomConcatList_ catlist,
362 ffetargetCharacterSize max);
363 static void ffecom_concat_list_kill_ (ffecomConcatList_ catlist);
364 static ffecomConcatList_ ffecom_concat_list_new_ (ffebld expr,
365 ffetargetCharacterSize max);
366 static void ffecom_debug_kludge_ (tree aggr, const char *aggr_type,
367 ffesymbol member, tree member_type,
368 ffetargetOffset offset);
369 static void ffecom_do_entry_ (ffesymbol fn, int entrynum);
370 static tree ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
371 bool *dest_used, bool assignp, bool widenp);
372 static tree ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
373 ffebld dest, bool *dest_used);
374 static tree ffecom_expr_power_integer_ (ffebld expr);
375 static void ffecom_expr_transform_ (ffebld expr);
376 static void ffecom_f2c_make_type_ (tree *type, int tcode, const char *name);
377 static void ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size,
379 static ffeglobal ffecom_finish_global_ (ffeglobal global);
380 static ffesymbol ffecom_finish_symbol_transform_ (ffesymbol s);
381 static tree ffecom_get_appended_identifier_ (char us, const char *text);
382 static tree ffecom_get_external_identifier_ (ffesymbol s);
383 static tree ffecom_get_identifier_ (const char *text);
384 static tree ffecom_gen_sfuncdef_ (ffesymbol s,
387 static const char *ffecom_gfrt_args_ (ffecomGfrt ix);
388 static tree ffecom_gfrt_tree_ (ffecomGfrt ix);
389 static tree ffecom_init_zero_ (tree decl);
390 static tree ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg,
392 static tree ffecom_intrinsic_len_ (ffebld expr);
393 static void ffecom_let_char_ (tree dest_tree,
395 ffetargetCharacterSize dest_size,
397 static void ffecom_make_gfrt_ (ffecomGfrt ix);
398 static void ffecom_member_phase1_ (ffestorag mst, ffestorag st);
399 static void ffecom_member_phase2_ (ffestorag mst, ffestorag st);
400 static void ffecom_prepare_let_char_ (ffetargetCharacterSize dest_size,
402 static void ffecom_push_dummy_decls_ (ffebld dumlist,
404 static void ffecom_start_progunit_ (void);
405 static ffesymbol ffecom_sym_transform_ (ffesymbol s);
406 static ffesymbol ffecom_sym_transform_assign_ (ffesymbol s);
407 static void ffecom_transform_common_ (ffesymbol s);
408 static void ffecom_transform_equiv_ (ffestorag st);
409 static tree ffecom_transform_namelist_ (ffesymbol s);
410 static void ffecom_tree_canonize_ptr_ (tree *decl, tree *offset,
412 static void ffecom_tree_canonize_ref_ (tree *decl, tree *offset,
413 tree *size, tree tree);
414 static tree ffecom_tree_divide_ (tree tree_type, tree left, tree right,
415 tree dest_tree, ffebld dest,
416 bool *dest_used, tree hook);
417 static tree ffecom_type_localvar_ (ffesymbol s,
420 static tree ffecom_type_namelist_ (void);
421 static tree ffecom_type_vardesc_ (void);
422 static tree ffecom_vardesc_ (ffebld expr);
423 static tree ffecom_vardesc_array_ (ffesymbol s);
424 static tree ffecom_vardesc_dims_ (ffesymbol s);
425 static tree ffecom_convert_narrow_ (tree type, tree expr);
426 static tree ffecom_convert_widen_ (tree type, tree expr);
427 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
429 /* These are static functions that parallel those found in the C front
430 end and thus have the same names. */
432 #if FFECOM_targetCURRENT == FFECOM_targetGCC
433 static tree bison_rule_compstmt_ (void);
434 static void bison_rule_pushlevel_ (void);
435 static void delete_block (tree block);
436 static int duplicate_decls (tree newdecl, tree olddecl);
437 static void finish_decl (tree decl, tree init, bool is_top_level);
438 static void finish_function (int nested);
439 static const char *lang_printable_name (tree decl, int v);
440 static tree lookup_name_current_level (tree name);
441 static struct binding_level *make_binding_level (void);
442 static void pop_f_function_context (void);
443 static void push_f_function_context (void);
444 static void push_parm_decl (tree parm);
445 static tree pushdecl_top_level (tree decl);
446 static int kept_level_p (void);
447 static tree storedecls (tree decls);
448 static void store_parm_decls (int is_main_program);
449 static tree start_decl (tree decl, bool is_top_level);
450 static void start_function (tree name, tree type, int nested, int public);
451 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
452 #if FFECOM_GCC_INCLUDE
453 static void ffecom_file_ (const char *name);
454 static void ffecom_initialize_char_syntax_ (void);
455 static void ffecom_close_include_ (FILE *f);
456 static int ffecom_decode_include_option_ (char *spec);
457 static FILE *ffecom_open_include_ (char *name, ffewhereLine l,
459 #endif /* FFECOM_GCC_INCLUDE */
461 /* Static objects accessed by functions in this module. */
463 static ffesymbol ffecom_primary_entry_ = NULL;
464 static ffesymbol ffecom_nested_entry_ = NULL;
465 static ffeinfoKind ffecom_primary_entry_kind_;
466 static bool ffecom_primary_entry_is_proc_;
467 #if FFECOM_targetCURRENT == FFECOM_targetGCC
468 static tree ffecom_outer_function_decl_;
469 static tree ffecom_previous_function_decl_;
470 static tree ffecom_which_entrypoint_decl_;
471 static tree ffecom_float_zero_ = NULL_TREE;
472 static tree ffecom_float_half_ = NULL_TREE;
473 static tree ffecom_double_zero_ = NULL_TREE;
474 static tree ffecom_double_half_ = NULL_TREE;
475 static tree ffecom_func_result_;/* For functions. */
476 static tree ffecom_func_length_;/* For CHARACTER fns. */
477 static ffebld ffecom_list_blockdata_;
478 static ffebld ffecom_list_common_;
479 static ffebld ffecom_master_arglist_;
480 static ffeinfoBasictype ffecom_master_bt_;
481 static ffeinfoKindtype ffecom_master_kt_;
482 static ffetargetCharacterSize ffecom_master_size_;
483 static int ffecom_num_fns_ = 0;
484 static int ffecom_num_entrypoints_ = 0;
485 static bool ffecom_is_altreturning_ = FALSE;
486 static tree ffecom_multi_type_node_;
487 static tree ffecom_multi_retval_;
489 ffecom_multi_fields_[FFEINFO_basictype][FFEINFO_kindtype];
490 static bool ffecom_member_namelisted_; /* _member_phase1_ namelisted? */
491 static bool ffecom_doing_entry_ = FALSE;
492 static bool ffecom_transform_only_dummies_ = FALSE;
493 static int ffecom_typesize_pointer_;
494 static int ffecom_typesize_integer1_;
496 /* Holds pointer-to-function expressions. */
498 static tree ffecom_gfrt_[FFECOM_gfrt]
501 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) NULL_TREE,
502 #include "com-rt.def"
506 /* Holds the external names of the functions. */
508 static const char *ffecom_gfrt_name_[FFECOM_gfrt]
511 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) NAME,
512 #include "com-rt.def"
516 /* Whether the function returns. */
518 static bool ffecom_gfrt_volatile_[FFECOM_gfrt]
521 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) VOLATILE,
522 #include "com-rt.def"
526 /* Whether the function returns type complex. */
528 static bool ffecom_gfrt_complex_[FFECOM_gfrt]
531 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) COMPLEX,
532 #include "com-rt.def"
536 /* Whether the function is const
537 (i.e., has no side effects and only depends on its arguments). */
539 static bool ffecom_gfrt_const_[FFECOM_gfrt]
542 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) CONST,
543 #include "com-rt.def"
547 /* Type code for the function return value. */
549 static ffecomRttype_ ffecom_gfrt_type_[FFECOM_gfrt]
552 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) TYPE,
553 #include "com-rt.def"
557 /* String of codes for the function's arguments. */
559 static const char *ffecom_gfrt_argstring_[FFECOM_gfrt]
562 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) ARGS,
563 #include "com-rt.def"
566 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
568 /* Internal macros. */
570 #if FFECOM_targetCURRENT == FFECOM_targetGCC
572 /* We let tm.h override the types used here, to handle trivial differences
573 such as the choice of unsigned int or long unsigned int for size_t.
574 When machines start needing nontrivial differences in the size type,
575 it would be best to do something here to figure out automatically
576 from other information what type to use. */
579 #define SIZE_TYPE "long unsigned int"
582 #define ffecom_concat_list_count_(catlist) ((catlist).count)
583 #define ffecom_concat_list_expr_(catlist,i) ((catlist).exprs[(i)])
584 #define ffecom_concat_list_maxlen_(catlist) ((catlist).maxlen)
585 #define ffecom_concat_list_minlen_(catlist) ((catlist).minlen)
587 #define ffecom_char_args_(i,l,e) ffecom_char_args_x_((i),(l),(e),FALSE)
588 #define ffecom_char_args_with_null_(i,l,e) ffecom_char_args_x_((i),(l),(e),TRUE)
590 /* For each binding contour we allocate a binding_level structure
591 * which records the names defined in that contour.
594 * 1) one for each function definition,
595 * where internal declarations of the parameters appear.
597 * The current meaning of a name can be found by searching the levels from
598 * the current one out to the global one.
601 /* Note that the information in the `names' component of the global contour
602 is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers. */
606 /* A chain of _DECL nodes for all variables, constants, functions,
607 and typedef types. These are in the reverse of the order supplied.
611 /* For each level (except not the global one),
612 a chain of BLOCK nodes for all the levels
613 that were entered and exited one level down. */
616 /* The BLOCK node for this level, if one has been preallocated.
617 If 0, the BLOCK is allocated (if needed) when the level is popped. */
620 /* The binding level which this one is contained in (inherits from). */
621 struct binding_level *level_chain;
623 /* 0: no ffecom_prepare_* functions called at this level yet;
624 1: ffecom_prepare* functions called, except not ffecom_prepare_end;
625 2: ffecom_prepare_end called. */
629 #define NULL_BINDING_LEVEL (struct binding_level *) NULL
631 /* The binding level currently in effect. */
633 static struct binding_level *current_binding_level;
635 /* A chain of binding_level structures awaiting reuse. */
637 static struct binding_level *free_binding_level;
639 /* The outermost binding level, for names of file scope.
640 This is created when the compiler is started and exists
641 through the entire run. */
643 static struct binding_level *global_binding_level;
645 /* Binding level structures are initialized by copying this one. */
647 static struct binding_level clear_binding_level
649 {NULL, NULL, NULL, NULL_BINDING_LEVEL, 0};
651 /* Language-dependent contents of an identifier. */
653 struct lang_identifier
655 struct tree_identifier ignore;
656 tree global_value, local_value, label_value;
660 /* Macros for access to language-specific slots in an identifier. */
661 /* Each of these slots contains a DECL node or null. */
663 /* This represents the value which the identifier has in the
664 file-scope namespace. */
665 #define IDENTIFIER_GLOBAL_VALUE(NODE) \
666 (((struct lang_identifier *)(NODE))->global_value)
667 /* This represents the value which the identifier has in the current
669 #define IDENTIFIER_LOCAL_VALUE(NODE) \
670 (((struct lang_identifier *)(NODE))->local_value)
671 /* This represents the value which the identifier has as a label in
672 the current label scope. */
673 #define IDENTIFIER_LABEL_VALUE(NODE) \
674 (((struct lang_identifier *)(NODE))->label_value)
675 /* This is nonzero if the identifier was "made up" by g77 code. */
676 #define IDENTIFIER_INVENTED(NODE) \
677 (((struct lang_identifier *)(NODE))->invented)
679 /* In identifiers, C uses the following fields in a special way:
680 TREE_PUBLIC to record that there was a previous local extern decl.
681 TREE_USED to record that such a decl was used.
682 TREE_ADDRESSABLE to record that the address of such a decl was used. */
684 /* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
685 that have names. Here so we can clear out their names' definitions
686 at the end of the function. */
688 static tree named_labels;
690 /* A list of LABEL_DECLs from outer contexts that are currently shadowed. */
692 static tree shadowed_labels;
694 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
696 /* Return the subscript expression, modified to do range-checking.
698 `array' is the array to be checked against.
699 `element' is the subscript expression to check.
700 `dim' is the dimension number (starting at 0).
701 `total_dims' is the total number of dimensions (0 for CHARACTER substring).
705 ffecom_subscript_check_ (tree array, tree element, int dim, int total_dims,
706 const char *array_name)
708 tree low = TYPE_MIN_VALUE (TYPE_DOMAIN (array));
709 tree high = TYPE_MAX_VALUE (TYPE_DOMAIN (array));
714 if (element == error_mark_node)
717 if (TREE_TYPE (low) != TREE_TYPE (element))
719 if (TYPE_PRECISION (TREE_TYPE (low))
720 > TYPE_PRECISION (TREE_TYPE (element)))
721 element = convert (TREE_TYPE (low), element);
724 low = convert (TREE_TYPE (element), low);
726 high = convert (TREE_TYPE (element), high);
730 element = ffecom_save_tree (element);
731 cond = ffecom_2 (LE_EXPR, integer_type_node,
736 cond = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
738 ffecom_2 (LE_EXPR, integer_type_node,
755 var = xmalloc (strlen (array_name) + 20);
756 sprintf (var, "%s[%s-substring]",
758 dim ? "end" : "start");
759 len = strlen (var) + 1;
760 arg1 = build_string (len, var);
765 len = strlen (array_name) + 1;
766 arg1 = build_string (len, array_name);
770 var = xmalloc (strlen (array_name) + 40);
771 sprintf (var, "%s[subscript-%d-of-%d]",
773 dim + 1, total_dims);
774 len = strlen (var) + 1;
775 arg1 = build_string (len, var);
781 = build_type_variant (build_array_type (char_type_node,
785 build_int_2 (len, 0))),
787 TREE_CONSTANT (arg1) = 1;
788 TREE_STATIC (arg1) = 1;
789 arg1 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg1)),
792 /* s_rnge adds one to the element to print it, so bias against
793 that -- want to print a faithful *subscript* value. */
794 arg2 = convert (ffecom_f2c_ftnint_type_node,
795 ffecom_2 (MINUS_EXPR,
798 convert (TREE_TYPE (element),
801 proc = xmalloc ((len = strlen (input_filename)
802 + IDENTIFIER_LENGTH (DECL_NAME (current_function_decl))
805 sprintf (&proc[0], "%s/%s",
807 IDENTIFIER_POINTER (DECL_NAME (current_function_decl)));
808 arg3 = build_string (len, proc);
813 = build_type_variant (build_array_type (char_type_node,
817 build_int_2 (len, 0))),
819 TREE_CONSTANT (arg3) = 1;
820 TREE_STATIC (arg3) = 1;
821 arg3 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg3)),
824 arg4 = convert (ffecom_f2c_ftnint_type_node,
825 build_int_2 (lineno, 0));
827 arg1 = build_tree_list (NULL_TREE, arg1);
828 arg2 = build_tree_list (NULL_TREE, arg2);
829 arg3 = build_tree_list (NULL_TREE, arg3);
830 arg4 = build_tree_list (NULL_TREE, arg4);
831 TREE_CHAIN (arg3) = arg4;
832 TREE_CHAIN (arg2) = arg3;
833 TREE_CHAIN (arg1) = arg2;
837 die = ffecom_call_gfrt (FFECOM_gfrtRANGE,
839 TREE_SIDE_EFFECTS (die) = 1;
841 element = ffecom_3 (COND_EXPR,
850 /* Return the computed element of an array reference.
852 `item' is NULL_TREE, or the transformed pointer to the array.
853 `expr' is the original opARRAYREF expression, which is transformed
854 if `item' is NULL_TREE.
855 `want_ptr' is non-zero if a pointer to the element, instead of
856 the element itself, is to be returned. */
859 ffecom_arrayref_ (tree item, ffebld expr, int want_ptr)
861 ffebld dims[FFECOM_dimensionsMAX];
864 int flatten = ffe_is_flatten_arrays ();
870 const char *array_name;
874 if (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER)
875 array_name = ffesymbol_text (ffebld_symter (ffebld_left (expr)));
877 array_name = "[expr?]";
879 /* Build up ARRAY_REFs in reverse order (since we're column major
880 here in Fortran land). */
882 for (i = 0, list = ffebld_right (expr);
884 ++i, list = ffebld_trail (list))
886 dims[i] = ffebld_head (list);
887 type = ffeinfo_type (ffebld_basictype (dims[i]),
888 ffebld_kindtype (dims[i]));
890 && ffecom_typesize_pointer_ > ffecom_typesize_integer1_
891 && ffetype_size (type) > ffecom_typesize_integer1_)
892 /* E.g. ARRAY(INDEX), given INTEGER*8 INDEX, on a system with 64-bit
893 pointers and 32-bit integers. Do the full 64-bit pointer
894 arithmetic, for codes using arrays for nonstandard heap-like
901 need_ptr = want_ptr || flatten;
906 item = ffecom_ptr_to_expr (ffebld_left (expr));
908 item = ffecom_expr (ffebld_left (expr));
910 if (item == error_mark_node)
913 if (ffeinfo_where (ffebld_info (expr)) == FFEINFO_whereFLEETING
914 && ! mark_addressable (item))
915 return error_mark_node;
918 if (item == error_mark_node)
925 for (--i, array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
927 --i, array = TYPE_MAIN_VARIANT (TREE_TYPE (array)))
929 min = TYPE_MIN_VALUE (TYPE_DOMAIN (array));
930 element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
931 if (flag_bounds_check)
932 element = ffecom_subscript_check_ (array, element, i, total_dims,
934 if (element == error_mark_node)
937 /* Widen integral arithmetic as desired while preserving
939 tree_type = TREE_TYPE (element);
940 tree_type_x = tree_type;
942 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
943 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
944 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
946 if (TREE_TYPE (min) != tree_type_x)
947 min = convert (tree_type_x, min);
948 if (TREE_TYPE (element) != tree_type_x)
949 element = convert (tree_type_x, element);
951 item = ffecom_2 (PLUS_EXPR,
952 build_pointer_type (TREE_TYPE (array)),
954 size_binop (MULT_EXPR,
955 size_in_bytes (TREE_TYPE (array)),
957 fold (build (MINUS_EXPR,
963 item = ffecom_1 (INDIRECT_REF,
964 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))),
974 array = TYPE_MAIN_VARIANT (TREE_TYPE (item));
976 element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
977 if (flag_bounds_check)
978 element = ffecom_subscript_check_ (array, element, i, total_dims,
980 if (element == error_mark_node)
983 /* Widen integral arithmetic as desired while preserving
985 tree_type = TREE_TYPE (element);
986 tree_type_x = tree_type;
988 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
989 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
990 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
992 element = convert (tree_type_x, element);
994 item = ffecom_2 (ARRAY_REF,
995 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))),
1004 /* This is like gcc's stabilize_reference -- in fact, most of the code
1005 comes from that -- but it handles the situation where the reference
1006 is going to have its subparts picked at, and it shouldn't change
1007 (or trigger extra invocations of functions in the subtrees) due to
1008 this. save_expr is a bit overzealous, because we don't need the
1009 entire thing calculated and saved like a temp. So, for DECLs, no
1010 change is needed, because these are stable aggregates, and ARRAY_REF
1011 and such might well be stable too, but for things like calculations,
1012 we do need to calculate a snapshot of a value before picking at it. */
1014 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1016 ffecom_stabilize_aggregate_ (tree ref)
1019 enum tree_code code = TREE_CODE (ref);
1026 /* No action is needed in this case. */
1032 case FIX_TRUNC_EXPR:
1033 case FIX_FLOOR_EXPR:
1034 case FIX_ROUND_EXPR:
1036 result = build_nt (code, stabilize_reference (TREE_OPERAND (ref, 0)));
1040 result = build_nt (INDIRECT_REF,
1041 stabilize_reference_1 (TREE_OPERAND (ref, 0)));
1045 result = build_nt (COMPONENT_REF,
1046 stabilize_reference (TREE_OPERAND (ref, 0)),
1047 TREE_OPERAND (ref, 1));
1051 result = build_nt (BIT_FIELD_REF,
1052 stabilize_reference (TREE_OPERAND (ref, 0)),
1053 stabilize_reference_1 (TREE_OPERAND (ref, 1)),
1054 stabilize_reference_1 (TREE_OPERAND (ref, 2)));
1058 result = build_nt (ARRAY_REF,
1059 stabilize_reference (TREE_OPERAND (ref, 0)),
1060 stabilize_reference_1 (TREE_OPERAND (ref, 1)));
1064 result = build_nt (COMPOUND_EXPR,
1065 stabilize_reference_1 (TREE_OPERAND (ref, 0)),
1066 stabilize_reference (TREE_OPERAND (ref, 1)));
1074 return save_expr (ref);
1077 return error_mark_node;
1080 TREE_TYPE (result) = TREE_TYPE (ref);
1081 TREE_READONLY (result) = TREE_READONLY (ref);
1082 TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (ref);
1083 TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (ref);
1089 /* A rip-off of gcc's convert.c convert_to_complex function,
1090 reworked to handle complex implemented as C structures
1091 (RECORD_TYPE with two fields, real and imaginary `r' and `i'). */
1093 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1095 ffecom_convert_to_complex_ (tree type, tree expr)
1097 register enum tree_code form = TREE_CODE (TREE_TYPE (expr));
1100 assert (TREE_CODE (type) == RECORD_TYPE);
1102 subtype = TREE_TYPE (TYPE_FIELDS (type));
1104 if (form == REAL_TYPE || form == INTEGER_TYPE || form == ENUMERAL_TYPE)
1106 expr = convert (subtype, expr);
1107 return ffecom_2 (COMPLEX_EXPR, type, expr,
1108 convert (subtype, integer_zero_node));
1111 if (form == RECORD_TYPE)
1113 tree elt_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr)));
1114 if (TYPE_MAIN_VARIANT (elt_type) == TYPE_MAIN_VARIANT (subtype))
1118 expr = save_expr (expr);
1119 return ffecom_2 (COMPLEX_EXPR,
1122 ffecom_1 (REALPART_EXPR,
1123 TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))),
1126 ffecom_1 (IMAGPART_EXPR,
1127 TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))),
1132 if (form == POINTER_TYPE || form == REFERENCE_TYPE)
1133 error ("pointer value used where a complex was expected");
1135 error ("aggregate value used where a complex was expected");
1137 return ffecom_2 (COMPLEX_EXPR, type,
1138 convert (subtype, integer_zero_node),
1139 convert (subtype, integer_zero_node));
1143 /* Like gcc's convert(), but crashes if widening might happen. */
1145 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1147 ffecom_convert_narrow_ (type, expr)
1150 register tree e = expr;
1151 register enum tree_code code = TREE_CODE (type);
1153 if (type == TREE_TYPE (e)
1154 || TREE_CODE (e) == ERROR_MARK)
1156 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
1157 return fold (build1 (NOP_EXPR, type, e));
1158 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
1159 || code == ERROR_MARK)
1160 return error_mark_node;
1161 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
1163 assert ("void value not ignored as it ought to be" == NULL);
1164 return error_mark_node;
1166 assert (code != VOID_TYPE);
1167 if ((code != RECORD_TYPE)
1168 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
1169 assert ("converting COMPLEX to REAL" == NULL);
1170 assert (code != ENUMERAL_TYPE);
1171 if (code == INTEGER_TYPE)
1173 assert ((TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE
1174 && TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)))
1175 || (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
1176 && (TYPE_PRECISION (type)
1177 == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (e))))));
1178 return fold (convert_to_integer (type, e));
1180 if (code == POINTER_TYPE)
1182 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
1183 return fold (convert_to_pointer (type, e));
1185 if (code == REAL_TYPE)
1187 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
1188 assert (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)));
1189 return fold (convert_to_real (type, e));
1191 if (code == COMPLEX_TYPE)
1193 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
1194 assert (TYPE_PRECISION (TREE_TYPE (type)) <= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
1195 return fold (convert_to_complex (type, e));
1197 if (code == RECORD_TYPE)
1199 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
1200 /* Check that at least the first field name agrees. */
1201 assert (DECL_NAME (TYPE_FIELDS (type))
1202 == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e))));
1203 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1204 <= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
1205 if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1206 == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))))
1208 return fold (ffecom_convert_to_complex_ (type, e));
1211 assert ("conversion to non-scalar type requested" == NULL);
1212 return error_mark_node;
1216 /* Like gcc's convert(), but crashes if narrowing might happen. */
1218 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1220 ffecom_convert_widen_ (type, expr)
1223 register tree e = expr;
1224 register enum tree_code code = TREE_CODE (type);
1226 if (type == TREE_TYPE (e)
1227 || TREE_CODE (e) == ERROR_MARK)
1229 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
1230 return fold (build1 (NOP_EXPR, type, e));
1231 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
1232 || code == ERROR_MARK)
1233 return error_mark_node;
1234 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
1236 assert ("void value not ignored as it ought to be" == NULL);
1237 return error_mark_node;
1239 assert (code != VOID_TYPE);
1240 if ((code != RECORD_TYPE)
1241 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
1242 assert ("narrowing COMPLEX to REAL" == NULL);
1243 assert (code != ENUMERAL_TYPE);
1244 if (code == INTEGER_TYPE)
1246 assert ((TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE
1247 && TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)))
1248 || (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
1249 && (TYPE_PRECISION (type)
1250 == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (e))))));
1251 return fold (convert_to_integer (type, e));
1253 if (code == POINTER_TYPE)
1255 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
1256 return fold (convert_to_pointer (type, e));
1258 if (code == REAL_TYPE)
1260 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
1261 assert (TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)));
1262 return fold (convert_to_real (type, e));
1264 if (code == COMPLEX_TYPE)
1266 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
1267 assert (TYPE_PRECISION (TREE_TYPE (type)) >= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
1268 return fold (convert_to_complex (type, e));
1270 if (code == RECORD_TYPE)
1272 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
1273 /* Check that at least the first field name agrees. */
1274 assert (DECL_NAME (TYPE_FIELDS (type))
1275 == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e))));
1276 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1277 >= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
1278 if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1279 == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))))
1281 return fold (ffecom_convert_to_complex_ (type, e));
1284 assert ("conversion to non-scalar type requested" == NULL);
1285 return error_mark_node;
1289 /* Handles making a COMPLEX type, either the standard
1290 (but buggy?) gbe way, or the safer (but less elegant?)
1293 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1295 ffecom_make_complex_type_ (tree subtype)
1301 if (ffe_is_emulate_complex ())
1303 type = make_node (RECORD_TYPE);
1304 realfield = ffecom_decl_field (type, NULL_TREE, "r", subtype);
1305 imagfield = ffecom_decl_field (type, realfield, "i", subtype);
1306 TYPE_FIELDS (type) = realfield;
1311 type = make_node (COMPLEX_TYPE);
1312 TREE_TYPE (type) = subtype;
1320 /* Chooses either the gbe or the f2c way to build a
1321 complex constant. */
1323 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1325 ffecom_build_complex_constant_ (tree type, tree realpart, tree imagpart)
1329 if (ffe_is_emulate_complex ())
1331 bothparts = build_tree_list (TYPE_FIELDS (type), realpart);
1332 TREE_CHAIN (bothparts) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), imagpart);
1333 bothparts = build (CONSTRUCTOR, type, NULL_TREE, bothparts);
1337 bothparts = build_complex (type, realpart, imagpart);
1344 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1346 ffecom_arglist_expr_ (const char *c, ffebld expr)
1349 tree *plist = &list;
1350 tree trail = NULL_TREE; /* Append char length args here. */
1351 tree *ptrail = &trail;
1356 tree wanted = NULL_TREE;
1357 static char zed[] = "0";
1362 while (expr != NULL)
1385 wanted = ffecom_f2c_complex_type_node;
1389 wanted = ffecom_f2c_doublereal_type_node;
1393 wanted = ffecom_f2c_doublecomplex_type_node;
1397 wanted = ffecom_f2c_real_type_node;
1401 wanted = ffecom_f2c_integer_type_node;
1405 wanted = ffecom_f2c_longint_type_node;
1409 assert ("bad argstring code" == NULL);
1415 exprh = ffebld_head (expr);
1419 if ((wanted == NULL_TREE)
1422 (ffecom_tree_type[ffeinfo_basictype (ffebld_info (exprh))]
1423 [ffeinfo_kindtype (ffebld_info (exprh))])
1424 == TYPE_MODE (wanted))))
1426 = build_tree_list (NULL_TREE,
1427 ffecom_arg_ptr_to_expr (exprh,
1431 item = ffecom_arg_expr (exprh, &length);
1432 item = ffecom_convert_widen_ (wanted, item);
1435 item = ffecom_1 (ADDR_EXPR,
1436 build_pointer_type (TREE_TYPE (item)),
1440 = build_tree_list (NULL_TREE,
1444 plist = &TREE_CHAIN (*plist);
1445 expr = ffebld_trail (expr);
1446 if (length != NULL_TREE)
1448 *ptrail = build_tree_list (NULL_TREE, length);
1449 ptrail = &TREE_CHAIN (*ptrail);
1453 /* We've run out of args in the call; if the implementation expects
1454 more, supply null pointers for them, which the implementation can
1455 check to see if an arg was omitted. */
1457 while (*c != '\0' && *c != '0')
1462 assert ("missing arg to run-time routine!" == NULL);
1477 assert ("bad arg string code" == NULL);
1481 = build_tree_list (NULL_TREE,
1483 plist = &TREE_CHAIN (*plist);
1492 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1494 ffecom_widest_expr_type_ (ffebld list)
1497 ffebld widest = NULL;
1499 ffetype widest_type = NULL;
1502 for (; list != NULL; list = ffebld_trail (list))
1504 item = ffebld_head (list);
1507 if ((widest != NULL)
1508 && (ffeinfo_basictype (ffebld_info (item))
1509 != ffeinfo_basictype (ffebld_info (widest))))
1511 type = ffeinfo_type (ffeinfo_basictype (ffebld_info (item)),
1512 ffeinfo_kindtype (ffebld_info (item)));
1513 if ((widest == FFEINFO_kindtypeNONE)
1514 || (ffetype_size (type)
1515 > ffetype_size (widest_type)))
1522 assert (widest != NULL);
1523 t = ffecom_tree_type[ffeinfo_basictype (ffebld_info (widest))]
1524 [ffeinfo_kindtype (ffebld_info (widest))];
1525 assert (t != NULL_TREE);
1530 /* Check whether a partial overlap between two expressions is possible.
1532 Can *starting* to write a portion of expr1 change the value
1533 computed (perhaps already, *partially*) by expr2?
1535 Currently, this is a concern only for a COMPLEX expr1. But if it
1536 isn't in COMMON or local EQUIVALENCE, since we don't support
1537 aliasing of arguments, it isn't a concern. */
1540 ffecom_possible_partial_overlap_ (ffebld expr1, ffebld expr2 ATTRIBUTE_UNUSED)
1545 switch (ffebld_op (expr1))
1547 case FFEBLD_opSYMTER:
1548 sym = ffebld_symter (expr1);
1551 case FFEBLD_opARRAYREF:
1552 if (ffebld_op (ffebld_left (expr1)) != FFEBLD_opSYMTER)
1554 sym = ffebld_symter (ffebld_left (expr1));
1561 if (ffesymbol_where (sym) != FFEINFO_whereCOMMON
1562 && (ffesymbol_where (sym) != FFEINFO_whereLOCAL
1563 || ! (st = ffesymbol_storage (sym))
1564 || ! ffestorag_parent (st)))
1567 /* It's in COMMON or local EQUIVALENCE. */
1572 /* Check whether dest and source might overlap. ffebld versions of these
1573 might or might not be passed, will be NULL if not.
1575 The test is really whether source_tree is modifiable and, if modified,
1576 might overlap destination such that the value(s) in the destination might
1577 change before it is finally modified. dest_* are the canonized
1578 destination itself. */
1580 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1582 ffecom_overlap_ (tree dest_decl, tree dest_offset, tree dest_size,
1583 tree source_tree, ffebld source UNUSED,
1591 if (source_tree == NULL_TREE)
1594 switch (TREE_CODE (source_tree))
1597 case IDENTIFIER_NODE:
1608 case TRUNC_DIV_EXPR:
1610 case FLOOR_DIV_EXPR:
1611 case ROUND_DIV_EXPR:
1612 case TRUNC_MOD_EXPR:
1614 case FLOOR_MOD_EXPR:
1615 case ROUND_MOD_EXPR:
1617 case EXACT_DIV_EXPR:
1618 case FIX_TRUNC_EXPR:
1620 case FIX_FLOOR_EXPR:
1621 case FIX_ROUND_EXPR:
1636 case BIT_ANDTC_EXPR:
1638 case TRUTH_ANDIF_EXPR:
1639 case TRUTH_ORIF_EXPR:
1640 case TRUTH_AND_EXPR:
1642 case TRUTH_XOR_EXPR:
1643 case TRUTH_NOT_EXPR:
1659 return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1660 TREE_OPERAND (source_tree, 1), NULL,
1664 return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1665 TREE_OPERAND (source_tree, 0), NULL,
1670 case NON_LVALUE_EXPR:
1672 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1675 ffecom_tree_canonize_ptr_ (&source_decl, &source_offset,
1677 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1682 ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1683 TREE_OPERAND (source_tree, 1), NULL,
1685 || ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1686 TREE_OPERAND (source_tree, 2), NULL,
1691 ffecom_tree_canonize_ref_ (&source_decl, &source_offset,
1693 TREE_OPERAND (source_tree, 0));
1697 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1700 source_decl = source_tree;
1701 source_offset = bitsize_zero_node;
1702 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1706 case REFERENCE_EXPR:
1707 case PREDECREMENT_EXPR:
1708 case PREINCREMENT_EXPR:
1709 case POSTDECREMENT_EXPR:
1710 case POSTINCREMENT_EXPR:
1718 /* Come here when source_decl, source_offset, and source_size filled
1719 in appropriately. */
1721 if (source_decl == NULL_TREE)
1722 return FALSE; /* No decl involved, so no overlap. */
1724 if (source_decl != dest_decl)
1725 return FALSE; /* Different decl, no overlap. */
1727 if (TREE_CODE (dest_size) == ERROR_MARK)
1728 return TRUE; /* Assignment into entire assumed-size
1729 array? Shouldn't happen.... */
1731 t = ffecom_2 (LE_EXPR, integer_type_node,
1732 ffecom_2 (PLUS_EXPR, TREE_TYPE (dest_offset),
1734 convert (TREE_TYPE (dest_offset),
1736 convert (TREE_TYPE (dest_offset),
1739 if (integer_onep (t))
1740 return FALSE; /* Destination precedes source. */
1743 || (source_size == NULL_TREE)
1744 || (TREE_CODE (source_size) == ERROR_MARK)
1745 || integer_zerop (source_size))
1746 return TRUE; /* No way to tell if dest follows source. */
1748 t = ffecom_2 (LE_EXPR, integer_type_node,
1749 ffecom_2 (PLUS_EXPR, TREE_TYPE (source_offset),
1751 convert (TREE_TYPE (source_offset),
1753 convert (TREE_TYPE (source_offset),
1756 if (integer_onep (t))
1757 return FALSE; /* Destination follows source. */
1759 return TRUE; /* Destination and source overlap. */
1763 /* Check whether dest might overlap any of a list of arguments or is
1764 in a COMMON area the callee might know about (and thus modify). */
1766 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1768 ffecom_args_overlapping_ (tree dest_tree, ffebld dest UNUSED,
1769 tree args, tree callee_commons,
1777 ffecom_tree_canonize_ref_ (&dest_decl, &dest_offset, &dest_size,
1780 if (dest_decl == NULL_TREE)
1781 return FALSE; /* Seems unlikely! */
1783 /* If the decl cannot be determined reliably, or if its in COMMON
1784 and the callee isn't known to not futz with COMMON via other
1785 means, overlap might happen. */
1787 if ((TREE_CODE (dest_decl) == ERROR_MARK)
1788 || ((callee_commons != NULL_TREE)
1789 && TREE_PUBLIC (dest_decl)))
1792 for (; args != NULL_TREE; args = TREE_CHAIN (args))
1794 if (((arg = TREE_VALUE (args)) != NULL_TREE)
1795 && ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1796 arg, NULL, scalar_args))
1804 /* Build a string for a variable name as used by NAMELIST. This means that
1805 if we're using the f2c library, we build an uppercase string, since
1808 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1810 ffecom_build_f2c_string_ (int i, const char *s)
1812 if (!ffe_is_f2c_library ())
1813 return build_string (i, s);
1822 if (((size_t) i) > ARRAY_SIZE (space))
1823 tmp = malloc_new_ks (malloc_pool_image (), "f2c_string", i);
1827 for (p = s, q = tmp; *p != '\0'; ++p, ++q)
1831 t = build_string (i, tmp);
1833 if (((size_t) i) > ARRAY_SIZE (space))
1834 malloc_kill_ks (malloc_pool_image (), tmp, i);
1841 /* Returns CALL_EXPR or equivalent with given type (pass NULL_TREE for
1842 type to just get whatever the function returns), handling the
1843 f2c value-returning convention, if required, by prepending
1844 to the arglist a pointer to a temporary to receive the return value. */
1846 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1848 ffecom_call_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1849 tree type, tree args, tree dest_tree,
1850 ffebld dest, bool *dest_used, tree callee_commons,
1851 bool scalar_args, tree hook)
1856 if (dest_used != NULL)
1861 if ((dest_used == NULL)
1863 || (ffeinfo_basictype (ffebld_info (dest))
1864 != FFEINFO_basictypeCOMPLEX)
1865 || (ffeinfo_kindtype (ffebld_info (dest)) != kt)
1866 || ((type != NULL_TREE) && (TREE_TYPE (dest_tree) != type))
1867 || ffecom_args_overlapping_ (dest_tree, dest, args,
1872 tempvar = ffecom_make_tempvar (ffecom_tree_type
1873 [FFEINFO_basictypeCOMPLEX][kt],
1874 FFETARGET_charactersizeNONE,
1884 tempvar = dest_tree;
1889 = build_tree_list (NULL_TREE,
1890 ffecom_1 (ADDR_EXPR,
1891 build_pointer_type (TREE_TYPE (tempvar)),
1893 TREE_CHAIN (item) = args;
1895 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1898 if (tempvar != dest_tree)
1899 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item, tempvar);
1902 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1905 if ((type != NULL_TREE) && (TREE_TYPE (item) != type))
1906 item = ffecom_convert_narrow_ (type, item);
1912 /* Given two arguments, transform them and make a call to the given
1913 function via ffecom_call_. */
1915 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1917 ffecom_call_binop_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1918 tree type, ffebld left, ffebld right,
1919 tree dest_tree, ffebld dest, bool *dest_used,
1920 tree callee_commons, bool scalar_args, bool ref, tree hook)
1929 /* Pass arguments by reference. */
1930 left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
1931 right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
1935 /* Pass arguments by value. */
1936 left_tree = ffecom_arg_expr (left, &left_length);
1937 right_tree = ffecom_arg_expr (right, &right_length);
1941 left_tree = build_tree_list (NULL_TREE, left_tree);
1942 right_tree = build_tree_list (NULL_TREE, right_tree);
1943 TREE_CHAIN (left_tree) = right_tree;
1945 if (left_length != NULL_TREE)
1947 left_length = build_tree_list (NULL_TREE, left_length);
1948 TREE_CHAIN (right_tree) = left_length;
1951 if (right_length != NULL_TREE)
1953 right_length = build_tree_list (NULL_TREE, right_length);
1954 if (left_length != NULL_TREE)
1955 TREE_CHAIN (left_length) = right_length;
1957 TREE_CHAIN (right_tree) = right_length;
1960 return ffecom_call_ (fn, kt, is_f2c_complex, type, left_tree,
1961 dest_tree, dest, dest_used, callee_commons,
1966 /* Return ptr/length args for char subexpression
1968 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
1969 subexpressions by constructing the appropriate trees for the ptr-to-
1970 character-text and length-of-character-text arguments in a calling
1973 Note that if with_null is TRUE, and the expression is an opCONTER,
1974 a null byte is appended to the string. */
1976 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1978 ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
1982 ffetargetCharacter1 val;
1983 ffetargetCharacterSize newlen;
1985 switch (ffebld_op (expr))
1987 case FFEBLD_opCONTER:
1988 val = ffebld_constant_character1 (ffebld_conter (expr));
1989 newlen = ffetarget_length_character1 (val);
1992 /* Begin FFETARGET-NULL-KLUDGE. */
1996 *length = build_int_2 (newlen, 0);
1997 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
1998 high = build_int_2 (newlen, 0);
1999 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
2000 item = build_string (newlen,
2001 ffetarget_text_character1 (val));
2002 /* End FFETARGET-NULL-KLUDGE. */
2004 = build_type_variant
2008 (ffecom_f2c_ftnlen_type_node,
2009 ffecom_f2c_ftnlen_one_node,
2012 TREE_CONSTANT (item) = 1;
2013 TREE_STATIC (item) = 1;
2014 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
2018 case FFEBLD_opSYMTER:
2020 ffesymbol s = ffebld_symter (expr);
2022 item = ffesymbol_hook (s).decl_tree;
2023 if (item == NULL_TREE)
2025 s = ffecom_sym_transform_ (s);
2026 item = ffesymbol_hook (s).decl_tree;
2028 if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
2030 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
2031 *length = ffesymbol_hook (s).length_tree;
2034 *length = build_int_2 (ffesymbol_size (s), 0);
2035 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2038 else if (item == error_mark_node)
2039 *length = error_mark_node;
2041 /* FFEINFO_kindFUNCTION. */
2042 *length = NULL_TREE;
2043 if (!ffesymbol_hook (s).addr
2044 && (item != error_mark_node))
2045 item = ffecom_1 (ADDR_EXPR,
2046 build_pointer_type (TREE_TYPE (item)),
2051 case FFEBLD_opARRAYREF:
2053 ffecom_char_args_ (&item, length, ffebld_left (expr));
2055 if (item == error_mark_node || *length == error_mark_node)
2057 item = *length = error_mark_node;
2061 item = ffecom_arrayref_ (item, expr, 1);
2065 case FFEBLD_opSUBSTR:
2069 ffebld thing = ffebld_right (expr);
2072 const char *char_name;
2076 assert (ffebld_op (thing) == FFEBLD_opITEM);
2077 start = ffebld_head (thing);
2078 thing = ffebld_trail (thing);
2079 assert (ffebld_trail (thing) == NULL);
2080 end = ffebld_head (thing);
2082 /* Determine name for pretty-printing range-check errors. */
2083 for (left_symter = ffebld_left (expr);
2084 left_symter && ffebld_op (left_symter) == FFEBLD_opARRAYREF;
2085 left_symter = ffebld_left (left_symter))
2087 if (ffebld_op (left_symter) == FFEBLD_opSYMTER)
2088 char_name = ffesymbol_text (ffebld_symter (left_symter));
2090 char_name = "[expr?]";
2092 ffecom_char_args_ (&item, length, ffebld_left (expr));
2094 if (item == error_mark_node || *length == error_mark_node)
2096 item = *length = error_mark_node;
2100 array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
2102 /* ~~~~Handle INTEGER*8 start/end, a la FFEBLD_opARRAYREF. */
2110 end_tree = ffecom_expr (end);
2111 if (flag_bounds_check)
2112 end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
2114 end_tree = convert (ffecom_f2c_ftnlen_type_node,
2117 if (end_tree == error_mark_node)
2119 item = *length = error_mark_node;
2128 start_tree = ffecom_expr (start);
2129 if (flag_bounds_check)
2130 start_tree = ffecom_subscript_check_ (array, start_tree, 0, 0,
2132 start_tree = convert (ffecom_f2c_ftnlen_type_node,
2135 if (start_tree == error_mark_node)
2137 item = *length = error_mark_node;
2141 start_tree = ffecom_save_tree (start_tree);
2143 item = ffecom_2 (PLUS_EXPR, TREE_TYPE (item),
2145 ffecom_2 (MINUS_EXPR,
2146 TREE_TYPE (start_tree),
2148 ffecom_f2c_ftnlen_one_node));
2152 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
2153 ffecom_f2c_ftnlen_one_node,
2154 ffecom_2 (MINUS_EXPR,
2155 ffecom_f2c_ftnlen_type_node,
2161 end_tree = ffecom_expr (end);
2162 if (flag_bounds_check)
2163 end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
2165 end_tree = convert (ffecom_f2c_ftnlen_type_node,
2168 if (end_tree == error_mark_node)
2170 item = *length = error_mark_node;
2174 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
2175 ffecom_f2c_ftnlen_one_node,
2176 ffecom_2 (MINUS_EXPR,
2177 ffecom_f2c_ftnlen_type_node,
2178 end_tree, start_tree));
2184 case FFEBLD_opFUNCREF:
2186 ffesymbol s = ffebld_symter (ffebld_left (expr));
2189 ffetargetCharacterSize size = ffeinfo_size (ffebld_info (expr));
2192 if (size == FFETARGET_charactersizeNONE)
2193 /* ~~Kludge alert! This should someday be fixed. */
2196 *length = build_int_2 (size, 0);
2197 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2199 if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
2200 == FFEINFO_whereINTRINSIC)
2204 /* Invocation of an intrinsic returning CHARACTER*1. */
2205 item = ffecom_expr_intrinsic_ (expr, NULL_TREE,
2209 ix = ffeintrin_gfrt_direct (ffebld_symter_implementation (ffebld_left (expr)));
2210 assert (ix != FFECOM_gfrt);
2211 item = ffecom_gfrt_tree_ (ix);
2216 item = ffesymbol_hook (s).decl_tree;
2217 if (item == NULL_TREE)
2219 s = ffecom_sym_transform_ (s);
2220 item = ffesymbol_hook (s).decl_tree;
2222 if (item == error_mark_node)
2224 item = *length = error_mark_node;
2228 if (!ffesymbol_hook (s).addr)
2229 item = ffecom_1_fn (item);
2233 tempvar = ffecom_push_tempvar (char_type_node, size, -1, TRUE);
2235 tempvar = ffebld_nonter_hook (expr);
2238 tempvar = ffecom_1 (ADDR_EXPR,
2239 build_pointer_type (TREE_TYPE (tempvar)),
2242 args = build_tree_list (NULL_TREE, tempvar);
2244 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT) /* Sfunc args by value. */
2245 TREE_CHAIN (args) = ffecom_list_expr (ffebld_right (expr));
2248 TREE_CHAIN (args) = build_tree_list (NULL_TREE, *length);
2249 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
2251 TREE_CHAIN (TREE_CHAIN (args))
2252 = ffecom_arglist_expr_ (ffecom_gfrt_args_ (ix),
2253 ffebld_right (expr));
2257 TREE_CHAIN (TREE_CHAIN (args))
2258 = ffecom_list_ptr_to_expr (ffebld_right (expr));
2262 item = ffecom_3s (CALL_EXPR,
2263 TREE_TYPE (TREE_TYPE (TREE_TYPE (item))),
2264 item, args, NULL_TREE);
2265 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item,
2270 case FFEBLD_opCONVERT:
2272 ffecom_char_args_ (&item, length, ffebld_left (expr));
2274 if (item == error_mark_node || *length == error_mark_node)
2276 item = *length = error_mark_node;
2280 if ((ffebld_size_known (ffebld_left (expr))
2281 == FFETARGET_charactersizeNONE)
2282 || (ffebld_size_known (ffebld_left (expr)) < (ffebld_size (expr))))
2283 { /* Possible blank-padding needed, copy into
2290 tempvar = ffecom_make_tempvar (char_type_node,
2291 ffebld_size (expr), -1);
2293 tempvar = ffebld_nonter_hook (expr);
2296 tempvar = ffecom_1 (ADDR_EXPR,
2297 build_pointer_type (TREE_TYPE (tempvar)),
2300 newlen = build_int_2 (ffebld_size (expr), 0);
2301 TREE_TYPE (newlen) = ffecom_f2c_ftnlen_type_node;
2303 args = build_tree_list (NULL_TREE, tempvar);
2304 TREE_CHAIN (args) = build_tree_list (NULL_TREE, item);
2305 TREE_CHAIN (TREE_CHAIN (args)) = build_tree_list (NULL_TREE, newlen);
2306 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (args)))
2307 = build_tree_list (NULL_TREE, *length);
2309 item = ffecom_call_gfrt (FFECOM_gfrtCOPY, args, NULL_TREE);
2310 TREE_SIDE_EFFECTS (item) = 1;
2311 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), fold (item),
2316 { /* Just truncate the length. */
2317 *length = build_int_2 (ffebld_size (expr), 0);
2318 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2323 assert ("bad op for single char arg expr" == NULL);
2332 /* Check the size of the type to be sure it doesn't overflow the
2333 "portable" capacities of the compiler back end. `dummy' types
2334 can generally overflow the normal sizes as long as the computations
2335 themselves don't overflow. A particular target of the back end
2336 must still enforce its size requirements, though, and the back
2337 end takes care of this in stor-layout.c. */
2339 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2341 ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy)
2343 if (TREE_CODE (type) == ERROR_MARK)
2346 if (TYPE_SIZE (type) == NULL_TREE)
2349 if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
2352 if ((tree_int_cst_sgn (TYPE_SIZE (type)) < 0)
2353 || (!dummy && (((TREE_INT_CST_HIGH (TYPE_SIZE (type)) != 0))
2354 || TREE_OVERFLOW (TYPE_SIZE (type)))))
2356 ffebad_start (FFEBAD_ARRAY_LARGE);
2357 ffebad_string (ffesymbol_text (s));
2358 ffebad_here (0, ffesymbol_where_line (s), ffesymbol_where_column (s));
2361 return error_mark_node;
2368 /* Builds a length argument (PARM_DECL). Also wraps type in an array type
2369 where the dimension info is (1:size) where <size> is ffesymbol_size(s) if
2370 known, length_arg if not known (FFETARGET_charactersizeNONE). */
2372 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2374 ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s)
2376 ffetargetCharacterSize sz = ffesymbol_size (s);
2381 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
2382 tlen = NULL_TREE; /* A statement function, no length passed. */
2385 if (ffesymbol_where (s) == FFEINFO_whereDUMMY)
2386 tlen = ffecom_get_invented_identifier ("__g77_length_%s",
2387 ffesymbol_text (s));
2389 tlen = ffecom_get_invented_identifier ("__g77_%s", "length");
2390 tlen = build_decl (PARM_DECL, tlen, ffecom_f2c_ftnlen_type_node);
2392 DECL_ARTIFICIAL (tlen) = 1;
2396 if (sz == FFETARGET_charactersizeNONE)
2398 assert (tlen != NULL_TREE);
2399 highval = variable_size (tlen);
2403 highval = build_int_2 (sz, 0);
2404 TREE_TYPE (highval) = ffecom_f2c_ftnlen_type_node;
2407 type = build_array_type (type,
2408 build_range_type (ffecom_f2c_ftnlen_type_node,
2409 ffecom_f2c_ftnlen_one_node,
2417 /* ffecom_concat_list_gather_ -- Gather list of concatenated string exprs
2419 ffecomConcatList_ catlist;
2420 ffebld expr; // expr of CHARACTER basictype.
2421 ffetargetCharacterSize max; // max chars to gather or _...NONE if no max
2422 catlist = ffecom_concat_list_gather_(catlist,expr,max);
2424 Scans expr for character subexpressions, updates and returns catlist
2427 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2428 static ffecomConcatList_
2429 ffecom_concat_list_gather_ (ffecomConcatList_ catlist, ffebld expr,
2430 ffetargetCharacterSize max)
2432 ffetargetCharacterSize sz;
2434 recurse: /* :::::::::::::::::::: */
2439 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen >= max))
2440 return catlist; /* Don't append any more items. */
2442 switch (ffebld_op (expr))
2444 case FFEBLD_opCONTER:
2445 case FFEBLD_opSYMTER:
2446 case FFEBLD_opARRAYREF:
2447 case FFEBLD_opFUNCREF:
2448 case FFEBLD_opSUBSTR:
2449 case FFEBLD_opCONVERT: /* Callers should strip this off beforehand
2450 if they don't need to preserve it. */
2451 if (catlist.count == catlist.max)
2452 { /* Make a (larger) list. */
2456 newmax = (catlist.max == 0) ? 8 : catlist.max * 2;
2457 newx = malloc_new_ks (malloc_pool_image (), "catlist",
2458 newmax * sizeof (newx[0]));
2459 if (catlist.max != 0)
2461 memcpy (newx, catlist.exprs, catlist.max * sizeof (newx[0]));
2462 malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2463 catlist.max * sizeof (newx[0]));
2465 catlist.max = newmax;
2466 catlist.exprs = newx;
2468 if ((sz = ffebld_size_known (expr)) != FFETARGET_charactersizeNONE)
2469 catlist.minlen += sz;
2471 ++catlist.minlen; /* Not true for F90; can be 0 length. */
2472 if ((sz = ffebld_size_max (expr)) == FFETARGET_charactersizeNONE)
2473 catlist.maxlen = sz;
2475 catlist.maxlen += sz;
2476 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen > max))
2477 { /* This item overlaps (or is beyond) the end
2478 of the destination. */
2479 switch (ffebld_op (expr))
2481 case FFEBLD_opCONTER:
2482 case FFEBLD_opSYMTER:
2483 case FFEBLD_opARRAYREF:
2484 case FFEBLD_opFUNCREF:
2485 case FFEBLD_opSUBSTR:
2486 /* ~~Do useful truncations here. */
2490 assert ("op changed or inconsistent switches!" == NULL);
2494 catlist.exprs[catlist.count++] = expr;
2497 case FFEBLD_opPAREN:
2498 expr = ffebld_left (expr);
2499 goto recurse; /* :::::::::::::::::::: */
2501 case FFEBLD_opCONCATENATE:
2502 catlist = ffecom_concat_list_gather_ (catlist, ffebld_left (expr), max);
2503 expr = ffebld_right (expr);
2504 goto recurse; /* :::::::::::::::::::: */
2506 #if 0 /* Breaks passing small actual arg to larger
2507 dummy arg of sfunc */
2508 case FFEBLD_opCONVERT:
2509 expr = ffebld_left (expr);
2511 ffetargetCharacterSize cmax;
2513 cmax = catlist.len + ffebld_size_known (expr);
2515 if ((max == FFETARGET_charactersizeNONE) || (max > cmax))
2518 goto recurse; /* :::::::::::::::::::: */
2525 assert ("bad op in _gather_" == NULL);
2531 /* ffecom_concat_list_kill_ -- Kill list of concatenated string exprs
2533 ffecomConcatList_ catlist;
2534 ffecom_concat_list_kill_(catlist);
2536 Anything allocated within the list info is deallocated. */
2538 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2540 ffecom_concat_list_kill_ (ffecomConcatList_ catlist)
2542 if (catlist.max != 0)
2543 malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2544 catlist.max * sizeof (catlist.exprs[0]));
2548 /* Make list of concatenated string exprs.
2550 Returns a flattened list of concatenated subexpressions given a
2551 tree of such expressions. */
2553 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2554 static ffecomConcatList_
2555 ffecom_concat_list_new_ (ffebld expr, ffetargetCharacterSize max)
2557 ffecomConcatList_ catlist;
2559 catlist.maxlen = catlist.minlen = catlist.max = catlist.count = 0;
2560 return ffecom_concat_list_gather_ (catlist, expr, max);
2565 /* Provide some kind of useful info on member of aggregate area,
2566 since current g77/gcc technology does not provide debug info
2567 on these members. */
2569 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2571 ffecom_debug_kludge_ (tree aggr, const char *aggr_type, ffesymbol member,
2572 tree member_type UNUSED, ffetargetOffset offset)
2582 for (type_id = member_type;
2583 TREE_CODE (type_id) != IDENTIFIER_NODE;
2586 switch (TREE_CODE (type_id))
2590 type_id = TYPE_NAME (type_id);
2595 type_id = TREE_TYPE (type_id);
2599 assert ("no IDENTIFIER_NODE for type!" == NULL);
2600 type_id = error_mark_node;
2606 if (ffecom_transform_only_dummies_
2607 || !ffe_is_debug_kludge ())
2608 return; /* Can't do this yet, maybe later. */
2611 + strlen (aggr_type)
2612 + IDENTIFIER_LENGTH (DECL_NAME (aggr));
2614 + IDENTIFIER_LENGTH (type_id);
2617 if (((size_t) len) >= ARRAY_SIZE (space))
2618 buff = malloc_new_ks (malloc_pool_image (), "debug_kludge", len + 1);
2622 sprintf (&buff[0], "At (%s) `%s' plus %ld bytes",
2624 IDENTIFIER_POINTER (DECL_NAME (aggr)),
2627 value = build_string (len, buff);
2629 = build_type_variant (build_array_type (char_type_node,
2633 build_int_2 (strlen (buff), 0))),
2635 decl = build_decl (VAR_DECL,
2636 ffecom_get_identifier_ (ffesymbol_text (member)),
2638 TREE_CONSTANT (decl) = 1;
2639 TREE_STATIC (decl) = 1;
2640 DECL_INITIAL (decl) = error_mark_node;
2641 DECL_IN_SYSTEM_HEADER (decl) = 1; /* Don't let -Wunused complain. */
2642 decl = start_decl (decl, FALSE);
2643 finish_decl (decl, value, FALSE);
2645 if (buff != &space[0])
2646 malloc_kill_ks (malloc_pool_image (), buff, len + 1);
2650 /* ffecom_do_entry_ -- Do compilation of a particular entrypoint
2652 ffesymbol fn; // the SUBROUTINE, FUNCTION, or ENTRY symbol itself
2653 int i; // entry# for this entrypoint (used by master fn)
2654 ffecom_do_entrypoint_(s,i);
2656 Makes a public entry point that calls our private master fn (already
2659 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2661 ffecom_do_entry_ (ffesymbol fn, int entrynum)
2664 tree type; /* Type of function. */
2665 tree multi_retval; /* Var holding return value (union). */
2666 tree result; /* Var holding result. */
2667 ffeinfoBasictype bt;
2671 bool charfunc; /* All entry points return same type
2673 bool cmplxfunc; /* Use f2c way of returning COMPLEX. */
2674 bool multi; /* Master fn has multiple return types. */
2675 bool altreturning = FALSE; /* This entry point has alternate returns. */
2676 int old_lineno = lineno;
2677 const char *old_input_filename = input_filename;
2679 input_filename = ffesymbol_where_filename (fn);
2680 lineno = ffesymbol_where_filelinenum (fn);
2682 ffecom_doing_entry_ = TRUE; /* Don't bother with array dimensions. */
2684 switch (ffecom_primary_entry_kind_)
2686 case FFEINFO_kindFUNCTION:
2688 /* Determine actual return type for function. */
2690 gt = FFEGLOBAL_typeFUNC;
2691 bt = ffesymbol_basictype (fn);
2692 kt = ffesymbol_kindtype (fn);
2693 if (bt == FFEINFO_basictypeNONE)
2695 ffeimplic_establish_symbol (fn);
2696 if (ffesymbol_funcresult (fn) != NULL)
2697 ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
2698 bt = ffesymbol_basictype (fn);
2699 kt = ffesymbol_kindtype (fn);
2702 if (bt == FFEINFO_basictypeCHARACTER)
2703 charfunc = TRUE, cmplxfunc = FALSE;
2704 else if ((bt == FFEINFO_basictypeCOMPLEX)
2705 && ffesymbol_is_f2c (fn))
2706 charfunc = FALSE, cmplxfunc = TRUE;
2708 charfunc = cmplxfunc = FALSE;
2711 type = ffecom_tree_fun_type_void;
2712 else if (ffesymbol_is_f2c (fn))
2713 type = ffecom_tree_fun_type[bt][kt];
2715 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
2717 if ((type == NULL_TREE)
2718 || (TREE_TYPE (type) == NULL_TREE))
2719 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */
2721 multi = (ffecom_master_bt_ == FFEINFO_basictypeNONE);
2724 case FFEINFO_kindSUBROUTINE:
2725 gt = FFEGLOBAL_typeSUBR;
2726 bt = FFEINFO_basictypeNONE;
2727 kt = FFEINFO_kindtypeNONE;
2728 if (ffecom_is_altreturning_)
2729 { /* Am _I_ altreturning? */
2730 for (item = ffesymbol_dummyargs (fn);
2732 item = ffebld_trail (item))
2734 if (ffebld_op (ffebld_head (item)) == FFEBLD_opSTAR)
2736 altreturning = TRUE;
2741 type = ffecom_tree_subr_type;
2743 type = ffecom_tree_fun_type_void;
2746 type = ffecom_tree_fun_type_void;
2753 assert ("say what??" == NULL);
2755 case FFEINFO_kindANY:
2756 gt = FFEGLOBAL_typeANY;
2757 bt = FFEINFO_basictypeNONE;
2758 kt = FFEINFO_kindtypeNONE;
2759 type = error_mark_node;
2766 /* build_decl uses the current lineno and input_filename to set the decl
2767 source info. So, I've putzed with ffestd and ffeste code to update that
2768 source info to point to the appropriate statement just before calling
2769 ffecom_do_entrypoint (which calls this fn). */
2771 start_function (ffecom_get_external_identifier_ (fn),
2773 0, /* nested/inline */
2774 1); /* TREE_PUBLIC */
2776 if (((g = ffesymbol_global (fn)) != NULL)
2777 && ((ffeglobal_type (g) == gt)
2778 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
2780 ffeglobal_set_hook (g, current_function_decl);
2783 /* Reset args in master arg list so they get retransitioned. */
2785 for (item = ffecom_master_arglist_;
2787 item = ffebld_trail (item))
2792 arg = ffebld_head (item);
2793 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2794 continue; /* Alternate return or some such thing. */
2795 s = ffebld_symter (arg);
2796 ffesymbol_hook (s).decl_tree = NULL_TREE;
2797 ffesymbol_hook (s).length_tree = NULL_TREE;
2800 /* Build dummy arg list for this entry point. */
2802 if (charfunc || cmplxfunc)
2803 { /* Prepend arg for where result goes. */
2808 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
2810 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
2812 result = ffecom_get_invented_identifier ("__g77_%s", "result");
2814 /* Make length arg _and_ enhance type info for CHAR arg itself. */
2817 length = ffecom_char_enhance_arg_ (&type, fn);
2819 length = NULL_TREE; /* Not ref'd if !charfunc. */
2821 type = build_pointer_type (type);
2822 result = build_decl (PARM_DECL, result, type);
2824 push_parm_decl (result);
2825 ffecom_func_result_ = result;
2829 push_parm_decl (length);
2830 ffecom_func_length_ = length;
2834 result = DECL_RESULT (current_function_decl);
2836 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (fn), FALSE);
2838 store_parm_decls (0);
2840 ffecom_start_compstmt ();
2841 /* Disallow temp vars at this level. */
2842 current_binding_level->prep_state = 2;
2844 /* Make local var to hold return type for multi-type master fn. */
2848 multi_retval = ffecom_get_invented_identifier ("__g77_%s",
2850 multi_retval = build_decl (VAR_DECL, multi_retval,
2851 ffecom_multi_type_node_);
2852 multi_retval = start_decl (multi_retval, FALSE);
2853 finish_decl (multi_retval, NULL_TREE, FALSE);
2856 multi_retval = NULL_TREE; /* Not actually ref'd if !multi. */
2858 /* Here we emit the actual code for the entry point. */
2864 tree arglist = NULL_TREE;
2865 tree *plist = &arglist;
2871 /* Prepare actual arg list based on master arg list. */
2873 for (list = ffecom_master_arglist_;
2875 list = ffebld_trail (list))
2877 arg = ffebld_head (list);
2878 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2880 s = ffebld_symter (arg);
2881 if (ffesymbol_hook (s).decl_tree == NULL_TREE
2882 || ffesymbol_hook (s).decl_tree == error_mark_node)
2883 actarg = null_pointer_node; /* We don't have this arg. */
2885 actarg = ffesymbol_hook (s).decl_tree;
2886 *plist = build_tree_list (NULL_TREE, actarg);
2887 plist = &TREE_CHAIN (*plist);
2890 /* This code appends the length arguments for character
2891 variables/arrays. */
2893 for (list = ffecom_master_arglist_;
2895 list = ffebld_trail (list))
2897 arg = ffebld_head (list);
2898 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2900 s = ffebld_symter (arg);
2901 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
2902 continue; /* Only looking for CHARACTER arguments. */
2903 if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
2904 continue; /* Only looking for variables and arrays. */
2905 if (ffesymbol_hook (s).length_tree == NULL_TREE
2906 || ffesymbol_hook (s).length_tree == error_mark_node)
2907 actarg = ffecom_f2c_ftnlen_zero_node; /* We don't have this arg. */
2909 actarg = ffesymbol_hook (s).length_tree;
2910 *plist = build_tree_list (NULL_TREE, actarg);
2911 plist = &TREE_CHAIN (*plist);
2914 /* Prepend character-value return info to actual arg list. */
2918 prepend = build_tree_list (NULL_TREE, ffecom_func_result_);
2919 TREE_CHAIN (prepend)
2920 = build_tree_list (NULL_TREE, ffecom_func_length_);
2921 TREE_CHAIN (TREE_CHAIN (prepend)) = arglist;
2925 /* Prepend multi-type return value to actual arg list. */
2930 = build_tree_list (NULL_TREE,
2931 ffecom_1 (ADDR_EXPR,
2932 build_pointer_type (TREE_TYPE (multi_retval)),
2934 TREE_CHAIN (prepend) = arglist;
2938 /* Prepend my entry-point number to the actual arg list. */
2940 prepend = build_tree_list (NULL_TREE, build_int_2 (entrynum, 0));
2941 TREE_CHAIN (prepend) = arglist;
2944 /* Build the call to the master function. */
2946 master_fn = ffecom_1_fn (ffecom_previous_function_decl_);
2947 call = ffecom_3s (CALL_EXPR,
2948 TREE_TYPE (TREE_TYPE (TREE_TYPE (master_fn))),
2949 master_fn, arglist, NULL_TREE);
2951 /* Decide whether the master function is a function or subroutine, and
2952 handle the return value for my entry point. */
2954 if (charfunc || ((ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
2957 expand_expr_stmt (call);
2958 expand_null_return ();
2960 else if (multi && cmplxfunc)
2962 expand_expr_stmt (call);
2964 = ffecom_1 (INDIRECT_REF,
2965 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
2967 result = ffecom_modify (NULL_TREE, result,
2968 ffecom_2 (COMPONENT_REF, TREE_TYPE (result),
2970 ffecom_multi_fields_[bt][kt]));
2971 expand_expr_stmt (result);
2972 expand_null_return ();
2976 expand_expr_stmt (call);
2978 = ffecom_modify (NULL_TREE, result,
2979 convert (TREE_TYPE (result),
2980 ffecom_2 (COMPONENT_REF,
2981 ffecom_tree_type[bt][kt],
2983 ffecom_multi_fields_[bt][kt])));
2984 expand_return (result);
2989 = ffecom_1 (INDIRECT_REF,
2990 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
2992 result = ffecom_modify (NULL_TREE, result, call);
2993 expand_expr_stmt (result);
2994 expand_null_return ();
2998 result = ffecom_modify (NULL_TREE,
3000 convert (TREE_TYPE (result),
3002 expand_return (result);
3006 ffecom_end_compstmt ();
3008 finish_function (0);
3010 lineno = old_lineno;
3011 input_filename = old_input_filename;
3013 ffecom_doing_entry_ = FALSE;
3017 /* Transform expr into gcc tree with possible destination
3019 Recursive descent on expr while making corresponding tree nodes and
3020 attaching type info and such. If destination supplied and compatible
3021 with temporary that would be made in certain cases, temporary isn't
3022 made, destination used instead, and dest_used flag set TRUE. */
3024 #if FFECOM_targetCURRENT == FFECOM_targetGCC
3026 ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
3027 bool *dest_used, bool assignp, bool widenp)
3032 ffeinfoBasictype bt;
3035 tree dt; /* decl_tree for an ffesymbol. */
3036 tree tree_type, tree_type_x;
3039 enum tree_code code;
3041 assert (expr != NULL);
3043 if (dest_used != NULL)
3046 bt = ffeinfo_basictype (ffebld_info (expr));
3047 kt = ffeinfo_kindtype (ffebld_info (expr));
3048 tree_type = ffecom_tree_type[bt][kt];
3050 /* Widen integral arithmetic as desired while preserving signedness. */
3051 tree_type_x = NULL_TREE;
3052 if (widenp && tree_type
3053 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
3054 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
3055 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
3057 switch (ffebld_op (expr))
3059 case FFEBLD_opACCTER:
3062 ffebit bits = ffebld_accter_bits (expr);
3063 ffetargetOffset source_offset = 0;
3064 ffetargetOffset dest_offset = ffebld_accter_pad (expr);
3067 assert (dest_offset == 0
3068 || (bt == FFEINFO_basictypeCHARACTER
3069 && kt == FFEINFO_kindtypeCHARACTER1));
3074 ffebldConstantUnion cu;
3077 ffebldConstantArray ca = ffebld_accter (expr);
3079 ffebit_test (bits, source_offset, &value, &length);
3085 for (i = 0; i < length; ++i)
3087 cu = ffebld_constantarray_get (ca, bt, kt,
3090 t = ffecom_constantunion (&cu, bt, kt, tree_type);
3093 && dest_offset != 0)
3094 purpose = build_int_2 (dest_offset, 0);
3096 purpose = NULL_TREE;
3098 if (list == NULL_TREE)
3099 list = item = build_tree_list (purpose, t);
3102 TREE_CHAIN (item) = build_tree_list (purpose, t);
3103 item = TREE_CHAIN (item);
3107 source_offset += length;
3108 dest_offset += length;
3112 item = build_int_2 ((ffebld_accter_size (expr)
3113 + ffebld_accter_pad (expr)) - 1, 0);
3114 ffebit_kill (ffebld_accter_bits (expr));
3115 TREE_TYPE (item) = ffecom_integer_type_node;
3119 build_range_type (ffecom_integer_type_node,
3120 ffecom_integer_zero_node,
3122 list = build (CONSTRUCTOR, item, NULL_TREE, list);
3123 TREE_CONSTANT (list) = 1;
3124 TREE_STATIC (list) = 1;
3127 case FFEBLD_opARRTER:
3132 if (ffebld_arrter_pad (expr) == 0)
3136 assert (bt == FFEINFO_basictypeCHARACTER
3137 && kt == FFEINFO_kindtypeCHARACTER1);
3139 /* Becomes PURPOSE first time through loop. */
3140 item = build_int_2 (ffebld_arrter_pad (expr), 0);
3143 for (i = 0; i < ffebld_arrter_size (expr); ++i)
3145 ffebldConstantUnion cu
3146 = ffebld_constantarray_get (ffebld_arrter (expr), bt, kt, i);
3148 t = ffecom_constantunion (&cu, bt, kt, tree_type);
3150 if (list == NULL_TREE)
3151 /* Assume item is PURPOSE first time through loop. */
3152 list = item = build_tree_list (item, t);
3155 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
3156 item = TREE_CHAIN (item);
3161 item = build_int_2 ((ffebld_arrter_size (expr)
3162 + ffebld_arrter_pad (expr)) - 1, 0);
3163 TREE_TYPE (item) = ffecom_integer_type_node;
3167 build_range_type (ffecom_integer_type_node,
3168 ffecom_integer_zero_node,
3170 list = build (CONSTRUCTOR, item, NULL_TREE, list);
3171 TREE_CONSTANT (list) = 1;
3172 TREE_STATIC (list) = 1;
3175 case FFEBLD_opCONTER:
3176 assert (ffebld_conter_pad (expr) == 0);
3178 = ffecom_constantunion (&ffebld_constant_union (ffebld_conter (expr)),
3182 case FFEBLD_opSYMTER:
3183 if ((ffebld_symter_generic (expr) != FFEINTRIN_genNONE)
3184 || (ffebld_symter_specific (expr) != FFEINTRIN_specNONE))
3185 return ffecom_ptr_to_expr (expr); /* Same as %REF(intrinsic). */
3186 s = ffebld_symter (expr);
3187 t = ffesymbol_hook (s).decl_tree;
3190 { /* ASSIGN'ed-label expr. */
3191 if (ffe_is_ugly_assign ())
3193 /* User explicitly wants ASSIGN'ed variables to be at the same
3194 memory address as the variables when used in non-ASSIGN
3195 contexts. That can make old, arcane, non-standard code
3196 work, but don't try to do it when a pointer wouldn't fit
3197 in the normal variable (take other approach, and warn,
3202 s = ffecom_sym_transform_ (s);
3203 t = ffesymbol_hook (s).decl_tree;
3204 assert (t != NULL_TREE);
3207 if (t == error_mark_node)
3210 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (t)))
3211 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
3213 if (ffesymbol_hook (s).addr)
3214 t = ffecom_1 (INDIRECT_REF,
3215 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
3219 if (ffesymbol_hook (s).assign_tree == NULL_TREE)
3221 ffebad_start_msg ("ASSIGN'ed label cannot fit into `%A' at %0 -- using wider sibling",
3222 FFEBAD_severityWARNING);
3223 ffebad_string (ffesymbol_text (s));
3224 ffebad_here (0, ffesymbol_where_line (s),
3225 ffesymbol_where_column (s));
3230 /* Don't use the normal variable's tree for ASSIGN, though mark
3231 it as in the system header (housekeeping). Use an explicit,
3232 specially created sibling that is known to be wide enough
3233 to hold pointers to labels. */
3236 && TREE_CODE (t) == VAR_DECL)
3237 DECL_IN_SYSTEM_HEADER (t) = 1; /* Don't let -Wunused complain. */
3239 t = ffesymbol_hook (s).assign_tree;
3242 s = ffecom_sym_transform_assign_ (s);
3243 t = ffesymbol_hook (s).assign_tree;
3244 assert (t != NULL_TREE);
3251 s = ffecom_sym_transform_ (s);
3252 t = ffesymbol_hook (s).decl_tree;
3253 assert (t != NULL_TREE);
3255 if (ffesymbol_hook (s).addr)
3256 t = ffecom_1 (INDIRECT_REF,
3257 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
3261 case FFEBLD_opARRAYREF:
3262 return ffecom_arrayref_ (NULL_TREE, expr, 0);
3264 case FFEBLD_opUPLUS:
3265 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3266 return ffecom_1 (NOP_EXPR, tree_type, left);
3268 case FFEBLD_opPAREN:
3269 /* ~~~Make sure Fortran rules respected here */
3270 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3271 return ffecom_1 (NOP_EXPR, tree_type, left);
3273 case FFEBLD_opUMINUS:
3274 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3277 tree_type = tree_type_x;
3278 left = convert (tree_type, left);
3280 return ffecom_1 (NEGATE_EXPR, tree_type, left);
3283 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3284 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3287 tree_type = tree_type_x;
3288 left = convert (tree_type, left);
3289 right = convert (tree_type, right);
3291 return ffecom_2 (PLUS_EXPR, tree_type, left, right);
3293 case FFEBLD_opSUBTRACT:
3294 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3295 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3298 tree_type = tree_type_x;
3299 left = convert (tree_type, left);
3300 right = convert (tree_type, right);
3302 return ffecom_2 (MINUS_EXPR, tree_type, left, right);
3304 case FFEBLD_opMULTIPLY:
3305 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3306 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3309 tree_type = tree_type_x;
3310 left = convert (tree_type, left);
3311 right = convert (tree_type, right);
3313 return ffecom_2 (MULT_EXPR, tree_type, left, right);
3315 case FFEBLD_opDIVIDE:
3316 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3317 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3320 tree_type = tree_type_x;
3321 left = convert (tree_type, left);
3322 right = convert (tree_type, right);
3324 return ffecom_tree_divide_ (tree_type, left, right,
3325 dest_tree, dest, dest_used,
3326 ffebld_nonter_hook (expr));
3328 case FFEBLD_opPOWER:
3330 ffebld left = ffebld_left (expr);
3331 ffebld right = ffebld_right (expr);
3333 ffeinfoKindtype rtkt;
3334 ffeinfoKindtype ltkt;
3337 switch (ffeinfo_basictype (ffebld_info (right)))
3340 case FFEINFO_basictypeINTEGER:
3343 item = ffecom_expr_power_integer_ (expr);
3344 if (item != NULL_TREE)
3348 rtkt = FFEINFO_kindtypeINTEGER1;
3349 switch (ffeinfo_basictype (ffebld_info (left)))
3351 case FFEINFO_basictypeINTEGER:
3352 if ((ffeinfo_kindtype (ffebld_info (left))
3353 == FFEINFO_kindtypeINTEGER4)
3354 || (ffeinfo_kindtype (ffebld_info (right))
3355 == FFEINFO_kindtypeINTEGER4))
3357 code = FFECOM_gfrtPOW_QQ;
3358 ltkt = FFEINFO_kindtypeINTEGER4;
3359 rtkt = FFEINFO_kindtypeINTEGER4;
3363 code = FFECOM_gfrtPOW_II;
3364 ltkt = FFEINFO_kindtypeINTEGER1;
3368 case FFEINFO_basictypeREAL:
3369 if (ffeinfo_kindtype (ffebld_info (left))
3370 == FFEINFO_kindtypeREAL1)
3372 code = FFECOM_gfrtPOW_RI;
3373 ltkt = FFEINFO_kindtypeREAL1;
3377 code = FFECOM_gfrtPOW_DI;
3378 ltkt = FFEINFO_kindtypeREAL2;
3382 case FFEINFO_basictypeCOMPLEX:
3383 if (ffeinfo_kindtype (ffebld_info (left))
3384 == FFEINFO_kindtypeREAL1)
3386 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */
3387 ltkt = FFEINFO_kindtypeREAL1;
3391 code = FFECOM_gfrtPOW_ZI; /* Overlapping result okay. */
3392 ltkt = FFEINFO_kindtypeREAL2;
3397 assert ("bad pow_*i" == NULL);
3398 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */
3399 ltkt = FFEINFO_kindtypeREAL1;
3402 if (ffeinfo_kindtype (ffebld_info (left)) != ltkt)
3403 left = ffeexpr_convert (left, NULL, NULL,
3404 ffeinfo_basictype (ffebld_info (left)),
3406 FFETARGET_charactersizeNONE,
3407 FFEEXPR_contextLET);
3408 if (ffeinfo_kindtype (ffebld_info (right)) != rtkt)
3409 right = ffeexpr_convert (right, NULL, NULL,
3410 FFEINFO_basictypeINTEGER,
3412 FFETARGET_charactersizeNONE,
3413 FFEEXPR_contextLET);
3416 case FFEINFO_basictypeREAL:
3417 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3418 left = ffeexpr_convert (left, NULL, NULL, FFEINFO_basictypeREAL,
3419 FFEINFO_kindtypeREALDOUBLE, 0,
3420 FFETARGET_charactersizeNONE,
3421 FFEEXPR_contextLET);
3422 if (ffeinfo_kindtype (ffebld_info (right))
3423 == FFEINFO_kindtypeREAL1)
3424 right = ffeexpr_convert (right, NULL, NULL,
3425 FFEINFO_basictypeREAL,
3426 FFEINFO_kindtypeREALDOUBLE, 0,
3427 FFETARGET_charactersizeNONE,
3428 FFEEXPR_contextLET);
3429 /* We used to call FFECOM_gfrtPOW_DD here,
3430 which passes arguments by reference. */
3431 code = FFECOM_gfrtL_POW;
3432 /* Pass arguments by value. */
3436 case FFEINFO_basictypeCOMPLEX:
3437 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3438 left = ffeexpr_convert (left, NULL, NULL,
3439 FFEINFO_basictypeCOMPLEX,
3440 FFEINFO_kindtypeREALDOUBLE, 0,
3441 FFETARGET_charactersizeNONE,
3442 FFEEXPR_contextLET);
3443 if (ffeinfo_kindtype (ffebld_info (right))
3444 == FFEINFO_kindtypeREAL1)
3445 right = ffeexpr_convert (right, NULL, NULL,
3446 FFEINFO_basictypeCOMPLEX,
3447 FFEINFO_kindtypeREALDOUBLE, 0,
3448 FFETARGET_charactersizeNONE,
3449 FFEEXPR_contextLET);
3450 code = FFECOM_gfrtPOW_ZZ; /* Overlapping result okay. */
3451 ref = TRUE; /* Pass arguments by reference. */
3455 assert ("bad pow_x*" == NULL);
3456 code = FFECOM_gfrtPOW_II;
3459 return ffecom_call_binop_ (ffecom_gfrt_tree_ (code),
3460 ffecom_gfrt_kindtype (code),
3461 (ffe_is_f2c_library ()
3462 && ffecom_gfrt_complex_[code]),
3463 tree_type, left, right,
3464 dest_tree, dest, dest_used,
3465 NULL_TREE, FALSE, ref,
3466 ffebld_nonter_hook (expr));
3472 case FFEINFO_basictypeLOGICAL:
3473 item = ffecom_truth_value_invert (ffecom_expr (ffebld_left (expr)));
3474 return convert (tree_type, item);
3476 case FFEINFO_basictypeINTEGER:
3477 return ffecom_1 (BIT_NOT_EXPR, tree_type,
3478 ffecom_expr (ffebld_left (expr)));
3481 assert ("NOT bad basictype" == NULL);
3483 case FFEINFO_basictypeANY:
3484 return error_mark_node;
3488 case FFEBLD_opFUNCREF:
3489 assert (ffeinfo_basictype (ffebld_info (expr))
3490 != FFEINFO_basictypeCHARACTER);
3492 case FFEBLD_opSUBRREF:
3493 if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
3494 == FFEINFO_whereINTRINSIC)
3495 { /* Invocation of an intrinsic. */
3496 item = ffecom_expr_intrinsic_ (expr, dest_tree, dest,
3500 s = ffebld_symter (ffebld_left (expr));
3501 dt = ffesymbol_hook (s).decl_tree;
3502 if (dt == NULL_TREE)
3504 s = ffecom_sym_transform_ (s);
3505 dt = ffesymbol_hook (s).decl_tree;
3507 if (dt == error_mark_node)
3510 if (ffesymbol_hook (s).addr)
3513 item = ffecom_1_fn (dt);
3515 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
3516 args = ffecom_list_expr (ffebld_right (expr));
3518 args = ffecom_list_ptr_to_expr (ffebld_right (expr));
3520 if (args == error_mark_node)
3521 return error_mark_node;
3523 item = ffecom_call_ (item, kt,
3524 ffesymbol_is_f2c (s)
3525 && (bt == FFEINFO_basictypeCOMPLEX)
3526 && (ffesymbol_where (s)
3527 != FFEINFO_whereCONSTANT),
3530 dest_tree, dest, dest_used,
3531 error_mark_node, FALSE,
3532 ffebld_nonter_hook (expr));
3533 TREE_SIDE_EFFECTS (item) = 1;
3539 case FFEINFO_basictypeLOGICAL:
3541 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3542 ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3543 ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3544 return convert (tree_type, item);
3546 case FFEINFO_basictypeINTEGER:
3547 return ffecom_2 (BIT_AND_EXPR, tree_type,
3548 ffecom_expr (ffebld_left (expr)),
3549 ffecom_expr (ffebld_right (expr)));
3552 assert ("AND bad basictype" == NULL);
3554 case FFEINFO_basictypeANY:
3555 return error_mark_node;
3562 case FFEINFO_basictypeLOGICAL:
3564 = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
3565 ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3566 ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3567 return convert (tree_type, item);
3569 case FFEINFO_basictypeINTEGER:
3570 return ffecom_2 (BIT_IOR_EXPR, tree_type,
3571 ffecom_expr (ffebld_left (expr)),
3572 ffecom_expr (ffebld_right (expr)));
3575 assert ("OR bad basictype" == NULL);
3577 case FFEINFO_basictypeANY:
3578 return error_mark_node;
3586 case FFEINFO_basictypeLOGICAL:
3588 = ffecom_2 (NE_EXPR, integer_type_node,
3589 ffecom_expr (ffebld_left (expr)),
3590 ffecom_expr (ffebld_right (expr)));
3591 return convert (tree_type, ffecom_truth_value (item));
3593 case FFEINFO_basictypeINTEGER:
3594 return ffecom_2 (BIT_XOR_EXPR, tree_type,
3595 ffecom_expr (ffebld_left (expr)),
3596 ffecom_expr (ffebld_right (expr)));
3599 assert ("XOR/NEQV bad basictype" == NULL);
3601 case FFEINFO_basictypeANY:
3602 return error_mark_node;
3609 case FFEINFO_basictypeLOGICAL:
3611 = ffecom_2 (EQ_EXPR, integer_type_node,
3612 ffecom_expr (ffebld_left (expr)),
3613 ffecom_expr (ffebld_right (expr)));
3614 return convert (tree_type, ffecom_truth_value (item));
3616 case FFEINFO_basictypeINTEGER:
3618 ffecom_1 (BIT_NOT_EXPR, tree_type,
3619 ffecom_2 (BIT_XOR_EXPR, tree_type,
3620 ffecom_expr (ffebld_left (expr)),
3621 ffecom_expr (ffebld_right (expr))));
3624 assert ("EQV bad basictype" == NULL);
3626 case FFEINFO_basictypeANY:
3627 return error_mark_node;
3631 case FFEBLD_opCONVERT:
3632 if (ffebld_op (ffebld_left (expr)) == FFEBLD_opANY)
3633 return error_mark_node;
3637 case FFEINFO_basictypeLOGICAL:
3638 case FFEINFO_basictypeINTEGER:
3639 case FFEINFO_basictypeREAL:
3640 return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3642 case FFEINFO_basictypeCOMPLEX:
3643 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3645 case FFEINFO_basictypeINTEGER:
3646 case FFEINFO_basictypeLOGICAL:
3647 case FFEINFO_basictypeREAL:
3648 item = ffecom_expr (ffebld_left (expr));
3649 if (item == error_mark_node)
3650 return error_mark_node;
3651 /* convert() takes care of converting to the subtype first,
3652 at least in gcc-2.7.2. */
3653 item = convert (tree_type, item);
3656 case FFEINFO_basictypeCOMPLEX:
3657 return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3660 assert ("CONVERT COMPLEX bad basictype" == NULL);
3662 case FFEINFO_basictypeANY:
3663 return error_mark_node;
3668 assert ("CONVERT bad basictype" == NULL);
3670 case FFEINFO_basictypeANY:
3671 return error_mark_node;
3677 goto relational; /* :::::::::::::::::::: */
3681 goto relational; /* :::::::::::::::::::: */
3685 goto relational; /* :::::::::::::::::::: */
3689 goto relational; /* :::::::::::::::::::: */
3693 goto relational; /* :::::::::::::::::::: */
3698 relational: /* :::::::::::::::::::: */
3699 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3701 case FFEINFO_basictypeLOGICAL:
3702 case FFEINFO_basictypeINTEGER:
3703 case FFEINFO_basictypeREAL:
3704 item = ffecom_2 (code, integer_type_node,
3705 ffecom_expr (ffebld_left (expr)),
3706 ffecom_expr (ffebld_right (expr)));
3707 return convert (tree_type, item);
3709 case FFEINFO_basictypeCOMPLEX:
3710 assert (code == EQ_EXPR || code == NE_EXPR);
3713 tree arg1 = ffecom_expr (ffebld_left (expr));
3714 tree arg2 = ffecom_expr (ffebld_right (expr));
3716 if (arg1 == error_mark_node || arg2 == error_mark_node)
3717 return error_mark_node;
3719 arg1 = ffecom_save_tree (arg1);
3720 arg2 = ffecom_save_tree (arg2);
3722 if (TREE_CODE (TREE_TYPE (arg1)) == COMPLEX_TYPE)
3724 real_type = TREE_TYPE (TREE_TYPE (arg1));
3725 assert (real_type == TREE_TYPE (TREE_TYPE (arg2)));
3729 real_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg1)));
3730 assert (real_type == TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg2))));
3734 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3735 ffecom_2 (EQ_EXPR, integer_type_node,
3736 ffecom_1 (REALPART_EXPR, real_type, arg1),
3737 ffecom_1 (REALPART_EXPR, real_type, arg2)),
3738 ffecom_2 (EQ_EXPR, integer_type_node,
3739 ffecom_1 (IMAGPART_EXPR, real_type, arg1),
3740 ffecom_1 (IMAGPART_EXPR, real_type,
3742 if (code == EQ_EXPR)
3743 item = ffecom_truth_value (item);
3745 item = ffecom_truth_value_invert (item);
3746 return convert (tree_type, item);
3749 case FFEINFO_basictypeCHARACTER:
3751 ffebld left = ffebld_left (expr);
3752 ffebld right = ffebld_right (expr);
3758 /* f2c run-time functions do the implicit blank-padding for us,
3759 so we don't usually have to implement blank-padding ourselves.
3760 (The exception is when we pass an argument to a separately
3761 compiled statement function -- if we know the arg is not the
3762 same length as the dummy, we must truncate or extend it. If
3763 we "inline" statement functions, that necessity goes away as
3766 Strip off the CONVERT operators that blank-pad. (Truncation by
3767 CONVERT shouldn't happen here, but it can happen in
3770 while (ffebld_op (left) == FFEBLD_opCONVERT)
3771 left = ffebld_left (left);
3772 while (ffebld_op (right) == FFEBLD_opCONVERT)
3773 right = ffebld_left (right);
3775 left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
3776 right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
3778 if (left_tree == error_mark_node || left_length == error_mark_node
3779 || right_tree == error_mark_node
3780 || right_length == error_mark_node)
3781 return error_mark_node;
3783 if ((ffebld_size_known (left) == 1)
3784 && (ffebld_size_known (right) == 1))
3787 = ffecom_1 (INDIRECT_REF,
3788 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3791 = ffecom_1 (INDIRECT_REF,
3792 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3796 = ffecom_2 (code, integer_type_node,
3797 ffecom_2 (ARRAY_REF,
3798 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3801 ffecom_2 (ARRAY_REF,
3802 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3808 item = build_tree_list (NULL_TREE, left_tree);
3809 TREE_CHAIN (item) = build_tree_list (NULL_TREE, right_tree);
3810 TREE_CHAIN (TREE_CHAIN (item)) = build_tree_list (NULL_TREE,
3812 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
3813 = build_tree_list (NULL_TREE, right_length);
3814 item = ffecom_call_gfrt (FFECOM_gfrtCMP, item, NULL_TREE);
3815 item = ffecom_2 (code, integer_type_node,
3817 convert (TREE_TYPE (item),
3818 integer_zero_node));
3820 item = convert (tree_type, item);
3826 assert ("relational bad basictype" == NULL);
3828 case FFEINFO_basictypeANY:
3829 return error_mark_node;
3833 case FFEBLD_opPERCENT_LOC:
3834 item = ffecom_arg_ptr_to_expr (ffebld_left (expr), &list);
3835 return convert (tree_type, item);
3839 case FFEBLD_opBOUNDS:
3840 case FFEBLD_opREPEAT:
3841 case FFEBLD_opLABTER:
3842 case FFEBLD_opLABTOK:
3843 case FFEBLD_opIMPDO:
3844 case FFEBLD_opCONCATENATE:
3845 case FFEBLD_opSUBSTR:
3847 assert ("bad op" == NULL);
3850 return error_mark_node;
3854 assert ("didn't think anything got here anymore!!" == NULL);
3856 switch (ffebld_arity (expr))
3859 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3860 TREE_OPERAND (item, 1) = ffecom_expr (ffebld_right (expr));
3861 if (TREE_OPERAND (item, 0) == error_mark_node
3862 || TREE_OPERAND (item, 1) == error_mark_node)
3863 return error_mark_node;
3867 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3868 if (TREE_OPERAND (item, 0) == error_mark_node)
3869 return error_mark_node;
3881 /* Returns the tree that does the intrinsic invocation.
3883 Note: this function applies only to intrinsics returning
3884 CHARACTER*1 or non-CHARACTER results, and to intrinsic
3887 #if FFECOM_targetCURRENT == FFECOM_targetGCC
3889 ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
3890 ffebld dest, bool *dest_used)
3893 tree saved_expr1; /* For those who need it. */
3894 tree saved_expr2; /* For those who need it. */
3895 ffeinfoBasictype bt;
3899 tree real_type; /* REAL type corresponding to COMPLEX. */
3901 ffebld list = ffebld_right (expr); /* List of (some) args. */
3902 ffebld arg1; /* For handy reference. */
3905 ffeintrinImp codegen_imp;
3908 assert (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER);
3910 if (dest_used != NULL)
3913 bt = ffeinfo_basictype (ffebld_info (expr));
3914 kt = ffeinfo_kindtype (ffebld_info (expr));
3915 tree_type = ffecom_tree_type[bt][kt];
3919 arg1 = ffebld_head (list);
3920 if (arg1 != NULL && ffebld_op (arg1) == FFEBLD_opANY)
3921 return error_mark_node;
3922 if ((list = ffebld_trail (list)) != NULL)
3924 arg2 = ffebld_head (list);
3925 if (arg2 != NULL && ffebld_op (arg2) == FFEBLD_opANY)
3926 return error_mark_node;
3927 if ((list = ffebld_trail (list)) != NULL)
3929 arg3 = ffebld_head (list);
3930 if (arg3 != NULL && ffebld_op (arg3) == FFEBLD_opANY)
3931 return error_mark_node;
3940 arg1 = arg2 = arg3 = NULL;
3942 /* <list> ends up at the opITEM of the 3rd arg, or NULL if there are < 3
3943 args. This is used by the MAX/MIN expansions. */
3946 arg1_type = ffecom_tree_type
3947 [ffeinfo_basictype (ffebld_info (arg1))]
3948 [ffeinfo_kindtype (ffebld_info (arg1))];
3950 arg1_type = NULL_TREE; /* Really not needed, but might catch bugs
3953 /* There are several ways for each of the cases in the following switch
3954 statements to exit (from simplest to use to most complicated):
3956 break; (when expr_tree == NULL)
3958 A standard call is made to the specific intrinsic just as if it had been
3959 passed in as a dummy procedure and called as any old procedure. This
3960 method can produce slower code but in some cases it's the easiest way for
3961 now. However, if a (presumably faster) direct call is available,
3962 that is used, so this is the easiest way in many more cases now.
3964 gfrt = FFECOM_gfrtWHATEVER;
3967 gfrt contains the gfrt index of a library function to call, passing the
3968 argument(s) by value rather than by reference. Used when a more
3969 careful choice of library function is needed than that provided
3970 by the vanilla `break;'.
3974 The expr_tree has been completely set up and is ready to be returned
3975 as is. No further actions are taken. Use this when the tree is not
3976 in the simple form for one of the arity_n labels. */
3978 /* For info on how the switch statement cases were written, see the files
3979 enclosed in comments below the switch statement. */
3981 codegen_imp = ffebld_symter_implementation (ffebld_left (expr));
3982 gfrt = ffeintrin_gfrt_direct (codegen_imp);
3983 if (gfrt == FFECOM_gfrt)
3984 gfrt = ffeintrin_gfrt_indirect (codegen_imp);
3986 switch (codegen_imp)
3988 case FFEINTRIN_impABS:
3989 case FFEINTRIN_impCABS:
3990 case FFEINTRIN_impCDABS:
3991 case FFEINTRIN_impDABS:
3992 case FFEINTRIN_impIABS:
3993 if (ffeinfo_basictype (ffebld_info (arg1))
3994 == FFEINFO_basictypeCOMPLEX)
3996 if (kt == FFEINFO_kindtypeREAL1)
3997 gfrt = FFECOM_gfrtCABS;
3998 else if (kt == FFEINFO_kindtypeREAL2)
3999 gfrt = FFECOM_gfrtCDABS;
4002 return ffecom_1 (ABS_EXPR, tree_type,
4003 convert (tree_type, ffecom_expr (arg1)));
4005 case FFEINTRIN_impACOS:
4006 case FFEINTRIN_impDACOS:
4009 case FFEINTRIN_impAIMAG:
4010 case FFEINTRIN_impDIMAG:
4011 case FFEINTRIN_impIMAGPART:
4012 if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
4013 arg1_type = TREE_TYPE (arg1_type);
4015 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
4019 ffecom_1 (IMAGPART_EXPR, arg1_type,
4020 ffecom_expr (arg1)));
4022 case FFEINTRIN_impAINT:
4023 case FFEINTRIN_impDINT:
4025 /* ~~Someday implement FIX_TRUNC_EXPR yielding same type as arg. */
4026 return ffecom_1 (FIX_TRUNC_EXPR, tree_type, ffecom_expr (arg1));
4027 #else /* in the meantime, must use floor to avoid range problems with ints */
4028 /* r__1 = r1 >= 0 ? floor(r1) : -floor(-r1); */
4029 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4032 ffecom_3 (COND_EXPR, double_type_node,
4034 (ffecom_2 (GE_EXPR, integer_type_node,
4037 ffecom_float_zero_))),
4038 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4039 build_tree_list (NULL_TREE,
4040 convert (double_type_node,
4043 ffecom_1 (NEGATE_EXPR, double_type_node,
4044 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4045 build_tree_list (NULL_TREE,
4046 convert (double_type_node,
4047 ffecom_1 (NEGATE_EXPR,
4055 case FFEINTRIN_impANINT:
4056 case FFEINTRIN_impDNINT:
4057 #if 0 /* This way of doing it won't handle real
4058 numbers of large magnitudes. */
4059 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4060 expr_tree = convert (tree_type,
4061 convert (integer_type_node,
4062 ffecom_3 (COND_EXPR, tree_type,
4067 ffecom_float_zero_)),
4068 ffecom_2 (PLUS_EXPR,
4071 ffecom_float_half_),
4072 ffecom_2 (MINUS_EXPR,
4075 ffecom_float_half_))));
4077 #else /* So we instead call floor. */
4078 /* r__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1) */
4079 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4082 ffecom_3 (COND_EXPR, double_type_node,
4084 (ffecom_2 (GE_EXPR, integer_type_node,
4087 ffecom_float_zero_))),
4088 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4089 build_tree_list (NULL_TREE,
4090 convert (double_type_node,
4091 ffecom_2 (PLUS_EXPR,
4095 ffecom_float_half_)))),
4097 ffecom_1 (NEGATE_EXPR, double_type_node,
4098 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4099 build_tree_list (NULL_TREE,
4100 convert (double_type_node,
4101 ffecom_2 (MINUS_EXPR,
4104 ffecom_float_half_),
4111 case FFEINTRIN_impASIN:
4112 case FFEINTRIN_impDASIN:
4113 case FFEINTRIN_impATAN:
4114 case FFEINTRIN_impDATAN:
4115 case FFEINTRIN_impATAN2:
4116 case FFEINTRIN_impDATAN2:
4119 case FFEINTRIN_impCHAR:
4120 case FFEINTRIN_impACHAR:
4122 tempvar = ffecom_make_tempvar (char_type_node, 1, -1);
4124 tempvar = ffebld_nonter_hook (expr);
4128 tree tmv = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (tempvar)));
4130 expr_tree = ffecom_modify (tmv,
4131 ffecom_2 (ARRAY_REF, tmv, tempvar,
4133 convert (tmv, ffecom_expr (arg1)));
4135 expr_tree = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar),
4138 expr_tree = ffecom_1 (ADDR_EXPR,
4139 build_pointer_type (TREE_TYPE (expr_tree)),
4143 case FFEINTRIN_impCMPLX:
4144 case FFEINTRIN_impDCMPLX:
4147 convert (tree_type, ffecom_expr (arg1));
4149 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
4151 ffecom_2 (COMPLEX_EXPR, tree_type,
4152 convert (real_type, ffecom_expr (arg1)),
4154 ffecom_expr (arg2)));
4156 case FFEINTRIN_impCOMPLEX:
4158 ffecom_2 (COMPLEX_EXPR, tree_type,
4160 ffecom_expr (arg2));
4162 case FFEINTRIN_impCONJG:
4163 case FFEINTRIN_impDCONJG:
4167 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
4168 arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4170 ffecom_2 (COMPLEX_EXPR, tree_type,
4171 ffecom_1 (REALPART_EXPR, real_type, arg1_tree),
4172 ffecom_1 (NEGATE_EXPR, real_type,
4173 ffecom_1 (IMAGPART_EXPR, real_type, arg1_tree)));
4176 case FFEINTRIN_impCOS:
4177 case FFEINTRIN_impCCOS:
4178 case FFEINTRIN_impCDCOS:
4179 case FFEINTRIN_impDCOS:
4180 if (bt == FFEINFO_basictypeCOMPLEX)
4182 if (kt == FFEINFO_kindtypeREAL1)
4183 gfrt = FFECOM_gfrtCCOS; /* Overlapping result okay. */
4184 else if (kt == FFEINFO_kindtypeREAL2)
4185 gfrt = FFECOM_gfrtCDCOS; /* Overlapping result okay. */
4189 case FFEINTRIN_impCOSH:
4190 case FFEINTRIN_impDCOSH:
4193 case FFEINTRIN_impDBLE:
4194 case FFEINTRIN_impDFLOAT:
4195 case FFEINTRIN_impDREAL:
4196 case FFEINTRIN_impFLOAT:
4197 case FFEINTRIN_impIDINT:
4198 case FFEINTRIN_impIFIX:
4199 case FFEINTRIN_impINT2:
4200 case FFEINTRIN_impINT8:
4201 case FFEINTRIN_impINT:
4202 case FFEINTRIN_impLONG:
4203 case FFEINTRIN_impREAL:
4204 case FFEINTRIN_impSHORT:
4205 case FFEINTRIN_impSNGL:
4206 return convert (tree_type, ffecom_expr (arg1));
4208 case FFEINTRIN_impDIM:
4209 case FFEINTRIN_impDDIM:
4210 case FFEINTRIN_impIDIM:
4211 saved_expr1 = ffecom_save_tree (convert (tree_type,
4212 ffecom_expr (arg1)));
4213 saved_expr2 = ffecom_save_tree (convert (tree_type,
4214 ffecom_expr (arg2)));
4216 ffecom_3 (COND_EXPR, tree_type,
4218 (ffecom_2 (GT_EXPR, integer_type_node,
4221 ffecom_2 (MINUS_EXPR, tree_type,
4224 convert (tree_type, ffecom_float_zero_));
4226 case FFEINTRIN_impDPROD:
4228 ffecom_2 (MULT_EXPR, tree_type,
4229 convert (tree_type, ffecom_expr (arg1)),
4230 convert (tree_type, ffecom_expr (arg2)));
4232 case FFEINTRIN_impEXP:
4233 case FFEINTRIN_impCDEXP:
4234 case FFEINTRIN_impCEXP:
4235 case FFEINTRIN_impDEXP:
4236 if (bt == FFEINFO_basictypeCOMPLEX)
4238 if (kt == FFEINFO_kindtypeREAL1)
4239 gfrt = FFECOM_gfrtCEXP; /* Overlapping result okay. */
4240 else if (kt == FFEINFO_kindtypeREAL2)
4241 gfrt = FFECOM_gfrtCDEXP; /* Overlapping result okay. */
4245 case FFEINTRIN_impICHAR:
4246 case FFEINTRIN_impIACHAR:
4247 #if 0 /* The simple approach. */
4248 ffecom_char_args_ (&expr_tree, &saved_expr1 /* Ignored */ , arg1);
4250 = ffecom_1 (INDIRECT_REF,
4251 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
4254 = ffecom_2 (ARRAY_REF,
4255 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
4258 return convert (tree_type, expr_tree);
4259 #else /* The more interesting (and more optimal) approach. */
4260 expr_tree = ffecom_intrinsic_ichar_ (tree_type, arg1, &saved_expr1);
4261 expr_tree = ffecom_3 (COND_EXPR, tree_type,
4264 convert (tree_type, integer_zero_node));
4268 case FFEINTRIN_impINDEX:
4271 case FFEINTRIN_impLEN:
4273 break; /* The simple approach. */
4275 return ffecom_intrinsic_len_ (arg1); /* The more optimal approach. */
4278 case FFEINTRIN_impLGE:
4279 case FFEINTRIN_impLGT:
4280 case FFEINTRIN_impLLE:
4281 case FFEINTRIN_impLLT:
4284 case FFEINTRIN_impLOG:
4285 case FFEINTRIN_impALOG:
4286 case FFEINTRIN_impCDLOG:
4287 case FFEINTRIN_impCLOG:
4288 case FFEINTRIN_impDLOG:
4289 if (bt == FFEINFO_basictypeCOMPLEX)
4291 if (kt == FFEINFO_kindtypeREAL1)
4292 gfrt = FFECOM_gfrtCLOG; /* Overlapping result okay. */
4293 else if (kt == FFEINFO_kindtypeREAL2)
4294 gfrt = FFECOM_gfrtCDLOG; /* Overlapping result okay. */
4298 case FFEINTRIN_impLOG10:
4299 case FFEINTRIN_impALOG10:
4300 case FFEINTRIN_impDLOG10:
4301 if (gfrt != FFECOM_gfrt)
4302 break; /* Already picked one, stick with it. */
4304 if (kt == FFEINFO_kindtypeREAL1)
4305 /* We used to call FFECOM_gfrtALOG10 here. */
4306 gfrt = FFECOM_gfrtL_LOG10;
4307 else if (kt == FFEINFO_kindtypeREAL2)
4308 /* We used to call FFECOM_gfrtDLOG10 here. */
4309 gfrt = FFECOM_gfrtL_LOG10;
4312 case FFEINTRIN_impMAX:
4313 case FFEINTRIN_impAMAX0:
4314 case FFEINTRIN_impAMAX1:
4315 case FFEINTRIN_impDMAX1:
4316 case FFEINTRIN_impMAX0:
4317 case FFEINTRIN_impMAX1:
4318 if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4319 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4321 arg1_type = tree_type;
4322 expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4323 convert (arg1_type, ffecom_expr (arg1)),
4324 convert (arg1_type, ffecom_expr (arg2)));
4325 for (; list != NULL; list = ffebld_trail (list))
4327 if ((ffebld_head (list) == NULL)
4328 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4330 expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4333 ffecom_expr (ffebld_head (list))));
4335 return convert (tree_type, expr_tree);
4337 case FFEINTRIN_impMIN:
4338 case FFEINTRIN_impAMIN0:
4339 case FFEINTRIN_impAMIN1:
4340 case FFEINTRIN_impDMIN1:
4341 case FFEINTRIN_impMIN0:
4342 case FFEINTRIN_impMIN1:
4343 if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4344 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4346 arg1_type = tree_type;
4347 expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4348 convert (arg1_type, ffecom_expr (arg1)),
4349 convert (arg1_type, ffecom_expr (arg2)));
4350 for (; list != NULL; list = ffebld_trail (list))
4352 if ((ffebld_head (list) == NULL)
4353 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4355 expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4358 ffecom_expr (ffebld_head (list))));
4360 return convert (tree_type, expr_tree);
4362 case FFEINTRIN_impMOD:
4363 case FFEINTRIN_impAMOD:
4364 case FFEINTRIN_impDMOD:
4365 if (bt != FFEINFO_basictypeREAL)
4366 return ffecom_2 (TRUNC_MOD_EXPR, tree_type,
4367 convert (tree_type, ffecom_expr (arg1)),
4368 convert (tree_type, ffecom_expr (arg2)));
4370 if (kt == FFEINFO_kindtypeREAL1)
4371 /* We used to call FFECOM_gfrtAMOD here. */
4372 gfrt = FFECOM_gfrtL_FMOD;
4373 else if (kt == FFEINFO_kindtypeREAL2)
4374 /* We used to call FFECOM_gfrtDMOD here. */
4375 gfrt = FFECOM_gfrtL_FMOD;
4378 case FFEINTRIN_impNINT:
4379 case FFEINTRIN_impIDNINT:
4381 /* ~~Ideally FIX_ROUND_EXPR would be implemented, but it ain't yet. */
4382 return ffecom_1 (FIX_ROUND_EXPR, tree_type, ffecom_expr (arg1));
4384 /* i__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1); */
4385 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4387 convert (ffecom_integer_type_node,
4388 ffecom_3 (COND_EXPR, arg1_type,
4390 (ffecom_2 (GE_EXPR, integer_type_node,
4393 ffecom_float_zero_))),
4394 ffecom_2 (PLUS_EXPR, arg1_type,
4397 ffecom_float_half_)),
4398 ffecom_2 (MINUS_EXPR, arg1_type,
4401 ffecom_float_half_))));
4404 case FFEINTRIN_impSIGN:
4405 case FFEINTRIN_impDSIGN:
4406 case FFEINTRIN_impISIGN:
4408 tree arg2_tree = ffecom_expr (arg2);
4412 (ffecom_1 (ABS_EXPR, tree_type,
4414 ffecom_expr (arg1))));
4416 = ffecom_3 (COND_EXPR, tree_type,
4418 (ffecom_2 (GE_EXPR, integer_type_node,
4420 convert (TREE_TYPE (arg2_tree),
4421 integer_zero_node))),
4423 ffecom_1 (NEGATE_EXPR, tree_type, saved_expr1));
4424 /* Make sure SAVE_EXPRs get referenced early enough. */
4426 = ffecom_2 (COMPOUND_EXPR, tree_type,
4427 convert (void_type_node, saved_expr1),
4432 case FFEINTRIN_impSIN:
4433 case FFEINTRIN_impCDSIN:
4434 case FFEINTRIN_impCSIN:
4435 case FFEINTRIN_impDSIN:
4436 if (bt == FFEINFO_basictypeCOMPLEX)
4438 if (kt == FFEINFO_kindtypeREAL1)
4439 gfrt = FFECOM_gfrtCSIN; /* Overlapping result okay. */
4440 else if (kt == FFEINFO_kindtypeREAL2)
4441 gfrt = FFECOM_gfrtCDSIN; /* Overlapping result okay. */
4445 case FFEINTRIN_impSINH:
4446 case FFEINTRIN_impDSINH:
4449 case FFEINTRIN_impSQRT:
4450 case FFEINTRIN_impCDSQRT:
4451 case FFEINTRIN_impCSQRT:
4452 case FFEINTRIN_impDSQRT:
4453 if (bt == FFEINFO_basictypeCOMPLEX)
4455 if (kt == FFEINFO_kindtypeREAL1)
4456 gfrt = FFECOM_gfrtCSQRT; /* Overlapping result okay. */
4457 else if (kt == FFEINFO_kindtypeREAL2)
4458 gfrt = FFECOM_gfrtCDSQRT; /* Overlapping result okay. */
4462 case FFEINTRIN_impTAN:
4463 case FFEINTRIN_impDTAN:
4464 case FFEINTRIN_impTANH:
4465 case FFEINTRIN_impDTANH:
4468 case FFEINTRIN_impREALPART:
4469 if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
4470 arg1_type = TREE_TYPE (arg1_type);
4472 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
4476 ffecom_1 (REALPART_EXPR, arg1_type,
4477 ffecom_expr (arg1)));
4479 case FFEINTRIN_impIAND:
4480 case FFEINTRIN_impAND:
4481 return ffecom_2 (BIT_AND_EXPR, tree_type,
4483 ffecom_expr (arg1)),
4485 ffecom_expr (arg2)));
4487 case FFEINTRIN_impIOR:
4488 case FFEINTRIN_impOR:
4489 return ffecom_2 (BIT_IOR_EXPR, tree_type,
4491 ffecom_expr (arg1)),
4493 ffecom_expr (arg2)));
4495 case FFEINTRIN_impIEOR:
4496 case FFEINTRIN_impXOR:
4497 return ffecom_2 (BIT_XOR_EXPR, tree_type,
4499 ffecom_expr (arg1)),
4501 ffecom_expr (arg2)));
4503 case FFEINTRIN_impLSHIFT:
4504 return ffecom_2 (LSHIFT_EXPR, tree_type,
4506 convert (integer_type_node,
4507 ffecom_expr (arg2)));
4509 case FFEINTRIN_impRSHIFT:
4510 return ffecom_2 (RSHIFT_EXPR, tree_type,
4512 convert (integer_type_node,
4513 ffecom_expr (arg2)));
4515 case FFEINTRIN_impNOT:
4516 return ffecom_1 (BIT_NOT_EXPR, tree_type, ffecom_expr (arg1));
4518 case FFEINTRIN_impBIT_SIZE:
4519 return convert (tree_type, TYPE_SIZE (arg1_type));
4521 case FFEINTRIN_impBTEST:
4523 ffetargetLogical1 true;
4524 ffetargetLogical1 false;
4528 ffetarget_logical1 (&true, TRUE);
4529 ffetarget_logical1 (&false, FALSE);
4531 true_tree = convert (tree_type, integer_one_node);
4533 true_tree = convert (tree_type, build_int_2 (true, 0));
4535 false_tree = convert (tree_type, integer_zero_node);
4537 false_tree = convert (tree_type, build_int_2 (false, 0));
4540 ffecom_3 (COND_EXPR, tree_type,
4542 (ffecom_2 (EQ_EXPR, integer_type_node,
4543 ffecom_2 (BIT_AND_EXPR, arg1_type,
4545 ffecom_2 (LSHIFT_EXPR, arg1_type,
4548 convert (integer_type_node,
4549 ffecom_expr (arg2)))),
4551 integer_zero_node))),
4556 case FFEINTRIN_impIBCLR:
4558 ffecom_2 (BIT_AND_EXPR, tree_type,
4560 ffecom_1 (BIT_NOT_EXPR, tree_type,
4561 ffecom_2 (LSHIFT_EXPR, tree_type,
4564 convert (integer_type_node,
4565 ffecom_expr (arg2)))));
4567 case FFEINTRIN_impIBITS:
4569 tree arg3_tree = ffecom_save_tree (convert (integer_type_node,
4570 ffecom_expr (arg3)));
4572 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4575 = ffecom_2 (BIT_AND_EXPR, tree_type,
4576 ffecom_2 (RSHIFT_EXPR, tree_type,
4578 convert (integer_type_node,
4579 ffecom_expr (arg2))),
4581 ffecom_2 (RSHIFT_EXPR, uns_type,
4582 ffecom_1 (BIT_NOT_EXPR,
4585 integer_zero_node)),
4586 ffecom_2 (MINUS_EXPR,
4588 TYPE_SIZE (uns_type),
4590 #if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4592 = ffecom_3 (COND_EXPR, tree_type,
4594 (ffecom_2 (NE_EXPR, integer_type_node,
4596 integer_zero_node)),
4598 convert (tree_type, integer_zero_node));
4603 case FFEINTRIN_impIBSET:
4605 ffecom_2 (BIT_IOR_EXPR, tree_type,
4607 ffecom_2 (LSHIFT_EXPR, tree_type,
4608 convert (tree_type, integer_one_node),
4609 convert (integer_type_node,
4610 ffecom_expr (arg2))));
4612 case FFEINTRIN_impISHFT:
4614 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4615 tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4616 ffecom_expr (arg2)));
4618 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4621 = ffecom_3 (COND_EXPR, tree_type,
4623 (ffecom_2 (GE_EXPR, integer_type_node,
4625 integer_zero_node)),
4626 ffecom_2 (LSHIFT_EXPR, tree_type,
4630 ffecom_2 (RSHIFT_EXPR, uns_type,
4631 convert (uns_type, arg1_tree),
4632 ffecom_1 (NEGATE_EXPR,
4635 #if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4637 = ffecom_3 (COND_EXPR, tree_type,
4639 (ffecom_2 (NE_EXPR, integer_type_node,
4641 TYPE_SIZE (uns_type))),
4643 convert (tree_type, integer_zero_node));
4645 /* Make sure SAVE_EXPRs get referenced early enough. */
4647 = ffecom_2 (COMPOUND_EXPR, tree_type,
4648 convert (void_type_node, arg1_tree),
4649 ffecom_2 (COMPOUND_EXPR, tree_type,
4650 convert (void_type_node, arg2_tree),
4655 case FFEINTRIN_impISHFTC:
4657 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4658 tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4659 ffecom_expr (arg2)));
4660 tree arg3_tree = (arg3 == NULL) ? TYPE_SIZE (tree_type)
4661 : ffecom_save_tree (convert (integer_type_node, ffecom_expr (arg3)));
4667 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4670 = ffecom_2 (LSHIFT_EXPR, tree_type,
4671 ffecom_1 (BIT_NOT_EXPR, tree_type,
4672 convert (tree_type, integer_zero_node)),
4674 #if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4676 = ffecom_3 (COND_EXPR, tree_type,
4678 (ffecom_2 (NE_EXPR, integer_type_node,
4680 TYPE_SIZE (uns_type))),
4682 convert (tree_type, integer_zero_node));
4684 mask_arg1 = ffecom_save_tree (mask_arg1);
4686 = ffecom_2 (BIT_AND_EXPR, tree_type,
4688 ffecom_1 (BIT_NOT_EXPR, tree_type,
4690 masked_arg1 = ffecom_save_tree (masked_arg1);
4692 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4694 ffecom_2 (RSHIFT_EXPR, uns_type,
4695 convert (uns_type, masked_arg1),
4696 ffecom_1 (NEGATE_EXPR,
4699 ffecom_2 (LSHIFT_EXPR, tree_type,
4701 ffecom_2 (PLUS_EXPR, integer_type_node,
4705 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4706 ffecom_2 (LSHIFT_EXPR, tree_type,
4710 ffecom_2 (RSHIFT_EXPR, uns_type,
4711 convert (uns_type, masked_arg1),
4712 ffecom_2 (MINUS_EXPR,
4717 = ffecom_3 (COND_EXPR, tree_type,
4719 (ffecom_2 (LT_EXPR, integer_type_node,
4721 integer_zero_node)),
4725 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4726 ffecom_2 (BIT_AND_EXPR, tree_type,
4729 ffecom_2 (BIT_AND_EXPR, tree_type,
4730 ffecom_1 (BIT_NOT_EXPR, tree_type,
4734 = ffecom_3 (COND_EXPR, tree_type,
4736 (ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
4737 ffecom_2 (EQ_EXPR, integer_type_node,
4742 ffecom_2 (EQ_EXPR, integer_type_node,
4744 integer_zero_node))),
4747 /* Make sure SAVE_EXPRs get referenced early enough. */
4749 = ffecom_2 (COMPOUND_EXPR, tree_type,
4750 convert (void_type_node, arg1_tree),
4751 ffecom_2 (COMPOUND_EXPR, tree_type,
4752 convert (void_type_node, arg2_tree),
4753 ffecom_2 (COMPOUND_EXPR, tree_type,
4754 convert (void_type_node,
4756 ffecom_2 (COMPOUND_EXPR, tree_type,
4757 convert (void_type_node,
4761 = ffecom_2 (COMPOUND_EXPR, tree_type,
4762 convert (void_type_node,
4768 case FFEINTRIN_impLOC:
4770 tree arg1_tree = ffecom_expr (arg1);
4773 = convert (tree_type,
4774 ffecom_1 (ADDR_EXPR,
4775 build_pointer_type (TREE_TYPE (arg1_tree)),
4780 case FFEINTRIN_impMVBITS:
4785 ffebld arg4 = ffebld_head (ffebld_trail (list));
4788 ffebld arg5 = ffebld_head (ffebld_trail (ffebld_trail (list)));
4792 tree arg5_plus_arg3;
4794 arg2_tree = convert (integer_type_node,
4795 ffecom_expr (arg2));
4796 arg3_tree = ffecom_save_tree (convert (integer_type_node,
4797 ffecom_expr (arg3)));
4798 arg4_tree = ffecom_expr_rw (NULL_TREE, arg4);
4799 arg4_type = TREE_TYPE (arg4_tree);
4801 arg1_tree = ffecom_save_tree (convert (arg4_type,
4802 ffecom_expr (arg1)));
4804 arg5_tree = ffecom_save_tree (convert (integer_type_node,
4805 ffecom_expr (arg5)));
4808 = ffecom_2 (LSHIFT_EXPR, arg4_type,
4809 ffecom_2 (BIT_AND_EXPR, arg4_type,
4810 ffecom_2 (RSHIFT_EXPR, arg4_type,
4813 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4814 ffecom_2 (LSHIFT_EXPR, arg4_type,
4815 ffecom_1 (BIT_NOT_EXPR,
4819 integer_zero_node)),
4823 = ffecom_save_tree (ffecom_2 (PLUS_EXPR, arg4_type,
4827 = ffecom_2 (LSHIFT_EXPR, arg4_type,
4828 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4830 integer_zero_node)),
4832 #if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4834 = ffecom_3 (COND_EXPR, arg4_type,
4836 (ffecom_2 (NE_EXPR, integer_type_node,
4838 convert (TREE_TYPE (arg5_plus_arg3),
4839 TYPE_SIZE (arg4_type)))),
4841 convert (arg4_type, integer_zero_node));
4844 = ffecom_2 (BIT_AND_EXPR, arg4_type,
4846 ffecom_2 (BIT_IOR_EXPR, arg4_type,
4848 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4849 ffecom_2 (LSHIFT_EXPR, arg4_type,
4850 ffecom_1 (BIT_NOT_EXPR,
4854 integer_zero_node)),
4857 = ffecom_2 (BIT_IOR_EXPR, arg4_type,
4860 #if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4862 = ffecom_3 (COND_EXPR, arg4_type,
4864 (ffecom_2 (NE_EXPR, integer_type_node,
4866 convert (TREE_TYPE (arg3_tree),
4867 integer_zero_node))),
4871 = ffecom_3 (COND_EXPR, arg4_type,
4873 (ffecom_2 (NE_EXPR, integer_type_node,
4875 convert (TREE_TYPE (arg3_tree),
4876 TYPE_SIZE (arg4_type)))),
4881 = ffecom_2s (MODIFY_EXPR, void_type_node,
4884 /* Make sure SAVE_EXPRs get referenced early enough. */
4886 = ffecom_2 (COMPOUND_EXPR, void_type_node,
4888 ffecom_2 (COMPOUND_EXPR, void_type_node,
4890 ffecom_2 (COMPOUND_EXPR, void_type_node,
4892 ffecom_2 (COMPOUND_EXPR, void_type_node,
4896 = ffecom_2 (COMPOUND_EXPR, void_type_node,
4903 case FFEINTRIN_impDERF:
4904 case FFEINTRIN_impERF:
4905 case FFEINTRIN_impDERFC:
4906 case FFEINTRIN_impERFC:
4909 case FFEINTRIN_impIARGC:
4910 /* extern int xargc; i__1 = xargc - 1; */
4911 expr_tree = ffecom_2 (MINUS_EXPR, TREE_TYPE (ffecom_tree_xargc_),
4913 convert (TREE_TYPE (ffecom_tree_xargc_),
4917 case FFEINTRIN_impSIGNAL_func:
4918 case FFEINTRIN_impSIGNAL_subr:
4924 arg1_tree = convert (ffecom_f2c_integer_type_node,
4925 ffecom_expr (arg1));
4926 arg1_tree = ffecom_1 (ADDR_EXPR,
4927 build_pointer_type (TREE_TYPE (arg1_tree)),
4930 /* Pass procedure as a pointer to it, anything else by value. */
4931 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
4932 arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
4934 arg2_tree = ffecom_ptr_to_expr (arg2);
4935 arg2_tree = convert (TREE_TYPE (null_pointer_node),
4939 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
4941 arg3_tree = NULL_TREE;
4943 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4944 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4945 TREE_CHAIN (arg1_tree) = arg2_tree;
4948 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4949 ffecom_gfrt_kindtype (gfrt),
4951 ((codegen_imp == FFEINTRIN_impSIGNAL_subr) ?
4955 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
4956 ffebld_nonter_hook (expr));
4958 if (arg3_tree != NULL_TREE)
4960 = ffecom_modify (NULL_TREE, arg3_tree,
4961 convert (TREE_TYPE (arg3_tree),
4966 case FFEINTRIN_impALARM:
4972 arg1_tree = convert (ffecom_f2c_integer_type_node,
4973 ffecom_expr (arg1));
4974 arg1_tree = ffecom_1 (ADDR_EXPR,
4975 build_pointer_type (TREE_TYPE (arg1_tree)),
4978 /* Pass procedure as a pointer to it, anything else by value. */
4979 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
4980 arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
4982 arg2_tree = ffecom_ptr_to_expr (arg2);
4983 arg2_tree = convert (TREE_TYPE (null_pointer_node),
4987 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
4989 arg3_tree = NULL_TREE;
4991 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4992 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4993 TREE_CHAIN (arg1_tree) = arg2_tree;
4996 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4997 ffecom_gfrt_kindtype (gfrt),
5001 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5002 ffebld_nonter_hook (expr));
5004 if (arg3_tree != NULL_TREE)
5006 = ffecom_modify (NULL_TREE, arg3_tree,
5007 convert (TREE_TYPE (arg3_tree),
5012 case FFEINTRIN_impCHDIR_subr:
5013 case FFEINTRIN_impFDATE_subr:
5014 case FFEINTRIN_impFGET_subr:
5015 case FFEINTRIN_impFPUT_subr:
5016 case FFEINTRIN_impGETCWD_subr:
5017 case FFEINTRIN_impHOSTNM_subr:
5018 case FFEINTRIN_impSYSTEM_subr:
5019 case FFEINTRIN_impUNLINK_subr:
5021 tree arg1_len = integer_zero_node;
5025 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5028 arg2_tree = ffecom_expr_w (NULL_TREE, arg2);
5030 arg2_tree = NULL_TREE;
5032 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5033 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5034 TREE_CHAIN (arg1_tree) = arg1_len;
5037 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5038 ffecom_gfrt_kindtype (gfrt),
5042 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5043 ffebld_nonter_hook (expr));
5045 if (arg2_tree != NULL_TREE)
5047 = ffecom_modify (NULL_TREE, arg2_tree,
5048 convert (TREE_TYPE (arg2_tree),
5053 case FFEINTRIN_impEXIT:
5057 expr_tree = build_tree_list (NULL_TREE,
5058 ffecom_1 (ADDR_EXPR,
5060 (ffecom_integer_type_node),
5061 integer_zero_node));
5064 ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5065 ffecom_gfrt_kindtype (gfrt),
5069 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5070 ffebld_nonter_hook (expr));
5072 case FFEINTRIN_impFLUSH:
5074 gfrt = FFECOM_gfrtFLUSH;
5076 gfrt = FFECOM_gfrtFLUSH1;
5079 case FFEINTRIN_impCHMOD_subr:
5080 case FFEINTRIN_impLINK_subr:
5081 case FFEINTRIN_impRENAME_subr:
5082 case FFEINTRIN_impSYMLNK_subr:
5084 tree arg1_len = integer_zero_node;
5086 tree arg2_len = integer_zero_node;
5090 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5091 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
5093 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5095 arg3_tree = NULL_TREE;
5097 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5098 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5099 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5100 arg2_len = build_tree_list (NULL_TREE, arg2_len);
5101 TREE_CHAIN (arg1_tree) = arg2_tree;
5102 TREE_CHAIN (arg2_tree) = arg1_len;
5103 TREE_CHAIN (arg1_len) = arg2_len;
5104 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5105 ffecom_gfrt_kindtype (gfrt),
5109 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5110 ffebld_nonter_hook (expr));
5111 if (arg3_tree != NULL_TREE)
5112 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5113 convert (TREE_TYPE (arg3_tree),
5118 case FFEINTRIN_impLSTAT_subr:
5119 case FFEINTRIN_impSTAT_subr:
5121 tree arg1_len = integer_zero_node;
5126 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5128 arg2_tree = ffecom_ptr_to_expr (arg2);
5131 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5133 arg3_tree = NULL_TREE;
5135 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5136 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5137 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5138 TREE_CHAIN (arg1_tree) = arg2_tree;
5139 TREE_CHAIN (arg2_tree) = arg1_len;
5140 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5141 ffecom_gfrt_kindtype (gfrt),
5145 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5146 ffebld_nonter_hook (expr));
5147 if (arg3_tree != NULL_TREE)
5148 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5149 convert (TREE_TYPE (arg3_tree),
5154 case FFEINTRIN_impFGETC_subr:
5155 case FFEINTRIN_impFPUTC_subr:
5159 tree arg2_len = integer_zero_node;
5162 arg1_tree = convert (ffecom_f2c_integer_type_node,
5163 ffecom_expr (arg1));
5164 arg1_tree = ffecom_1 (ADDR_EXPR,
5165 build_pointer_type (TREE_TYPE (arg1_tree)),
5168 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
5170 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5172 arg3_tree = NULL_TREE;
5174 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5175 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5176 arg2_len = build_tree_list (NULL_TREE, arg2_len);
5177 TREE_CHAIN (arg1_tree) = arg2_tree;
5178 TREE_CHAIN (arg2_tree) = arg2_len;
5180 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5181 ffecom_gfrt_kindtype (gfrt),
5185 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5186 ffebld_nonter_hook (expr));
5187 if (arg3_tree != NULL_TREE)
5188 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5189 convert (TREE_TYPE (arg3_tree),
5194 case FFEINTRIN_impFSTAT_subr:
5200 arg1_tree = convert (ffecom_f2c_integer_type_node,
5201 ffecom_expr (arg1));
5202 arg1_tree = ffecom_1 (ADDR_EXPR,
5203 build_pointer_type (TREE_TYPE (arg1_tree)),
5206 arg2_tree = convert (ffecom_f2c_ptr_to_integer_type_node,
5207 ffecom_ptr_to_expr (arg2));
5210 arg3_tree = NULL_TREE;
5212 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5214 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5215 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5216 TREE_CHAIN (arg1_tree) = arg2_tree;
5217 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5218 ffecom_gfrt_kindtype (gfrt),
5222 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5223 ffebld_nonter_hook (expr));
5224 if (arg3_tree != NULL_TREE) {
5225 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5226 convert (TREE_TYPE (arg3_tree),
5232 case FFEINTRIN_impKILL_subr:
5238 arg1_tree = convert (ffecom_f2c_integer_type_node,
5239 ffecom_expr (arg1));
5240 arg1_tree = ffecom_1 (ADDR_EXPR,
5241 build_pointer_type (TREE_TYPE (arg1_tree)),
5244 arg2_tree = convert (ffecom_f2c_integer_type_node,
5245 ffecom_expr (arg2));
5246 arg2_tree = ffecom_1 (ADDR_EXPR,
5247 build_pointer_type (TREE_TYPE (arg2_tree)),
5251 arg3_tree = NULL_TREE;
5253 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5255 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5256 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5257 TREE_CHAIN (arg1_tree) = arg2_tree;
5258 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5259 ffecom_gfrt_kindtype (gfrt),
5263 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5264 ffebld_nonter_hook (expr));
5265 if (arg3_tree != NULL_TREE) {
5266 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5267 convert (TREE_TYPE (arg3_tree),
5273 case FFEINTRIN_impCTIME_subr:
5274 case FFEINTRIN_impTTYNAM_subr:
5276 tree arg1_len = integer_zero_node;
5280 arg1_tree = ffecom_arg_ptr_to_expr (arg2, &arg1_len);
5282 arg2_tree = convert (((codegen_imp == FFEINTRIN_impCTIME_subr) ?
5283 ffecom_f2c_longint_type_node :
5284 ffecom_f2c_integer_type_node),
5285 ffecom_expr (arg1));
5286 arg2_tree = ffecom_1 (ADDR_EXPR,
5287 build_pointer_type (TREE_TYPE (arg2_tree)),
5290 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5291 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5292 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5293 TREE_CHAIN (arg1_len) = arg2_tree;
5294 TREE_CHAIN (arg1_tree) = arg1_len;
5297 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5298 ffecom_gfrt_kindtype (gfrt),
5302 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5303 ffebld_nonter_hook (expr));
5304 TREE_SIDE_EFFECTS (expr_tree) = 1;
5308 case FFEINTRIN_impIRAND:
5309 case FFEINTRIN_impRAND:
5310 /* Arg defaults to 0 (normal random case) */
5315 arg1_tree = ffecom_integer_zero_node;
5317 arg1_tree = ffecom_expr (arg1);
5318 arg1_tree = convert (ffecom_f2c_integer_type_node,
5320 arg1_tree = ffecom_1 (ADDR_EXPR,
5321 build_pointer_type (TREE_TYPE (arg1_tree)),
5323 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5325 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5326 ffecom_gfrt_kindtype (gfrt),
5328 ((codegen_imp == FFEINTRIN_impIRAND) ?
5329 ffecom_f2c_integer_type_node :
5330 ffecom_f2c_real_type_node),
5332 dest_tree, dest, dest_used,
5334 ffebld_nonter_hook (expr));
5338 case FFEINTRIN_impFTELL_subr:
5339 case FFEINTRIN_impUMASK_subr:
5344 arg1_tree = convert (ffecom_f2c_integer_type_node,
5345 ffecom_expr (arg1));
5346 arg1_tree = ffecom_1 (ADDR_EXPR,
5347 build_pointer_type (TREE_TYPE (arg1_tree)),
5351 arg2_tree = NULL_TREE;
5353 arg2_tree = ffecom_expr_w (NULL_TREE, arg2);
5355 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5356 ffecom_gfrt_kindtype (gfrt),
5359 build_tree_list (NULL_TREE, arg1_tree),
5360 NULL_TREE, NULL, NULL, NULL_TREE,
5362 ffebld_nonter_hook (expr));
5363 if (arg2_tree != NULL_TREE) {
5364 expr_tree = ffecom_modify (NULL_TREE, arg2_tree,
5365 convert (TREE_TYPE (arg2_tree),
5371 case FFEINTRIN_impCPU_TIME:
5372 case FFEINTRIN_impSECOND_subr:
5376 arg1_tree = ffecom_expr_w (NULL_TREE, arg1);
5379 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5380 ffecom_gfrt_kindtype (gfrt),
5384 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5385 ffebld_nonter_hook (expr));
5388 = ffecom_modify (NULL_TREE, arg1_tree,
5389 convert (TREE_TYPE (arg1_tree),
5394 case FFEINTRIN_impDTIME_subr:
5395 case FFEINTRIN_impETIME_subr:
5400 result_tree = ffecom_expr_w (NULL_TREE, arg2);
5402 arg1_tree = ffecom_ptr_to_expr (arg1);
5404 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5405 ffecom_gfrt_kindtype (gfrt),
5408 build_tree_list (NULL_TREE, arg1_tree),
5409 NULL_TREE, NULL, NULL, NULL_TREE,
5411 ffebld_nonter_hook (expr));
5412 expr_tree = ffecom_modify (NULL_TREE, result_tree,
5413 convert (TREE_TYPE (result_tree),
5418 /* Straightforward calls of libf2c routines: */
5419 case FFEINTRIN_impABORT:
5420 case FFEINTRIN_impACCESS:
5421 case FFEINTRIN_impBESJ0:
5422 case FFEINTRIN_impBESJ1:
5423 case FFEINTRIN_impBESJN:
5424 case FFEINTRIN_impBESY0:
5425 case FFEINTRIN_impBESY1:
5426 case FFEINTRIN_impBESYN:
5427 case FFEINTRIN_impCHDIR_func:
5428 case FFEINTRIN_impCHMOD_func:
5429 case FFEINTRIN_impDATE:
5430 case FFEINTRIN_impDATE_AND_TIME:
5431 case FFEINTRIN_impDBESJ0:
5432 case FFEINTRIN_impDBESJ1:
5433 case FFEINTRIN_impDBESJN:
5434 case FFEINTRIN_impDBESY0:
5435 case FFEINTRIN_impDBESY1:
5436 case FFEINTRIN_impDBESYN:
5437 case FFEINTRIN_impDTIME_func:
5438 case FFEINTRIN_impETIME_func:
5439 case FFEINTRIN_impFGETC_func:
5440 case FFEINTRIN_impFGET_func:
5441 case FFEINTRIN_impFNUM:
5442 case FFEINTRIN_impFPUTC_func:
5443 case FFEINTRIN_impFPUT_func:
5444 case FFEINTRIN_impFSEEK:
5445 case FFEINTRIN_impFSTAT_func:
5446 case FFEINTRIN_impFTELL_func:
5447 case FFEINTRIN_impGERROR:
5448 case FFEINTRIN_impGETARG:
5449 case FFEINTRIN_impGETCWD_func:
5450 case FFEINTRIN_impGETENV:
5451 case FFEINTRIN_impGETGID:
5452 case FFEINTRIN_impGETLOG:
5453 case FFEINTRIN_impGETPID:
5454 case FFEINTRIN_impGETUID:
5455 case FFEINTRIN_impGMTIME:
5456 case FFEINTRIN_impHOSTNM_func:
5457 case FFEINTRIN_impIDATE_unix:
5458 case FFEINTRIN_impIDATE_vxt:
5459 case FFEINTRIN_impIERRNO:
5460 case FFEINTRIN_impISATTY:
5461 case FFEINTRIN_impITIME:
5462 case FFEINTRIN_impKILL_func:
5463 case FFEINTRIN_impLINK_func:
5464 case FFEINTRIN_impLNBLNK:
5465 case FFEINTRIN_impLSTAT_func:
5466 case FFEINTRIN_impLTIME:
5467 case FFEINTRIN_impMCLOCK8:
5468 case FFEINTRIN_impMCLOCK:
5469 case FFEINTRIN_impPERROR:
5470 case FFEINTRIN_impRENAME_func:
5471 case FFEINTRIN_impSECNDS:
5472 case FFEINTRIN_impSECOND_func:
5473 case FFEINTRIN_impSLEEP:
5474 case FFEINTRIN_impSRAND:
5475 case FFEINTRIN_impSTAT_func:
5476 case FFEINTRIN_impSYMLNK_func:
5477 case FFEINTRIN_impSYSTEM_CLOCK:
5478 case FFEINTRIN_impSYSTEM_func:
5479 case FFEINTRIN_impTIME8:
5480 case FFEINTRIN_impTIME_unix:
5481 case FFEINTRIN_impTIME_vxt:
5482 case FFEINTRIN_impUMASK_func:
5483 case FFEINTRIN_impUNLINK_func:
5486 case FFEINTRIN_impCTIME_func: /* CHARACTER functions not handled here. */
5487 case FFEINTRIN_impFDATE_func: /* CHARACTER functions not handled here. */
5488 case FFEINTRIN_impTTYNAM_func: /* CHARACTER functions not handled here. */
5489 case FFEINTRIN_impNONE:
5490 case FFEINTRIN_imp: /* Hush up gcc warning. */
5491 fprintf (stderr, "No %s implementation.\n",
5492 ffeintrin_name_implementation (ffebld_symter_implementation (ffebld_left (expr))));
5493 assert ("unimplemented intrinsic" == NULL);
5494 return error_mark_node;
5497 assert (gfrt != FFECOM_gfrt); /* Must have an implementation! */
5499 expr_tree = ffecom_arglist_expr_ (ffecom_gfrt_args_ (gfrt),
5500 ffebld_right (expr));
5502 return ffecom_call_ (ffecom_gfrt_tree_ (gfrt), ffecom_gfrt_kindtype (gfrt),
5503 (ffe_is_f2c_library () && ffecom_gfrt_complex_[gfrt]),
5505 expr_tree, dest_tree, dest, dest_used,
5507 ffebld_nonter_hook (expr));
5509 /* See bottom of this file for f2c transforms used to determine
5510 many of the above implementations. The info seems to confuse
5511 Emacs's C mode indentation, which is why it's been moved to
5512 the bottom of this source file. */
5516 /* For power (exponentiation) where right-hand operand is type INTEGER,
5517 generate in-line code to do it the fast way (which, if the operand
5518 is a constant, might just mean a series of multiplies). */
5520 #if FFECOM_targetCURRENT == FFECOM_targetGCC
5522 ffecom_expr_power_integer_ (ffebld expr)
5524 tree l = ffecom_expr (ffebld_left (expr));
5525 tree r = ffecom_expr (ffebld_right (expr));
5526 tree ltype = TREE_TYPE (l);
5527 tree rtype = TREE_TYPE (r);
5528 tree result = NULL_TREE;
5530 if (l == error_mark_node
5531 || r == error_mark_node)
5532 return error_mark_node;
5534 if (TREE_CODE (r) == INTEGER_CST)
5536 int sgn = tree_int_cst_sgn (r);
5539 return convert (ltype, integer_one_node);
5541 if ((TREE_CODE (ltype) == INTEGER_TYPE)
5544 /* Reciprocal of integer is either 0, -1, or 1, so after
5545 calculating that (which we leave to the back end to do
5546 or not do optimally), don't bother with any multiplying. */
5548 result = ffecom_tree_divide_ (ltype,
5549 convert (ltype, integer_one_node),
5551 NULL_TREE, NULL, NULL, NULL_TREE);
5552 r = ffecom_1 (NEGATE_EXPR,
5555 if ((TREE_INT_CST_LOW (r) & 1) == 0)
5556 result = ffecom_1 (ABS_EXPR, rtype,
5560 /* Generate appropriate series of multiplies, preceded
5561 by divide if the exponent is negative. */
5567 l = ffecom_tree_divide_ (ltype,
5568 convert (ltype, integer_one_node),
5570 NULL_TREE, NULL, NULL,
5571 ffebld_nonter_hook (expr));
5572 r = ffecom_1 (NEGATE_EXPR, rtype, r);
5573 assert (TREE_CODE (r) == INTEGER_CST);
5575 if (tree_int_cst_sgn (r) < 0)
5576 { /* The "most negative" number. */
5577 r = ffecom_1 (NEGATE_EXPR, rtype,
5578 ffecom_2 (RSHIFT_EXPR, rtype,
5582 l = ffecom_2 (MULT_EXPR, ltype,
5590 if (TREE_INT_CST_LOW (r) & 1)
5592 if (result == NULL_TREE)
5595 result = ffecom_2 (MULT_EXPR, ltype,
5600 r = ffecom_2 (RSHIFT_EXPR, rtype,
5603 if (integer_zerop (r))
5605 assert (TREE_CODE (r) == INTEGER_CST);
5608 l = ffecom_2 (MULT_EXPR, ltype,
5615 /* Though rhs isn't a constant, in-line code cannot be expanded
5616 while transforming dummies
5617 because the back end cannot be easily convinced to generate
5618 stores (MODIFY_EXPR), handle temporaries, and so on before
5619 all the appropriate rtx's have been generated for things like
5620 dummy args referenced in rhs -- which doesn't happen until
5621 store_parm_decls() is called (expand_function_start, I believe,
5622 does the actual rtx-stuffing of PARM_DECLs).
5624 So, in this case, let the caller generate the call to the
5625 run-time-library function to evaluate the power for us. */
5627 if (ffecom_transform_only_dummies_)
5630 /* Right-hand operand not a constant, expand in-line code to figure
5631 out how to do the multiplies, &c.
5633 The returned expression is expressed this way in GNU C, where l and
5636 ({ typeof (r) rtmp = r;
5637 typeof (l) ltmp = l;
5644 if ((basetypeof (l) == basetypeof (int))
5647 result = ((typeof (l)) 1) / ltmp;
5648 if ((ltmp < 0) && (((-rtmp) & 1) == 0))
5654 if ((basetypeof (l) != basetypeof (int))
5657 ltmp = ((typeof (l)) 1) / ltmp;
5661 rtmp = -(rtmp >> 1);
5669 if ((rtmp >>= 1) == 0)
5678 Note that some of the above is compile-time collapsable, such as
5679 the first part of the if statements that checks the base type of
5680 l against int. The if statements are phrased that way to suggest
5681 an easy way to generate the if/else constructs here, knowing that
5682 the back end should (and probably does) eliminate the resulting
5683 dead code (either the int case or the non-int case), something
5684 it couldn't do without the redundant phrasing, requiring explicit
5685 dead-code elimination here, which would be kind of difficult to
5692 tree basetypeof_l_is_int;
5697 = build_int_2 ((TREE_CODE (ltype) == INTEGER_TYPE), 0);
5699 se = expand_start_stmt_expr ();
5701 ffecom_start_compstmt ();
5704 rtmp = ffecom_make_tempvar ("power_r", rtype,
5705 FFETARGET_charactersizeNONE, -1);
5706 ltmp = ffecom_make_tempvar ("power_l", ltype,
5707 FFETARGET_charactersizeNONE, -1);
5708 result = ffecom_make_tempvar ("power_res", ltype,
5709 FFETARGET_charactersizeNONE, -1);
5710 if (TREE_CODE (ltype) == COMPLEX_TYPE
5711 || TREE_CODE (ltype) == RECORD_TYPE)
5712 divide = ffecom_make_tempvar ("power_div", ltype,
5713 FFETARGET_charactersizeNONE, -1);
5720 hook = ffebld_nonter_hook (expr);
5722 assert (TREE_CODE (hook) == TREE_VEC);
5723 assert (TREE_VEC_LENGTH (hook) == 4);
5724 rtmp = TREE_VEC_ELT (hook, 0);
5725 ltmp = TREE_VEC_ELT (hook, 1);
5726 result = TREE_VEC_ELT (hook, 2);
5727 divide = TREE_VEC_ELT (hook, 3);
5728 if (TREE_CODE (ltype) == COMPLEX_TYPE
5729 || TREE_CODE (ltype) == RECORD_TYPE)
5736 expand_expr_stmt (ffecom_modify (void_type_node,
5739 expand_expr_stmt (ffecom_modify (void_type_node,
5742 expand_start_cond (ffecom_truth_value
5743 (ffecom_2 (EQ_EXPR, integer_type_node,
5745 convert (rtype, integer_zero_node))),
5747 expand_expr_stmt (ffecom_modify (void_type_node,
5749 convert (ltype, integer_one_node)));
5750 expand_start_else ();
5751 if (! integer_zerop (basetypeof_l_is_int))
5753 expand_start_cond (ffecom_2 (LT_EXPR, integer_type_node,
5756 integer_zero_node)),
5758 expand_expr_stmt (ffecom_modify (void_type_node,
5762 convert (ltype, integer_one_node),
5764 NULL_TREE, NULL, NULL,
5766 expand_start_cond (ffecom_truth_value
5767 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
5768 ffecom_2 (LT_EXPR, integer_type_node,
5771 integer_zero_node)),
5772 ffecom_2 (EQ_EXPR, integer_type_node,
5773 ffecom_2 (BIT_AND_EXPR,
5775 ffecom_1 (NEGATE_EXPR,
5781 integer_zero_node)))),
5783 expand_expr_stmt (ffecom_modify (void_type_node,
5785 ffecom_1 (NEGATE_EXPR,
5789 expand_start_else ();
5791 expand_expr_stmt (ffecom_modify (void_type_node,
5793 convert (ltype, integer_one_node)));
5794 expand_start_cond (ffecom_truth_value
5795 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
5796 ffecom_truth_value_invert
5797 (basetypeof_l_is_int),
5798 ffecom_2 (LT_EXPR, integer_type_node,
5801 integer_zero_node)))),
5803 expand_expr_stmt (ffecom_modify (void_type_node,
5807 convert (ltype, integer_one_node),
5809 NULL_TREE, NULL, NULL,
5811 expand_expr_stmt (ffecom_modify (void_type_node,
5813 ffecom_1 (NEGATE_EXPR, rtype,
5815 expand_start_cond (ffecom_truth_value
5816 (ffecom_2 (LT_EXPR, integer_type_node,
5818 convert (rtype, integer_zero_node))),
5820 expand_expr_stmt (ffecom_modify (void_type_node,
5822 ffecom_1 (NEGATE_EXPR, rtype,
5823 ffecom_2 (RSHIFT_EXPR,
5826 integer_one_node))));
5827 expand_expr_stmt (ffecom_modify (void_type_node,
5829 ffecom_2 (MULT_EXPR, ltype,
5834 expand_start_loop (1);
5835 expand_start_cond (ffecom_truth_value
5836 (ffecom_2 (BIT_AND_EXPR, rtype,
5838 convert (rtype, integer_one_node))),
5840 expand_expr_stmt (ffecom_modify (void_type_node,
5842 ffecom_2 (MULT_EXPR, ltype,
5846 expand_exit_loop_if_false (NULL,
5848 (ffecom_modify (rtype,
5850 ffecom_2 (RSHIFT_EXPR,
5853 integer_one_node))));
5854 expand_expr_stmt (ffecom_modify (void_type_node,
5856 ffecom_2 (MULT_EXPR, ltype,
5861 if (!integer_zerop (basetypeof_l_is_int))
5863 expand_expr_stmt (result);
5865 t = ffecom_end_compstmt ();
5867 result = expand_end_stmt_expr (se);
5869 /* This code comes from c-parse.in, after its expand_end_stmt_expr. */
5871 if (TREE_CODE (t) == BLOCK)
5873 /* Make a BIND_EXPR for the BLOCK already made. */
5874 result = build (BIND_EXPR, TREE_TYPE (result),
5875 NULL_TREE, result, t);
5876 /* Remove the block from the tree at this point.
5877 It gets put back at the proper place
5878 when the BIND_EXPR is expanded. */
5889 /* ffecom_expr_transform_ -- Transform symbols in expr
5891 ffebld expr; // FFE expression.
5892 ffecom_expr_transform_ (expr);
5894 Recursive descent on expr while transforming any untransformed SYMTERs. */
5896 #if FFECOM_targetCURRENT == FFECOM_targetGCC
5898 ffecom_expr_transform_ (ffebld expr)
5903 tail_recurse: /* :::::::::::::::::::: */
5908 switch (ffebld_op (expr))
5910 case FFEBLD_opSYMTER:
5911 s = ffebld_symter (expr);
5912 t = ffesymbol_hook (s).decl_tree;
5913 if ((t == NULL_TREE)
5914 && ((ffesymbol_kind (s) != FFEINFO_kindNONE)
5915 || ((ffesymbol_where (s) != FFEINFO_whereNONE)
5916 && (ffesymbol_where (s) != FFEINFO_whereINTRINSIC))))
5918 s = ffecom_sym_transform_ (s);
5919 t = ffesymbol_hook (s).decl_tree; /* Sfunc expr non-dummy,
5922 break; /* Ok if (t == NULL) here. */
5925 ffecom_expr_transform_ (ffebld_head (expr));
5926 expr = ffebld_trail (expr);
5927 goto tail_recurse; /* :::::::::::::::::::: */
5933 switch (ffebld_arity (expr))
5936 ffecom_expr_transform_ (ffebld_left (expr));
5937 expr = ffebld_right (expr);
5938 goto tail_recurse; /* :::::::::::::::::::: */
5941 expr = ffebld_left (expr);
5942 goto tail_recurse; /* :::::::::::::::::::: */
5952 /* Make a type based on info in live f2c.h file. */
5954 #if FFECOM_targetCURRENT == FFECOM_targetGCC
5956 ffecom_f2c_make_type_ (tree *type, int tcode, const char *name)
5960 case FFECOM_f2ccodeCHAR:
5961 *type = make_signed_type (CHAR_TYPE_SIZE);
5964 case FFECOM_f2ccodeSHORT:
5965 *type = make_signed_type (SHORT_TYPE_SIZE);
5968 case FFECOM_f2ccodeINT:
5969 *type = make_signed_type (INT_TYPE_SIZE);
5972 case FFECOM_f2ccodeLONG:
5973 *type = make_signed_type (LONG_TYPE_SIZE);
5976 case FFECOM_f2ccodeLONGLONG:
5977 *type = make_signed_type (LONG_LONG_TYPE_SIZE);
5980 case FFECOM_f2ccodeCHARPTR:
5981 *type = build_pointer_type (DEFAULT_SIGNED_CHAR
5982 ? signed_char_type_node
5983 : unsigned_char_type_node);
5986 case FFECOM_f2ccodeFLOAT:
5987 *type = make_node (REAL_TYPE);
5988 TYPE_PRECISION (*type) = FLOAT_TYPE_SIZE;
5989 layout_type (*type);
5992 case FFECOM_f2ccodeDOUBLE:
5993 *type = make_node (REAL_TYPE);
5994 TYPE_PRECISION (*type) = DOUBLE_TYPE_SIZE;
5995 layout_type (*type);
5998 case FFECOM_f2ccodeLONGDOUBLE:
5999 *type = make_node (REAL_TYPE);
6000 TYPE_PRECISION (*type) = LONG_DOUBLE_TYPE_SIZE;
6001 layout_type (*type);
6004 case FFECOM_f2ccodeTWOREALS:
6005 *type = ffecom_make_complex_type_ (ffecom_f2c_real_type_node);
6008 case FFECOM_f2ccodeTWODOUBLEREALS:
6009 *type = ffecom_make_complex_type_ (ffecom_f2c_doublereal_type_node);
6013 assert ("unexpected FFECOM_f2ccodeXYZZY!" == NULL);
6014 *type = error_mark_node;
6018 pushdecl (build_decl (TYPE_DECL,
6019 ffecom_get_invented_identifier ("__g77_f2c_%s", name),
6024 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6025 /* Set the f2c list-directed-I/O code for whatever (integral) type has the
6029 ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size,
6035 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
6036 if ((t = ffecom_tree_type[bt][j]) != NULL_TREE
6037 && compare_tree_int (TYPE_SIZE (t), size) == 0)
6039 assert (code != -1);
6040 ffecom_f2c_typecode_[bt][j] = code;
6046 /* Finish up globals after doing all program units in file
6048 Need to handle only uninitialized COMMON areas. */
6050 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6052 ffecom_finish_global_ (ffeglobal global)
6058 if (ffeglobal_type (global) != FFEGLOBAL_typeCOMMON)
6061 if (ffeglobal_common_init (global))
6064 cbt = ffeglobal_hook (global);
6065 if ((cbt == NULL_TREE)
6066 || !ffeglobal_common_have_size (global))
6067 return global; /* No need to make common, never ref'd. */
6069 DECL_EXTERNAL (cbt) = 0;
6071 /* Give the array a size now. */
6073 size = build_int_2 ((ffeglobal_common_size (global)
6074 + ffeglobal_common_pad (global)) - 1,
6077 cbtype = TREE_TYPE (cbt);
6078 TYPE_DOMAIN (cbtype) = build_range_type (integer_type_node,
6081 if (!TREE_TYPE (size))
6082 TREE_TYPE (size) = TYPE_DOMAIN (cbtype);
6083 layout_type (cbtype);
6085 cbt = start_decl (cbt, FALSE);
6086 assert (cbt == ffeglobal_hook (global));
6088 finish_decl (cbt, NULL_TREE, FALSE);
6094 /* Finish up any untransformed symbols. */
6096 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6098 ffecom_finish_symbol_transform_ (ffesymbol s)
6100 if ((s == NULL) || (TREE_CODE (current_function_decl) == ERROR_MARK))
6103 /* It's easy to know to transform an untransformed symbol, to make sure
6104 we put out debugging info for it. But COMMON variables, unlike
6105 EQUIVALENCE ones, aren't given declarations in addition to the
6106 tree expressions that specify offsets, because COMMON variables
6107 can be referenced in the outer scope where only dummy arguments
6108 (PARM_DECLs) should really be seen. To be safe, just don't do any
6109 VAR_DECLs for COMMON variables when we transform them for real
6110 use, and therefore we do all the VAR_DECL creating here. */
6112 if (ffesymbol_hook (s).decl_tree == NULL_TREE)
6114 if (ffesymbol_kind (s) != FFEINFO_kindNONE
6115 || (ffesymbol_where (s) != FFEINFO_whereNONE
6116 && ffesymbol_where (s) != FFEINFO_whereINTRINSIC
6117 && ffesymbol_where (s) != FFEINFO_whereDUMMY))
6118 /* Not transformed, and not CHARACTER*(*), and not a dummy
6119 argument, which can happen only if the entry point names
6120 it "rides in on" are all invalidated for other reasons. */
6121 s = ffecom_sym_transform_ (s);
6124 if ((ffesymbol_where (s) == FFEINFO_whereCOMMON)
6125 && (ffesymbol_hook (s).decl_tree != error_mark_node))
6127 /* This isn't working, at least for dbxout. The .s file looks
6128 okay to me (burley), but in gdb 4.9 at least, the variables
6129 appear to reside somewhere outside of the common area, so
6130 it doesn't make sense to mislead anyone by generating the info
6131 on those variables until this is fixed. NOTE: Same problem
6132 with EQUIVALENCE, sadly...see similar #if later. */
6133 ffecom_member_phase2_ (ffesymbol_storage (ffesymbol_common (s)),
6134 ffesymbol_storage (s));
6141 /* Append underscore(s) to name before calling get_identifier. "us"
6142 is nonzero if the name already contains an underscore and thus
6143 needs two underscores appended. */
6145 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6147 ffecom_get_appended_identifier_ (char us, const char *name)
6153 newname = xmalloc ((i = strlen (name)) + 1
6154 + ffe_is_underscoring ()
6156 memcpy (newname, name, i);
6158 newname[i + us] = '_';
6159 newname[i + 1 + us] = '\0';
6160 id = get_identifier (newname);
6168 /* Decide whether to append underscore to name before calling
6171 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6173 ffecom_get_external_identifier_ (ffesymbol s)
6176 const char *name = ffesymbol_text (s);
6178 /* If name is a built-in name, just return it as is. */
6180 if (!ffe_is_underscoring ()
6181 || (strcmp (name, FFETARGET_nameBLANK_COMMON) == 0)
6182 #if FFETARGET_isENFORCED_MAIN_NAME
6183 || (strcmp (name, FFETARGET_nameENFORCED_NAME) == 0)
6185 || (strcmp (name, FFETARGET_nameUNNAMED_MAIN) == 0)
6187 || (strcmp (name, FFETARGET_nameUNNAMED_BLOCK_DATA) == 0))
6188 return get_identifier (name);
6190 us = ffe_is_second_underscore ()
6191 ? (strchr (name, '_') != NULL)
6194 return ffecom_get_appended_identifier_ (us, name);
6198 /* Decide whether to append underscore to internal name before calling
6201 This is for non-external, top-function-context names only. Transform
6202 identifier so it doesn't conflict with the transformed result
6203 of using a _different_ external name. E.g. if "CALL FOO" is
6204 transformed into "FOO_();", then the variable in "FOO_ = 3"
6205 must be transformed into something that does not conflict, since
6206 these two things should be independent.
6208 The transformation is as follows. If the name does not contain
6209 an underscore, there is no possible conflict, so just return.
6210 If the name does contain an underscore, then transform it just
6211 like we transform an external identifier. */
6213 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6215 ffecom_get_identifier_ (const char *name)
6217 /* If name does not contain an underscore, just return it as is. */
6219 if (!ffe_is_underscoring ()
6220 || (strchr (name, '_') == NULL))
6221 return get_identifier (name);
6223 return ffecom_get_appended_identifier_ (ffe_is_second_underscore (),
6228 /* ffecom_gen_sfuncdef_ -- Generate definition of statement function
6231 ffesymbol s; // kindFUNCTION, whereIMMEDIATE.
6232 t = ffecom_gen_sfuncdef_(s,ffesymbol_basictype(s),
6233 ffesymbol_kindtype(s));
6235 Call after setting up containing function and getting trees for all
6238 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6240 ffecom_gen_sfuncdef_ (ffesymbol s, ffeinfoBasictype bt, ffeinfoKindtype kt)
6242 ffebld expr = ffesymbol_sfexpr (s);
6246 bool charfunc = (bt == FFEINFO_basictypeCHARACTER);
6247 static bool recurse = FALSE;
6248 int old_lineno = lineno;
6249 const char *old_input_filename = input_filename;
6251 ffecom_nested_entry_ = s;
6253 /* For now, we don't have a handy pointer to where the sfunc is actually
6254 defined, though that should be easy to add to an ffesymbol. (The
6255 token/where info available might well point to the place where the type
6256 of the sfunc is declared, especially if that precedes the place where
6257 the sfunc itself is defined, which is typically the case.) We should
6258 put out a null pointer rather than point somewhere wrong, but I want to
6259 see how it works at this point. */
6261 input_filename = ffesymbol_where_filename (s);
6262 lineno = ffesymbol_where_filelinenum (s);
6264 /* Pretransform the expression so any newly discovered things belong to the
6265 outer program unit, not to the statement function. */
6267 ffecom_expr_transform_ (expr);
6269 /* Make sure no recursive invocation of this fn (a specific case of failing
6270 to pretransform an sfunc's expression, i.e. where its expression
6271 references another untransformed sfunc) happens. */
6276 push_f_function_context ();
6279 type = void_type_node;
6282 type = ffecom_tree_type[bt][kt];
6283 if (type == NULL_TREE)
6284 type = integer_type_node; /* _sym_exec_transition reports
6288 start_function (ffecom_get_identifier_ (ffesymbol_text (s)),
6289 build_function_type (type, NULL_TREE),
6290 1, /* nested/inline */
6291 0); /* TREE_PUBLIC */
6293 /* We don't worry about COMPLEX return values here, because this is
6294 entirely internal to our code, and gcc has the ability to return COMPLEX
6295 directly as a value. */
6298 { /* Prepend arg for where result goes. */
6301 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
6303 result = ffecom_get_invented_identifier ("__g77_%s", "result");
6305 ffecom_char_enhance_arg_ (&type, s); /* Ignore returned length. */
6307 type = build_pointer_type (type);
6308 result = build_decl (PARM_DECL, result, type);
6310 push_parm_decl (result);
6313 result = NULL_TREE; /* Not ref'd if !charfunc. */
6315 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (s), TRUE);
6317 store_parm_decls (0);
6319 ffecom_start_compstmt ();
6325 ffetargetCharacterSize sz = ffesymbol_size (s);
6328 result_length = build_int_2 (sz, 0);
6329 TREE_TYPE (result_length) = ffecom_f2c_ftnlen_type_node;
6331 ffecom_prepare_let_char_ (sz, expr);
6333 ffecom_prepare_end ();
6335 ffecom_let_char_ (result, result_length, sz, expr);
6336 expand_null_return ();
6340 ffecom_prepare_expr (expr);
6342 ffecom_prepare_end ();
6344 expand_return (ffecom_modify (NULL_TREE,
6345 DECL_RESULT (current_function_decl),
6346 ffecom_expr (expr)));
6350 ffecom_end_compstmt ();
6352 func = current_function_decl;
6353 finish_function (1);
6355 pop_f_function_context ();
6359 lineno = old_lineno;
6360 input_filename = old_input_filename;
6362 ffecom_nested_entry_ = NULL;
6369 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6371 ffecom_gfrt_args_ (ffecomGfrt ix)
6373 return ffecom_gfrt_argstring_[ix];
6377 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6379 ffecom_gfrt_tree_ (ffecomGfrt ix)
6381 if (ffecom_gfrt_[ix] == NULL_TREE)
6382 ffecom_make_gfrt_ (ix);
6384 return ffecom_1 (ADDR_EXPR,
6385 build_pointer_type (TREE_TYPE (ffecom_gfrt_[ix])),
6390 /* Return initialize-to-zero expression for this VAR_DECL. */
6392 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6393 /* A somewhat evil way to prevent the garbage collector
6394 from collecting 'tree' structures. */
6395 #define NUM_TRACKED_CHUNK 63
6396 static struct tree_ggc_tracker
6398 struct tree_ggc_tracker *next;
6399 tree trees[NUM_TRACKED_CHUNK];
6400 } *tracker_head = NULL;
6403 mark_tracker_head (void *arg)
6405 struct tree_ggc_tracker *head;
6408 for (head = * (struct tree_ggc_tracker **) arg;
6413 for (i = 0; i < NUM_TRACKED_CHUNK; i++)
6414 ggc_mark_tree (head->trees[i]);
6419 ffecom_save_tree_forever (tree t)
6422 if (tracker_head != NULL)
6423 for (i = 0; i < NUM_TRACKED_CHUNK; i++)
6424 if (tracker_head->trees[i] == NULL)
6426 tracker_head->trees[i] = t;
6431 /* Need to allocate a new block. */
6432 struct tree_ggc_tracker *old_head = tracker_head;
6434 tracker_head = ggc_alloc (sizeof (*tracker_head));
6435 tracker_head->next = old_head;
6436 tracker_head->trees[0] = t;
6437 for (i = 1; i < NUM_TRACKED_CHUNK; i++)
6438 tracker_head->trees[i] = NULL;
6443 ffecom_init_zero_ (tree decl)
6446 int incremental = TREE_STATIC (decl);
6447 tree type = TREE_TYPE (decl);
6451 make_decl_rtl (decl, NULL);
6452 assemble_variable (decl, TREE_PUBLIC (decl) ? 1 : 0, 0, 1);
6455 if ((TREE_CODE (type) != ARRAY_TYPE)
6456 && (TREE_CODE (type) != RECORD_TYPE)
6457 && (TREE_CODE (type) != UNION_TYPE)
6459 init = convert (type, integer_zero_node);
6460 else if (!incremental)
6462 init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
6463 TREE_CONSTANT (init) = 1;
6464 TREE_STATIC (init) = 1;
6468 assemble_zeros (int_size_in_bytes (type));
6469 init = error_mark_node;
6476 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6478 ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg,
6484 switch (ffebld_op (arg))
6486 case FFEBLD_opCONTER: /* For F90, check 0-length. */
6487 if (ffetarget_length_character1
6488 (ffebld_constant_character1
6489 (ffebld_conter (arg))) == 0)
6491 *maybe_tree = integer_zero_node;
6492 return convert (tree_type, integer_zero_node);
6495 *maybe_tree = integer_one_node;
6496 expr_tree = build_int_2 (*ffetarget_text_character1
6497 (ffebld_constant_character1
6498 (ffebld_conter (arg))),
6500 TREE_TYPE (expr_tree) = tree_type;
6503 case FFEBLD_opSYMTER:
6504 case FFEBLD_opARRAYREF:
6505 case FFEBLD_opFUNCREF:
6506 case FFEBLD_opSUBSTR:
6507 ffecom_char_args_ (&expr_tree, &length_tree, arg);
6509 if ((expr_tree == error_mark_node)
6510 || (length_tree == error_mark_node))
6512 *maybe_tree = error_mark_node;
6513 return error_mark_node;
6516 if (integer_zerop (length_tree))
6518 *maybe_tree = integer_zero_node;
6519 return convert (tree_type, integer_zero_node);
6523 = ffecom_1 (INDIRECT_REF,
6524 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
6527 = ffecom_2 (ARRAY_REF,
6528 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
6531 expr_tree = convert (tree_type, expr_tree);
6533 if (TREE_CODE (length_tree) == INTEGER_CST)
6534 *maybe_tree = integer_one_node;
6535 else /* Must check length at run time. */
6537 = ffecom_truth_value
6538 (ffecom_2 (GT_EXPR, integer_type_node,
6540 ffecom_f2c_ftnlen_zero_node));
6543 case FFEBLD_opPAREN:
6544 case FFEBLD_opCONVERT:
6545 if (ffeinfo_size (ffebld_info (arg)) == 0)
6547 *maybe_tree = integer_zero_node;
6548 return convert (tree_type, integer_zero_node);
6550 return ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
6553 case FFEBLD_opCONCATENATE:
6560 expr_left = ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
6562 expr_right = ffecom_intrinsic_ichar_ (tree_type, ffebld_right (arg),
6564 *maybe_tree = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
6567 expr_tree = ffecom_3 (COND_EXPR, tree_type,
6575 assert ("bad op in ICHAR" == NULL);
6576 return error_mark_node;
6581 /* ffecom_intrinsic_len_ -- Return length info for char arg (LEN())
6585 length_arg = ffecom_intrinsic_len_ (expr);
6587 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
6588 subexpressions by constructing the appropriate tree for the
6589 length-of-character-text argument in a calling sequence. */
6591 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6593 ffecom_intrinsic_len_ (ffebld expr)
6595 ffetargetCharacter1 val;
6598 switch (ffebld_op (expr))
6600 case FFEBLD_opCONTER:
6601 val = ffebld_constant_character1 (ffebld_conter (expr));
6602 length = build_int_2 (ffetarget_length_character1 (val), 0);
6603 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6606 case FFEBLD_opSYMTER:
6608 ffesymbol s = ffebld_symter (expr);
6611 item = ffesymbol_hook (s).decl_tree;
6612 if (item == NULL_TREE)
6614 s = ffecom_sym_transform_ (s);
6615 item = ffesymbol_hook (s).decl_tree;
6617 if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
6619 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
6620 length = ffesymbol_hook (s).length_tree;
6623 length = build_int_2 (ffesymbol_size (s), 0);
6624 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6627 else if (item == error_mark_node)
6628 length = error_mark_node;
6629 else /* FFEINFO_kindFUNCTION: */
6634 case FFEBLD_opARRAYREF:
6635 length = ffecom_intrinsic_len_ (ffebld_left (expr));
6638 case FFEBLD_opSUBSTR:
6642 ffebld thing = ffebld_right (expr);
6646 assert (ffebld_op (thing) == FFEBLD_opITEM);
6647 start = ffebld_head (thing);
6648 thing = ffebld_trail (thing);
6649 assert (ffebld_trail (thing) == NULL);
6650 end = ffebld_head (thing);
6652 length = ffecom_intrinsic_len_ (ffebld_left (expr));
6654 if (length == error_mark_node)
6663 length = convert (ffecom_f2c_ftnlen_type_node,
6669 start_tree = convert (ffecom_f2c_ftnlen_type_node,
6670 ffecom_expr (start));
6672 if (start_tree == error_mark_node)
6674 length = error_mark_node;
6680 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6681 ffecom_f2c_ftnlen_one_node,
6682 ffecom_2 (MINUS_EXPR,
6683 ffecom_f2c_ftnlen_type_node,
6689 end_tree = convert (ffecom_f2c_ftnlen_type_node,
6692 if (end_tree == error_mark_node)
6694 length = error_mark_node;
6698 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6699 ffecom_f2c_ftnlen_one_node,
6700 ffecom_2 (MINUS_EXPR,
6701 ffecom_f2c_ftnlen_type_node,
6702 end_tree, start_tree));
6708 case FFEBLD_opCONCATENATE:
6710 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6711 ffecom_intrinsic_len_ (ffebld_left (expr)),
6712 ffecom_intrinsic_len_ (ffebld_right (expr)));
6715 case FFEBLD_opFUNCREF:
6716 case FFEBLD_opCONVERT:
6717 length = build_int_2 (ffebld_size (expr), 0);
6718 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6722 assert ("bad op for single char arg expr" == NULL);
6723 length = ffecom_f2c_ftnlen_zero_node;
6727 assert (length != NULL_TREE);
6733 /* Handle CHARACTER assignments.
6735 Generates code to do the assignment. Used by ordinary assignment
6736 statement handler ffecom_let_stmt and by statement-function
6737 handler to generate code for a statement function. */
6739 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6741 ffecom_let_char_ (tree dest_tree, tree dest_length,
6742 ffetargetCharacterSize dest_size, ffebld source)
6744 ffecomConcatList_ catlist;
6749 if ((dest_tree == error_mark_node)
6750 || (dest_length == error_mark_node))
6753 assert (dest_tree != NULL_TREE);
6754 assert (dest_length != NULL_TREE);
6756 /* Source might be an opCONVERT, which just means it is a different size
6757 than the destination. Since the underlying implementation here handles
6758 that (directly or via the s_copy or s_cat run-time-library functions),
6759 we don't need the "convenience" of an opCONVERT that tells us to
6760 truncate or blank-pad, particularly since the resulting implementation
6761 would probably be slower than otherwise. */
6763 while (ffebld_op (source) == FFEBLD_opCONVERT)
6764 source = ffebld_left (source);
6766 catlist = ffecom_concat_list_new_ (source, dest_size);
6767 switch (ffecom_concat_list_count_ (catlist))
6769 case 0: /* Shouldn't happen, but in case it does... */
6770 ffecom_concat_list_kill_ (catlist);
6771 source_tree = null_pointer_node;
6772 source_length = ffecom_f2c_ftnlen_zero_node;
6773 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6774 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
6775 TREE_CHAIN (TREE_CHAIN (expr_tree))
6776 = build_tree_list (NULL_TREE, dest_length);
6777 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6778 = build_tree_list (NULL_TREE, source_length);
6780 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree, NULL_TREE);
6781 TREE_SIDE_EFFECTS (expr_tree) = 1;
6783 expand_expr_stmt (expr_tree);
6787 case 1: /* The (fairly) easy case. */
6788 ffecom_char_args_ (&source_tree, &source_length,
6789 ffecom_concat_list_expr_ (catlist, 0));
6790 ffecom_concat_list_kill_ (catlist);
6791 assert (source_tree != NULL_TREE);
6792 assert (source_length != NULL_TREE);
6794 if ((source_tree == error_mark_node)
6795 || (source_length == error_mark_node))
6801 = ffecom_1 (INDIRECT_REF,
6802 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6806 = ffecom_2 (ARRAY_REF,
6807 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6812 = ffecom_1 (INDIRECT_REF,
6813 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6817 = ffecom_2 (ARRAY_REF,
6818 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6823 expr_tree = ffecom_modify (void_type_node, dest_tree, source_tree);
6825 expand_expr_stmt (expr_tree);
6830 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6831 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
6832 TREE_CHAIN (TREE_CHAIN (expr_tree))
6833 = build_tree_list (NULL_TREE, dest_length);
6834 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6835 = build_tree_list (NULL_TREE, source_length);
6837 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree, NULL_TREE);
6838 TREE_SIDE_EFFECTS (expr_tree) = 1;
6840 expand_expr_stmt (expr_tree);
6844 default: /* Must actually concatenate things. */
6848 /* Heavy-duty concatenation. */
6851 int count = ffecom_concat_list_count_ (catlist);
6863 = ffecom_push_tempvar (ffecom_f2c_ftnlen_type_node,
6864 FFETARGET_charactersizeNONE, count, TRUE);
6865 item_array = items = ffecom_push_tempvar (ffecom_f2c_address_type_node,
6866 FFETARGET_charactersizeNONE,
6872 hook = ffebld_nonter_hook (source);
6874 assert (TREE_CODE (hook) == TREE_VEC);
6875 assert (TREE_VEC_LENGTH (hook) == 2);
6876 length_array = lengths = TREE_VEC_ELT (hook, 0);
6877 item_array = items = TREE_VEC_ELT (hook, 1);
6881 for (i = 0; i < count; ++i)
6883 ffecom_char_args_ (&citem, &clength,
6884 ffecom_concat_list_expr_ (catlist, i));
6885 if ((citem == error_mark_node)
6886 || (clength == error_mark_node))
6888 ffecom_concat_list_kill_ (catlist);
6893 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
6894 ffecom_modify (void_type_node,
6895 ffecom_2 (ARRAY_REF,
6896 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
6898 build_int_2 (i, 0)),
6902 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
6903 ffecom_modify (void_type_node,
6904 ffecom_2 (ARRAY_REF,
6905 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
6907 build_int_2 (i, 0)),
6912 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6913 TREE_CHAIN (expr_tree)
6914 = build_tree_list (NULL_TREE,
6915 ffecom_1 (ADDR_EXPR,
6916 build_pointer_type (TREE_TYPE (items)),
6918 TREE_CHAIN (TREE_CHAIN (expr_tree))
6919 = build_tree_list (NULL_TREE,
6920 ffecom_1 (ADDR_EXPR,
6921 build_pointer_type (TREE_TYPE (lengths)),
6923 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6926 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
6927 convert (ffecom_f2c_ftnlen_type_node,
6928 build_int_2 (count, 0))));
6929 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree))))
6930 = build_tree_list (NULL_TREE, dest_length);
6932 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCAT, expr_tree, NULL_TREE);
6933 TREE_SIDE_EFFECTS (expr_tree) = 1;
6935 expand_expr_stmt (expr_tree);
6938 ffecom_concat_list_kill_ (catlist);
6942 /* ffecom_make_gfrt_ -- Make initial info for run-time routine
6945 ffecom_make_gfrt_(ix);
6947 Assumes gfrt_[ix] is NULL_TREE, and replaces it with the FUNCTION_DECL
6948 for the indicated run-time routine (ix). */
6950 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6952 ffecom_make_gfrt_ (ffecomGfrt ix)
6957 switch (ffecom_gfrt_type_[ix])
6959 case FFECOM_rttypeVOID_:
6960 ttype = void_type_node;
6963 case FFECOM_rttypeVOIDSTAR_:
6964 ttype = TREE_TYPE (null_pointer_node); /* `void *'. */
6967 case FFECOM_rttypeFTNINT_:
6968 ttype = ffecom_f2c_ftnint_type_node;
6971 case FFECOM_rttypeINTEGER_:
6972 ttype = ffecom_f2c_integer_type_node;
6975 case FFECOM_rttypeLONGINT_:
6976 ttype = ffecom_f2c_longint_type_node;
6979 case FFECOM_rttypeLOGICAL_:
6980 ttype = ffecom_f2c_logical_type_node;
6983 case FFECOM_rttypeREAL_F2C_:
6984 ttype = double_type_node;
6987 case FFECOM_rttypeREAL_GNU_:
6988 ttype = float_type_node;
6991 case FFECOM_rttypeCOMPLEX_F2C_:
6992 ttype = void_type_node;
6995 case FFECOM_rttypeCOMPLEX_GNU_:
6996 ttype = ffecom_f2c_complex_type_node;
6999 case FFECOM_rttypeDOUBLE_:
7000 ttype = double_type_node;
7003 case FFECOM_rttypeDOUBLEREAL_:
7004 ttype = ffecom_f2c_doublereal_type_node;
7007 case FFECOM_rttypeDBLCMPLX_F2C_:
7008 ttype = void_type_node;
7011 case FFECOM_rttypeDBLCMPLX_GNU_:
7012 ttype = ffecom_f2c_doublecomplex_type_node;
7015 case FFECOM_rttypeCHARACTER_:
7016 ttype = void_type_node;
7021 assert ("bad rttype" == NULL);
7025 ttype = build_function_type (ttype, NULL_TREE);
7026 t = build_decl (FUNCTION_DECL,
7027 get_identifier (ffecom_gfrt_name_[ix]),
7029 DECL_EXTERNAL (t) = 1;
7030 TREE_READONLY (t) = ffecom_gfrt_const_[ix] ? 1 : 0;
7031 TREE_PUBLIC (t) = 1;
7032 TREE_THIS_VOLATILE (t) = ffecom_gfrt_volatile_[ix] ? 1 : 0;
7034 /* Sanity check: A function that's const cannot be volatile. */
7036 assert (ffecom_gfrt_const_[ix] ? !ffecom_gfrt_volatile_[ix] : 1);
7038 /* Sanity check: A function that's const cannot return complex. */
7040 assert (ffecom_gfrt_const_[ix] ? !ffecom_gfrt_complex_[ix] : 1);
7042 t = start_decl (t, TRUE);
7044 finish_decl (t, NULL_TREE, TRUE);
7046 ffecom_gfrt_[ix] = t;
7050 /* Phase 1 pass over each member of a COMMON/EQUIVALENCE group. */
7052 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7054 ffecom_member_phase1_ (ffestorag mst UNUSED, ffestorag st)
7056 ffesymbol s = ffestorag_symbol (st);
7058 if (ffesymbol_namelisted (s))
7059 ffecom_member_namelisted_ = TRUE;
7063 /* Phase 2 pass over each member of a COMMON/EQUIVALENCE group. Declare
7064 the member so debugger will see it. Otherwise nobody should be
7065 referencing the member. */
7067 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7069 ffecom_member_phase2_ (ffestorag mst, ffestorag st)
7077 || ((mt = ffestorag_hook (mst)) == NULL)
7078 || (mt == error_mark_node))
7082 || ((s = ffestorag_symbol (st)) == NULL))
7085 type = ffecom_type_localvar_ (s,
7086 ffesymbol_basictype (s),
7087 ffesymbol_kindtype (s));
7088 if (type == error_mark_node)
7091 t = build_decl (VAR_DECL,
7092 ffecom_get_identifier_ (ffesymbol_text (s)),
7095 TREE_STATIC (t) = TREE_STATIC (mt);
7096 DECL_INITIAL (t) = NULL_TREE;
7097 TREE_ASM_WRITTEN (t) = 1;
7101 = gen_rtx (MEM, TYPE_MODE (type),
7102 plus_constant (XEXP (DECL_RTL (mt), 0),
7103 ffestorag_modulo (mst)
7104 + ffestorag_offset (st)
7105 - ffestorag_offset (mst)));
7107 t = start_decl (t, FALSE);
7109 finish_decl (t, NULL_TREE, FALSE);
7113 /* Prepare source expression for assignment into a destination perhaps known
7114 to be of a specific size. */
7117 ffecom_prepare_let_char_ (ffetargetCharacterSize dest_size, ffebld source)
7119 ffecomConcatList_ catlist;
7124 tree tempvar = NULL_TREE;
7126 while (ffebld_op (source) == FFEBLD_opCONVERT)
7127 source = ffebld_left (source);
7129 catlist = ffecom_concat_list_new_ (source, dest_size);
7130 count = ffecom_concat_list_count_ (catlist);
7135 = ffecom_make_tempvar ("let_char_len", ffecom_f2c_ftnlen_type_node,
7136 FFETARGET_charactersizeNONE, count);
7138 = ffecom_make_tempvar ("let_char_item", ffecom_f2c_address_type_node,
7139 FFETARGET_charactersizeNONE, count);
7141 tempvar = make_tree_vec (2);
7142 TREE_VEC_ELT (tempvar, 0) = ltmp;
7143 TREE_VEC_ELT (tempvar, 1) = itmp;
7146 for (i = 0; i < count; ++i)
7147 ffecom_prepare_arg_ptr_to_expr (ffecom_concat_list_expr_ (catlist, i));
7149 ffecom_concat_list_kill_ (catlist);
7153 ffebld_nonter_set_hook (source, tempvar);
7154 current_binding_level->prep_state = 1;
7158 /* ffecom_push_dummy_decls_ -- Transform dummy args, push parm decls in order
7160 Ignores STAR (alternate-return) dummies. All other get exec-transitioned
7161 (which generates their trees) and then their trees get push_parm_decl'd.
7163 The second arg is TRUE if the dummies are for a statement function, in
7164 which case lengths are not pushed for character arguments (since they are
7165 always known by both the caller and the callee, though the code allows
7166 for someday permitting CHAR*(*) stmtfunc dummies). */
7168 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7170 ffecom_push_dummy_decls_ (ffebld dummy_list, bool stmtfunc)
7177 ffecom_transform_only_dummies_ = TRUE;
7179 /* First push the parms corresponding to actual dummy "contents". */
7181 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
7183 dummy = ffebld_head (dumlist);
7184 switch (ffebld_op (dummy))
7188 continue; /* Forget alternate returns. */
7193 assert (ffebld_op (dummy) == FFEBLD_opSYMTER);
7194 s = ffebld_symter (dummy);
7195 parm = ffesymbol_hook (s).decl_tree;
7196 if (parm == NULL_TREE)
7198 s = ffecom_sym_transform_ (s);
7199 parm = ffesymbol_hook (s).decl_tree;
7200 assert (parm != NULL_TREE);
7202 if (parm != error_mark_node)
7203 push_parm_decl (parm);
7206 /* Then, for CHARACTER dummies, push the parms giving their lengths. */
7208 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
7210 dummy = ffebld_head (dumlist);
7211 switch (ffebld_op (dummy))
7215 continue; /* Forget alternate returns, they mean
7221 s = ffebld_symter (dummy);
7222 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
7223 continue; /* Only looking for CHARACTER arguments. */
7224 if (stmtfunc && (ffesymbol_size (s) != FFETARGET_charactersizeNONE))
7225 continue; /* Stmtfunc arg with known size needs no
7227 if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
7228 continue; /* Only looking for variables and arrays. */
7229 parm = ffesymbol_hook (s).length_tree;
7230 assert (parm != NULL_TREE);
7231 if (parm != error_mark_node)
7232 push_parm_decl (parm);
7235 ffecom_transform_only_dummies_ = FALSE;
7239 /* ffecom_start_progunit_ -- Beginning of program unit
7241 Does GNU back end stuff necessary to teach it about the start of its
7242 equivalent of a Fortran program unit. */
7244 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7246 ffecom_start_progunit_ ()
7248 ffesymbol fn = ffecom_primary_entry_;
7250 tree id; /* Identifier (name) of function. */
7251 tree type; /* Type of function. */
7252 tree result; /* Result of function. */
7253 ffeinfoBasictype bt;
7257 ffeglobalType egt = FFEGLOBAL_type;
7260 bool altentries = (ffecom_num_entrypoints_ != 0);
7263 && (ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
7264 && (ffecom_master_bt_ == FFEINFO_basictypeNONE);
7265 bool main_program = FALSE;
7266 int old_lineno = lineno;
7267 const char *old_input_filename = input_filename;
7269 assert (fn != NULL);
7270 assert (ffesymbol_hook (fn).decl_tree == NULL_TREE);
7272 input_filename = ffesymbol_where_filename (fn);
7273 lineno = ffesymbol_where_filelinenum (fn);
7275 switch (ffecom_primary_entry_kind_)
7277 case FFEINFO_kindPROGRAM:
7278 main_program = TRUE;
7279 gt = FFEGLOBAL_typeMAIN;
7280 bt = FFEINFO_basictypeNONE;
7281 kt = FFEINFO_kindtypeNONE;
7282 type = ffecom_tree_fun_type_void;
7287 case FFEINFO_kindBLOCKDATA:
7288 gt = FFEGLOBAL_typeBDATA;
7289 bt = FFEINFO_basictypeNONE;
7290 kt = FFEINFO_kindtypeNONE;
7291 type = ffecom_tree_fun_type_void;
7296 case FFEINFO_kindFUNCTION:
7297 gt = FFEGLOBAL_typeFUNC;
7298 egt = FFEGLOBAL_typeEXT;
7299 bt = ffesymbol_basictype (fn);
7300 kt = ffesymbol_kindtype (fn);
7301 if (bt == FFEINFO_basictypeNONE)
7303 ffeimplic_establish_symbol (fn);
7304 if (ffesymbol_funcresult (fn) != NULL)
7305 ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
7306 bt = ffesymbol_basictype (fn);
7307 kt = ffesymbol_kindtype (fn);
7311 charfunc = cmplxfunc = FALSE;
7312 else if (bt == FFEINFO_basictypeCHARACTER)
7313 charfunc = TRUE, cmplxfunc = FALSE;
7314 else if ((bt == FFEINFO_basictypeCOMPLEX)
7315 && ffesymbol_is_f2c (fn)
7317 charfunc = FALSE, cmplxfunc = TRUE;
7319 charfunc = cmplxfunc = FALSE;
7321 if (multi || charfunc)
7322 type = ffecom_tree_fun_type_void;
7323 else if (ffesymbol_is_f2c (fn) && !altentries)
7324 type = ffecom_tree_fun_type[bt][kt];
7326 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
7328 if ((type == NULL_TREE)
7329 || (TREE_TYPE (type) == NULL_TREE))
7330 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */
7333 case FFEINFO_kindSUBROUTINE:
7334 gt = FFEGLOBAL_typeSUBR;
7335 egt = FFEGLOBAL_typeEXT;
7336 bt = FFEINFO_basictypeNONE;
7337 kt = FFEINFO_kindtypeNONE;
7338 if (ffecom_is_altreturning_)
7339 type = ffecom_tree_subr_type;
7341 type = ffecom_tree_fun_type_void;
7347 assert ("say what??" == NULL);
7349 case FFEINFO_kindANY:
7350 gt = FFEGLOBAL_typeANY;
7351 bt = FFEINFO_basictypeNONE;
7352 kt = FFEINFO_kindtypeNONE;
7353 type = error_mark_node;
7361 id = ffecom_get_invented_identifier ("__g77_masterfun_%s",
7362 ffesymbol_text (fn));
7364 #if FFETARGET_isENFORCED_MAIN
7365 else if (main_program)
7366 id = get_identifier (FFETARGET_nameENFORCED_MAIN_NAME);
7369 id = ffecom_get_external_identifier_ (fn);
7373 0, /* nested/inline */
7374 !altentries); /* TREE_PUBLIC */
7376 TREE_USED (current_function_decl) = 1; /* Avoid spurious warning if altentries. */
7379 && ((g = ffesymbol_global (fn)) != NULL)
7380 && ((ffeglobal_type (g) == gt)
7381 || (ffeglobal_type (g) == egt)))
7383 ffeglobal_set_hook (g, current_function_decl);
7386 /* Arg handling needs exec-transitioned ffesymbols to work with. But
7387 exec-transitioning needs current_function_decl to be filled in. So we
7388 do these things in two phases. */
7391 { /* 1st arg identifies which entrypoint. */
7392 ffecom_which_entrypoint_decl_
7393 = build_decl (PARM_DECL,
7394 ffecom_get_invented_identifier ("__g77_%s",
7395 "which_entrypoint"),
7397 push_parm_decl (ffecom_which_entrypoint_decl_);
7403 { /* Arg for result (return value). */
7408 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
7410 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
7412 type = ffecom_multi_type_node_;
7414 result = ffecom_get_invented_identifier ("__g77_%s", "result");
7416 /* Make length arg _and_ enhance type info for CHAR arg itself. */
7419 length = ffecom_char_enhance_arg_ (&type, fn);
7421 length = NULL_TREE; /* Not ref'd if !charfunc. */
7423 type = build_pointer_type (type);
7424 result = build_decl (PARM_DECL, result, type);
7426 push_parm_decl (result);
7428 ffecom_multi_retval_ = result;
7430 ffecom_func_result_ = result;
7434 push_parm_decl (length);
7435 ffecom_func_length_ = length;
7439 if (ffecom_primary_entry_is_proc_)
7442 arglist = ffecom_master_arglist_;
7444 arglist = ffesymbol_dummyargs (fn);
7445 ffecom_push_dummy_decls_ (arglist, FALSE);
7448 if (TREE_CODE (current_function_decl) != ERROR_MARK)
7449 store_parm_decls (main_program ? 1 : 0);
7451 ffecom_start_compstmt ();
7452 /* Disallow temp vars at this level. */
7453 current_binding_level->prep_state = 2;
7455 lineno = old_lineno;
7456 input_filename = old_input_filename;
7458 /* This handles any symbols still untransformed, in case -g specified.
7459 This used to be done in ffecom_finish_progunit, but it turns out to
7460 be necessary to do it here so that statement functions are
7461 expanded before code. But don't bother for BLOCK DATA. */
7463 if (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
7464 ffesymbol_drive (ffecom_finish_symbol_transform_);
7468 /* ffecom_sym_transform_ -- Transform FFE sym into backend sym
7471 ffecom_sym_transform_(s);
7473 The ffesymbol_hook info for s is updated with appropriate backend info
7476 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7478 ffecom_sym_transform_ (ffesymbol s)
7480 tree t; /* Transformed thingy. */
7481 tree tlen; /* Length if CHAR*(*). */
7482 bool addr; /* Is t the address of the thingy? */
7483 ffeinfoBasictype bt;
7486 int old_lineno = lineno;
7487 const char *old_input_filename = input_filename;
7489 /* Must ensure special ASSIGN variables are declared at top of outermost
7490 block, else they'll end up in the innermost block when their first
7491 ASSIGN is seen, which leaves them out of scope when they're the
7492 subject of a GOTO or I/O statement.
7494 We make this variable even if -fugly-assign. Just let it go unused,
7495 in case it turns out there are cases where we really want to use this
7496 variable anyway (e.g. ASSIGN to INTEGER*2 variable). */
7498 if (! ffecom_transform_only_dummies_
7499 && ffesymbol_assigned (s)
7500 && ! ffesymbol_hook (s).assign_tree)
7501 s = ffecom_sym_transform_assign_ (s);
7503 if (ffesymbol_sfdummyparent (s) == NULL)
7505 input_filename = ffesymbol_where_filename (s);
7506 lineno = ffesymbol_where_filelinenum (s);
7510 ffesymbol sf = ffesymbol_sfdummyparent (s);
7512 input_filename = ffesymbol_where_filename (sf);
7513 lineno = ffesymbol_where_filelinenum (sf);
7516 bt = ffeinfo_basictype (ffebld_info (s));
7517 kt = ffeinfo_kindtype (ffebld_info (s));
7523 switch (ffesymbol_kind (s))
7525 case FFEINFO_kindNONE:
7526 switch (ffesymbol_where (s))
7528 case FFEINFO_whereDUMMY: /* Subroutine or function. */
7529 assert (ffecom_transform_only_dummies_);
7531 /* Before 0.4, this could be ENTITY/DUMMY, but see
7532 ffestu_sym_end_transition -- no longer true (in particular, if
7533 it could be an ENTITY, it _will_ be made one, so that
7534 possibility won't come through here). So we never make length
7535 arg for CHARACTER type. */
7537 t = build_decl (PARM_DECL,
7538 ffecom_get_identifier_ (ffesymbol_text (s)),
7539 ffecom_tree_ptr_to_subr_type);
7541 DECL_ARTIFICIAL (t) = 1;
7546 case FFEINFO_whereGLOBAL: /* Subroutine or function. */
7547 assert (!ffecom_transform_only_dummies_);
7549 if (((g = ffesymbol_global (s)) != NULL)
7550 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
7551 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
7552 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
7553 && (ffeglobal_hook (g) != NULL_TREE)
7554 && ffe_is_globals ())
7556 t = ffeglobal_hook (g);
7560 t = build_decl (FUNCTION_DECL,
7561 ffecom_get_external_identifier_ (s),
7562 ffecom_tree_subr_type); /* Assume subr. */
7563 DECL_EXTERNAL (t) = 1;
7564 TREE_PUBLIC (t) = 1;
7566 t = start_decl (t, FALSE);
7567 finish_decl (t, NULL_TREE, FALSE);
7570 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
7571 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
7572 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
7573 ffeglobal_set_hook (g, t);
7575 ffecom_save_tree_forever (t);
7580 assert ("NONE where unexpected" == NULL);
7582 case FFEINFO_whereANY:
7587 case FFEINFO_kindENTITY:
7588 switch (ffeinfo_where (ffesymbol_info (s)))
7591 case FFEINFO_whereCONSTANT:
7592 /* ~~Debugging info needed? */
7593 assert (!ffecom_transform_only_dummies_);
7594 t = error_mark_node; /* Shouldn't ever see this in expr. */
7597 case FFEINFO_whereLOCAL:
7598 assert (!ffecom_transform_only_dummies_);
7601 ffestorag st = ffesymbol_storage (s);
7605 && (ffestorag_size (st) == 0))
7607 t = error_mark_node;
7611 type = ffecom_type_localvar_ (s, bt, kt);
7613 if (type == error_mark_node)
7615 t = error_mark_node;
7620 && (ffestorag_parent (st) != NULL))
7621 { /* Child of EQUIVALENCE parent. */
7624 ffetargetOffset offset;
7626 est = ffestorag_parent (st);
7627 ffecom_transform_equiv_ (est);
7629 et = ffestorag_hook (est);
7630 assert (et != NULL_TREE);
7632 if (! TREE_STATIC (et))
7633 put_var_into_stack (et);
7635 offset = ffestorag_modulo (est)
7636 + ffestorag_offset (ffesymbol_storage (s))
7637 - ffestorag_offset (est);
7639 ffecom_debug_kludge_ (et, "EQUIVALENCE", s, type, offset);
7641 /* (t_type *) (((char *) &et) + offset) */
7643 t = convert (string_type_node, /* (char *) */
7644 ffecom_1 (ADDR_EXPR,
7645 build_pointer_type (TREE_TYPE (et)),
7647 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
7649 build_int_2 (offset, 0));
7650 t = convert (build_pointer_type (type),
7652 TREE_CONSTANT (t) = staticp (et);
7659 bool init = ffesymbol_is_init (s);
7661 t = build_decl (VAR_DECL,
7662 ffecom_get_identifier_ (ffesymbol_text (s)),
7666 || ffesymbol_namelisted (s)
7667 #ifdef FFECOM_sizeMAXSTACKITEM
7669 && (ffestorag_size (st) > FFECOM_sizeMAXSTACKITEM))
7671 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
7672 && (ffecom_primary_entry_kind_
7673 != FFEINFO_kindBLOCKDATA)
7674 && (ffesymbol_is_save (s) || ffe_is_saveall ())))
7675 TREE_STATIC (t) = !ffesymbol_attr (s, FFESYMBOL_attrADJUSTABLE);
7677 TREE_STATIC (t) = 0; /* No need to make static. */
7679 if (init || ffe_is_init_local_zero ())
7680 DECL_INITIAL (t) = error_mark_node;
7682 /* Keep -Wunused from complaining about var if it
7683 is used as sfunc arg or DATA implied-DO. */
7684 if (ffesymbol_attrs (s) & FFESYMBOL_attrsSFARG)
7685 DECL_IN_SYSTEM_HEADER (t) = 1;
7687 t = start_decl (t, FALSE);
7691 if (ffesymbol_init (s) != NULL)
7692 initexpr = ffecom_expr (ffesymbol_init (s));
7694 initexpr = ffecom_init_zero_ (t);
7696 else if (ffe_is_init_local_zero ())
7697 initexpr = ffecom_init_zero_ (t);
7699 initexpr = NULL_TREE; /* Not ref'd if !init. */
7701 finish_decl (t, initexpr, FALSE);
7703 if (st != NULL && DECL_SIZE (t) != error_mark_node)
7705 assert (TREE_CODE (DECL_SIZE_UNIT (t)) == INTEGER_CST);
7706 assert (0 == compare_tree_int (DECL_SIZE_UNIT (t),
7707 ffestorag_size (st)));
7713 case FFEINFO_whereRESULT:
7714 assert (!ffecom_transform_only_dummies_);
7716 if (bt == FFEINFO_basictypeCHARACTER)
7717 { /* Result is already in list of dummies, use
7719 t = ffecom_func_result_;
7720 tlen = ffecom_func_length_;
7724 if ((ffecom_num_entrypoints_ == 0)
7725 && (bt == FFEINFO_basictypeCOMPLEX)
7726 && (ffesymbol_is_f2c (ffecom_primary_entry_)))
7727 { /* Result is already in list of dummies, use
7729 t = ffecom_func_result_;
7733 if (ffecom_func_result_ != NULL_TREE)
7735 t = ffecom_func_result_;
7738 if ((ffecom_num_entrypoints_ != 0)
7739 && (ffecom_master_bt_ == FFEINFO_basictypeNONE))
7741 assert (ffecom_multi_retval_ != NULL_TREE);
7742 t = ffecom_1 (INDIRECT_REF, ffecom_multi_type_node_,
7743 ffecom_multi_retval_);
7744 t = ffecom_2 (COMPONENT_REF, ffecom_tree_type[bt][kt],
7745 t, ffecom_multi_fields_[bt][kt]);
7750 t = build_decl (VAR_DECL,
7751 ffecom_get_identifier_ (ffesymbol_text (s)),
7752 ffecom_tree_type[bt][kt]);
7753 TREE_STATIC (t) = 0; /* Put result on stack. */
7754 t = start_decl (t, FALSE);
7755 finish_decl (t, NULL_TREE, FALSE);
7757 ffecom_func_result_ = t;
7761 case FFEINFO_whereDUMMY:
7769 bool adjustable = FALSE; /* Conditionally adjustable? */
7771 type = ffecom_tree_type[bt][kt];
7772 if (ffesymbol_sfdummyparent (s) != NULL)
7774 if (current_function_decl == ffecom_outer_function_decl_)
7775 { /* Exec transition before sfunc
7776 context; get it later. */
7779 t = ffecom_get_identifier_ (ffesymbol_text
7780 (ffesymbol_sfdummyparent (s)));
7783 t = ffecom_get_identifier_ (ffesymbol_text (s));
7785 assert (ffecom_transform_only_dummies_);
7787 old_sizes = get_pending_sizes ();
7788 put_pending_sizes (old_sizes);
7790 if (bt == FFEINFO_basictypeCHARACTER)
7791 tlen = ffecom_char_enhance_arg_ (&type, s);
7792 type = ffecom_check_size_overflow_ (s, type, TRUE);
7794 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
7796 if (type == error_mark_node)
7799 dim = ffebld_head (dl);
7800 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
7801 if ((ffebld_left (dim) == NULL) || ffecom_doing_entry_)
7802 low = ffecom_integer_one_node;
7804 low = ffecom_expr (ffebld_left (dim));
7805 assert (ffebld_right (dim) != NULL);
7806 if ((ffebld_op (ffebld_right (dim)) == FFEBLD_opSTAR)
7807 || ffecom_doing_entry_)
7809 /* Used to just do high=low. But for ffecom_tree_
7810 canonize_ref_, it probably is important to correctly
7811 assess the size. E.g. given COMPLEX C(*),CFUNC and
7812 C(2)=CFUNC(C), overlap can happen, while it can't
7813 for, say, C(1)=CFUNC(C(2)). */
7814 /* Even more recently used to set to INT_MAX, but that
7815 broke when some overflow checking went into the back
7816 end. Now we just leave the upper bound unspecified. */
7820 high = ffecom_expr (ffebld_right (dim));
7822 /* Determine whether array is conditionally adjustable,
7823 to decide whether back-end magic is needed.
7825 Normally the front end uses the back-end function
7826 variable_size to wrap SAVE_EXPR's around expressions
7827 affecting the size/shape of an array so that the
7828 size/shape info doesn't change during execution
7829 of the compiled code even though variables and
7830 functions referenced in those expressions might.
7832 variable_size also makes sure those saved expressions
7833 get evaluated immediately upon entry to the
7834 compiled procedure -- the front end normally doesn't
7835 have to worry about that.
7837 However, there is a problem with this that affects
7838 g77's implementation of entry points, and that is
7839 that it is _not_ true that each invocation of the
7840 compiled procedure is permitted to evaluate
7841 array size/shape info -- because it is possible
7842 that, for some invocations, that info is invalid (in
7843 which case it is "promised" -- i.e. a violation of
7844 the Fortran standard -- that the compiled code
7845 won't reference the array or its size/shape
7846 during that particular invocation).
7848 To phrase this in C terms, consider this gcc function:
7850 void foo (int *n, float (*a)[*n])
7852 // a is "pointer to array ...", fyi.
7855 Suppose that, for some invocations, it is permitted
7856 for a caller of foo to do this:
7860 Now the _written_ code for foo can take such a call
7861 into account by either testing explicitly for whether
7862 (a == NULL) || (n == NULL) -- presumably it is
7863 not permitted to reference *a in various fashions
7864 if (n == NULL) I suppose -- or it can avoid it by
7865 looking at other info (other arguments, static/global
7868 However, this won't work in gcc 2.5.8 because it'll
7869 automatically emit the code to save the "*n"
7870 expression, which'll yield a NULL dereference for
7871 the "foo (NULL, NULL)" call, something the code
7872 for foo cannot prevent.
7874 g77 definitely needs to avoid executing such
7875 code anytime the pointer to the adjustable array
7876 is NULL, because even if its bounds expressions
7877 don't have any references to possible "absent"
7878 variables like "*n" -- say all variable references
7879 are to COMMON variables, i.e. global (though in C,
7880 local static could actually make sense) -- the
7881 expressions could yield other run-time problems
7882 for allowably "dead" values in those variables.
7884 For example, let's consider a more complicated
7890 void foo (float (*a)[i/j])
7895 The above is (essentially) quite valid for Fortran
7896 but, again, for a call like "foo (NULL);", it is
7897 permitted for i and j to be undefined when the
7898 call is made. If j happened to be zero, for
7899 example, emitting the code to evaluate "i/j"
7900 could result in a run-time error.
7902 Offhand, though I don't have my F77 or F90
7903 standards handy, it might even be valid for a
7904 bounds expression to contain a function reference,
7905 in which case I doubt it is permitted for an
7906 implementation to invoke that function in the
7907 Fortran case involved here (invocation of an
7908 alternate ENTRY point that doesn't have the adjustable
7909 array as one of its arguments).
7911 So, the code that the compiler would normally emit
7912 to preevaluate the size/shape info for an
7913 adjustable array _must not_ be executed at run time
7914 in certain cases. Specifically, for Fortran,
7915 the case is when the pointer to the adjustable
7916 array == NULL. (For gnu-ish C, it might be nice
7917 for the source code itself to specify an expression
7918 that, if TRUE, inhibits execution of the code. Or
7919 reverse the sense for elegance.)
7921 (Note that g77 could use a different test than NULL,
7922 actually, since it happens to always pass an
7923 integer to the called function that specifies which
7924 entry point is being invoked. Hmm, this might
7925 solve the next problem.)
7927 One way a user could, I suppose, write "foo" so
7928 it works is to insert COND_EXPR's for the
7929 size/shape info so the dangerous stuff isn't
7930 actually done, as in:
7932 void foo (int *n, float (*a)[(a == NULL) ? 0 : *n])
7937 The next problem is that the front end needs to
7938 be able to tell the back end about the array's
7939 decl _before_ it tells it about the conditional
7940 expression to inhibit evaluation of size/shape info,
7943 To solve this, the front end needs to be able
7944 to give the back end the expression to inhibit
7945 generation of the preevaluation code _after_
7946 it makes the decl for the adjustable array.
7948 Until then, the above example using the COND_EXPR
7949 doesn't pass muster with gcc because the "(a == NULL)"
7950 part has a reference to "a", which is still
7951 undefined at that point.
7953 g77 will therefore use a different mechanism in the
7957 && ((TREE_CODE (low) != INTEGER_CST)
7958 || (high && TREE_CODE (high) != INTEGER_CST)))
7961 #if 0 /* Old approach -- see below. */
7962 if (TREE_CODE (low) != INTEGER_CST)
7963 low = ffecom_3 (COND_EXPR, integer_type_node,
7964 ffecom_adjarray_passed_ (s),
7966 ffecom_integer_zero_node);
7968 if (high && TREE_CODE (high) != INTEGER_CST)
7969 high = ffecom_3 (COND_EXPR, integer_type_node,
7970 ffecom_adjarray_passed_ (s),
7972 ffecom_integer_zero_node);
7975 /* ~~~gcc/stor-layout.c (layout_type) should do this,
7976 probably. Fixes 950302-1.f. */
7978 if (TREE_CODE (low) != INTEGER_CST)
7979 low = variable_size (low);
7981 /* ~~~Similarly, this fixes dumb0.f. The C front end
7982 does this, which is why dumb0.c would work. */
7984 if (high && TREE_CODE (high) != INTEGER_CST)
7985 high = variable_size (high);
7990 build_range_type (ffecom_integer_type_node,
7992 type = ffecom_check_size_overflow_ (s, type, TRUE);
7995 if (type == error_mark_node)
7997 t = error_mark_node;
8001 if ((ffesymbol_sfdummyparent (s) == NULL)
8002 || (ffesymbol_basictype (s) == FFEINFO_basictypeCHARACTER))
8004 type = build_pointer_type (type);
8008 t = build_decl (PARM_DECL, t, type);
8010 DECL_ARTIFICIAL (t) = 1;
8013 /* If this arg is present in every entry point's list of
8014 dummy args, then we're done. */
8016 if (ffesymbol_numentries (s)
8017 == (ffecom_num_entrypoints_ + 1))
8022 /* If variable_size in stor-layout has been called during
8023 the above, then get_pending_sizes should have the
8024 yet-to-be-evaluated saved expressions pending.
8025 Make the whole lot of them get emitted, conditionally
8026 on whether the array decl ("t" above) is not NULL. */
8029 tree sizes = get_pending_sizes ();
8034 tem = TREE_CHAIN (tem))
8036 tree temv = TREE_VALUE (tem);
8042 = ffecom_2 (COMPOUND_EXPR,
8051 = ffecom_3 (COND_EXPR,
8058 convert (TREE_TYPE (sizes),
8059 integer_zero_node));
8060 sizes = ffecom_save_tree (sizes);
8063 = tree_cons (NULL_TREE, sizes, tem);
8067 put_pending_sizes (sizes);
8073 && (ffesymbol_numentries (s)
8074 != ffecom_num_entrypoints_ + 1))
8076 = ffecom_2 (NE_EXPR, integer_type_node,
8082 && (ffesymbol_numentries (s)
8083 != ffecom_num_entrypoints_ + 1))
8085 ffebad_start (FFEBAD_MISSING_ADJARRAY_UNSUPPORTED);
8086 ffebad_here (0, ffesymbol_where_line (s),
8087 ffesymbol_where_column (s));
8088 ffebad_string (ffesymbol_text (s));
8097 case FFEINFO_whereCOMMON:
8102 ffestorag st = ffesymbol_storage (s);
8105 cs = ffesymbol_common (s); /* The COMMON area itself. */
8106 if (st != NULL) /* Else not laid out. */
8108 ffecom_transform_common_ (cs);
8109 st = ffesymbol_storage (s);
8112 type = ffecom_type_localvar_ (s, bt, kt);
8114 cg = ffesymbol_global (cs); /* The global COMMON info. */
8116 || (ffeglobal_type (cg) != FFEGLOBAL_typeCOMMON))
8119 ct = ffeglobal_hook (cg); /* The common area's tree. */
8121 if ((ct == NULL_TREE)
8123 || (type == error_mark_node))
8124 t = error_mark_node;
8127 ffetargetOffset offset;
8130 cst = ffestorag_parent (st);
8131 assert (cst == ffesymbol_storage (cs));
8133 offset = ffestorag_modulo (cst)
8134 + ffestorag_offset (st)
8135 - ffestorag_offset (cst);
8137 ffecom_debug_kludge_ (ct, "COMMON", s, type, offset);
8139 /* (t_type *) (((char *) &ct) + offset) */
8141 t = convert (string_type_node, /* (char *) */
8142 ffecom_1 (ADDR_EXPR,
8143 build_pointer_type (TREE_TYPE (ct)),
8145 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
8147 build_int_2 (offset, 0));
8148 t = convert (build_pointer_type (type),
8150 TREE_CONSTANT (t) = 1;
8157 case FFEINFO_whereIMMEDIATE:
8158 case FFEINFO_whereGLOBAL:
8159 case FFEINFO_whereFLEETING:
8160 case FFEINFO_whereFLEETING_CADDR:
8161 case FFEINFO_whereFLEETING_IADDR:
8162 case FFEINFO_whereINTRINSIC:
8163 case FFEINFO_whereCONSTANT_SUBOBJECT:
8165 assert ("ENTITY where unheard of" == NULL);
8167 case FFEINFO_whereANY:
8168 t = error_mark_node;
8173 case FFEINFO_kindFUNCTION:
8174 switch (ffeinfo_where (ffesymbol_info (s)))
8176 case FFEINFO_whereLOCAL: /* Me. */
8177 assert (!ffecom_transform_only_dummies_);
8178 t = current_function_decl;
8181 case FFEINFO_whereGLOBAL:
8182 assert (!ffecom_transform_only_dummies_);
8184 if (((g = ffesymbol_global (s)) != NULL)
8185 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8186 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8187 && (ffeglobal_hook (g) != NULL_TREE)
8188 && ffe_is_globals ())
8190 t = ffeglobal_hook (g);
8194 if (ffesymbol_is_f2c (s)
8195 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
8196 t = ffecom_tree_fun_type[bt][kt];
8198 t = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
8200 t = build_decl (FUNCTION_DECL,
8201 ffecom_get_external_identifier_ (s),
8203 DECL_EXTERNAL (t) = 1;
8204 TREE_PUBLIC (t) = 1;
8206 t = start_decl (t, FALSE);
8207 finish_decl (t, NULL_TREE, FALSE);
8210 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8211 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8212 ffeglobal_set_hook (g, t);
8214 ffecom_save_tree_forever (t);
8218 case FFEINFO_whereDUMMY:
8219 assert (ffecom_transform_only_dummies_);
8221 if (ffesymbol_is_f2c (s)
8222 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
8223 t = ffecom_tree_ptr_to_fun_type[bt][kt];
8225 t = build_pointer_type
8226 (build_function_type (ffecom_tree_type[bt][kt], NULL_TREE));
8228 t = build_decl (PARM_DECL,
8229 ffecom_get_identifier_ (ffesymbol_text (s)),
8232 DECL_ARTIFICIAL (t) = 1;
8237 case FFEINFO_whereCONSTANT: /* Statement function. */
8238 assert (!ffecom_transform_only_dummies_);
8239 t = ffecom_gen_sfuncdef_ (s, bt, kt);
8242 case FFEINFO_whereINTRINSIC:
8243 assert (!ffecom_transform_only_dummies_);
8244 break; /* Let actual references generate their
8248 assert ("FUNCTION where unheard of" == NULL);
8250 case FFEINFO_whereANY:
8251 t = error_mark_node;
8256 case FFEINFO_kindSUBROUTINE:
8257 switch (ffeinfo_where (ffesymbol_info (s)))
8259 case FFEINFO_whereLOCAL: /* Me. */
8260 assert (!ffecom_transform_only_dummies_);
8261 t = current_function_decl;
8264 case FFEINFO_whereGLOBAL:
8265 assert (!ffecom_transform_only_dummies_);
8267 if (((g = ffesymbol_global (s)) != NULL)
8268 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8269 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8270 && (ffeglobal_hook (g) != NULL_TREE)
8271 && ffe_is_globals ())
8273 t = ffeglobal_hook (g);
8277 t = build_decl (FUNCTION_DECL,
8278 ffecom_get_external_identifier_ (s),
8279 ffecom_tree_subr_type);
8280 DECL_EXTERNAL (t) = 1;
8281 TREE_PUBLIC (t) = 1;
8283 t = start_decl (t, FALSE);
8284 finish_decl (t, NULL_TREE, FALSE);
8287 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8288 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8289 ffeglobal_set_hook (g, t);
8291 ffecom_save_tree_forever (t);
8295 case FFEINFO_whereDUMMY:
8296 assert (ffecom_transform_only_dummies_);
8298 t = build_decl (PARM_DECL,
8299 ffecom_get_identifier_ (ffesymbol_text (s)),
8300 ffecom_tree_ptr_to_subr_type);
8302 DECL_ARTIFICIAL (t) = 1;
8307 case FFEINFO_whereINTRINSIC:
8308 assert (!ffecom_transform_only_dummies_);
8309 break; /* Let actual references generate their
8313 assert ("SUBROUTINE where unheard of" == NULL);
8315 case FFEINFO_whereANY:
8316 t = error_mark_node;
8321 case FFEINFO_kindPROGRAM:
8322 switch (ffeinfo_where (ffesymbol_info (s)))
8324 case FFEINFO_whereLOCAL: /* Me. */
8325 assert (!ffecom_transform_only_dummies_);
8326 t = current_function_decl;
8329 case FFEINFO_whereCOMMON:
8330 case FFEINFO_whereDUMMY:
8331 case FFEINFO_whereGLOBAL:
8332 case FFEINFO_whereRESULT:
8333 case FFEINFO_whereFLEETING:
8334 case FFEINFO_whereFLEETING_CADDR:
8335 case FFEINFO_whereFLEETING_IADDR:
8336 case FFEINFO_whereIMMEDIATE:
8337 case FFEINFO_whereINTRINSIC:
8338 case FFEINFO_whereCONSTANT:
8339 case FFEINFO_whereCONSTANT_SUBOBJECT:
8341 assert ("PROGRAM where unheard of" == NULL);
8343 case FFEINFO_whereANY:
8344 t = error_mark_node;
8349 case FFEINFO_kindBLOCKDATA:
8350 switch (ffeinfo_where (ffesymbol_info (s)))
8352 case FFEINFO_whereLOCAL: /* Me. */
8353 assert (!ffecom_transform_only_dummies_);
8354 t = current_function_decl;
8357 case FFEINFO_whereGLOBAL:
8358 assert (!ffecom_transform_only_dummies_);
8360 t = build_decl (FUNCTION_DECL,
8361 ffecom_get_external_identifier_ (s),
8362 ffecom_tree_blockdata_type);
8363 DECL_EXTERNAL (t) = 1;
8364 TREE_PUBLIC (t) = 1;
8366 t = start_decl (t, FALSE);
8367 finish_decl (t, NULL_TREE, FALSE);
8369 ffecom_save_tree_forever (t);
8373 case FFEINFO_whereCOMMON:
8374 case FFEINFO_whereDUMMY:
8375 case FFEINFO_whereRESULT:
8376 case FFEINFO_whereFLEETING:
8377 case FFEINFO_whereFLEETING_CADDR:
8378 case FFEINFO_whereFLEETING_IADDR:
8379 case FFEINFO_whereIMMEDIATE:
8380 case FFEINFO_whereINTRINSIC:
8381 case FFEINFO_whereCONSTANT:
8382 case FFEINFO_whereCONSTANT_SUBOBJECT:
8384 assert ("BLOCKDATA where unheard of" == NULL);
8386 case FFEINFO_whereANY:
8387 t = error_mark_node;
8392 case FFEINFO_kindCOMMON:
8393 switch (ffeinfo_where (ffesymbol_info (s)))
8395 case FFEINFO_whereLOCAL:
8396 assert (!ffecom_transform_only_dummies_);
8397 ffecom_transform_common_ (s);
8400 case FFEINFO_whereNONE:
8401 case FFEINFO_whereCOMMON:
8402 case FFEINFO_whereDUMMY:
8403 case FFEINFO_whereGLOBAL:
8404 case FFEINFO_whereRESULT:
8405 case FFEINFO_whereFLEETING:
8406 case FFEINFO_whereFLEETING_CADDR:
8407 case FFEINFO_whereFLEETING_IADDR:
8408 case FFEINFO_whereIMMEDIATE:
8409 case FFEINFO_whereINTRINSIC:
8410 case FFEINFO_whereCONSTANT:
8411 case FFEINFO_whereCONSTANT_SUBOBJECT:
8413 assert ("COMMON where unheard of" == NULL);
8415 case FFEINFO_whereANY:
8416 t = error_mark_node;
8421 case FFEINFO_kindCONSTRUCT:
8422 switch (ffeinfo_where (ffesymbol_info (s)))
8424 case FFEINFO_whereLOCAL:
8425 assert (!ffecom_transform_only_dummies_);
8428 case FFEINFO_whereNONE:
8429 case FFEINFO_whereCOMMON:
8430 case FFEINFO_whereDUMMY:
8431 case FFEINFO_whereGLOBAL:
8432 case FFEINFO_whereRESULT:
8433 case FFEINFO_whereFLEETING:
8434 case FFEINFO_whereFLEETING_CADDR:
8435 case FFEINFO_whereFLEETING_IADDR:
8436 case FFEINFO_whereIMMEDIATE:
8437 case FFEINFO_whereINTRINSIC:
8438 case FFEINFO_whereCONSTANT:
8439 case FFEINFO_whereCONSTANT_SUBOBJECT:
8441 assert ("CONSTRUCT where unheard of" == NULL);
8443 case FFEINFO_whereANY:
8444 t = error_mark_node;
8449 case FFEINFO_kindNAMELIST:
8450 switch (ffeinfo_where (ffesymbol_info (s)))
8452 case FFEINFO_whereLOCAL:
8453 assert (!ffecom_transform_only_dummies_);
8454 t = ffecom_transform_namelist_ (s);
8457 case FFEINFO_whereNONE:
8458 case FFEINFO_whereCOMMON:
8459 case FFEINFO_whereDUMMY:
8460 case FFEINFO_whereGLOBAL:
8461 case FFEINFO_whereRESULT:
8462 case FFEINFO_whereFLEETING:
8463 case FFEINFO_whereFLEETING_CADDR:
8464 case FFEINFO_whereFLEETING_IADDR:
8465 case FFEINFO_whereIMMEDIATE:
8466 case FFEINFO_whereINTRINSIC:
8467 case FFEINFO_whereCONSTANT:
8468 case FFEINFO_whereCONSTANT_SUBOBJECT:
8470 assert ("NAMELIST where unheard of" == NULL);
8472 case FFEINFO_whereANY:
8473 t = error_mark_node;
8479 assert ("kind unheard of" == NULL);
8481 case FFEINFO_kindANY:
8482 t = error_mark_node;
8486 ffesymbol_hook (s).decl_tree = t;
8487 ffesymbol_hook (s).length_tree = tlen;
8488 ffesymbol_hook (s).addr = addr;
8490 lineno = old_lineno;
8491 input_filename = old_input_filename;
8497 /* Transform into ASSIGNable symbol.
8499 Symbol has already been transformed, but for whatever reason, the
8500 resulting decl_tree has been deemed not usable for an ASSIGN target.
8501 (E.g. it isn't wide enough to hold a pointer.) So, here we invent
8502 another local symbol of type void * and stuff that in the assign_tree
8503 argument. The F77/F90 standards allow this implementation. */
8505 #if FFECOM_targetCURRENT == FFECOM_targetGCC
8507 ffecom_sym_transform_assign_ (ffesymbol s)
8509 tree t; /* Transformed thingy. */
8510 int old_lineno = lineno;
8511 const char *old_input_filename = input_filename;
8513 if (ffesymbol_sfdummyparent (s) == NULL)
8515 input_filename = ffesymbol_where_filename (s);
8516 lineno = ffesymbol_where_filelinenum (s);
8520 ffesymbol sf = ffesymbol_sfdummyparent (s);
8522 input_filename = ffesymbol_where_filename (sf);
8523 lineno = ffesymbol_where_filelinenum (sf);
8526 assert (!ffecom_transform_only_dummies_);
8528 t = build_decl (VAR_DECL,
8529 ffecom_get_invented_identifier ("__g77_ASSIGN_%s",
8530 ffesymbol_text (s)),
8531 TREE_TYPE (null_pointer_node));
8533 switch (ffesymbol_where (s))
8535 case FFEINFO_whereLOCAL:
8536 /* Unlike for regular vars, SAVE status is easy to determine for
8537 ASSIGNed vars, since there's no initialization, there's no
8538 effective storage association (so "SAVE J" does not apply to
8539 K even given "EQUIVALENCE (J,K)"), there's no size issue
8540 to worry about, etc. */
8541 if ((ffesymbol_is_save (s) || ffe_is_saveall ())
8542 && (ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
8543 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA))
8544 TREE_STATIC (t) = 1; /* SAVEd in proc, make static. */
8546 TREE_STATIC (t) = 0; /* No need to make static. */
8549 case FFEINFO_whereCOMMON:
8550 TREE_STATIC (t) = 1; /* Assume COMMONs always SAVEd. */
8553 case FFEINFO_whereDUMMY:
8554 /* Note that twinning a DUMMY means the caller won't see
8555 the ASSIGNed value. But both F77 and F90 allow implementations
8556 to do this, i.e. disallow Fortran code that would try and
8557 take advantage of actually putting a label into a variable
8558 via a dummy argument (or any other storage association, for
8560 TREE_STATIC (t) = 0;
8564 TREE_STATIC (t) = 0;
8568 t = start_decl (t, FALSE);
8569 finish_decl (t, NULL_TREE, FALSE);
8571 ffesymbol_hook (s).assign_tree = t;
8573 lineno = old_lineno;
8574 input_filename = old_input_filename;
8580 /* Implement COMMON area in back end.
8582 Because COMMON-based variables can be referenced in the dimension
8583 expressions of dummy (adjustable) arrays, and because dummies
8584 (in the gcc back end) need to be put in the outer binding level
8585 of a function (which has two binding levels, the outer holding
8586 the dummies and the inner holding the other vars), special care
8587 must be taken to handle COMMON areas.
8589 The current strategy is basically to always tell the back end about
8590 the COMMON area as a top-level external reference to just a block
8591 of storage of the master type of that area (e.g. integer, real,
8592 character, whatever -- not a structure). As a distinct action,
8593 if initial values are provided, tell the back end about the area
8594 as a top-level non-external (initialized) area and remember not to
8595 allow further initialization or expansion of the area. Meanwhile,
8596 if no initialization happens at all, tell the back end about
8597 the largest size we've seen declared so the space does get reserved.
8598 (This function doesn't handle all that stuff, but it does some
8599 of the important things.)
8601 Meanwhile, for COMMON variables themselves, just keep creating
8602 references like *((float *) (&common_area + offset)) each time
8603 we reference the variable. In other words, don't make a VAR_DECL
8604 or any kind of component reference (like we used to do before 0.4),
8605 though we might do that as well just for debugging purposes (and
8606 stuff the rtl with the appropriate offset expression). */
8608 #if FFECOM_targetCURRENT == FFECOM_targetGCC
8610 ffecom_transform_common_ (ffesymbol s)
8612 ffestorag st = ffesymbol_storage (s);
8613 ffeglobal g = ffesymbol_global (s);
8618 bool is_init = ffestorag_is_init (st);
8620 assert (st != NULL);
8623 || (ffeglobal_type (g) != FFEGLOBAL_typeCOMMON))
8626 /* First update the size of the area in global terms. */
8628 ffeglobal_size_common (s, ffestorag_size (st));
8630 if (!ffeglobal_common_init (g))
8631 is_init = FALSE; /* No explicit init, don't let erroneous joins init. */
8633 cbt = ffeglobal_hook (g);
8635 /* If we already have declared this common block for a previous program
8636 unit, and either we already initialized it or we don't have new
8637 initialization for it, just return what we have without changing it. */
8639 if ((cbt != NULL_TREE)
8641 || !DECL_EXTERNAL (cbt)))
8643 if (st->hook == NULL) ffestorag_set_hook (st, cbt);
8647 /* Process inits. */
8651 if (ffestorag_init (st) != NULL)
8655 /* Set the padding for the expression, so ffecom_expr
8656 knows to insert that many zeros. */
8657 switch (ffebld_op (sexp = ffestorag_init (st)))
8659 case FFEBLD_opCONTER:
8660 ffebld_conter_set_pad (sexp, ffestorag_modulo (st));
8663 case FFEBLD_opARRTER:
8664 ffebld_arrter_set_pad (sexp, ffestorag_modulo (st));
8667 case FFEBLD_opACCTER:
8668 ffebld_accter_set_pad (sexp, ffestorag_modulo (st));
8672 assert ("bad op for cmn init (pad)" == NULL);
8676 init = ffecom_expr (sexp);
8677 if (init == error_mark_node)
8678 { /* Hopefully the back end complained! */
8680 if (cbt != NULL_TREE)
8685 init = error_mark_node;
8690 /* cbtype must be permanently allocated! */
8692 /* Allocate the MAX of the areas so far, seen filewide. */
8693 high = build_int_2 ((ffeglobal_common_size (g)
8694 + ffeglobal_common_pad (g)) - 1, 0);
8695 TREE_TYPE (high) = ffecom_integer_type_node;
8698 cbtype = build_array_type (char_type_node,
8699 build_range_type (integer_type_node,
8703 cbtype = build_array_type (char_type_node, NULL_TREE);
8705 if (cbt == NULL_TREE)
8708 = build_decl (VAR_DECL,
8709 ffecom_get_external_identifier_ (s),
8711 TREE_STATIC (cbt) = 1;
8712 TREE_PUBLIC (cbt) = 1;
8717 TREE_TYPE (cbt) = cbtype;
8719 DECL_EXTERNAL (cbt) = init ? 0 : 1;
8720 DECL_INITIAL (cbt) = init ? error_mark_node : NULL_TREE;
8722 cbt = start_decl (cbt, TRUE);
8723 if (ffeglobal_hook (g) != NULL)
8724 assert (cbt == ffeglobal_hook (g));
8726 assert (!init || !DECL_EXTERNAL (cbt));
8728 /* Make sure that any type can live in COMMON and be referenced
8729 without getting a bus error. We could pick the most restrictive
8730 alignment of all entities actually placed in the COMMON, but
8731 this seems easy enough. */
8733 DECL_ALIGN (cbt) = BIGGEST_ALIGNMENT;
8734 DECL_USER_ALIGN (cbt) = 0;
8736 if (is_init && (ffestorag_init (st) == NULL))
8737 init = ffecom_init_zero_ (cbt);
8739 finish_decl (cbt, init, TRUE);
8742 ffestorag_set_init (st, ffebld_new_any ());
8746 assert (DECL_SIZE_UNIT (cbt) != NULL_TREE);
8747 assert (TREE_CODE (DECL_SIZE_UNIT (cbt)) == INTEGER_CST);
8748 assert (0 == compare_tree_int (DECL_SIZE_UNIT (cbt),
8749 (ffeglobal_common_size (g)
8750 + ffeglobal_common_pad (g))));
8753 ffeglobal_set_hook (g, cbt);
8755 ffestorag_set_hook (st, cbt);
8757 ffecom_save_tree_forever (cbt);
8761 /* Make master area for local EQUIVALENCE. */
8763 #if FFECOM_targetCURRENT == FFECOM_targetGCC
8765 ffecom_transform_equiv_ (ffestorag eqst)
8771 bool is_init = ffestorag_is_init (eqst);
8773 assert (eqst != NULL);
8775 eqt = ffestorag_hook (eqst);
8777 if (eqt != NULL_TREE)
8780 /* Process inits. */
8784 if (ffestorag_init (eqst) != NULL)
8788 /* Set the padding for the expression, so ffecom_expr
8789 knows to insert that many zeros. */
8790 switch (ffebld_op (sexp = ffestorag_init (eqst)))
8792 case FFEBLD_opCONTER:
8793 ffebld_conter_set_pad (sexp, ffestorag_modulo (eqst));
8796 case FFEBLD_opARRTER:
8797 ffebld_arrter_set_pad (sexp, ffestorag_modulo (eqst));
8800 case FFEBLD_opACCTER:
8801 ffebld_accter_set_pad (sexp, ffestorag_modulo (eqst));
8805 assert ("bad op for eqv init (pad)" == NULL);
8809 init = ffecom_expr (sexp);
8810 if (init == error_mark_node)
8811 init = NULL_TREE; /* Hopefully the back end complained! */
8814 init = error_mark_node;
8816 else if (ffe_is_init_local_zero ())
8817 init = error_mark_node;
8821 ffecom_member_namelisted_ = FALSE;
8822 ffestorag_drive (ffestorag_list_equivs (eqst),
8823 &ffecom_member_phase1_,
8826 high = build_int_2 ((ffestorag_size (eqst)
8827 + ffestorag_modulo (eqst)) - 1, 0);
8828 TREE_TYPE (high) = ffecom_integer_type_node;
8830 eqtype = build_array_type (char_type_node,
8831 build_range_type (ffecom_integer_type_node,
8832 ffecom_integer_zero_node,
8835 eqt = build_decl (VAR_DECL,
8836 ffecom_get_invented_identifier ("__g77_equiv_%s",
8838 (ffestorag_symbol (eqst))),
8840 DECL_EXTERNAL (eqt) = 0;
8842 || ffecom_member_namelisted_
8843 #ifdef FFECOM_sizeMAXSTACKITEM
8844 || (ffestorag_size (eqst) > FFECOM_sizeMAXSTACKITEM)
8846 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
8847 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
8848 && (ffestorag_is_save (eqst) || ffe_is_saveall ())))
8849 TREE_STATIC (eqt) = 1;
8851 TREE_STATIC (eqt) = 0;
8852 TREE_PUBLIC (eqt) = 0;
8853 TREE_ADDRESSABLE (eqt) = 1; /* Ensure non-register allocation */
8854 DECL_CONTEXT (eqt) = current_function_decl;
8856 DECL_INITIAL (eqt) = error_mark_node;
8858 DECL_INITIAL (eqt) = NULL_TREE;
8860 eqt = start_decl (eqt, FALSE);
8862 /* Make sure that any type can live in EQUIVALENCE and be referenced
8863 without getting a bus error. We could pick the most restrictive
8864 alignment of all entities actually placed in the EQUIVALENCE, but
8865 this seems easy enough. */
8867 DECL_ALIGN (eqt) = BIGGEST_ALIGNMENT;
8868 DECL_USER_ALIGN (eqt) = 0;
8870 if ((!is_init && ffe_is_init_local_zero ())
8871 || (is_init && (ffestorag_init (eqst) == NULL)))
8872 init = ffecom_init_zero_ (eqt);
8874 finish_decl (eqt, init, FALSE);
8877 ffestorag_set_init (eqst, ffebld_new_any ());
8880 assert (TREE_CODE (DECL_SIZE_UNIT (eqt)) == INTEGER_CST);
8881 assert (0 == compare_tree_int (DECL_SIZE_UNIT (eqt),
8882 (ffestorag_size (eqst)
8883 + ffestorag_modulo (eqst))));
8886 ffestorag_set_hook (eqst, eqt);
8888 ffestorag_drive (ffestorag_list_equivs (eqst),
8889 &ffecom_member_phase2_,
8894 /* Implement NAMELIST in back end. See f2c/format.c for more info. */
8896 #if FFECOM_targetCURRENT == FFECOM_targetGCC
8898 ffecom_transform_namelist_ (ffesymbol s)
8901 tree nmltype = ffecom_type_namelist_ ();
8909 static int mynumber = 0;
8911 nmlt = build_decl (VAR_DECL,
8912 ffecom_get_invented_identifier ("__g77_namelist_%d",
8915 TREE_STATIC (nmlt) = 1;
8916 DECL_INITIAL (nmlt) = error_mark_node;
8918 nmlt = start_decl (nmlt, FALSE);
8920 /* Process inits. */
8922 i = strlen (ffesymbol_text (s));
8924 high = build_int_2 (i, 0);
8925 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
8927 nameinit = ffecom_build_f2c_string_ (i + 1,
8928 ffesymbol_text (s));
8929 TREE_TYPE (nameinit)
8930 = build_type_variant
8933 build_range_type (ffecom_f2c_ftnlen_type_node,
8934 ffecom_f2c_ftnlen_one_node,
8937 TREE_CONSTANT (nameinit) = 1;
8938 TREE_STATIC (nameinit) = 1;
8939 nameinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (nameinit)),
8942 varsinit = ffecom_vardesc_array_ (s);
8943 varsinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (varsinit)),
8945 TREE_CONSTANT (varsinit) = 1;
8946 TREE_STATIC (varsinit) = 1;
8951 for (i = 0, b = ffesymbol_namelist (s); b != NULL; b = ffebld_trail (b))
8954 nvarsinit = build_int_2 (i, 0);
8955 TREE_TYPE (nvarsinit) = integer_type_node;
8956 TREE_CONSTANT (nvarsinit) = 1;
8957 TREE_STATIC (nvarsinit) = 1;
8959 nmlinits = build_tree_list ((field = TYPE_FIELDS (nmltype)), nameinit);
8960 TREE_CHAIN (nmlinits) = build_tree_list ((field = TREE_CHAIN (field)),
8962 TREE_CHAIN (TREE_CHAIN (nmlinits))
8963 = build_tree_list ((field = TREE_CHAIN (field)), nvarsinit);
8965 nmlinits = build (CONSTRUCTOR, nmltype, NULL_TREE, nmlinits);
8966 TREE_CONSTANT (nmlinits) = 1;
8967 TREE_STATIC (nmlinits) = 1;
8969 finish_decl (nmlt, nmlinits, FALSE);
8971 nmlt = ffecom_1 (ADDR_EXPR, build_pointer_type (nmltype), nmlt);
8978 /* A subroutine of ffecom_tree_canonize_ref_. The incoming tree is
8979 analyzed on the assumption it is calculating a pointer to be
8980 indirected through. It must return the proper decl and offset,
8981 taking into account different units of measurements for offsets. */
8983 #if FFECOM_targetCURRENT == FFECOM_targetGCC
8985 ffecom_tree_canonize_ptr_ (tree *decl, tree *offset,
8988 switch (TREE_CODE (t))
8992 case NON_LVALUE_EXPR:
8993 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
8997 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
8998 if ((*decl == NULL_TREE)
8999 || (*decl == error_mark_node))
9002 if (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST)
9004 /* An offset into COMMON. */
9005 *offset = fold (build (PLUS_EXPR, TREE_TYPE (*offset),
9006 *offset, TREE_OPERAND (t, 1)));
9007 /* Convert offset (presumably in bytes) into canonical units
9008 (presumably bits). */
9009 *offset = size_binop (MULT_EXPR,
9010 convert (bitsizetype, *offset),
9011 TYPE_SIZE (TREE_TYPE (TREE_TYPE (t))));
9014 /* Not a COMMON reference, so an unrecognized pattern. */
9015 *decl = error_mark_node;
9020 *offset = bitsize_zero_node;
9024 if (TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL)
9026 /* A reference to COMMON. */
9027 *decl = TREE_OPERAND (t, 0);
9028 *offset = bitsize_zero_node;
9033 /* Not a COMMON reference, so an unrecognized pattern. */
9034 *decl = error_mark_node;
9040 /* Given a tree that is possibly intended for use as an lvalue, return
9041 information representing a canonical view of that tree as a decl, an
9042 offset into that decl, and a size for the lvalue.
9044 If there's no applicable decl, NULL_TREE is returned for the decl,
9045 and the other fields are left undefined.
9047 If the tree doesn't fit the recognizable forms, an ERROR_MARK node
9048 is returned for the decl, and the other fields are left undefined.
9050 Otherwise, the decl returned currently is either a VAR_DECL or a
9053 The offset returned is always valid, but of course not necessarily
9054 a constant, and not necessarily converted into the appropriate
9055 type, leaving that up to the caller (so as to avoid that overhead
9056 if the decls being looked at are different anyway).
9058 If the size cannot be determined (e.g. an adjustable array),
9059 an ERROR_MARK node is returned for the size. Otherwise, the
9060 size returned is valid, not necessarily a constant, and not
9061 necessarily converted into the appropriate type as with the
9064 Note that the offset and size expressions are expressed in the
9065 base storage units (usually bits) rather than in the units of
9066 the type of the decl, because two decls with different types
9067 might overlap but with apparently non-overlapping array offsets,
9068 whereas converting the array offsets to consistant offsets will
9069 reveal the overlap. */
9071 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9073 ffecom_tree_canonize_ref_ (tree *decl, tree *offset,
9076 /* The default path is to report a nonexistant decl. */
9082 switch (TREE_CODE (t))
9085 case IDENTIFIER_NODE:
9094 case TRUNC_DIV_EXPR:
9096 case FLOOR_DIV_EXPR:
9097 case ROUND_DIV_EXPR:
9098 case TRUNC_MOD_EXPR:
9100 case FLOOR_MOD_EXPR:
9101 case ROUND_MOD_EXPR:
9103 case EXACT_DIV_EXPR:
9104 case FIX_TRUNC_EXPR:
9106 case FIX_FLOOR_EXPR:
9107 case FIX_ROUND_EXPR:
9122 case BIT_ANDTC_EXPR:
9124 case TRUTH_ANDIF_EXPR:
9125 case TRUTH_ORIF_EXPR:
9126 case TRUTH_AND_EXPR:
9128 case TRUTH_XOR_EXPR:
9129 case TRUTH_NOT_EXPR:
9149 *offset = bitsize_zero_node;
9150 *size = TYPE_SIZE (TREE_TYPE (t));
9155 tree array = TREE_OPERAND (t, 0);
9156 tree element = TREE_OPERAND (t, 1);
9159 if ((array == NULL_TREE)
9160 || (element == NULL_TREE))
9162 *decl = error_mark_node;
9166 ffecom_tree_canonize_ref_ (decl, &init_offset, size,
9168 if ((*decl == NULL_TREE)
9169 || (*decl == error_mark_node))
9172 /* Calculate ((element - base) * NBBY) + init_offset. */
9173 *offset = fold (build (MINUS_EXPR, TREE_TYPE (element),
9175 TYPE_MIN_VALUE (TYPE_DOMAIN
9176 (TREE_TYPE (array)))));
9178 *offset = size_binop (MULT_EXPR,
9179 convert (bitsizetype, *offset),
9180 TYPE_SIZE (TREE_TYPE (TREE_TYPE (array))));
9182 *offset = size_binop (PLUS_EXPR, init_offset, *offset);
9184 *size = TYPE_SIZE (TREE_TYPE (t));
9190 /* Most of this code is to handle references to COMMON. And so
9191 far that is useful only for calling library functions, since
9192 external (user) functions might reference common areas. But
9193 even calling an external function, it's worthwhile to decode
9194 COMMON references because if not storing into COMMON, we don't
9195 want COMMON-based arguments to gratuitously force use of a
9198 *size = TYPE_SIZE (TREE_TYPE (t));
9200 ffecom_tree_canonize_ptr_ (decl, offset,
9201 TREE_OPERAND (t, 0));
9208 case NON_LVALUE_EXPR:
9211 case COND_EXPR: /* More cases than we can handle. */
9213 case REFERENCE_EXPR:
9214 case PREDECREMENT_EXPR:
9215 case PREINCREMENT_EXPR:
9216 case POSTDECREMENT_EXPR:
9217 case POSTINCREMENT_EXPR:
9220 *decl = error_mark_node;
9226 /* Do divide operation appropriate to type of operands. */
9228 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9230 ffecom_tree_divide_ (tree tree_type, tree left, tree right,
9231 tree dest_tree, ffebld dest, bool *dest_used,
9234 if ((left == error_mark_node)
9235 || (right == error_mark_node))
9236 return error_mark_node;
9238 switch (TREE_CODE (tree_type))
9241 return ffecom_2 (TRUNC_DIV_EXPR, tree_type,
9246 if (! optimize_size)
9247 return ffecom_2 (RDIV_EXPR, tree_type,
9253 if (TREE_TYPE (tree_type)
9254 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9255 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */
9257 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */
9259 left = ffecom_1 (ADDR_EXPR,
9260 build_pointer_type (TREE_TYPE (left)),
9262 left = build_tree_list (NULL_TREE, left);
9263 right = ffecom_1 (ADDR_EXPR,
9264 build_pointer_type (TREE_TYPE (right)),
9266 right = build_tree_list (NULL_TREE, right);
9267 TREE_CHAIN (left) = right;
9269 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9270 ffecom_gfrt_kindtype (ix),
9271 ffe_is_f2c_library (),
9274 dest_tree, dest, dest_used,
9275 NULL_TREE, TRUE, hook);
9283 if (TREE_TYPE (TYPE_FIELDS (tree_type))
9284 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9285 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */
9287 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */
9289 left = ffecom_1 (ADDR_EXPR,
9290 build_pointer_type (TREE_TYPE (left)),
9292 left = build_tree_list (NULL_TREE, left);
9293 right = ffecom_1 (ADDR_EXPR,
9294 build_pointer_type (TREE_TYPE (right)),
9296 right = build_tree_list (NULL_TREE, right);
9297 TREE_CHAIN (left) = right;
9299 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9300 ffecom_gfrt_kindtype (ix),
9301 ffe_is_f2c_library (),
9304 dest_tree, dest, dest_used,
9305 NULL_TREE, TRUE, hook);
9310 return ffecom_2 (RDIV_EXPR, tree_type,
9317 /* Build type info for non-dummy variable. */
9319 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9321 ffecom_type_localvar_ (ffesymbol s, ffeinfoBasictype bt,
9330 type = ffecom_tree_type[bt][kt];
9331 if (bt == FFEINFO_basictypeCHARACTER)
9333 hight = build_int_2 (ffesymbol_size (s), 0);
9334 TREE_TYPE (hight) = ffecom_f2c_ftnlen_type_node;
9339 build_range_type (ffecom_f2c_ftnlen_type_node,
9340 ffecom_f2c_ftnlen_one_node,
9342 type = ffecom_check_size_overflow_ (s, type, FALSE);
9345 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
9347 if (type == error_mark_node)
9350 dim = ffebld_head (dl);
9351 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
9353 if (ffebld_left (dim) == NULL)
9354 lowt = integer_one_node;
9356 lowt = ffecom_expr (ffebld_left (dim));
9358 if (TREE_CODE (lowt) != INTEGER_CST)
9359 lowt = variable_size (lowt);
9361 assert (ffebld_right (dim) != NULL);
9362 hight = ffecom_expr (ffebld_right (dim));
9364 if (TREE_CODE (hight) != INTEGER_CST)
9365 hight = variable_size (hight);
9367 type = build_array_type (type,
9368 build_range_type (ffecom_integer_type_node,
9370 type = ffecom_check_size_overflow_ (s, type, FALSE);
9377 /* Build Namelist type. */
9379 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9381 ffecom_type_namelist_ ()
9383 static tree type = NULL_TREE;
9385 if (type == NULL_TREE)
9387 static tree namefield, varsfield, nvarsfield;
9390 vardesctype = ffecom_type_vardesc_ ();
9392 type = make_node (RECORD_TYPE);
9394 vardesctype = build_pointer_type (build_pointer_type (vardesctype));
9396 namefield = ffecom_decl_field (type, NULL_TREE, "name",
9398 varsfield = ffecom_decl_field (type, namefield, "vars", vardesctype);
9399 nvarsfield = ffecom_decl_field (type, varsfield, "nvars",
9402 TYPE_FIELDS (type) = namefield;
9405 ggc_add_tree_root (&type, 1);
9413 /* Build Vardesc type. */
9415 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9417 ffecom_type_vardesc_ ()
9419 static tree type = NULL_TREE;
9420 static tree namefield, addrfield, dimsfield, typefield;
9422 if (type == NULL_TREE)
9424 type = make_node (RECORD_TYPE);
9426 namefield = ffecom_decl_field (type, NULL_TREE, "name",
9428 addrfield = ffecom_decl_field (type, namefield, "addr",
9430 dimsfield = ffecom_decl_field (type, addrfield, "dims",
9431 ffecom_f2c_ptr_to_ftnlen_type_node);
9432 typefield = ffecom_decl_field (type, dimsfield, "type",
9435 TYPE_FIELDS (type) = namefield;
9438 ggc_add_tree_root (&type, 1);
9446 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9448 ffecom_vardesc_ (ffebld expr)
9452 assert (ffebld_op (expr) == FFEBLD_opSYMTER);
9453 s = ffebld_symter (expr);
9455 if (ffesymbol_hook (s).vardesc_tree == NULL_TREE)
9458 tree vardesctype = ffecom_type_vardesc_ ();
9466 static int mynumber = 0;
9468 var = build_decl (VAR_DECL,
9469 ffecom_get_invented_identifier ("__g77_vardesc_%d",
9472 TREE_STATIC (var) = 1;
9473 DECL_INITIAL (var) = error_mark_node;
9475 var = start_decl (var, FALSE);
9477 /* Process inits. */
9479 nameinit = ffecom_build_f2c_string_ ((i = strlen (ffesymbol_text (s)))
9481 ffesymbol_text (s));
9482 TREE_TYPE (nameinit)
9483 = build_type_variant
9486 build_range_type (integer_type_node,
9488 build_int_2 (i, 0))),
9490 TREE_CONSTANT (nameinit) = 1;
9491 TREE_STATIC (nameinit) = 1;
9492 nameinit = ffecom_1 (ADDR_EXPR,
9493 build_pointer_type (TREE_TYPE (nameinit)),
9496 addrinit = ffecom_arg_ptr_to_expr (expr, &typeinit);
9498 dimsinit = ffecom_vardesc_dims_ (s);
9500 if (typeinit == NULL_TREE)
9502 ffeinfoBasictype bt = ffesymbol_basictype (s);
9503 ffeinfoKindtype kt = ffesymbol_kindtype (s);
9504 int tc = ffecom_f2c_typecode (bt, kt);
9507 typeinit = build_int_2 (tc, (tc < 0) ? -1 : 0);
9510 typeinit = ffecom_1 (NEGATE_EXPR, TREE_TYPE (typeinit), typeinit);
9512 varinits = build_tree_list ((field = TYPE_FIELDS (vardesctype)),
9514 TREE_CHAIN (varinits) = build_tree_list ((field = TREE_CHAIN (field)),
9516 TREE_CHAIN (TREE_CHAIN (varinits))
9517 = build_tree_list ((field = TREE_CHAIN (field)), dimsinit);
9518 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (varinits)))
9519 = build_tree_list ((field = TREE_CHAIN (field)), typeinit);
9521 varinits = build (CONSTRUCTOR, vardesctype, NULL_TREE, varinits);
9522 TREE_CONSTANT (varinits) = 1;
9523 TREE_STATIC (varinits) = 1;
9525 finish_decl (var, varinits, FALSE);
9527 var = ffecom_1 (ADDR_EXPR, build_pointer_type (vardesctype), var);
9529 ffesymbol_hook (s).vardesc_tree = var;
9532 return ffesymbol_hook (s).vardesc_tree;
9536 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9538 ffecom_vardesc_array_ (ffesymbol s)
9542 tree item = NULL_TREE;
9545 static int mynumber = 0;
9547 for (i = 0, list = NULL_TREE, b = ffesymbol_namelist (s);
9549 b = ffebld_trail (b), ++i)
9553 t = ffecom_vardesc_ (ffebld_head (b));
9555 if (list == NULL_TREE)
9556 list = item = build_tree_list (NULL_TREE, t);
9559 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
9560 item = TREE_CHAIN (item);
9564 item = build_array_type (build_pointer_type (ffecom_type_vardesc_ ()),
9565 build_range_type (integer_type_node,
9567 build_int_2 (i, 0)));
9568 list = build (CONSTRUCTOR, item, NULL_TREE, list);
9569 TREE_CONSTANT (list) = 1;
9570 TREE_STATIC (list) = 1;
9572 var = ffecom_get_invented_identifier ("__g77_vardesc_array_%d", mynumber++);
9573 var = build_decl (VAR_DECL, var, item);
9574 TREE_STATIC (var) = 1;
9575 DECL_INITIAL (var) = error_mark_node;
9576 var = start_decl (var, FALSE);
9577 finish_decl (var, list, FALSE);
9583 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9585 ffecom_vardesc_dims_ (ffesymbol s)
9587 if (ffesymbol_dims (s) == NULL)
9588 return convert (ffecom_f2c_ptr_to_ftnlen_type_node,
9596 tree item = NULL_TREE;
9600 tree baseoff = NULL_TREE;
9601 static int mynumber = 0;
9603 numdim = build_int_2 ((int) ffesymbol_rank (s), 0);
9604 TREE_TYPE (numdim) = ffecom_f2c_ftnlen_type_node;
9606 numelem = ffecom_expr (ffesymbol_arraysize (s));
9607 TREE_TYPE (numelem) = ffecom_f2c_ftnlen_type_node;
9610 backlist = NULL_TREE;
9611 for (b = ffesymbol_dims (s), e = ffesymbol_extents (s);
9613 b = ffebld_trail (b), e = ffebld_trail (e))
9619 if (ffebld_trail (b) == NULL)
9623 t = convert (ffecom_f2c_ftnlen_type_node,
9624 ffecom_expr (ffebld_head (e)));
9626 if (list == NULL_TREE)
9627 list = item = build_tree_list (NULL_TREE, t);
9630 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
9631 item = TREE_CHAIN (item);
9635 if (ffebld_left (ffebld_head (b)) == NULL)
9636 low = ffecom_integer_one_node;
9638 low = ffecom_expr (ffebld_left (ffebld_head (b)));
9639 low = convert (ffecom_f2c_ftnlen_type_node, low);
9641 back = build_tree_list (low, t);
9642 TREE_CHAIN (back) = backlist;
9646 for (item = backlist; item != NULL_TREE; item = TREE_CHAIN (item))
9648 if (TREE_VALUE (item) == NULL_TREE)
9649 baseoff = TREE_PURPOSE (item);
9651 baseoff = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
9652 TREE_PURPOSE (item),
9653 ffecom_2 (MULT_EXPR,
9654 ffecom_f2c_ftnlen_type_node,
9659 /* backlist now dead, along with all TREE_PURPOSEs on it. */
9661 baseoff = build_tree_list (NULL_TREE, baseoff);
9662 TREE_CHAIN (baseoff) = list;
9664 numelem = build_tree_list (NULL_TREE, numelem);
9665 TREE_CHAIN (numelem) = baseoff;
9667 numdim = build_tree_list (NULL_TREE, numdim);
9668 TREE_CHAIN (numdim) = numelem;
9670 item = build_array_type (ffecom_f2c_ftnlen_type_node,
9671 build_range_type (integer_type_node,
9674 ((int) ffesymbol_rank (s)
9676 list = build (CONSTRUCTOR, item, NULL_TREE, numdim);
9677 TREE_CONSTANT (list) = 1;
9678 TREE_STATIC (list) = 1;
9680 var = ffecom_get_invented_identifier ("__g77_dims_%d", mynumber++);
9681 var = build_decl (VAR_DECL, var, item);
9682 TREE_STATIC (var) = 1;
9683 DECL_INITIAL (var) = error_mark_node;
9684 var = start_decl (var, FALSE);
9685 finish_decl (var, list, FALSE);
9687 var = ffecom_1 (ADDR_EXPR, build_pointer_type (item), var);
9694 /* Essentially does a "fold (build1 (code, type, node))" while checking
9695 for certain housekeeping things.
9697 NOTE: for building an ADDR_EXPR around a FUNCTION_DECL, use
9698 ffecom_1_fn instead. */
9700 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9702 ffecom_1 (enum tree_code code, tree type, tree node)
9706 if ((node == error_mark_node)
9707 || (type == error_mark_node))
9708 return error_mark_node;
9710 if (code == ADDR_EXPR)
9712 if (!mark_addressable (node))
9713 assert ("can't mark_addressable this node!" == NULL);
9716 switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
9721 item = build (COMPONENT_REF, type, node, TYPE_FIELDS (TREE_TYPE (node)));
9725 item = build (COMPONENT_REF, type, node, TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (node))));
9730 if (TREE_CODE (type) != RECORD_TYPE)
9732 item = build1 (code, type, node);
9735 node = ffecom_stabilize_aggregate_ (node);
9736 realtype = TREE_TYPE (TYPE_FIELDS (type));
9738 ffecom_2 (COMPLEX_EXPR, type,
9739 ffecom_1 (NEGATE_EXPR, realtype,
9740 ffecom_1 (REALPART_EXPR, realtype,
9742 ffecom_1 (NEGATE_EXPR, realtype,
9743 ffecom_1 (IMAGPART_EXPR, realtype,
9748 item = build1 (code, type, node);
9752 if (TREE_SIDE_EFFECTS (node))
9753 TREE_SIDE_EFFECTS (item) = 1;
9754 if ((code == ADDR_EXPR) && staticp (node))
9755 TREE_CONSTANT (item) = 1;
9760 /* Like ffecom_1 (ADDR_EXPR, TREE_TYPE (node), node), except
9761 handles TREE_CODE (node) == FUNCTION_DECL. In particular,
9762 does not set TREE_ADDRESSABLE (because calling an inline
9763 function does not mean the function needs to be separately
9766 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9768 ffecom_1_fn (tree node)
9773 if (node == error_mark_node)
9774 return error_mark_node;
9776 type = build_type_variant (TREE_TYPE (node),
9777 TREE_READONLY (node),
9778 TREE_THIS_VOLATILE (node));
9779 item = build1 (ADDR_EXPR,
9780 build_pointer_type (type), node);
9781 if (TREE_SIDE_EFFECTS (node))
9782 TREE_SIDE_EFFECTS (item) = 1;
9784 TREE_CONSTANT (item) = 1;
9789 /* Essentially does a "fold (build (code, type, node1, node2))" while
9790 checking for certain housekeeping things. */
9792 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9794 ffecom_2 (enum tree_code code, tree type, tree node1,
9799 if ((node1 == error_mark_node)
9800 || (node2 == error_mark_node)
9801 || (type == error_mark_node))
9802 return error_mark_node;
9804 switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
9806 tree a, b, c, d, realtype;
9809 assert ("no CONJ_EXPR support yet" == NULL);
9810 return error_mark_node;
9813 item = build_tree_list (TYPE_FIELDS (type), node1);
9814 TREE_CHAIN (item) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), node2);
9815 item = build (CONSTRUCTOR, type, NULL_TREE, item);
9819 if (TREE_CODE (type) != RECORD_TYPE)
9821 item = build (code, type, node1, node2);
9824 node1 = ffecom_stabilize_aggregate_ (node1);
9825 node2 = ffecom_stabilize_aggregate_ (node2);
9826 realtype = TREE_TYPE (TYPE_FIELDS (type));
9828 ffecom_2 (COMPLEX_EXPR, type,
9829 ffecom_2 (PLUS_EXPR, realtype,
9830 ffecom_1 (REALPART_EXPR, realtype,
9832 ffecom_1 (REALPART_EXPR, realtype,
9834 ffecom_2 (PLUS_EXPR, realtype,
9835 ffecom_1 (IMAGPART_EXPR, realtype,
9837 ffecom_1 (IMAGPART_EXPR, realtype,
9842 if (TREE_CODE (type) != RECORD_TYPE)
9844 item = build (code, type, node1, node2);
9847 node1 = ffecom_stabilize_aggregate_ (node1);
9848 node2 = ffecom_stabilize_aggregate_ (node2);
9849 realtype = TREE_TYPE (TYPE_FIELDS (type));
9851 ffecom_2 (COMPLEX_EXPR, type,
9852 ffecom_2 (MINUS_EXPR, realtype,
9853 ffecom_1 (REALPART_EXPR, realtype,
9855 ffecom_1 (REALPART_EXPR, realtype,
9857 ffecom_2 (MINUS_EXPR, realtype,
9858 ffecom_1 (IMAGPART_EXPR, realtype,
9860 ffecom_1 (IMAGPART_EXPR, realtype,
9865 if (TREE_CODE (type) != RECORD_TYPE)
9867 item = build (code, type, node1, node2);
9870 node1 = ffecom_stabilize_aggregate_ (node1);
9871 node2 = ffecom_stabilize_aggregate_ (node2);
9872 realtype = TREE_TYPE (TYPE_FIELDS (type));
9873 a = save_expr (ffecom_1 (REALPART_EXPR, realtype,
9875 b = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
9877 c = save_expr (ffecom_1 (REALPART_EXPR, realtype,
9879 d = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
9882 ffecom_2 (COMPLEX_EXPR, type,
9883 ffecom_2 (MINUS_EXPR, realtype,
9884 ffecom_2 (MULT_EXPR, realtype,
9887 ffecom_2 (MULT_EXPR, realtype,
9890 ffecom_2 (PLUS_EXPR, realtype,
9891 ffecom_2 (MULT_EXPR, realtype,
9894 ffecom_2 (MULT_EXPR, realtype,
9900 if ((TREE_CODE (node1) != RECORD_TYPE)
9901 && (TREE_CODE (node2) != RECORD_TYPE))
9903 item = build (code, type, node1, node2);
9906 assert (TREE_CODE (node1) == RECORD_TYPE);
9907 assert (TREE_CODE (node2) == RECORD_TYPE);
9908 node1 = ffecom_stabilize_aggregate_ (node1);
9909 node2 = ffecom_stabilize_aggregate_ (node2);
9910 realtype = TREE_TYPE (TYPE_FIELDS (type));
9912 ffecom_2 (TRUTH_ANDIF_EXPR, type,
9913 ffecom_2 (code, type,
9914 ffecom_1 (REALPART_EXPR, realtype,
9916 ffecom_1 (REALPART_EXPR, realtype,
9918 ffecom_2 (code, type,
9919 ffecom_1 (IMAGPART_EXPR, realtype,
9921 ffecom_1 (IMAGPART_EXPR, realtype,
9926 if ((TREE_CODE (node1) != RECORD_TYPE)
9927 && (TREE_CODE (node2) != RECORD_TYPE))
9929 item = build (code, type, node1, node2);
9932 assert (TREE_CODE (node1) == RECORD_TYPE);
9933 assert (TREE_CODE (node2) == RECORD_TYPE);
9934 node1 = ffecom_stabilize_aggregate_ (node1);
9935 node2 = ffecom_stabilize_aggregate_ (node2);
9936 realtype = TREE_TYPE (TYPE_FIELDS (type));
9938 ffecom_2 (TRUTH_ORIF_EXPR, type,
9939 ffecom_2 (code, type,
9940 ffecom_1 (REALPART_EXPR, realtype,
9942 ffecom_1 (REALPART_EXPR, realtype,
9944 ffecom_2 (code, type,
9945 ffecom_1 (IMAGPART_EXPR, realtype,
9947 ffecom_1 (IMAGPART_EXPR, realtype,
9952 item = build (code, type, node1, node2);
9956 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2))
9957 TREE_SIDE_EFFECTS (item) = 1;
9962 /* ffecom_2pass_advise_entrypoint -- Advise that there's this entrypoint
9964 ffesymbol s; // the ENTRY point itself
9965 if (ffecom_2pass_advise_entrypoint(s))
9966 // the ENTRY point has been accepted
9968 Does whatever compiler needs to do when it learns about the entrypoint,
9969 like determine the return type of the master function, count the
9970 number of entrypoints, etc. Returns FALSE if the return type is
9971 not compatible with the return type(s) of other entrypoint(s).
9973 NOTE: for every call to this fn that returns TRUE, _do_entrypoint must
9974 later (after _finish_progunit) be called with the same entrypoint(s)
9975 as passed to this fn for which TRUE was returned.
9978 Return FALSE if the return type conflicts with previous entrypoints. */
9980 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9982 ffecom_2pass_advise_entrypoint (ffesymbol entry)
9984 ffebld list; /* opITEM. */
9985 ffebld mlist; /* opITEM. */
9986 ffebld plist; /* opITEM. */
9987 ffebld arg; /* ffebld_head(opITEM). */
9988 ffebld item; /* opITEM. */
9989 ffesymbol s; /* ffebld_symter(arg). */
9990 ffeinfoBasictype bt = ffesymbol_basictype (entry);
9991 ffeinfoKindtype kt = ffesymbol_kindtype (entry);
9992 ffetargetCharacterSize size = ffesymbol_size (entry);
9995 if (ffecom_num_entrypoints_ == 0)
9996 { /* First entrypoint, make list of main
9997 arglist's dummies. */
9998 assert (ffecom_primary_entry_ != NULL);
10000 ffecom_master_bt_ = ffesymbol_basictype (ffecom_primary_entry_);
10001 ffecom_master_kt_ = ffesymbol_kindtype (ffecom_primary_entry_);
10002 ffecom_master_size_ = ffesymbol_size (ffecom_primary_entry_);
10004 for (plist = NULL, list = ffesymbol_dummyargs (ffecom_primary_entry_);
10006 list = ffebld_trail (list))
10008 arg = ffebld_head (list);
10009 if (ffebld_op (arg) != FFEBLD_opSYMTER)
10010 continue; /* Alternate return or some such thing. */
10011 item = ffebld_new_item (arg, NULL);
10013 ffecom_master_arglist_ = item;
10015 ffebld_set_trail (plist, item);
10020 /* If necessary, scan entry arglist for alternate returns. Do this scan
10021 apparently redundantly (it's done below to UNIONize the arglists) so
10022 that we don't complain about RETURN 1 if an offending ENTRY is the only
10023 one with an alternate return. */
10025 if (!ffecom_is_altreturning_)
10027 for (list = ffesymbol_dummyargs (entry);
10029 list = ffebld_trail (list))
10031 arg = ffebld_head (list);
10032 if (ffebld_op (arg) == FFEBLD_opSTAR)
10034 ffecom_is_altreturning_ = TRUE;
10040 /* Now check type compatibility. */
10042 switch (ffecom_master_bt_)
10044 case FFEINFO_basictypeNONE:
10045 ok = (bt != FFEINFO_basictypeCHARACTER);
10048 case FFEINFO_basictypeCHARACTER:
10050 = (bt == FFEINFO_basictypeCHARACTER)
10051 && (kt == ffecom_master_kt_)
10052 && (size == ffecom_master_size_);
10055 case FFEINFO_basictypeANY:
10056 return FALSE; /* Just don't bother. */
10059 if (bt == FFEINFO_basictypeCHARACTER)
10065 if ((bt != ffecom_master_bt_) || (kt != ffecom_master_kt_))
10067 ffecom_master_bt_ = FFEINFO_basictypeNONE;
10068 ffecom_master_kt_ = FFEINFO_kindtypeNONE;
10075 ffebad_start (FFEBAD_ENTRY_CONFLICTS);
10076 ffest_ffebad_here_current_stmt (0);
10078 return FALSE; /* Can't handle entrypoint. */
10081 /* Entrypoint type compatible with previous types. */
10083 ++ffecom_num_entrypoints_;
10085 /* Master-arg-list = UNION(Master-arg-list,entry-arg-list). */
10087 for (list = ffesymbol_dummyargs (entry);
10089 list = ffebld_trail (list))
10091 arg = ffebld_head (list);
10092 if (ffebld_op (arg) != FFEBLD_opSYMTER)
10093 continue; /* Alternate return or some such thing. */
10094 s = ffebld_symter (arg);
10095 for (plist = NULL, mlist = ffecom_master_arglist_;
10097 plist = mlist, mlist = ffebld_trail (mlist))
10098 { /* plist points to previous item for easy
10099 appending of arg. */
10100 if (ffebld_symter (ffebld_head (mlist)) == s)
10101 break; /* Already have this arg in the master list. */
10104 continue; /* Already have this arg in the master list. */
10106 /* Append this arg to the master list. */
10108 item = ffebld_new_item (arg, NULL);
10110 ffecom_master_arglist_ = item;
10112 ffebld_set_trail (plist, item);
10119 /* ffecom_2pass_do_entrypoint -- Do compilation of entrypoint
10121 ffesymbol s; // the ENTRY point itself
10122 ffecom_2pass_do_entrypoint(s);
10124 Does whatever compiler needs to do to make the entrypoint actually
10125 happen. Must be called for each entrypoint after
10126 ffecom_finish_progunit is called. */
10128 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10130 ffecom_2pass_do_entrypoint (ffesymbol entry)
10132 static int mfn_num = 0;
10133 static int ent_num;
10135 if (mfn_num != ffecom_num_fns_)
10136 { /* First entrypoint for this program unit. */
10138 mfn_num = ffecom_num_fns_;
10139 ffecom_do_entry_ (ffecom_primary_entry_, 0);
10144 --ffecom_num_entrypoints_;
10146 ffecom_do_entry_ (entry, ent_num);
10151 /* Essentially does a "fold (build (code, type, node1, node2))" while
10152 checking for certain housekeeping things. Always sets
10153 TREE_SIDE_EFFECTS. */
10155 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10157 ffecom_2s (enum tree_code code, tree type, tree node1,
10162 if ((node1 == error_mark_node)
10163 || (node2 == error_mark_node)
10164 || (type == error_mark_node))
10165 return error_mark_node;
10167 item = build (code, type, node1, node2);
10168 TREE_SIDE_EFFECTS (item) = 1;
10169 return fold (item);
10173 /* Essentially does a "fold (build (code, type, node1, node2, node3))" while
10174 checking for certain housekeeping things. */
10176 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10178 ffecom_3 (enum tree_code code, tree type, tree node1,
10179 tree node2, tree node3)
10183 if ((node1 == error_mark_node)
10184 || (node2 == error_mark_node)
10185 || (node3 == error_mark_node)
10186 || (type == error_mark_node))
10187 return error_mark_node;
10189 item = build (code, type, node1, node2, node3);
10190 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2)
10191 || (node3 != NULL_TREE && TREE_SIDE_EFFECTS (node3)))
10192 TREE_SIDE_EFFECTS (item) = 1;
10193 return fold (item);
10197 /* Essentially does a "fold (build (code, type, node1, node2, node3))" while
10198 checking for certain housekeeping things. Always sets
10199 TREE_SIDE_EFFECTS. */
10201 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10203 ffecom_3s (enum tree_code code, tree type, tree node1,
10204 tree node2, tree node3)
10208 if ((node1 == error_mark_node)
10209 || (node2 == error_mark_node)
10210 || (node3 == error_mark_node)
10211 || (type == error_mark_node))
10212 return error_mark_node;
10214 item = build (code, type, node1, node2, node3);
10215 TREE_SIDE_EFFECTS (item) = 1;
10216 return fold (item);
10221 /* ffecom_arg_expr -- Transform argument expr into gcc tree
10223 See use by ffecom_list_expr.
10225 If expression is NULL, returns an integer zero tree. If it is not
10226 a CHARACTER expression, returns whatever ffecom_expr
10227 returns and sets the length return value to NULL_TREE. Otherwise
10228 generates code to evaluate the character expression, returns the proper
10229 pointer to the result, but does NOT set the length return value to a tree
10230 that specifies the length of the result. (In other words, the length
10231 variable is always set to NULL_TREE, because a length is never passed.)
10234 Don't set returned length, since nobody needs it (yet; someday if
10235 we allow CHARACTER*(*) dummies to statement functions, we'll need
10238 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10240 ffecom_arg_expr (ffebld expr, tree *length)
10244 *length = NULL_TREE;
10247 return integer_zero_node;
10249 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10250 return ffecom_expr (expr);
10252 return ffecom_arg_ptr_to_expr (expr, &ign);
10256 /* Transform expression into constant argument-pointer-to-expression tree.
10258 If the expression can be transformed into a argument-pointer-to-expression
10259 tree that is constant, that is done, and the tree returned. Else
10260 NULL_TREE is returned.
10262 That way, a caller can attempt to provide compile-time initialization
10263 of a variable and, if that fails, *then* choose to start a new block
10264 and resort to using temporaries, as appropriate. */
10267 ffecom_arg_ptr_to_const_expr (ffebld expr, tree *length)
10270 return integer_zero_node;
10272 if (ffebld_op (expr) == FFEBLD_opANY)
10275 *length = error_mark_node;
10276 return error_mark_node;
10279 if (ffebld_arity (expr) == 0
10280 && (ffebld_op (expr) != FFEBLD_opSYMTER
10281 || ffebld_where (expr) == FFEINFO_whereCOMMON
10282 || ffebld_where (expr) == FFEINFO_whereGLOBAL
10283 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
10287 t = ffecom_arg_ptr_to_expr (expr, length);
10288 assert (TREE_CONSTANT (t));
10289 assert (! length || TREE_CONSTANT (*length));
10294 && ffebld_size (expr) != FFETARGET_charactersizeNONE)
10295 *length = build_int_2 (ffebld_size (expr), 0);
10297 *length = NULL_TREE;
10301 /* ffecom_arg_ptr_to_expr -- Transform argument expr into gcc tree
10303 See use by ffecom_list_ptr_to_expr.
10305 If expression is NULL, returns an integer zero tree. If it is not
10306 a CHARACTER expression, returns whatever ffecom_ptr_to_expr
10307 returns and sets the length return value to NULL_TREE. Otherwise
10308 generates code to evaluate the character expression, returns the proper
10309 pointer to the result, AND sets the length return value to a tree that
10310 specifies the length of the result.
10312 If the length argument is NULL, this is a slightly special
10313 case of building a FORMAT expression, that is, an expression that
10314 will be used at run time without regard to length. For the current
10315 implementation, which uses the libf2c library, this means it is nice
10316 to append a null byte to the end of the expression, where feasible,
10317 to make sure any diagnostic about the FORMAT string terminates at
10320 For now, treat %REF(char-expr) as the same as char-expr with a NULL
10321 length argument. This might even be seen as a feature, if a null
10322 byte can always be appended. */
10324 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10326 ffecom_arg_ptr_to_expr (ffebld expr, tree *length)
10330 ffecomConcatList_ catlist;
10332 if (length != NULL)
10333 *length = NULL_TREE;
10336 return integer_zero_node;
10338 switch (ffebld_op (expr))
10340 case FFEBLD_opPERCENT_VAL:
10341 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10342 return ffecom_expr (ffebld_left (expr));
10347 temp_exp = ffecom_arg_ptr_to_expr (ffebld_left (expr), &temp_length);
10348 if (temp_exp == error_mark_node)
10349 return error_mark_node;
10351 return ffecom_1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (temp_exp)),
10355 case FFEBLD_opPERCENT_REF:
10356 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10357 return ffecom_ptr_to_expr (ffebld_left (expr));
10358 if (length != NULL)
10360 ign_length = NULL_TREE;
10361 length = &ign_length;
10363 expr = ffebld_left (expr);
10366 case FFEBLD_opPERCENT_DESCR:
10367 switch (ffeinfo_basictype (ffebld_info (expr)))
10369 #ifdef PASS_HOLLERITH_BY_DESCRIPTOR
10370 case FFEINFO_basictypeHOLLERITH:
10372 case FFEINFO_basictypeCHARACTER:
10373 break; /* Passed by descriptor anyway. */
10376 item = ffecom_ptr_to_expr (expr);
10377 if (item != error_mark_node)
10378 *length = TYPE_SIZE (TREE_TYPE (TREE_TYPE (item)));
10387 #ifdef PASS_HOLLERITH_BY_DESCRIPTOR
10388 if ((ffeinfo_basictype (ffebld_info (expr)) == FFEINFO_basictypeHOLLERITH)
10389 && (length != NULL))
10390 { /* Pass Hollerith by descriptor. */
10391 ffetargetHollerith h;
10393 assert (ffebld_op (expr) == FFEBLD_opCONTER);
10394 h = ffebld_cu_val_hollerith (ffebld_constant_union
10395 (ffebld_conter (expr)));
10397 = build_int_2 (h.length, 0);
10398 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
10402 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10403 return ffecom_ptr_to_expr (expr);
10405 assert (ffeinfo_kindtype (ffebld_info (expr))
10406 == FFEINFO_kindtypeCHARACTER1);
10408 while (ffebld_op (expr) == FFEBLD_opPAREN)
10409 expr = ffebld_left (expr);
10411 catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
10412 switch (ffecom_concat_list_count_ (catlist))
10414 case 0: /* Shouldn't happen, but in case it does... */
10415 if (length != NULL)
10417 *length = ffecom_f2c_ftnlen_zero_node;
10418 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
10420 ffecom_concat_list_kill_ (catlist);
10421 return null_pointer_node;
10423 case 1: /* The (fairly) easy case. */
10424 if (length == NULL)
10425 ffecom_char_args_with_null_ (&item, &ign_length,
10426 ffecom_concat_list_expr_ (catlist, 0));
10428 ffecom_char_args_ (&item, length,
10429 ffecom_concat_list_expr_ (catlist, 0));
10430 ffecom_concat_list_kill_ (catlist);
10431 assert (item != NULL_TREE);
10434 default: /* Must actually concatenate things. */
10439 int count = ffecom_concat_list_count_ (catlist);
10450 ffetargetCharacterSize sz;
10452 sz = ffecom_concat_list_maxlen_ (catlist);
10454 assert (sz != FFETARGET_charactersizeNONE);
10459 = ffecom_push_tempvar (ffecom_f2c_ftnlen_type_node,
10460 FFETARGET_charactersizeNONE, count, TRUE);
10463 = ffecom_push_tempvar (ffecom_f2c_address_type_node,
10464 FFETARGET_charactersizeNONE, count, TRUE);
10465 temporary = ffecom_push_tempvar (char_type_node,
10471 hook = ffebld_nonter_hook (expr);
10473 assert (TREE_CODE (hook) == TREE_VEC);
10474 assert (TREE_VEC_LENGTH (hook) == 3);
10475 length_array = lengths = TREE_VEC_ELT (hook, 0);
10476 item_array = items = TREE_VEC_ELT (hook, 1);
10477 temporary = TREE_VEC_ELT (hook, 2);
10481 known_length = ffecom_f2c_ftnlen_zero_node;
10483 for (i = 0; i < count; ++i)
10486 && (length == NULL))
10487 ffecom_char_args_with_null_ (&citem, &clength,
10488 ffecom_concat_list_expr_ (catlist, i));
10490 ffecom_char_args_ (&citem, &clength,
10491 ffecom_concat_list_expr_ (catlist, i));
10492 if ((citem == error_mark_node)
10493 || (clength == error_mark_node))
10495 ffecom_concat_list_kill_ (catlist);
10496 *length = error_mark_node;
10497 return error_mark_node;
10501 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
10502 ffecom_modify (void_type_node,
10503 ffecom_2 (ARRAY_REF,
10504 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
10506 build_int_2 (i, 0)),
10509 clength = ffecom_save_tree (clength);
10510 if (length != NULL)
10512 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
10516 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
10517 ffecom_modify (void_type_node,
10518 ffecom_2 (ARRAY_REF,
10519 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
10521 build_int_2 (i, 0)),
10526 temporary = ffecom_1 (ADDR_EXPR,
10527 build_pointer_type (TREE_TYPE (temporary)),
10530 item = build_tree_list (NULL_TREE, temporary);
10532 = build_tree_list (NULL_TREE,
10533 ffecom_1 (ADDR_EXPR,
10534 build_pointer_type (TREE_TYPE (items)),
10536 TREE_CHAIN (TREE_CHAIN (item))
10537 = build_tree_list (NULL_TREE,
10538 ffecom_1 (ADDR_EXPR,
10539 build_pointer_type (TREE_TYPE (lengths)),
10541 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
10544 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
10545 convert (ffecom_f2c_ftnlen_type_node,
10546 build_int_2 (count, 0))));
10547 num = build_int_2 (sz, 0);
10548 TREE_TYPE (num) = ffecom_f2c_ftnlen_type_node;
10549 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item))))
10550 = build_tree_list (NULL_TREE, num);
10552 item = ffecom_call_gfrt (FFECOM_gfrtCAT, item, NULL_TREE);
10553 TREE_SIDE_EFFECTS (item) = 1;
10554 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (temporary),
10558 if (length != NULL)
10559 *length = known_length;
10562 ffecom_concat_list_kill_ (catlist);
10563 assert (item != NULL_TREE);
10568 /* Generate call to run-time function.
10570 The first arg is the GNU Fortran Run-Time function index, the second
10571 arg is the list of arguments to pass to it. Returned is the expression
10572 (WITHOUT TREE_SIDE_EFFECTS set!) that makes the call and returns the
10573 result (which may be void). */
10575 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10577 ffecom_call_gfrt (ffecomGfrt ix, tree args, tree hook)
10579 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
10580 ffecom_gfrt_kindtype (ix),
10581 ffe_is_f2c_library () && ffecom_gfrt_complex_[ix],
10582 NULL_TREE, args, NULL_TREE, NULL,
10583 NULL, NULL_TREE, TRUE, hook);
10587 /* Transform constant-union to tree. */
10589 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10591 ffecom_constantunion (ffebldConstantUnion *cu, ffeinfoBasictype bt,
10592 ffeinfoKindtype kt, tree tree_type)
10598 case FFEINFO_basictypeINTEGER:
10604 #if FFETARGET_okINTEGER1
10605 case FFEINFO_kindtypeINTEGER1:
10606 val = ffebld_cu_val_integer1 (*cu);
10610 #if FFETARGET_okINTEGER2
10611 case FFEINFO_kindtypeINTEGER2:
10612 val = ffebld_cu_val_integer2 (*cu);
10616 #if FFETARGET_okINTEGER3
10617 case FFEINFO_kindtypeINTEGER3:
10618 val = ffebld_cu_val_integer3 (*cu);
10622 #if FFETARGET_okINTEGER4
10623 case FFEINFO_kindtypeINTEGER4:
10624 val = ffebld_cu_val_integer4 (*cu);
10629 assert ("bad INTEGER constant kind type" == NULL);
10630 /* Fall through. */
10631 case FFEINFO_kindtypeANY:
10632 return error_mark_node;
10634 item = build_int_2 (val, (val < 0) ? -1 : 0);
10635 TREE_TYPE (item) = tree_type;
10639 case FFEINFO_basictypeLOGICAL:
10645 #if FFETARGET_okLOGICAL1
10646 case FFEINFO_kindtypeLOGICAL1:
10647 val = ffebld_cu_val_logical1 (*cu);
10651 #if FFETARGET_okLOGICAL2
10652 case FFEINFO_kindtypeLOGICAL2:
10653 val = ffebld_cu_val_logical2 (*cu);
10657 #if FFETARGET_okLOGICAL3
10658 case FFEINFO_kindtypeLOGICAL3:
10659 val = ffebld_cu_val_logical3 (*cu);
10663 #if FFETARGET_okLOGICAL4
10664 case FFEINFO_kindtypeLOGICAL4:
10665 val = ffebld_cu_val_logical4 (*cu);
10670 assert ("bad LOGICAL constant kind type" == NULL);
10671 /* Fall through. */
10672 case FFEINFO_kindtypeANY:
10673 return error_mark_node;
10675 item = build_int_2 (val, (val < 0) ? -1 : 0);
10676 TREE_TYPE (item) = tree_type;
10680 case FFEINFO_basictypeREAL:
10682 REAL_VALUE_TYPE val;
10686 #if FFETARGET_okREAL1
10687 case FFEINFO_kindtypeREAL1:
10688 val = ffetarget_value_real1 (ffebld_cu_val_real1 (*cu));
10692 #if FFETARGET_okREAL2
10693 case FFEINFO_kindtypeREAL2:
10694 val = ffetarget_value_real2 (ffebld_cu_val_real2 (*cu));
10698 #if FFETARGET_okREAL3
10699 case FFEINFO_kindtypeREAL3:
10700 val = ffetarget_value_real3 (ffebld_cu_val_real3 (*cu));
10704 #if FFETARGET_okREAL4
10705 case FFEINFO_kindtypeREAL4:
10706 val = ffetarget_value_real4 (ffebld_cu_val_real4 (*cu));
10711 assert ("bad REAL constant kind type" == NULL);
10712 /* Fall through. */
10713 case FFEINFO_kindtypeANY:
10714 return error_mark_node;
10716 item = build_real (tree_type, val);
10720 case FFEINFO_basictypeCOMPLEX:
10722 REAL_VALUE_TYPE real;
10723 REAL_VALUE_TYPE imag;
10724 tree el_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
10728 #if FFETARGET_okCOMPLEX1
10729 case FFEINFO_kindtypeREAL1:
10730 real = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).real);
10731 imag = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).imaginary);
10735 #if FFETARGET_okCOMPLEX2
10736 case FFEINFO_kindtypeREAL2:
10737 real = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).real);
10738 imag = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).imaginary);
10742 #if FFETARGET_okCOMPLEX3
10743 case FFEINFO_kindtypeREAL3:
10744 real = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).real);
10745 imag = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).imaginary);
10749 #if FFETARGET_okCOMPLEX4
10750 case FFEINFO_kindtypeREAL4:
10751 real = ffetarget_value_real4 (ffebld_cu_val_complex4 (*cu).real);
10752 imag = ffetarget_value_real4 (ffebld_cu_val_complex4 (*cu).imaginary);
10757 assert ("bad REAL constant kind type" == NULL);
10758 /* Fall through. */
10759 case FFEINFO_kindtypeANY:
10760 return error_mark_node;
10762 item = ffecom_build_complex_constant_ (tree_type,
10763 build_real (el_type, real),
10764 build_real (el_type, imag));
10768 case FFEINFO_basictypeCHARACTER:
10769 { /* Happens only in DATA and similar contexts. */
10770 ffetargetCharacter1 val;
10774 #if FFETARGET_okCHARACTER1
10775 case FFEINFO_kindtypeLOGICAL1:
10776 val = ffebld_cu_val_character1 (*cu);
10781 assert ("bad CHARACTER constant kind type" == NULL);
10782 /* Fall through. */
10783 case FFEINFO_kindtypeANY:
10784 return error_mark_node;
10786 item = build_string (ffetarget_length_character1 (val),
10787 ffetarget_text_character1 (val));
10789 = build_type_variant (build_array_type (char_type_node,
10791 (integer_type_node,
10794 (ffetarget_length_character1
10800 case FFEINFO_basictypeHOLLERITH:
10802 ffetargetHollerith h;
10804 h = ffebld_cu_val_hollerith (*cu);
10806 /* If not at least as wide as default INTEGER, widen it. */
10807 if (h.length >= FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE)
10808 item = build_string (h.length, h.text);
10811 char str[FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE];
10813 memcpy (str, h.text, h.length);
10814 memset (&str[h.length], ' ',
10815 FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE
10817 item = build_string (FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE,
10821 = build_type_variant (build_array_type (char_type_node,
10823 (integer_type_node,
10831 case FFEINFO_basictypeTYPELESS:
10833 ffetargetInteger1 ival;
10834 ffetargetTypeless tless;
10837 tless = ffebld_cu_val_typeless (*cu);
10838 error = ffetarget_convert_integer1_typeless (&ival, tless);
10839 assert (error == FFEBAD);
10841 item = build_int_2 ((int) ival, 0);
10846 assert ("not yet on constant type" == NULL);
10847 /* Fall through. */
10848 case FFEINFO_basictypeANY:
10849 return error_mark_node;
10852 TREE_CONSTANT (item) = 1;
10859 /* Transform expression into constant tree.
10861 If the expression can be transformed into a tree that is constant,
10862 that is done, and the tree returned. Else NULL_TREE is returned.
10864 That way, a caller can attempt to provide compile-time initialization
10865 of a variable and, if that fails, *then* choose to start a new block
10866 and resort to using temporaries, as appropriate. */
10869 ffecom_const_expr (ffebld expr)
10872 return integer_zero_node;
10874 if (ffebld_op (expr) == FFEBLD_opANY)
10875 return error_mark_node;
10877 if (ffebld_arity (expr) == 0
10878 && (ffebld_op (expr) != FFEBLD_opSYMTER
10880 /* ~~Enable once common/equivalence is handled properly? */
10881 || ffebld_where (expr) == FFEINFO_whereCOMMON
10883 || ffebld_where (expr) == FFEINFO_whereGLOBAL
10884 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
10888 t = ffecom_expr (expr);
10889 assert (TREE_CONSTANT (t));
10896 /* Handy way to make a field in a struct/union. */
10898 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10900 ffecom_decl_field (tree context, tree prevfield,
10901 const char *name, tree type)
10905 field = build_decl (FIELD_DECL, get_identifier (name), type);
10906 DECL_CONTEXT (field) = context;
10907 DECL_ALIGN (field) = 0;
10908 DECL_USER_ALIGN (field) = 0;
10909 if (prevfield != NULL_TREE)
10910 TREE_CHAIN (prevfield) = field;
10918 ffecom_close_include (FILE *f)
10920 #if FFECOM_GCC_INCLUDE
10921 ffecom_close_include_ (f);
10926 ffecom_decode_include_option (char *spec)
10928 #if FFECOM_GCC_INCLUDE
10929 return ffecom_decode_include_option_ (spec);
10935 /* End a compound statement (block). */
10937 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10939 ffecom_end_compstmt (void)
10941 return bison_rule_compstmt_ ();
10943 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
10945 /* ffecom_end_transition -- Perform end transition on all symbols
10947 ffecom_end_transition();
10949 Calls ffecom_sym_end_transition for each global and local symbol. */
10952 ffecom_end_transition ()
10954 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10958 if (ffe_is_ffedebug ())
10959 fprintf (dmpout, "; end_stmt_transition\n");
10961 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10962 ffecom_list_blockdata_ = NULL;
10963 ffecom_list_common_ = NULL;
10966 ffesymbol_drive (ffecom_sym_end_transition);
10967 if (ffe_is_ffedebug ())
10969 ffestorag_report ();
10970 #if FFECOM_targetCURRENT == FFECOM_targetFFE
10971 ffesymbol_report_all ();
10975 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10976 ffecom_start_progunit_ ();
10978 for (item = ffecom_list_blockdata_;
10980 item = ffebld_trail (item))
10987 static int number = 0;
10989 callee = ffebld_head (item);
10990 s = ffebld_symter (callee);
10991 t = ffesymbol_hook (s).decl_tree;
10992 if (t == NULL_TREE)
10994 s = ffecom_sym_transform_ (s);
10995 t = ffesymbol_hook (s).decl_tree;
10998 dt = build_pointer_type (TREE_TYPE (t));
11000 var = build_decl (VAR_DECL,
11001 ffecom_get_invented_identifier ("__g77_forceload_%d",
11004 DECL_EXTERNAL (var) = 0;
11005 TREE_STATIC (var) = 1;
11006 TREE_PUBLIC (var) = 0;
11007 DECL_INITIAL (var) = error_mark_node;
11008 TREE_USED (var) = 1;
11010 var = start_decl (var, FALSE);
11012 t = ffecom_1 (ADDR_EXPR, dt, t);
11014 finish_decl (var, t, FALSE);
11017 /* This handles any COMMON areas that weren't referenced but have, for
11018 example, important initial data. */
11020 for (item = ffecom_list_common_;
11022 item = ffebld_trail (item))
11023 ffecom_transform_common_ (ffebld_symter (ffebld_head (item)));
11025 ffecom_list_common_ = NULL;
11029 /* ffecom_exec_transition -- Perform exec transition on all symbols
11031 ffecom_exec_transition();
11033 Calls ffecom_sym_exec_transition for each global and local symbol.
11034 Make sure error updating not inhibited. */
11037 ffecom_exec_transition ()
11041 if (ffe_is_ffedebug ())
11042 fprintf (dmpout, "; exec_stmt_transition\n");
11044 inhibited = ffebad_inhibit ();
11045 ffebad_set_inhibit (FALSE);
11047 ffesymbol_drive (ffecom_sym_exec_transition); /* Don't retract! */
11048 ffeequiv_exec_transition (); /* Handle all pending EQUIVALENCEs. */
11049 if (ffe_is_ffedebug ())
11051 ffestorag_report ();
11052 #if FFECOM_targetCURRENT == FFECOM_targetFFE
11053 ffesymbol_report_all ();
11058 ffebad_set_inhibit (TRUE);
11061 /* Handle assignment statement.
11063 Convert dest and source using ffecom_expr, then join them
11064 with an ASSIGN op and pass the whole thing to expand_expr_stmt. */
11066 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11068 ffecom_expand_let_stmt (ffebld dest, ffebld source)
11075 if (ffeinfo_basictype (ffebld_info (dest)) != FFEINFO_basictypeCHARACTER)
11080 /* This attempts to replicate the test below, but must not be
11081 true when the test below is false. (Always err on the side
11082 of creating unused temporaries, to avoid ICEs.) */
11083 if (ffebld_op (dest) != FFEBLD_opSYMTER
11084 || ((dest_tree = ffesymbol_hook (ffebld_symter (dest)).decl_tree)
11085 && (TREE_CODE (dest_tree) != VAR_DECL
11086 || TREE_ADDRESSABLE (dest_tree))))
11088 ffecom_prepare_expr_ (source, dest);
11093 ffecom_prepare_expr_ (source, NULL);
11097 ffecom_prepare_expr_w (NULL_TREE, dest);
11099 /* For COMPLEX assignment like C1=C2, if partial overlap is possible,
11100 create a temporary through which the assignment is to take place,
11101 since MODIFY_EXPR doesn't handle partial overlap properly. */
11102 if (ffebld_basictype (dest) == FFEINFO_basictypeCOMPLEX
11103 && ffecom_possible_partial_overlap_ (dest, source))
11105 assign_temp = ffecom_make_tempvar ("complex_let",
11107 [ffebld_basictype (dest)]
11108 [ffebld_kindtype (dest)],
11109 FFETARGET_charactersizeNONE,
11113 assign_temp = NULL_TREE;
11115 ffecom_prepare_end ();
11117 dest_tree = ffecom_expr_w (NULL_TREE, dest);
11118 if (dest_tree == error_mark_node)
11121 if ((TREE_CODE (dest_tree) != VAR_DECL)
11122 || TREE_ADDRESSABLE (dest_tree))
11123 source_tree = ffecom_expr_ (source, dest_tree, dest, &dest_used,
11127 assert (! dest_used);
11129 source_tree = ffecom_expr (source);
11131 if (source_tree == error_mark_node)
11135 expr_tree = source_tree;
11136 else if (assign_temp)
11139 /* The back end understands a conceptual move (evaluate source;
11140 store into dest), so use that, in case it can determine
11141 that it is going to use, say, two registers as temporaries
11142 anyway. So don't use the temp (and someday avoid generating
11143 it, once this code starts triggering regularly). */
11144 expr_tree = ffecom_2s (MOVE_EXPR, void_type_node,
11148 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11151 expand_expr_stmt (expr_tree);
11152 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11158 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11162 expand_expr_stmt (expr_tree);
11166 ffecom_prepare_let_char_ (ffebld_size_known (dest), source);
11167 ffecom_prepare_expr_w (NULL_TREE, dest);
11169 ffecom_prepare_end ();
11171 ffecom_char_args_ (&dest_tree, &dest_length, dest);
11172 ffecom_let_char_ (dest_tree, dest_length, ffebld_size_known (dest),
11177 /* ffecom_expr -- Transform expr into gcc tree
11180 ffebld expr; // FFE expression.
11181 tree = ffecom_expr(expr);
11183 Recursive descent on expr while making corresponding tree nodes and
11184 attaching type info and such. */
11186 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11188 ffecom_expr (ffebld expr)
11190 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, FALSE, FALSE);
11194 /* Like ffecom_expr, but return tree usable for assigned GOTO or FORMAT. */
11196 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11198 ffecom_expr_assign (ffebld expr)
11200 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE);
11204 /* Like ffecom_expr_rw, but return tree usable for ASSIGN. */
11206 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11208 ffecom_expr_assign_w (ffebld expr)
11210 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE);
11214 /* Transform expr for use as into read/write tree and stabilize the
11215 reference. Not for use on CHARACTER expressions.
11217 Recursive descent on expr while making corresponding tree nodes and
11218 attaching type info and such. */
11220 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11222 ffecom_expr_rw (tree type, ffebld expr)
11224 assert (expr != NULL);
11225 /* Different target types not yet supported. */
11226 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
11228 return stabilize_reference (ffecom_expr (expr));
11232 /* Transform expr for use as into write tree and stabilize the
11233 reference. Not for use on CHARACTER expressions.
11235 Recursive descent on expr while making corresponding tree nodes and
11236 attaching type info and such. */
11238 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11240 ffecom_expr_w (tree type, ffebld expr)
11242 assert (expr != NULL);
11243 /* Different target types not yet supported. */
11244 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
11246 return stabilize_reference (ffecom_expr (expr));
11250 /* Do global stuff. */
11252 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11254 ffecom_finish_compile ()
11256 assert (ffecom_outer_function_decl_ == NULL_TREE);
11257 assert (current_function_decl == NULL_TREE);
11259 ffeglobal_drive (ffecom_finish_global_);
11263 /* Public entry point for front end to access finish_decl. */
11265 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11267 ffecom_finish_decl (tree decl, tree init, bool is_top_level)
11269 assert (!is_top_level);
11270 finish_decl (decl, init, FALSE);
11274 /* Finish a program unit. */
11276 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11278 ffecom_finish_progunit ()
11280 ffecom_end_compstmt ();
11282 ffecom_previous_function_decl_ = current_function_decl;
11283 ffecom_which_entrypoint_decl_ = NULL_TREE;
11285 finish_function (0);
11290 /* Wrapper for get_identifier. pattern is sprintf-like. */
11292 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11294 ffecom_get_invented_identifier (const char *pattern, ...)
11300 va_start (ap, pattern);
11301 if (vasprintf (&nam, pattern, ap) == 0)
11304 decl = get_identifier (nam);
11306 IDENTIFIER_INVENTED (decl) = 1;
11311 ffecom_gfrt_basictype (ffecomGfrt gfrt)
11313 assert (gfrt < FFECOM_gfrt);
11315 switch (ffecom_gfrt_type_[gfrt])
11317 case FFECOM_rttypeVOID_:
11318 case FFECOM_rttypeVOIDSTAR_:
11319 return FFEINFO_basictypeNONE;
11321 case FFECOM_rttypeFTNINT_:
11322 return FFEINFO_basictypeINTEGER;
11324 case FFECOM_rttypeINTEGER_:
11325 return FFEINFO_basictypeINTEGER;
11327 case FFECOM_rttypeLONGINT_:
11328 return FFEINFO_basictypeINTEGER;
11330 case FFECOM_rttypeLOGICAL_:
11331 return FFEINFO_basictypeLOGICAL;
11333 case FFECOM_rttypeREAL_F2C_:
11334 case FFECOM_rttypeREAL_GNU_:
11335 return FFEINFO_basictypeREAL;
11337 case FFECOM_rttypeCOMPLEX_F2C_:
11338 case FFECOM_rttypeCOMPLEX_GNU_:
11339 return FFEINFO_basictypeCOMPLEX;
11341 case FFECOM_rttypeDOUBLE_:
11342 case FFECOM_rttypeDOUBLEREAL_:
11343 return FFEINFO_basictypeREAL;
11345 case FFECOM_rttypeDBLCMPLX_F2C_:
11346 case FFECOM_rttypeDBLCMPLX_GNU_:
11347 return FFEINFO_basictypeCOMPLEX;
11349 case FFECOM_rttypeCHARACTER_:
11350 return FFEINFO_basictypeCHARACTER;
11353 return FFEINFO_basictypeANY;
11358 ffecom_gfrt_kindtype (ffecomGfrt gfrt)
11360 assert (gfrt < FFECOM_gfrt);
11362 switch (ffecom_gfrt_type_[gfrt])
11364 case FFECOM_rttypeVOID_:
11365 case FFECOM_rttypeVOIDSTAR_:
11366 return FFEINFO_kindtypeNONE;
11368 case FFECOM_rttypeFTNINT_:
11369 return FFEINFO_kindtypeINTEGER1;
11371 case FFECOM_rttypeINTEGER_:
11372 return FFEINFO_kindtypeINTEGER1;
11374 case FFECOM_rttypeLONGINT_:
11375 return FFEINFO_kindtypeINTEGER4;
11377 case FFECOM_rttypeLOGICAL_:
11378 return FFEINFO_kindtypeLOGICAL1;
11380 case FFECOM_rttypeREAL_F2C_:
11381 case FFECOM_rttypeREAL_GNU_:
11382 return FFEINFO_kindtypeREAL1;
11384 case FFECOM_rttypeCOMPLEX_F2C_:
11385 case FFECOM_rttypeCOMPLEX_GNU_:
11386 return FFEINFO_kindtypeREAL1;
11388 case FFECOM_rttypeDOUBLE_:
11389 case FFECOM_rttypeDOUBLEREAL_:
11390 return FFEINFO_kindtypeREAL2;
11392 case FFECOM_rttypeDBLCMPLX_F2C_:
11393 case FFECOM_rttypeDBLCMPLX_GNU_:
11394 return FFEINFO_kindtypeREAL2;
11396 case FFECOM_rttypeCHARACTER_:
11397 return FFEINFO_kindtypeCHARACTER1;
11400 return FFEINFO_kindtypeANY;
11414 tree double_ftype_double;
11415 tree float_ftype_float;
11416 tree ldouble_ftype_ldouble;
11417 tree ffecom_tree_ptr_to_fun_type_void;
11419 /* This block of code comes from the now-obsolete cktyps.c. It checks
11420 whether the compiler environment is buggy in known ways, some of which
11421 would, if not explicitly checked here, result in subtle bugs in g77. */
11423 if (ffe_is_do_internal_checks ())
11425 static char names[][12]
11427 {"bar", "bletch", "foo", "foobar"};
11432 name = bsearch ("foo", &names[0], ARRAY_SIZE (names), sizeof (names[0]),
11433 (int (*)(const void *, const void *)) strcmp);
11434 if (name != (char *) &names[2])
11436 assert ("bsearch doesn't work, #define FFEPROJ_BSEARCH 0 in proj.h"
11441 ul = strtoul ("123456789", NULL, 10);
11442 if (ul != 123456789L)
11444 assert ("strtoul doesn't have enough range, #define FFEPROJ_STRTOUL 0\
11445 in proj.h" == NULL);
11449 fl = atof ("56.789");
11450 if ((fl < 56.788) || (fl > 56.79))
11452 assert ("atof not type double, fix your #include <stdio.h>"
11458 #if FFECOM_GCC_INCLUDE
11459 ffecom_initialize_char_syntax_ ();
11462 ffecom_outer_function_decl_ = NULL_TREE;
11463 current_function_decl = NULL_TREE;
11464 named_labels = NULL_TREE;
11465 current_binding_level = NULL_BINDING_LEVEL;
11466 free_binding_level = NULL_BINDING_LEVEL;
11467 /* Make the binding_level structure for global names. */
11469 global_binding_level = current_binding_level;
11470 current_binding_level->prep_state = 2;
11472 build_common_tree_nodes (1);
11474 /* Define `int' and `char' first so that dbx will output them first. */
11475 pushdecl (build_decl (TYPE_DECL, get_identifier ("int"),
11476 integer_type_node));
11477 pushdecl (build_decl (TYPE_DECL, get_identifier ("char"),
11479 pushdecl (build_decl (TYPE_DECL, get_identifier ("long int"),
11480 long_integer_type_node));
11481 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned int"),
11482 unsigned_type_node));
11483 pushdecl (build_decl (TYPE_DECL, get_identifier ("long unsigned int"),
11484 long_unsigned_type_node));
11485 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long int"),
11486 long_long_integer_type_node));
11487 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long unsigned int"),
11488 long_long_unsigned_type_node));
11489 pushdecl (build_decl (TYPE_DECL, get_identifier ("short int"),
11490 short_integer_type_node));
11491 pushdecl (build_decl (TYPE_DECL, get_identifier ("short unsigned int"),
11492 short_unsigned_type_node));
11494 /* Set the sizetype before we make other types. This *should* be the
11495 first type we create. */
11498 (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE))));
11499 ffecom_typesize_pointer_
11500 = TREE_INT_CST_LOW (TYPE_SIZE (sizetype)) / BITS_PER_UNIT;
11502 build_common_tree_nodes_2 (0);
11504 /* Define both `signed char' and `unsigned char'. */
11505 pushdecl (build_decl (TYPE_DECL, get_identifier ("signed char"),
11506 signed_char_type_node));
11508 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned char"),
11509 unsigned_char_type_node));
11511 pushdecl (build_decl (TYPE_DECL, get_identifier ("float"),
11513 pushdecl (build_decl (TYPE_DECL, get_identifier ("double"),
11514 double_type_node));
11515 pushdecl (build_decl (TYPE_DECL, get_identifier ("long double"),
11516 long_double_type_node));
11518 /* For now, override what build_common_tree_nodes has done. */
11519 complex_integer_type_node = ffecom_make_complex_type_ (integer_type_node);
11520 complex_float_type_node = ffecom_make_complex_type_ (float_type_node);
11521 complex_double_type_node = ffecom_make_complex_type_ (double_type_node);
11522 complex_long_double_type_node
11523 = ffecom_make_complex_type_ (long_double_type_node);
11525 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex int"),
11526 complex_integer_type_node));
11527 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex float"),
11528 complex_float_type_node));
11529 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex double"),
11530 complex_double_type_node));
11531 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex long double"),
11532 complex_long_double_type_node));
11534 pushdecl (build_decl (TYPE_DECL, get_identifier ("void"),
11536 /* We are not going to have real types in C with less than byte alignment,
11537 so we might as well not have any types that claim to have it. */
11538 TYPE_ALIGN (void_type_node) = BITS_PER_UNIT;
11539 TYPE_USER_ALIGN (void_type_node) = 0;
11541 string_type_node = build_pointer_type (char_type_node);
11543 ffecom_tree_fun_type_void
11544 = build_function_type (void_type_node, NULL_TREE);
11546 ffecom_tree_ptr_to_fun_type_void
11547 = build_pointer_type (ffecom_tree_fun_type_void);
11549 endlink = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
11552 = build_function_type (float_type_node,
11553 tree_cons (NULL_TREE, float_type_node, endlink));
11555 double_ftype_double
11556 = build_function_type (double_type_node,
11557 tree_cons (NULL_TREE, double_type_node, endlink));
11559 ldouble_ftype_ldouble
11560 = build_function_type (long_double_type_node,
11561 tree_cons (NULL_TREE, long_double_type_node,
11564 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11565 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11567 ffecom_tree_type[i][j] = NULL_TREE;
11568 ffecom_tree_fun_type[i][j] = NULL_TREE;
11569 ffecom_tree_ptr_to_fun_type[i][j] = NULL_TREE;
11570 ffecom_f2c_typecode_[i][j] = -1;
11573 /* Set up standard g77 types. Note that INTEGER and LOGICAL are set
11574 to size FLOAT_TYPE_SIZE because they have to be the same size as
11575 REAL, which also is FLOAT_TYPE_SIZE, according to the standard.
11576 Compiler options and other such stuff that change the ways these
11577 types are set should not affect this particular setup. */
11579 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1]
11580 = t = make_signed_type (FLOAT_TYPE_SIZE);
11581 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer"),
11583 type = ffetype_new ();
11585 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER1,
11587 ffetype_set_ams (type,
11588 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11589 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11590 ffetype_set_star (base_type,
11591 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11593 ffetype_set_kind (base_type, 1, type);
11594 ffecom_typesize_integer1_ = ffetype_size (type);
11595 assert (ffetype_size (type) == sizeof (ffetargetInteger1));
11597 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER1]
11598 = t = make_unsigned_type (FLOAT_TYPE_SIZE); /* HOLLERITH means unsigned. */
11599 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned"),
11602 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER2]
11603 = t = make_signed_type (CHAR_TYPE_SIZE);
11604 pushdecl (build_decl (TYPE_DECL, get_identifier ("byte"),
11606 type = ffetype_new ();
11607 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER2,
11609 ffetype_set_ams (type,
11610 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11611 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11612 ffetype_set_star (base_type,
11613 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11615 ffetype_set_kind (base_type, 3, type);
11616 assert (ffetype_size (type) == sizeof (ffetargetInteger2));
11618 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER2]
11619 = t = make_unsigned_type (CHAR_TYPE_SIZE);
11620 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned byte"),
11623 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER3]
11624 = t = make_signed_type (CHAR_TYPE_SIZE * 2);
11625 pushdecl (build_decl (TYPE_DECL, get_identifier ("word"),
11627 type = ffetype_new ();
11628 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER3,
11630 ffetype_set_ams (type,
11631 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11632 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11633 ffetype_set_star (base_type,
11634 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11636 ffetype_set_kind (base_type, 6, type);
11637 assert (ffetype_size (type) == sizeof (ffetargetInteger3));
11639 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER3]
11640 = t = make_unsigned_type (CHAR_TYPE_SIZE * 2);
11641 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned word"),
11644 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER4]
11645 = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
11646 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer4"),
11648 type = ffetype_new ();
11649 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER4,
11651 ffetype_set_ams (type,
11652 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11653 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11654 ffetype_set_star (base_type,
11655 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11657 ffetype_set_kind (base_type, 2, type);
11658 assert (ffetype_size (type) == sizeof (ffetargetInteger4));
11660 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER4]
11661 = t = make_unsigned_type (FLOAT_TYPE_SIZE * 2);
11662 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned4"),
11666 if (ffe_is_do_internal_checks ()
11667 && LONG_TYPE_SIZE != FLOAT_TYPE_SIZE
11668 && LONG_TYPE_SIZE != CHAR_TYPE_SIZE
11669 && LONG_TYPE_SIZE != SHORT_TYPE_SIZE
11670 && LONG_TYPE_SIZE != LONG_LONG_TYPE_SIZE)
11672 fprintf (stderr, "Sorry, no g77 support for LONG_TYPE_SIZE (%d bits) yet.\n",
11677 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL1]
11678 = t = make_signed_type (FLOAT_TYPE_SIZE);
11679 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical"),
11681 type = ffetype_new ();
11683 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL1,
11685 ffetype_set_ams (type,
11686 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11687 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11688 ffetype_set_star (base_type,
11689 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11691 ffetype_set_kind (base_type, 1, type);
11692 assert (ffetype_size (type) == sizeof (ffetargetLogical1));
11694 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL2]
11695 = t = make_signed_type (CHAR_TYPE_SIZE);
11696 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical2"),
11698 type = ffetype_new ();
11699 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL2,
11701 ffetype_set_ams (type,
11702 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11703 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11704 ffetype_set_star (base_type,
11705 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11707 ffetype_set_kind (base_type, 3, type);
11708 assert (ffetype_size (type) == sizeof (ffetargetLogical2));
11710 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL3]
11711 = t = make_signed_type (CHAR_TYPE_SIZE * 2);
11712 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical3"),
11714 type = ffetype_new ();
11715 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL3,
11717 ffetype_set_ams (type,
11718 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11719 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11720 ffetype_set_star (base_type,
11721 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11723 ffetype_set_kind (base_type, 6, type);
11724 assert (ffetype_size (type) == sizeof (ffetargetLogical3));
11726 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL4]
11727 = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
11728 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical4"),
11730 type = ffetype_new ();
11731 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL4,
11733 ffetype_set_ams (type,
11734 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11735 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11736 ffetype_set_star (base_type,
11737 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11739 ffetype_set_kind (base_type, 2, type);
11740 assert (ffetype_size (type) == sizeof (ffetargetLogical4));
11742 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
11743 = t = make_node (REAL_TYPE);
11744 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE;
11745 pushdecl (build_decl (TYPE_DECL, get_identifier ("real"),
11748 type = ffetype_new ();
11750 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREAL1,
11752 ffetype_set_ams (type,
11753 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11754 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11755 ffetype_set_star (base_type,
11756 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11758 ffetype_set_kind (base_type, 1, type);
11759 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
11760 = FFETARGET_f2cTYREAL;
11761 assert (ffetype_size (type) == sizeof (ffetargetReal1));
11763 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREALDOUBLE]
11764 = t = make_node (REAL_TYPE);
11765 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE * 2; /* Always twice REAL. */
11766 pushdecl (build_decl (TYPE_DECL, get_identifier ("double precision"),
11769 type = ffetype_new ();
11770 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREALDOUBLE,
11772 ffetype_set_ams (type,
11773 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11774 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11775 ffetype_set_star (base_type,
11776 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11778 ffetype_set_kind (base_type, 2, type);
11779 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]
11780 = FFETARGET_f2cTYDREAL;
11781 assert (ffetype_size (type) == sizeof (ffetargetReal2));
11783 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
11784 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]);
11785 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex"),
11787 type = ffetype_new ();
11789 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREAL1,
11791 ffetype_set_ams (type,
11792 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11793 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11794 ffetype_set_star (base_type,
11795 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11797 ffetype_set_kind (base_type, 1, type);
11798 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
11799 = FFETARGET_f2cTYCOMPLEX;
11800 assert (ffetype_size (type) == sizeof (ffetargetComplex1));
11802 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREALDOUBLE]
11803 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]);
11804 pushdecl (build_decl (TYPE_DECL, get_identifier ("double complex"),
11806 type = ffetype_new ();
11807 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREALDOUBLE,
11809 ffetype_set_ams (type,
11810 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11811 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11812 ffetype_set_star (base_type,
11813 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11815 ffetype_set_kind (base_type, 2,
11817 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL2]
11818 = FFETARGET_f2cTYDCOMPLEX;
11819 assert (ffetype_size (type) == sizeof (ffetargetComplex2));
11821 /* Make function and ptr-to-function types for non-CHARACTER types. */
11823 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11824 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11826 if ((t = ffecom_tree_type[i][j]) != NULL_TREE)
11828 if (i == FFEINFO_basictypeINTEGER)
11830 /* Figure out the smallest INTEGER type that can hold
11831 a pointer on this machine. */
11832 if (GET_MODE_SIZE (TYPE_MODE (t))
11833 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
11835 if ((ffecom_pointer_kind_ == FFEINFO_kindtypeNONE)
11836 || (GET_MODE_SIZE (TYPE_MODE (ffecom_tree_type[i][ffecom_pointer_kind_]))
11837 > GET_MODE_SIZE (TYPE_MODE (t))))
11838 ffecom_pointer_kind_ = j;
11841 else if (i == FFEINFO_basictypeCOMPLEX)
11842 t = void_type_node;
11843 /* For f2c compatibility, REAL functions are really
11844 implemented as DOUBLE PRECISION. */
11845 else if ((i == FFEINFO_basictypeREAL)
11846 && (j == FFEINFO_kindtypeREAL1))
11847 t = ffecom_tree_type
11848 [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2];
11850 t = ffecom_tree_fun_type[i][j] = build_function_type (t,
11852 ffecom_tree_ptr_to_fun_type[i][j] = build_pointer_type (t);
11856 /* Set up pointer types. */
11858 if (ffecom_pointer_kind_ == FFEINFO_basictypeNONE)
11859 fatal ("no INTEGER type can hold a pointer on this configuration");
11860 else if (0 && ffe_is_do_internal_checks ())
11861 fprintf (stderr, "Pointer type kt=%d\n", ffecom_pointer_kind_);
11862 ffetype_set_kind (ffeinfo_type (FFEINFO_basictypeINTEGER,
11863 FFEINFO_kindtypeINTEGERDEFAULT),
11865 ffeinfo_type (FFEINFO_basictypeINTEGER,
11866 ffecom_pointer_kind_));
11868 if (ffe_is_ugly_assign ())
11869 ffecom_label_kind_ = ffecom_pointer_kind_; /* Require ASSIGN etc to this. */
11871 ffecom_label_kind_ = FFEINFO_kindtypeINTEGERDEFAULT;
11872 if (0 && ffe_is_do_internal_checks ())
11873 fprintf (stderr, "Label type kt=%d\n", ffecom_label_kind_);
11875 ffecom_integer_type_node
11876 = ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1];
11877 ffecom_integer_zero_node = convert (ffecom_integer_type_node,
11878 integer_zero_node);
11879 ffecom_integer_one_node = convert (ffecom_integer_type_node,
11882 /* Yes, the "FLOAT_TYPE_SIZE" references below are intentional.
11883 Turns out that by TYLONG, runtime/libI77/lio.h really means
11884 "whatever size an ftnint is". For consistency and sanity,
11885 com.h and runtime/f2c.h.in agree that flag, ftnint, and ftlen
11886 all are INTEGER, which we also make out of whatever back-end
11887 integer type is FLOAT_TYPE_SIZE bits wide. This change, from
11888 LONG_TYPE_SIZE, for TYLONG and TYLOGICAL, was necessary to
11889 accommodate machines like the Alpha. Note that this suggests
11890 f2c and libf2c are missing a distinction perhaps needed on
11891 some machines between "int" and "long int". -- burley 0.5.5 950215 */
11893 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, FLOAT_TYPE_SIZE,
11894 FFETARGET_f2cTYLONG);
11895 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, SHORT_TYPE_SIZE,
11896 FFETARGET_f2cTYSHORT);
11897 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, CHAR_TYPE_SIZE,
11898 FFETARGET_f2cTYINT1);
11899 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, LONG_LONG_TYPE_SIZE,
11900 FFETARGET_f2cTYQUAD);
11901 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, FLOAT_TYPE_SIZE,
11902 FFETARGET_f2cTYLOGICAL);
11903 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, SHORT_TYPE_SIZE,
11904 FFETARGET_f2cTYLOGICAL2);
11905 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, CHAR_TYPE_SIZE,
11906 FFETARGET_f2cTYLOGICAL1);
11907 /* ~~~Not really such a type in libf2c, e.g. I/O support? */
11908 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, LONG_LONG_TYPE_SIZE,
11909 FFETARGET_f2cTYQUAD);
11911 /* CHARACTER stuff is all special-cased, so it is not handled in the above
11912 loop. CHARACTER items are built as arrays of unsigned char. */
11914 ffecom_tree_type[FFEINFO_basictypeCHARACTER]
11915 [FFEINFO_kindtypeCHARACTER1] = t = char_type_node;
11916 type = ffetype_new ();
11918 ffeinfo_set_type (FFEINFO_basictypeCHARACTER,
11919 FFEINFO_kindtypeCHARACTER1,
11921 ffetype_set_ams (type,
11922 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11923 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11924 ffetype_set_kind (base_type, 1, type);
11925 assert (ffetype_size (type)
11926 == sizeof (((ffetargetCharacter1) { 0, NULL }).text[0]));
11928 ffecom_tree_fun_type[FFEINFO_basictypeCHARACTER]
11929 [FFEINFO_kindtypeCHARACTER1] = ffecom_tree_fun_type_void;
11930 ffecom_tree_ptr_to_fun_type[FFEINFO_basictypeCHARACTER]
11931 [FFEINFO_kindtypeCHARACTER1]
11932 = ffecom_tree_ptr_to_fun_type_void;
11933 ffecom_f2c_typecode_[FFEINFO_basictypeCHARACTER][FFEINFO_kindtypeCHARACTER1]
11934 = FFETARGET_f2cTYCHAR;
11936 ffecom_f2c_typecode_[FFEINFO_basictypeANY][FFEINFO_kindtypeANY]
11939 /* Make multi-return-value type and fields. */
11941 ffecom_multi_type_node_ = make_node (UNION_TYPE);
11945 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11946 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11950 if (ffecom_tree_type[i][j] == NULL_TREE)
11951 continue; /* Not supported. */
11952 sprintf (&name[0], "bt_%s_kt_%s",
11953 ffeinfo_basictype_string ((ffeinfoBasictype) i),
11954 ffeinfo_kindtype_string ((ffeinfoKindtype) j));
11955 ffecom_multi_fields_[i][j] = build_decl (FIELD_DECL,
11956 get_identifier (name),
11957 ffecom_tree_type[i][j]);
11958 DECL_CONTEXT (ffecom_multi_fields_[i][j])
11959 = ffecom_multi_type_node_;
11960 DECL_ALIGN (ffecom_multi_fields_[i][j]) = 0;
11961 DECL_USER_ALIGN (ffecom_multi_fields_[i][j]) = 0;
11962 TREE_CHAIN (ffecom_multi_fields_[i][j]) = field;
11963 field = ffecom_multi_fields_[i][j];
11966 TYPE_FIELDS (ffecom_multi_type_node_) = field;
11967 layout_type (ffecom_multi_type_node_);
11969 /* Subroutines usually return integer because they might have alternate
11972 ffecom_tree_subr_type
11973 = build_function_type (integer_type_node, NULL_TREE);
11974 ffecom_tree_ptr_to_subr_type
11975 = build_pointer_type (ffecom_tree_subr_type);
11976 ffecom_tree_blockdata_type
11977 = build_function_type (void_type_node, NULL_TREE);
11979 builtin_function ("__builtin_sqrtf", float_ftype_float,
11980 BUILT_IN_FSQRT, BUILT_IN_NORMAL, "sqrtf");
11981 builtin_function ("__builtin_fsqrt", double_ftype_double,
11982 BUILT_IN_FSQRT, BUILT_IN_NORMAL, "sqrt");
11983 builtin_function ("__builtin_sqrtl", ldouble_ftype_ldouble,
11984 BUILT_IN_FSQRT, BUILT_IN_NORMAL, "sqrtl");
11985 builtin_function ("__builtin_sinf", float_ftype_float,
11986 BUILT_IN_SIN, BUILT_IN_NORMAL, "sinf");
11987 builtin_function ("__builtin_sin", double_ftype_double,
11988 BUILT_IN_SIN, BUILT_IN_NORMAL, "sin");
11989 builtin_function ("__builtin_sinl", ldouble_ftype_ldouble,
11990 BUILT_IN_SIN, BUILT_IN_NORMAL, "sinl");
11991 builtin_function ("__builtin_cosf", float_ftype_float,
11992 BUILT_IN_COS, BUILT_IN_NORMAL, "cosf");
11993 builtin_function ("__builtin_cos", double_ftype_double,
11994 BUILT_IN_COS, BUILT_IN_NORMAL, "cos");
11995 builtin_function ("__builtin_cosl", ldouble_ftype_ldouble,
11996 BUILT_IN_COS, BUILT_IN_NORMAL, "cosl");
11999 pedantic_lvalues = FALSE;
12002 ffecom_f2c_make_type_ (&ffecom_f2c_integer_type_node,
12005 ffecom_f2c_make_type_ (&ffecom_f2c_address_type_node,
12008 ffecom_f2c_make_type_ (&ffecom_f2c_real_type_node,
12011 ffecom_f2c_make_type_ (&ffecom_f2c_doublereal_type_node,
12012 FFECOM_f2cDOUBLEREAL,
12014 ffecom_f2c_make_type_ (&ffecom_f2c_complex_type_node,
12017 ffecom_f2c_make_type_ (&ffecom_f2c_doublecomplex_type_node,
12018 FFECOM_f2cDOUBLECOMPLEX,
12020 ffecom_f2c_make_type_ (&ffecom_f2c_longint_type_node,
12023 ffecom_f2c_make_type_ (&ffecom_f2c_logical_type_node,
12026 ffecom_f2c_make_type_ (&ffecom_f2c_flag_type_node,
12029 ffecom_f2c_make_type_ (&ffecom_f2c_ftnlen_type_node,
12032 ffecom_f2c_make_type_ (&ffecom_f2c_ftnint_type_node,
12036 ffecom_f2c_ftnlen_zero_node
12037 = convert (ffecom_f2c_ftnlen_type_node, integer_zero_node);
12039 ffecom_f2c_ftnlen_one_node
12040 = convert (ffecom_f2c_ftnlen_type_node, integer_one_node);
12042 ffecom_f2c_ftnlen_two_node = build_int_2 (2, 0);
12043 TREE_TYPE (ffecom_f2c_ftnlen_two_node) = ffecom_integer_type_node;
12045 ffecom_f2c_ptr_to_ftnlen_type_node
12046 = build_pointer_type (ffecom_f2c_ftnlen_type_node);
12048 ffecom_f2c_ptr_to_ftnint_type_node
12049 = build_pointer_type (ffecom_f2c_ftnint_type_node);
12051 ffecom_f2c_ptr_to_integer_type_node
12052 = build_pointer_type (ffecom_f2c_integer_type_node);
12054 ffecom_f2c_ptr_to_real_type_node
12055 = build_pointer_type (ffecom_f2c_real_type_node);
12057 ffecom_float_zero_ = build_real (float_type_node, dconst0);
12058 ffecom_double_zero_ = build_real (double_type_node, dconst0);
12060 REAL_VALUE_TYPE point_5;
12062 #ifdef REAL_ARITHMETIC
12063 REAL_ARITHMETIC (point_5, RDIV_EXPR, dconst1, dconst2);
12067 ffecom_float_half_ = build_real (float_type_node, point_5);
12068 ffecom_double_half_ = build_real (double_type_node, point_5);
12071 /* Do "extern int xargc;". */
12073 ffecom_tree_xargc_ = build_decl (VAR_DECL,
12074 get_identifier ("f__xargc"),
12075 integer_type_node);
12076 DECL_EXTERNAL (ffecom_tree_xargc_) = 1;
12077 TREE_STATIC (ffecom_tree_xargc_) = 1;
12078 TREE_PUBLIC (ffecom_tree_xargc_) = 1;
12079 ffecom_tree_xargc_ = start_decl (ffecom_tree_xargc_, FALSE);
12080 finish_decl (ffecom_tree_xargc_, NULL_TREE, FALSE);
12082 #if 0 /* This is being fixed, and seems to be working now. */
12083 if ((FLOAT_TYPE_SIZE != 32)
12084 || (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))) != 32))
12086 warning ("configuration: REAL, INTEGER, and LOGICAL are %d bits wide,",
12087 (int) FLOAT_TYPE_SIZE);
12088 warning ("and pointers are %d bits wide, but g77 doesn't yet work",
12089 (int) TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))));
12090 warning ("properly unless they all are 32 bits wide.");
12091 warning ("Please keep this in mind before you report bugs. g77 should");
12092 warning ("support non-32-bit machines better as of version 0.6.");
12096 #if 0 /* Code in ste.c that would crash has been commented out. */
12097 if (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)
12098 < TYPE_PRECISION (string_type_node))
12099 /* I/O will probably crash. */
12100 warning ("configuration: char * holds %d bits, but ftnlen only %d",
12101 TYPE_PRECISION (string_type_node),
12102 TYPE_PRECISION (ffecom_f2c_ftnlen_type_node));
12105 #if 0 /* ASSIGN-related stuff has been changed to accommodate this. */
12106 if (TYPE_PRECISION (ffecom_integer_type_node)
12107 < TYPE_PRECISION (string_type_node))
12108 /* ASSIGN 10 TO I will crash. */
12109 warning ("configuration: char * holds %d bits, but INTEGER only %d --\n\
12110 ASSIGN statement might fail",
12111 TYPE_PRECISION (string_type_node),
12112 TYPE_PRECISION (ffecom_integer_type_node));
12117 /* ffecom_init_2 -- Initialize
12119 ffecom_init_2(); */
12121 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12125 assert (ffecom_outer_function_decl_ == NULL_TREE);
12126 assert (current_function_decl == NULL_TREE);
12127 assert (ffecom_which_entrypoint_decl_ == NULL_TREE);
12129 ffecom_master_arglist_ = NULL;
12131 ffecom_primary_entry_ = NULL;
12132 ffecom_is_altreturning_ = FALSE;
12133 ffecom_func_result_ = NULL_TREE;
12134 ffecom_multi_retval_ = NULL_TREE;
12138 /* ffecom_list_expr -- Transform list of exprs into gcc tree
12141 ffebld expr; // FFE opITEM list.
12142 tree = ffecom_list_expr(expr);
12144 List of actual args is transformed into corresponding gcc backend list. */
12146 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12148 ffecom_list_expr (ffebld expr)
12151 tree *plist = &list;
12152 tree trail = NULL_TREE; /* Append char length args here. */
12153 tree *ptrail = &trail;
12156 while (expr != NULL)
12158 tree texpr = ffecom_arg_expr (ffebld_head (expr), &length);
12160 if (texpr == error_mark_node)
12161 return error_mark_node;
12163 *plist = build_tree_list (NULL_TREE, texpr);
12164 plist = &TREE_CHAIN (*plist);
12165 expr = ffebld_trail (expr);
12166 if (length != NULL_TREE)
12168 *ptrail = build_tree_list (NULL_TREE, length);
12169 ptrail = &TREE_CHAIN (*ptrail);
12179 /* ffecom_list_ptr_to_expr -- Transform list of exprs into gcc tree
12182 ffebld expr; // FFE opITEM list.
12183 tree = ffecom_list_ptr_to_expr(expr);
12185 List of actual args is transformed into corresponding gcc backend list for
12186 use in calling an external procedure (vs. a statement function). */
12188 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12190 ffecom_list_ptr_to_expr (ffebld expr)
12193 tree *plist = &list;
12194 tree trail = NULL_TREE; /* Append char length args here. */
12195 tree *ptrail = &trail;
12198 while (expr != NULL)
12200 tree texpr = ffecom_arg_ptr_to_expr (ffebld_head (expr), &length);
12202 if (texpr == error_mark_node)
12203 return error_mark_node;
12205 *plist = build_tree_list (NULL_TREE, texpr);
12206 plist = &TREE_CHAIN (*plist);
12207 expr = ffebld_trail (expr);
12208 if (length != NULL_TREE)
12210 *ptrail = build_tree_list (NULL_TREE, length);
12211 ptrail = &TREE_CHAIN (*ptrail);
12221 /* Obtain gcc's LABEL_DECL tree for label. */
12223 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12225 ffecom_lookup_label (ffelab label)
12229 if (ffelab_hook (label) == NULL_TREE)
12231 char labelname[16];
12233 switch (ffelab_type (label))
12235 case FFELAB_typeLOOPEND:
12236 case FFELAB_typeNOTLOOP:
12237 case FFELAB_typeENDIF:
12238 sprintf (labelname, "%" ffelabValue_f "u", ffelab_value (label));
12239 glabel = build_decl (LABEL_DECL, get_identifier (labelname),
12241 DECL_CONTEXT (glabel) = current_function_decl;
12242 DECL_MODE (glabel) = VOIDmode;
12245 case FFELAB_typeFORMAT:
12246 glabel = build_decl (VAR_DECL,
12247 ffecom_get_invented_identifier
12248 ("__g77_format_%d", (int) ffelab_value (label)),
12249 build_type_variant (build_array_type
12253 TREE_CONSTANT (glabel) = 1;
12254 TREE_STATIC (glabel) = 1;
12255 DECL_CONTEXT (glabel) = current_function_decl;
12256 DECL_INITIAL (glabel) = NULL;
12257 make_decl_rtl (glabel, NULL);
12258 expand_decl (glabel);
12260 ffecom_save_tree_forever (glabel);
12264 case FFELAB_typeANY:
12265 glabel = error_mark_node;
12269 assert ("bad label type" == NULL);
12273 ffelab_set_hook (label, glabel);
12277 glabel = ffelab_hook (label);
12284 /* Stabilizes the arguments. Don't use this if the lhs and rhs come from
12285 a single source specification (as in the fourth argument of MVBITS).
12286 If the type is NULL_TREE, the type of lhs is used to make the type of
12287 the MODIFY_EXPR. */
12289 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12291 ffecom_modify (tree newtype, tree lhs,
12294 if (lhs == error_mark_node || rhs == error_mark_node)
12295 return error_mark_node;
12297 if (newtype == NULL_TREE)
12298 newtype = TREE_TYPE (lhs);
12300 if (TREE_SIDE_EFFECTS (lhs))
12301 lhs = stabilize_reference (lhs);
12303 return ffecom_2s (MODIFY_EXPR, newtype, lhs, rhs);
12308 /* Register source file name. */
12311 ffecom_file (const char *name)
12313 #if FFECOM_GCC_INCLUDE
12314 ffecom_file_ (name);
12318 /* ffecom_notify_init_storage -- An aggregate storage is now fully init'ed
12321 ffecom_notify_init_storage(st);
12323 Gets called when all possible units in an aggregate storage area (a LOCAL
12324 with equivalences or a COMMON) have been initialized. The initialization
12325 info either is in ffestorag_init or, if that is NULL,
12326 ffestorag_accretion:
12328 ffestorag_init may contain an opCONTER or opARRTER. opCONTER may occur
12329 even for an array if the array is one element in length!
12331 ffestorag_accretion will contain an opACCTER. It is much like an
12332 opARRTER except it has an ffebit object in it instead of just a size.
12333 The back end can use the info in the ffebit object, if it wants, to
12334 reduce the amount of actual initialization, but in any case it should
12335 kill the ffebit object when done. Also, set accretion to NULL but
12336 init to a non-NULL value.
12338 After performing initialization, DO NOT set init to NULL, because that'll
12339 tell the front end it is ok for more initialization to happen. Instead,
12340 set init to an opANY expression or some such thing that you can use to
12341 tell that you've already initialized the object.
12344 Support two-pass FFE. */
12347 ffecom_notify_init_storage (ffestorag st)
12349 ffebld init; /* The initialization expression. */
12350 #if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12351 ffetargetOffset size; /* The size of the entity. */
12352 ffetargetAlign pad; /* Its initial padding. */
12355 if (ffestorag_init (st) == NULL)
12357 init = ffestorag_accretion (st);
12358 assert (init != NULL);
12359 ffestorag_set_accretion (st, NULL);
12360 ffestorag_set_accretes (st, 0);
12362 #if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12363 /* For GNU backend, just turn ACCTER into ARRTER and proceed. */
12364 size = ffebld_accter_size (init);
12365 pad = ffebld_accter_pad (init);
12366 ffebit_kill (ffebld_accter_bits (init));
12367 ffebld_set_op (init, FFEBLD_opARRTER);
12368 ffebld_set_arrter (init, ffebld_accter (init));
12369 ffebld_arrter_set_size (init, size);
12370 ffebld_arrter_set_pad (init, size);
12374 ffestorag_set_init (st, init);
12379 init = ffestorag_init (st);
12382 #if FFECOM_ONEPASS /* Process the inits, wipe 'em out. */
12383 ffestorag_set_init (st, ffebld_new_any ());
12385 if (ffebld_op (init) == FFEBLD_opANY)
12386 return; /* Oh, we already did this! */
12388 #if FFECOM_targetCURRENT == FFECOM_targetFFE
12392 if (ffestorag_symbol (st) != NULL)
12393 s = ffestorag_symbol (st);
12395 s = ffestorag_typesymbol (st);
12397 fprintf (dmpout, "= initialize_storage \"%s\" ",
12398 (s != NULL) ? ffesymbol_text (s) : "(unnamed)");
12399 ffebld_dump (init);
12400 fputc ('\n', dmpout);
12404 #endif /* if FFECOM_ONEPASS */
12407 /* ffecom_notify_init_symbol -- A symbol is now fully init'ed
12410 ffecom_notify_init_symbol(s);
12412 Gets called when all possible units in a symbol (not placed in COMMON
12413 or involved in EQUIVALENCE, unless it as yet has no ffestorag object)
12414 have been initialized. The initialization info either is in
12415 ffesymbol_init or, if that is NULL, ffesymbol_accretion:
12417 ffesymbol_init may contain an opCONTER or opARRTER. opCONTER may occur
12418 even for an array if the array is one element in length!
12420 ffesymbol_accretion will contain an opACCTER. It is much like an
12421 opARRTER except it has an ffebit object in it instead of just a size.
12422 The back end can use the info in the ffebit object, if it wants, to
12423 reduce the amount of actual initialization, but in any case it should
12424 kill the ffebit object when done. Also, set accretion to NULL but
12425 init to a non-NULL value.
12427 After performing initialization, DO NOT set init to NULL, because that'll
12428 tell the front end it is ok for more initialization to happen. Instead,
12429 set init to an opANY expression or some such thing that you can use to
12430 tell that you've already initialized the object.
12433 Support two-pass FFE. */
12436 ffecom_notify_init_symbol (ffesymbol s)
12438 ffebld init; /* The initialization expression. */
12439 #if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12440 ffetargetOffset size; /* The size of the entity. */
12441 ffetargetAlign pad; /* Its initial padding. */
12444 if (ffesymbol_storage (s) == NULL)
12445 return; /* Do nothing until COMMON/EQUIVALENCE
12446 possibilities checked. */
12448 if ((ffesymbol_init (s) == NULL)
12449 && ((init = ffesymbol_accretion (s)) != NULL))
12451 ffesymbol_set_accretion (s, NULL);
12452 ffesymbol_set_accretes (s, 0);
12454 #if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12455 /* For GNU backend, just turn ACCTER into ARRTER and proceed. */
12456 size = ffebld_accter_size (init);
12457 pad = ffebld_accter_pad (init);
12458 ffebit_kill (ffebld_accter_bits (init));
12459 ffebld_set_op (init, FFEBLD_opARRTER);
12460 ffebld_set_arrter (init, ffebld_accter (init));
12461 ffebld_arrter_set_size (init, size);
12462 ffebld_arrter_set_pad (init, size);
12466 ffesymbol_set_init (s, init);
12471 init = ffesymbol_init (s);
12475 ffesymbol_set_init (s, ffebld_new_any ());
12477 if (ffebld_op (init) == FFEBLD_opANY)
12478 return; /* Oh, we already did this! */
12480 #if FFECOM_targetCURRENT == FFECOM_targetFFE
12481 fprintf (dmpout, "= initialize_symbol \"%s\" ", ffesymbol_text (s));
12482 ffebld_dump (init);
12483 fputc ('\n', dmpout);
12486 #endif /* if FFECOM_ONEPASS */
12489 /* ffecom_notify_primary_entry -- Learn which is the primary entry point
12492 ffecom_notify_primary_entry(s);
12494 Gets called when implicit or explicit PROGRAM statement seen or when
12495 FUNCTION, SUBROUTINE, or BLOCK DATA statement seen, with the primary
12496 global symbol that serves as the entry point. */
12499 ffecom_notify_primary_entry (ffesymbol s)
12501 ffecom_primary_entry_ = s;
12502 ffecom_primary_entry_kind_ = ffesymbol_kind (s);
12504 if ((ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
12505 || (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE))
12506 ffecom_primary_entry_is_proc_ = TRUE;
12508 ffecom_primary_entry_is_proc_ = FALSE;
12510 if (!ffe_is_silent ())
12512 if (ffecom_primary_entry_kind_ == FFEINFO_kindPROGRAM)
12513 fprintf (stderr, "%s:\n", ffesymbol_text (s));
12515 fprintf (stderr, " %s:\n", ffesymbol_text (s));
12518 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12519 if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
12524 for (list = ffesymbol_dummyargs (s);
12526 list = ffebld_trail (list))
12528 arg = ffebld_head (list);
12529 if (ffebld_op (arg) == FFEBLD_opSTAR)
12531 ffecom_is_altreturning_ = TRUE;
12540 ffecom_open_include (char *name, ffewhereLine l, ffewhereColumn c)
12542 #if FFECOM_GCC_INCLUDE
12543 return ffecom_open_include_ (name, l, c);
12545 return fopen (name, "r");
12549 /* ffecom_ptr_to_expr -- Transform expr into gcc tree with & in front
12552 ffebld expr; // FFE expression.
12553 tree = ffecom_ptr_to_expr(expr);
12555 Like ffecom_expr, but sticks address-of in front of most things. */
12557 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12559 ffecom_ptr_to_expr (ffebld expr)
12562 ffeinfoBasictype bt;
12563 ffeinfoKindtype kt;
12566 assert (expr != NULL);
12568 switch (ffebld_op (expr))
12570 case FFEBLD_opSYMTER:
12571 s = ffebld_symter (expr);
12572 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
12576 ix = ffeintrin_gfrt_indirect (ffebld_symter_implementation (expr));
12577 assert (ix != FFECOM_gfrt);
12578 if ((item = ffecom_gfrt_[ix]) == NULL_TREE)
12580 ffecom_make_gfrt_ (ix);
12581 item = ffecom_gfrt_[ix];
12586 item = ffesymbol_hook (s).decl_tree;
12587 if (item == NULL_TREE)
12589 s = ffecom_sym_transform_ (s);
12590 item = ffesymbol_hook (s).decl_tree;
12593 assert (item != NULL);
12594 if (item == error_mark_node)
12596 if (!ffesymbol_hook (s).addr)
12597 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12601 case FFEBLD_opARRAYREF:
12602 return ffecom_arrayref_ (NULL_TREE, expr, 1);
12604 case FFEBLD_opCONTER:
12606 bt = ffeinfo_basictype (ffebld_info (expr));
12607 kt = ffeinfo_kindtype (ffebld_info (expr));
12609 item = ffecom_constantunion (&ffebld_constant_union
12610 (ffebld_conter (expr)), bt, kt,
12611 ffecom_tree_type[bt][kt]);
12612 if (item == error_mark_node)
12613 return error_mark_node;
12614 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12619 return error_mark_node;
12622 bt = ffeinfo_basictype (ffebld_info (expr));
12623 kt = ffeinfo_kindtype (ffebld_info (expr));
12625 item = ffecom_expr (expr);
12626 if (item == error_mark_node)
12627 return error_mark_node;
12629 /* The back end currently optimizes a bit too zealously for us, in that
12630 we fail JCB001 if the following block of code is omitted. It checks
12631 to see if the transformed expression is a symbol or array reference,
12632 and encloses it in a SAVE_EXPR if that is the case. */
12635 if ((TREE_CODE (item) == VAR_DECL)
12636 || (TREE_CODE (item) == PARM_DECL)
12637 || (TREE_CODE (item) == RESULT_DECL)
12638 || (TREE_CODE (item) == INDIRECT_REF)
12639 || (TREE_CODE (item) == ARRAY_REF)
12640 || (TREE_CODE (item) == COMPONENT_REF)
12642 || (TREE_CODE (item) == OFFSET_REF)
12644 || (TREE_CODE (item) == BUFFER_REF)
12645 || (TREE_CODE (item) == REALPART_EXPR)
12646 || (TREE_CODE (item) == IMAGPART_EXPR))
12648 item = ffecom_save_tree (item);
12651 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12656 assert ("fall-through error" == NULL);
12657 return error_mark_node;
12661 /* Obtain a temp var with given data type.
12663 size is FFETARGET_charactersizeNONE for a non-CHARACTER type
12664 or >= 0 for a CHARACTER type.
12666 elements is -1 for a scalar or > 0 for an array of type. */
12668 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12670 ffecom_make_tempvar (const char *commentary, tree type,
12671 ffetargetCharacterSize size, int elements)
12674 static int mynumber;
12676 assert (current_binding_level->prep_state < 2);
12678 if (type == error_mark_node)
12679 return error_mark_node;
12681 if (size != FFETARGET_charactersizeNONE)
12682 type = build_array_type (type,
12683 build_range_type (ffecom_f2c_ftnlen_type_node,
12684 ffecom_f2c_ftnlen_one_node,
12685 build_int_2 (size, 0)));
12686 if (elements != -1)
12687 type = build_array_type (type,
12688 build_range_type (integer_type_node,
12690 build_int_2 (elements - 1,
12692 t = build_decl (VAR_DECL,
12693 ffecom_get_invented_identifier ("__g77_%s_%d",
12698 t = start_decl (t, FALSE);
12699 finish_decl (t, NULL_TREE, FALSE);
12705 /* Prepare argument pointer to expression.
12707 Like ffecom_prepare_expr, except for expressions to be evaluated
12708 via ffecom_arg_ptr_to_expr. */
12711 ffecom_prepare_arg_ptr_to_expr (ffebld expr)
12713 /* ~~For now, it seems to be the same thing. */
12714 ffecom_prepare_expr (expr);
12718 /* End of preparations. */
12721 ffecom_prepare_end (void)
12723 int prep_state = current_binding_level->prep_state;
12725 assert (prep_state < 2);
12726 current_binding_level->prep_state = 2;
12728 return (prep_state == 1) ? TRUE : FALSE;
12731 /* Prepare expression.
12733 This is called before any code is generated for the current block.
12734 It scans the expression, declares any temporaries that might be needed
12735 during evaluation of the expression, and stores those temporaries in
12736 the appropriate "hook" fields of the expression. `dest', if not NULL,
12737 specifies the destination that ffecom_expr_ will see, in case that
12738 helps avoid generating unused temporaries.
12740 ~~Improve to avoid allocating unused temporaries by taking `dest'
12741 into account vis-a-vis aliasing requirements of complex/character
12745 ffecom_prepare_expr_ (ffebld expr, ffebld dest UNUSED)
12747 ffeinfoBasictype bt;
12748 ffeinfoKindtype kt;
12749 ffetargetCharacterSize sz;
12750 tree tempvar = NULL_TREE;
12752 assert (current_binding_level->prep_state < 2);
12757 bt = ffeinfo_basictype (ffebld_info (expr));
12758 kt = ffeinfo_kindtype (ffebld_info (expr));
12759 sz = ffeinfo_size (ffebld_info (expr));
12761 /* Generate whatever temporaries are needed to represent the result
12762 of the expression. */
12764 if (bt == FFEINFO_basictypeCHARACTER)
12766 while (ffebld_op (expr) == FFEBLD_opPAREN)
12767 expr = ffebld_left (expr);
12770 switch (ffebld_op (expr))
12773 /* Don't make temps for SYMTER, CONTER, etc. */
12774 if (ffebld_arity (expr) == 0)
12779 case FFEINFO_basictypeCOMPLEX:
12780 if (ffebld_op (expr) == FFEBLD_opFUNCREF)
12784 if (ffebld_op (ffebld_left (expr)) != FFEBLD_opSYMTER)
12787 s = ffebld_symter (ffebld_left (expr));
12788 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT
12789 || (ffesymbol_where (s) != FFEINFO_whereINTRINSIC
12790 && ! ffesymbol_is_f2c (s))
12791 || (ffesymbol_where (s) == FFEINFO_whereINTRINSIC
12792 && ! ffe_is_f2c_library ()))
12795 else if (ffebld_op (expr) == FFEBLD_opPOWER)
12797 /* Requires special treatment. There's no POW_CC function
12798 in libg2c, so POW_ZZ is used, which means we always
12799 need a double-complex temp, not a single-complex. */
12800 kt = FFEINFO_kindtypeREAL2;
12802 else if (ffebld_op (expr) != FFEBLD_opDIVIDE)
12803 /* The other ops don't need temps for complex operands. */
12806 /* ~~~Avoid making temps for some intrinsics, such as AIMAG(C),
12807 REAL(C). See 19990325-0.f, routine `check', for cases. */
12808 tempvar = ffecom_make_tempvar ("complex",
12810 [FFEINFO_basictypeCOMPLEX][kt],
12811 FFETARGET_charactersizeNONE,
12815 case FFEINFO_basictypeCHARACTER:
12816 if (ffebld_op (expr) != FFEBLD_opFUNCREF)
12819 if (sz == FFETARGET_charactersizeNONE)
12820 /* ~~Kludge alert! This should someday be fixed. */
12823 tempvar = ffecom_make_tempvar ("char", char_type_node, sz, -1);
12832 case FFEBLD_opPOWER:
12835 tree rtmp, ltmp, result;
12837 ltype = ffecom_type_expr (ffebld_left (expr));
12838 rtype = ffecom_type_expr (ffebld_right (expr));
12840 rtmp = ffecom_make_tempvar (rtype, FFETARGET_charactersizeNONE, -1);
12841 ltmp = ffecom_make_tempvar (ltype, FFETARGET_charactersizeNONE, -1);
12842 result = ffecom_make_tempvar (ltype, FFETARGET_charactersizeNONE, -1);
12844 tempvar = make_tree_vec (3);
12845 TREE_VEC_ELT (tempvar, 0) = rtmp;
12846 TREE_VEC_ELT (tempvar, 1) = ltmp;
12847 TREE_VEC_ELT (tempvar, 2) = result;
12852 case FFEBLD_opCONCATENATE:
12854 /* This gets special handling, because only one set of temps
12855 is needed for a tree of these -- the tree is treated as
12856 a flattened list of concatenations when generating code. */
12858 ffecomConcatList_ catlist;
12859 tree ltmp, itmp, result;
12863 catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
12864 count = ffecom_concat_list_count_ (catlist);
12869 = ffecom_make_tempvar ("concat_len",
12870 ffecom_f2c_ftnlen_type_node,
12871 FFETARGET_charactersizeNONE, count);
12873 = ffecom_make_tempvar ("concat_item",
12874 ffecom_f2c_address_type_node,
12875 FFETARGET_charactersizeNONE, count);
12877 = ffecom_make_tempvar ("concat_res",
12879 ffecom_concat_list_maxlen_ (catlist),
12882 tempvar = make_tree_vec (3);
12883 TREE_VEC_ELT (tempvar, 0) = ltmp;
12884 TREE_VEC_ELT (tempvar, 1) = itmp;
12885 TREE_VEC_ELT (tempvar, 2) = result;
12888 for (i = 0; i < count; ++i)
12889 ffecom_prepare_arg_ptr_to_expr (ffecom_concat_list_expr_ (catlist,
12892 ffecom_concat_list_kill_ (catlist);
12896 ffebld_nonter_set_hook (expr, tempvar);
12897 current_binding_level->prep_state = 1;
12902 case FFEBLD_opCONVERT:
12903 if (bt == FFEINFO_basictypeCHARACTER
12904 && ((ffebld_size_known (ffebld_left (expr))
12905 == FFETARGET_charactersizeNONE)
12906 || (ffebld_size_known (ffebld_left (expr)) >= sz)))
12907 tempvar = ffecom_make_tempvar ("convert", char_type_node, sz, -1);
12913 ffebld_nonter_set_hook (expr, tempvar);
12914 current_binding_level->prep_state = 1;
12917 /* Prepare subexpressions for this expr. */
12919 switch (ffebld_op (expr))
12921 case FFEBLD_opPERCENT_LOC:
12922 ffecom_prepare_ptr_to_expr (ffebld_left (expr));
12925 case FFEBLD_opPERCENT_VAL:
12926 case FFEBLD_opPERCENT_REF:
12927 ffecom_prepare_expr (ffebld_left (expr));
12930 case FFEBLD_opPERCENT_DESCR:
12931 ffecom_prepare_arg_ptr_to_expr (ffebld_left (expr));
12934 case FFEBLD_opITEM:
12940 item = ffebld_trail (item))
12941 if (ffebld_head (item) != NULL)
12942 ffecom_prepare_expr (ffebld_head (item));
12947 /* Need to handle character conversion specially. */
12948 switch (ffebld_arity (expr))
12951 ffecom_prepare_expr (ffebld_left (expr));
12952 ffecom_prepare_expr (ffebld_right (expr));
12956 ffecom_prepare_expr (ffebld_left (expr));
12967 /* Prepare expression for reading and writing.
12969 Like ffecom_prepare_expr, except for expressions to be evaluated
12970 via ffecom_expr_rw. */
12973 ffecom_prepare_expr_rw (tree type, ffebld expr)
12975 /* This is all we support for now. */
12976 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
12978 /* ~~For now, it seems to be the same thing. */
12979 ffecom_prepare_expr (expr);
12983 /* Prepare expression for writing.
12985 Like ffecom_prepare_expr, except for expressions to be evaluated
12986 via ffecom_expr_w. */
12989 ffecom_prepare_expr_w (tree type, ffebld expr)
12991 /* This is all we support for now. */
12992 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
12994 /* ~~For now, it seems to be the same thing. */
12995 ffecom_prepare_expr (expr);
12999 /* Prepare expression for returning.
13001 Like ffecom_prepare_expr, except for expressions to be evaluated
13002 via ffecom_return_expr. */
13005 ffecom_prepare_return_expr (ffebld expr)
13007 assert (current_binding_level->prep_state < 2);
13009 if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE
13010 && ffecom_is_altreturning_
13012 ffecom_prepare_expr (expr);
13015 /* Prepare pointer to expression.
13017 Like ffecom_prepare_expr, except for expressions to be evaluated
13018 via ffecom_ptr_to_expr. */
13021 ffecom_prepare_ptr_to_expr (ffebld expr)
13023 /* ~~For now, it seems to be the same thing. */
13024 ffecom_prepare_expr (expr);
13028 /* Transform expression into constant pointer-to-expression tree.
13030 If the expression can be transformed into a pointer-to-expression tree
13031 that is constant, that is done, and the tree returned. Else NULL_TREE
13034 That way, a caller can attempt to provide compile-time initialization
13035 of a variable and, if that fails, *then* choose to start a new block
13036 and resort to using temporaries, as appropriate. */
13039 ffecom_ptr_to_const_expr (ffebld expr)
13042 return integer_zero_node;
13044 if (ffebld_op (expr) == FFEBLD_opANY)
13045 return error_mark_node;
13047 if (ffebld_arity (expr) == 0
13048 && (ffebld_op (expr) != FFEBLD_opSYMTER
13049 || ffebld_where (expr) == FFEINFO_whereCOMMON
13050 || ffebld_where (expr) == FFEINFO_whereGLOBAL
13051 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
13055 t = ffecom_ptr_to_expr (expr);
13056 assert (TREE_CONSTANT (t));
13063 /* ffecom_return_expr -- Returns return-value expr given alt return expr
13065 tree rtn; // NULL_TREE means use expand_null_return()
13066 ffebld expr; // NULL if no alt return expr to RETURN stmt
13067 rtn = ffecom_return_expr(expr);
13069 Based on the program unit type and other info (like return function
13070 type, return master function type when alternate ENTRY points,
13071 whether subroutine has any alternate RETURN points, etc), returns the
13072 appropriate expression to be returned to the caller, or NULL_TREE
13073 meaning no return value or the caller expects it to be returned somewhere
13074 else (which is handled by other parts of this module). */
13076 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13078 ffecom_return_expr (ffebld expr)
13082 switch (ffecom_primary_entry_kind_)
13084 case FFEINFO_kindPROGRAM:
13085 case FFEINFO_kindBLOCKDATA:
13089 case FFEINFO_kindSUBROUTINE:
13090 if (!ffecom_is_altreturning_)
13091 rtn = NULL_TREE; /* No alt returns, never an expr. */
13092 else if (expr == NULL)
13093 rtn = integer_zero_node;
13095 rtn = ffecom_expr (expr);
13098 case FFEINFO_kindFUNCTION:
13099 if ((ffecom_multi_retval_ != NULL_TREE)
13100 || (ffesymbol_basictype (ffecom_primary_entry_)
13101 == FFEINFO_basictypeCHARACTER)
13102 || ((ffesymbol_basictype (ffecom_primary_entry_)
13103 == FFEINFO_basictypeCOMPLEX)
13104 && (ffecom_num_entrypoints_ == 0)
13105 && ffesymbol_is_f2c (ffecom_primary_entry_)))
13106 { /* Value is returned by direct assignment
13107 into (implicit) dummy. */
13111 rtn = ffecom_func_result_;
13113 /* Spurious error if RETURN happens before first reference! So elide
13114 this code. In particular, for debugging registry, rtn should always
13115 be non-null after all, but TREE_USED won't be set until we encounter
13116 a reference in the code. Perfectly okay (but weird) code that,
13117 e.g., has "GOTO 20;10 RETURN;20 RTN=0;GOTO 10", would result in
13118 this diagnostic for no reason. Have people use -O -Wuninitialized
13119 and leave it to the back end to find obviously weird cases. */
13121 /* Used to "assert(rtn != NULL_TREE);" here, but it's kind of a valid
13122 situation; if the return value has never been referenced, it won't
13123 have a tree under 2pass mode. */
13124 if ((rtn == NULL_TREE)
13125 || !TREE_USED (rtn))
13127 ffebad_start (FFEBAD_RETURN_VALUE_UNSET);
13128 ffebad_here (0, ffesymbol_where_line (ffecom_primary_entry_),
13129 ffesymbol_where_column (ffecom_primary_entry_));
13130 ffebad_string (ffesymbol_text (ffesymbol_funcresult
13131 (ffecom_primary_entry_)));
13138 assert ("bad unit kind" == NULL);
13139 case FFEINFO_kindANY:
13140 rtn = error_mark_node;
13148 /* Do save_expr only if tree is not error_mark_node. */
13150 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13152 ffecom_save_tree (tree t)
13154 return save_expr (t);
13158 /* Start a compound statement (block). */
13160 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13162 ffecom_start_compstmt (void)
13164 bison_rule_pushlevel_ ();
13166 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
13168 /* Public entry point for front end to access start_decl. */
13170 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13172 ffecom_start_decl (tree decl, bool is_initialized)
13174 DECL_INITIAL (decl) = is_initialized ? error_mark_node : NULL_TREE;
13175 return start_decl (decl, FALSE);
13179 /* ffecom_sym_commit -- Symbol's state being committed to reality
13182 ffecom_sym_commit(s);
13184 Does whatever the backend needs when a symbol is committed after having
13185 been backtrackable for a period of time. */
13187 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13189 ffecom_sym_commit (ffesymbol s UNUSED)
13191 assert (!ffesymbol_retractable ());
13195 /* ffecom_sym_end_transition -- Perform end transition on all symbols
13197 ffecom_sym_end_transition();
13199 Does backend-specific stuff and also calls ffest_sym_end_transition
13200 to do the necessary FFE stuff.
13202 Backtracking is never enabled when this fn is called, so don't worry
13206 ffecom_sym_end_transition (ffesymbol s)
13210 assert (!ffesymbol_retractable ());
13212 s = ffest_sym_end_transition (s);
13214 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13215 if ((ffesymbol_kind (s) == FFEINFO_kindBLOCKDATA)
13216 && (ffesymbol_where (s) == FFEINFO_whereGLOBAL))
13218 ffecom_list_blockdata_
13219 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
13220 FFEINTRIN_specNONE,
13221 FFEINTRIN_impNONE),
13222 ffecom_list_blockdata_);
13226 /* This is where we finally notice that a symbol has partial initialization
13227 and finalize it. */
13229 if (ffesymbol_accretion (s) != NULL)
13231 assert (ffesymbol_init (s) == NULL);
13232 ffecom_notify_init_symbol (s);
13234 else if (((st = ffesymbol_storage (s)) != NULL)
13235 && ((st = ffestorag_parent (st)) != NULL)
13236 && (ffestorag_accretion (st) != NULL))
13238 assert (ffestorag_init (st) == NULL);
13239 ffecom_notify_init_storage (st);
13242 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13243 if ((ffesymbol_kind (s) == FFEINFO_kindCOMMON)
13244 && (ffesymbol_where (s) == FFEINFO_whereLOCAL)
13245 && (ffesymbol_storage (s) != NULL))
13247 ffecom_list_common_
13248 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
13249 FFEINTRIN_specNONE,
13250 FFEINTRIN_impNONE),
13251 ffecom_list_common_);
13258 /* ffecom_sym_exec_transition -- Perform exec transition on all symbols
13260 ffecom_sym_exec_transition();
13262 Does backend-specific stuff and also calls ffest_sym_exec_transition
13263 to do the necessary FFE stuff.
13265 See the long-winded description in ffecom_sym_learned for info
13266 on handling the situation where backtracking is inhibited. */
13269 ffecom_sym_exec_transition (ffesymbol s)
13271 s = ffest_sym_exec_transition (s);
13276 /* ffecom_sym_learned -- Initial or more info gained on symbol after exec
13279 s = ffecom_sym_learned(s);
13281 Called when a new symbol is seen after the exec transition or when more
13282 info (perhaps) is gained for an UNCERTAIN symbol. The symbol state when
13283 it arrives here is that all its latest info is updated already, so its
13284 state may be UNCERTAIN or UNDERSTOOD, it might already have the hook
13285 field filled in if its gone through here or exec_transition first, and
13288 The backend probably wants to check ffesymbol_retractable() to see if
13289 backtracking is in effect. If so, the FFE's changes to the symbol may
13290 be retracted (undone) or committed (ratified), at which time the
13291 appropriate ffecom_sym_retract or _commit function will be called
13294 If the backend has its own backtracking mechanism, great, use it so that
13295 committal is a simple operation. Though it doesn't make much difference,
13296 I suppose: the reason for tentative symbol evolution in the FFE is to
13297 enable error detection in weird incorrect statements early and to disable
13298 incorrect error detection on a correct statement. The backend is not
13299 likely to introduce any information that'll get involved in these
13300 considerations, so it is probably just fine that the implementation
13301 model for this fn and for _exec_transition is to not do anything
13302 (besides the required FFE stuff) if ffesymbol_retractable() returns TRUE
13303 and instead wait until ffecom_sym_commit is called (which it never
13304 will be as long as we're using ambiguity-detecting statement analysis in
13305 the FFE, which we are initially to shake out the code, but don't depend
13306 on this), otherwise go ahead and do whatever is needed.
13308 In essence, then, when this fn and _exec_transition get called while
13309 backtracking is enabled, a general mechanism would be to flag which (or
13310 both) of these were called (and in what order? neat question as to what
13311 might happen that I'm too lame to think through right now) and then when
13312 _commit is called reproduce the original calling sequence, if any, for
13313 the two fns (at which point backtracking will, of course, be disabled). */
13316 ffecom_sym_learned (ffesymbol s)
13318 ffestorag_exec_layout (s);
13323 /* ffecom_sym_retract -- Symbol's state being retracted from reality
13326 ffecom_sym_retract(s);
13328 Does whatever the backend needs when a symbol is retracted after having
13329 been backtrackable for a period of time. */
13331 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13333 ffecom_sym_retract (ffesymbol s UNUSED)
13335 assert (!ffesymbol_retractable ());
13337 #if 0 /* GCC doesn't commit any backtrackable sins,
13338 so nothing needed here. */
13339 switch (ffesymbol_hook (s).state)
13341 case 0: /* nothing happened yet. */
13344 case 1: /* exec transition happened. */
13347 case 2: /* learned happened. */
13350 case 3: /* learned then exec. */
13353 case 4: /* exec then learned. */
13357 assert ("bad hook state" == NULL);
13364 /* Create temporary gcc label. */
13366 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13368 ffecom_temp_label ()
13371 static int mynumber = 0;
13373 glabel = build_decl (LABEL_DECL,
13374 ffecom_get_invented_identifier ("__g77_label_%d",
13377 DECL_CONTEXT (glabel) = current_function_decl;
13378 DECL_MODE (glabel) = VOIDmode;
13384 /* Return an expression that is usable as an arg in a conditional context
13385 (IF, DO WHILE, .NOT., and so on).
13387 Use the one provided for the back end as of >2.6.0. */
13389 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13391 ffecom_truth_value (tree expr)
13393 return truthvalue_conversion (expr);
13397 /* Return the inversion of a truth value (the inversion of what
13398 ffecom_truth_value builds).
13400 Apparently invert_truthvalue, which is properly in the back end, is
13401 enough for now, so just use it. */
13403 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13405 ffecom_truth_value_invert (tree expr)
13407 return invert_truthvalue (ffecom_truth_value (expr));
13412 /* Return the tree that is the type of the expression, as would be
13413 returned in TREE_TYPE(ffecom_expr(expr)), without otherwise
13414 transforming the expression, generating temporaries, etc. */
13417 ffecom_type_expr (ffebld expr)
13419 ffeinfoBasictype bt;
13420 ffeinfoKindtype kt;
13423 assert (expr != NULL);
13425 bt = ffeinfo_basictype (ffebld_info (expr));
13426 kt = ffeinfo_kindtype (ffebld_info (expr));
13427 tree_type = ffecom_tree_type[bt][kt];
13429 switch (ffebld_op (expr))
13431 case FFEBLD_opCONTER:
13432 case FFEBLD_opSYMTER:
13433 case FFEBLD_opARRAYREF:
13434 case FFEBLD_opUPLUS:
13435 case FFEBLD_opPAREN:
13436 case FFEBLD_opUMINUS:
13438 case FFEBLD_opSUBTRACT:
13439 case FFEBLD_opMULTIPLY:
13440 case FFEBLD_opDIVIDE:
13441 case FFEBLD_opPOWER:
13443 case FFEBLD_opFUNCREF:
13444 case FFEBLD_opSUBRREF:
13448 case FFEBLD_opNEQV:
13450 case FFEBLD_opCONVERT:
13457 case FFEBLD_opPERCENT_LOC:
13460 case FFEBLD_opACCTER:
13461 case FFEBLD_opARRTER:
13462 case FFEBLD_opITEM:
13463 case FFEBLD_opSTAR:
13464 case FFEBLD_opBOUNDS:
13465 case FFEBLD_opREPEAT:
13466 case FFEBLD_opLABTER:
13467 case FFEBLD_opLABTOK:
13468 case FFEBLD_opIMPDO:
13469 case FFEBLD_opCONCATENATE:
13470 case FFEBLD_opSUBSTR:
13472 assert ("bad op for ffecom_type_expr" == NULL);
13473 /* Fall through. */
13475 return error_mark_node;
13479 /* Return PARM_DECL for arg#1 of master fn containing alternate ENTRY points
13481 If the PARM_DECL already exists, return it, else create it. It's an
13482 integer_type_node argument for the master function that implements a
13483 subroutine or function with more than one entrypoint and is bound at
13484 run time with the entrypoint number (0 for SUBROUTINE/FUNCTION, 1 for
13485 first ENTRY statement, and so on). */
13487 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13489 ffecom_which_entrypoint_decl ()
13491 assert (ffecom_which_entrypoint_decl_ != NULL_TREE);
13493 return ffecom_which_entrypoint_decl_;
13498 /* The following sections consists of private and public functions
13499 that have the same names and perform roughly the same functions
13500 as counterparts in the C front end. Changes in the C front end
13501 might affect how things should be done here. Only functions
13502 needed by the back end should be public here; the rest should
13503 be private (static in the C sense). Functions needed by other
13504 g77 front-end modules should be accessed by them via public
13505 ffecom_* names, which should themselves call private versions
13506 in this section so the private versions are easy to recognize
13507 when upgrading to a new gcc and finding interesting changes
13510 Functions named after rule "foo:" in c-parse.y are named
13511 "bison_rule_foo_" so they are easy to find. */
13513 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13516 bison_rule_pushlevel_ ()
13518 emit_line_note (input_filename, lineno);
13520 clear_last_expr ();
13521 expand_start_bindings (0);
13525 bison_rule_compstmt_ ()
13528 int keep = kept_level_p ();
13530 /* Make the temps go away. */
13532 current_binding_level->names = NULL_TREE;
13534 emit_line_note (input_filename, lineno);
13535 expand_end_bindings (getdecls (), keep, 0);
13536 t = poplevel (keep, 1, 0);
13541 /* Return a definition for a builtin function named NAME and whose data type
13542 is TYPE. TYPE should be a function type with argument types.
13543 FUNCTION_CODE tells later passes how to compile calls to this function.
13544 See tree.h for its possible values.
13546 If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME,
13547 the name to be called if we can't opencode the function. */
13550 builtin_function (const char *name, tree type, int function_code,
13551 enum built_in_class class,
13552 const char *library_name)
13554 tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
13555 DECL_EXTERNAL (decl) = 1;
13556 TREE_PUBLIC (decl) = 1;
13558 DECL_ASSEMBLER_NAME (decl) = get_identifier (library_name);
13559 make_decl_rtl (decl, NULL_PTR);
13561 DECL_BUILT_IN_CLASS (decl) = class;
13562 DECL_FUNCTION_CODE (decl) = function_code;
13567 /* Handle when a new declaration NEWDECL
13568 has the same name as an old one OLDDECL
13569 in the same binding contour.
13570 Prints an error message if appropriate.
13572 If safely possible, alter OLDDECL to look like NEWDECL, and return 1.
13573 Otherwise, return 0. */
13576 duplicate_decls (tree newdecl, tree olddecl)
13578 int types_match = 1;
13579 int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
13580 && DECL_INITIAL (newdecl) != 0);
13581 tree oldtype = TREE_TYPE (olddecl);
13582 tree newtype = TREE_TYPE (newdecl);
13584 if (olddecl == newdecl)
13587 if (TREE_CODE (newtype) == ERROR_MARK
13588 || TREE_CODE (oldtype) == ERROR_MARK)
13591 /* New decl is completely inconsistent with the old one =>
13592 tell caller to replace the old one.
13593 This is always an error except in the case of shadowing a builtin. */
13594 if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
13597 /* For real parm decl following a forward decl,
13598 return 1 so old decl will be reused. */
13599 if (types_match && TREE_CODE (newdecl) == PARM_DECL
13600 && TREE_ASM_WRITTEN (olddecl) && ! TREE_ASM_WRITTEN (newdecl))
13603 /* The new declaration is the same kind of object as the old one.
13604 The declarations may partially match. Print warnings if they don't
13605 match enough. Ultimately, copy most of the information from the new
13606 decl to the old one, and keep using the old one. */
13608 if (TREE_CODE (olddecl) == FUNCTION_DECL
13609 && DECL_BUILT_IN (olddecl))
13611 /* A function declaration for a built-in function. */
13612 if (!TREE_PUBLIC (newdecl))
13614 else if (!types_match)
13616 /* Accept the return type of the new declaration if same modes. */
13617 tree oldreturntype = TREE_TYPE (TREE_TYPE (olddecl));
13618 tree newreturntype = TREE_TYPE (TREE_TYPE (newdecl));
13620 if (TYPE_MODE (oldreturntype) == TYPE_MODE (newreturntype))
13622 /* Function types may be shared, so we can't just modify
13623 the return type of olddecl's function type. */
13625 = build_function_type (newreturntype,
13626 TYPE_ARG_TYPES (TREE_TYPE (olddecl)));
13630 TREE_TYPE (olddecl) = newtype;
13636 else if (TREE_CODE (olddecl) == FUNCTION_DECL
13637 && DECL_SOURCE_LINE (olddecl) == 0)
13639 /* A function declaration for a predeclared function
13640 that isn't actually built in. */
13641 if (!TREE_PUBLIC (newdecl))
13643 else if (!types_match)
13645 /* If the types don't match, preserve volatility indication.
13646 Later on, we will discard everything else about the
13647 default declaration. */
13648 TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
13652 /* Copy all the DECL_... slots specified in the new decl
13653 except for any that we copy here from the old type.
13655 Past this point, we don't change OLDTYPE and NEWTYPE
13656 even if we change the types of NEWDECL and OLDDECL. */
13660 /* Merge the data types specified in the two decls. */
13661 if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl))
13662 TREE_TYPE (newdecl)
13663 = TREE_TYPE (olddecl)
13664 = TREE_TYPE (newdecl);
13666 /* Lay the type out, unless already done. */
13667 if (oldtype != TREE_TYPE (newdecl))
13669 if (TREE_TYPE (newdecl) != error_mark_node)
13670 layout_type (TREE_TYPE (newdecl));
13671 if (TREE_CODE (newdecl) != FUNCTION_DECL
13672 && TREE_CODE (newdecl) != TYPE_DECL
13673 && TREE_CODE (newdecl) != CONST_DECL)
13674 layout_decl (newdecl, 0);
13678 /* Since the type is OLDDECL's, make OLDDECL's size go with. */
13679 DECL_SIZE (newdecl) = DECL_SIZE (olddecl);
13680 DECL_SIZE_UNIT (newdecl) = DECL_SIZE_UNIT (olddecl);
13681 if (TREE_CODE (olddecl) != FUNCTION_DECL)
13682 if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
13684 DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
13685 DECL_USER_ALIGN (newdecl) |= DECL_USER_ALIGN (olddecl);
13689 /* Keep the old rtl since we can safely use it. */
13690 DECL_RTL (newdecl) = DECL_RTL (olddecl);
13692 /* Merge the type qualifiers. */
13693 if (DECL_BUILT_IN_NONANSI (olddecl) && TREE_THIS_VOLATILE (olddecl)
13694 && !TREE_THIS_VOLATILE (newdecl))
13695 TREE_THIS_VOLATILE (olddecl) = 0;
13696 if (TREE_READONLY (newdecl))
13697 TREE_READONLY (olddecl) = 1;
13698 if (TREE_THIS_VOLATILE (newdecl))
13700 TREE_THIS_VOLATILE (olddecl) = 1;
13701 if (TREE_CODE (newdecl) == VAR_DECL)
13702 make_var_volatile (newdecl);
13705 /* Keep source location of definition rather than declaration.
13706 Likewise, keep decl at outer scope. */
13707 if ((DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0)
13708 || (DECL_CONTEXT (newdecl) != 0 && DECL_CONTEXT (olddecl) == 0))
13710 DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl);
13711 DECL_SOURCE_FILE (newdecl) = DECL_SOURCE_FILE (olddecl);
13713 if (DECL_CONTEXT (olddecl) == 0
13714 && TREE_CODE (newdecl) != FUNCTION_DECL)
13715 DECL_CONTEXT (newdecl) = 0;
13718 /* Merge the unused-warning information. */
13719 if (DECL_IN_SYSTEM_HEADER (olddecl))
13720 DECL_IN_SYSTEM_HEADER (newdecl) = 1;
13721 else if (DECL_IN_SYSTEM_HEADER (newdecl))
13722 DECL_IN_SYSTEM_HEADER (olddecl) = 1;
13724 /* Merge the initialization information. */
13725 if (DECL_INITIAL (newdecl) == 0)
13726 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
13728 /* Merge the section attribute.
13729 We want to issue an error if the sections conflict but that must be
13730 done later in decl_attributes since we are called before attributes
13732 if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
13733 DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
13736 if (TREE_CODE (newdecl) == FUNCTION_DECL)
13738 DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
13739 DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
13743 /* If cannot merge, then use the new type and qualifiers,
13744 and don't preserve the old rtl. */
13747 TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
13748 TREE_READONLY (olddecl) = TREE_READONLY (newdecl);
13749 TREE_THIS_VOLATILE (olddecl) = TREE_THIS_VOLATILE (newdecl);
13750 TREE_SIDE_EFFECTS (olddecl) = TREE_SIDE_EFFECTS (newdecl);
13753 /* Merge the storage class information. */
13754 /* For functions, static overrides non-static. */
13755 if (TREE_CODE (newdecl) == FUNCTION_DECL)
13757 TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl);
13758 /* This is since we don't automatically
13759 copy the attributes of NEWDECL into OLDDECL. */
13760 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
13761 /* If this clears `static', clear it in the identifier too. */
13762 if (! TREE_PUBLIC (olddecl))
13763 TREE_PUBLIC (DECL_NAME (olddecl)) = 0;
13765 if (DECL_EXTERNAL (newdecl))
13767 TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
13768 DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
13769 /* An extern decl does not override previous storage class. */
13770 TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
13774 TREE_STATIC (olddecl) = TREE_STATIC (newdecl);
13775 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
13778 /* If either decl says `inline', this fn is inline,
13779 unless its definition was passed already. */
13780 if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == 0)
13781 DECL_INLINE (olddecl) = 1;
13782 DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
13784 /* Get rid of any built-in function if new arg types don't match it
13785 or if we have a function definition. */
13786 if (TREE_CODE (newdecl) == FUNCTION_DECL
13787 && DECL_BUILT_IN (olddecl)
13788 && (!types_match || new_is_definition))
13790 TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
13791 DECL_BUILT_IN_CLASS (olddecl) = NOT_BUILT_IN;
13794 /* If redeclaring a builtin function, and not a definition,
13796 Also preserve various other info from the definition. */
13797 if (TREE_CODE (newdecl) == FUNCTION_DECL && !new_is_definition)
13799 if (DECL_BUILT_IN (olddecl))
13801 DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
13802 DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
13805 DECL_FRAME_SIZE (newdecl) = DECL_FRAME_SIZE (olddecl);
13807 DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
13808 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
13809 DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
13810 DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
13813 /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
13814 But preserve olddecl's DECL_UID. */
13816 register unsigned olddecl_uid = DECL_UID (olddecl);
13818 memcpy ((char *) olddecl + sizeof (struct tree_common),
13819 (char *) newdecl + sizeof (struct tree_common),
13820 sizeof (struct tree_decl) - sizeof (struct tree_common));
13821 DECL_UID (olddecl) = olddecl_uid;
13827 /* Finish processing of a declaration;
13828 install its initial value.
13829 If the length of an array type is not known before,
13830 it must be determined now, from the initial value, or it is an error. */
13833 finish_decl (tree decl, tree init, bool is_top_level)
13835 register tree type = TREE_TYPE (decl);
13836 int was_incomplete = (DECL_SIZE (decl) == 0);
13837 bool at_top_level = (current_binding_level == global_binding_level);
13838 bool top_level = is_top_level || at_top_level;
13840 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
13842 assert (!is_top_level || !at_top_level);
13844 if (TREE_CODE (decl) == PARM_DECL)
13845 assert (init == NULL_TREE);
13846 /* Remember that PARM_DECL doesn't have a DECL_INITIAL field per se -- it
13847 overlaps DECL_ARG_TYPE. */
13848 else if (init == NULL_TREE)
13849 assert (DECL_INITIAL (decl) == NULL_TREE);
13851 assert (DECL_INITIAL (decl) == error_mark_node);
13853 if (init != NULL_TREE)
13855 if (TREE_CODE (decl) != TYPE_DECL)
13856 DECL_INITIAL (decl) = init;
13859 /* typedef foo = bar; store the type of bar as the type of foo. */
13860 TREE_TYPE (decl) = TREE_TYPE (init);
13861 DECL_INITIAL (decl) = init = 0;
13865 /* Deduce size of array from initialization, if not already known */
13867 if (TREE_CODE (type) == ARRAY_TYPE
13868 && TYPE_DOMAIN (type) == 0
13869 && TREE_CODE (decl) != TYPE_DECL)
13871 assert (top_level);
13872 assert (was_incomplete);
13874 layout_decl (decl, 0);
13877 if (TREE_CODE (decl) == VAR_DECL)
13879 if (DECL_SIZE (decl) == NULL_TREE
13880 && TYPE_SIZE (TREE_TYPE (decl)) != NULL_TREE)
13881 layout_decl (decl, 0);
13883 if (DECL_SIZE (decl) == NULL_TREE
13884 && (TREE_STATIC (decl)
13886 /* A static variable with an incomplete type is an error if it is
13887 initialized. Also if it is not file scope. Otherwise, let it
13888 through, but if it is not `extern' then it may cause an error
13890 (DECL_INITIAL (decl) != 0 || DECL_CONTEXT (decl) != 0)
13892 /* An automatic variable with an incomplete type is an error. */
13893 !DECL_EXTERNAL (decl)))
13895 assert ("storage size not known" == NULL);
13899 if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
13900 && (DECL_SIZE (decl) != 0)
13901 && (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST))
13903 assert ("storage size not constant" == NULL);
13908 /* Output the assembler code and/or RTL code for variables and functions,
13909 unless the type is an undefined structure or union. If not, it will get
13910 done when the type is completed. */
13912 if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
13914 rest_of_decl_compilation (decl, NULL,
13915 DECL_CONTEXT (decl) == 0,
13918 if (DECL_CONTEXT (decl) != 0)
13920 /* Recompute the RTL of a local array now if it used to be an
13921 incomplete type. */
13923 && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
13925 /* If we used it already as memory, it must stay in memory. */
13926 TREE_ADDRESSABLE (decl) = TREE_USED (decl);
13927 /* If it's still incomplete now, no init will save it. */
13928 if (DECL_SIZE (decl) == 0)
13929 DECL_INITIAL (decl) = 0;
13930 expand_decl (decl);
13932 /* Compute and store the initial value. */
13933 if (TREE_CODE (decl) != FUNCTION_DECL)
13934 expand_decl_init (decl);
13937 else if (TREE_CODE (decl) == TYPE_DECL)
13939 rest_of_decl_compilation (decl, NULL_PTR,
13940 DECL_CONTEXT (decl) == 0,
13944 /* At the end of a declaration, throw away any variable type sizes of types
13945 defined inside that declaration. There is no use computing them in the
13946 following function definition. */
13947 if (current_binding_level == global_binding_level)
13948 get_pending_sizes ();
13951 /* Finish up a function declaration and compile that function
13952 all the way to assembler language output. The free the storage
13953 for the function definition.
13955 This is called after parsing the body of the function definition.
13957 NESTED is nonzero if the function being finished is nested in another. */
13960 finish_function (int nested)
13962 register tree fndecl = current_function_decl;
13964 assert (fndecl != NULL_TREE);
13965 if (TREE_CODE (fndecl) != ERROR_MARK)
13968 assert (DECL_CONTEXT (fndecl) != NULL_TREE);
13970 assert (DECL_CONTEXT (fndecl) == NULL_TREE);
13973 /* TREE_READONLY (fndecl) = 1;
13974 This caused &foo to be of type ptr-to-const-function
13975 which then got a warning when stored in a ptr-to-function variable. */
13977 poplevel (1, 0, 1);
13979 if (TREE_CODE (fndecl) != ERROR_MARK)
13981 BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
13983 /* Must mark the RESULT_DECL as being in this function. */
13985 DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
13987 /* Obey `register' declarations if `setjmp' is called in this fn. */
13988 /* Generate rtl for function exit. */
13989 expand_function_end (input_filename, lineno, 0);
13991 /* If this is a nested function, protect the local variables in the stack
13992 above us from being collected while we're compiling this function. */
13994 ggc_push_context ();
13996 /* Run the optimizers and output the assembler code for this function. */
13997 rest_of_compilation (fndecl);
13999 /* Undo the GC context switch. */
14001 ggc_pop_context ();
14004 if (TREE_CODE (fndecl) != ERROR_MARK
14006 && DECL_SAVED_INSNS (fndecl) == 0)
14008 /* Stop pointing to the local nodes about to be freed. */
14009 /* But DECL_INITIAL must remain nonzero so we know this was an actual
14010 function definition. */
14011 /* For a nested function, this is done in pop_f_function_context. */
14012 /* If rest_of_compilation set this to 0, leave it 0. */
14013 if (DECL_INITIAL (fndecl) != 0)
14014 DECL_INITIAL (fndecl) = error_mark_node;
14015 DECL_ARGUMENTS (fndecl) = 0;
14020 /* Let the error reporting routines know that we're outside a function.
14021 For a nested function, this value is used in pop_c_function_context
14022 and then reset via pop_function_context. */
14023 ffecom_outer_function_decl_ = current_function_decl = NULL;
14027 /* Plug-in replacement for identifying the name of a decl and, for a
14028 function, what we call it in diagnostics. For now, "program unit"
14029 should suffice, since it's a bit of a hassle to figure out which
14030 of several kinds of things it is. Note that it could conceivably
14031 be a statement function, which probably isn't really a program unit
14032 per se, but if that comes up, it should be easy to check (being a
14033 nested function and all). */
14035 static const char *
14036 lang_printable_name (tree decl, int v)
14038 /* Just to keep GCC quiet about the unused variable.
14039 In theory, differing values of V should produce different
14044 if (TREE_CODE (decl) == ERROR_MARK)
14045 return "erroneous code";
14046 return IDENTIFIER_POINTER (DECL_NAME (decl));
14050 /* g77's function to print out name of current function that caused
14055 lang_print_error_function (const char *file)
14057 static ffeglobal last_g = NULL;
14058 static ffesymbol last_s = NULL;
14063 if ((ffecom_primary_entry_ == NULL)
14064 || (ffesymbol_global (ffecom_primary_entry_) == NULL))
14072 g = ffesymbol_global (ffecom_primary_entry_);
14073 if (ffecom_nested_entry_ == NULL)
14075 s = ffecom_primary_entry_;
14076 switch (ffesymbol_kind (s))
14078 case FFEINFO_kindFUNCTION:
14082 case FFEINFO_kindSUBROUTINE:
14083 kind = "subroutine";
14086 case FFEINFO_kindPROGRAM:
14090 case FFEINFO_kindBLOCKDATA:
14091 kind = "block-data";
14095 kind = ffeinfo_kind_message (ffesymbol_kind (s));
14101 s = ffecom_nested_entry_;
14102 kind = "statement function";
14106 if ((last_g != g) || (last_s != s))
14109 fprintf (stderr, "%s: ", file);
14112 fprintf (stderr, "Outside of any program unit:\n");
14115 const char *name = ffesymbol_text (s);
14117 fprintf (stderr, "In %s `%s':\n", kind, name);
14126 /* Similar to `lookup_name' but look only at current binding level. */
14129 lookup_name_current_level (tree name)
14133 if (current_binding_level == global_binding_level)
14134 return IDENTIFIER_GLOBAL_VALUE (name);
14136 if (IDENTIFIER_LOCAL_VALUE (name) == 0)
14139 for (t = current_binding_level->names; t; t = TREE_CHAIN (t))
14140 if (DECL_NAME (t) == name)
14146 /* Create a new `struct binding_level'. */
14148 static struct binding_level *
14149 make_binding_level ()
14152 return (struct binding_level *) xmalloc (sizeof (struct binding_level));
14155 /* Save and restore the variables in this file and elsewhere
14156 that keep track of the progress of compilation of the current function.
14157 Used for nested functions. */
14161 struct f_function *next;
14163 tree shadowed_labels;
14164 struct binding_level *binding_level;
14167 struct f_function *f_function_chain;
14169 /* Restore the variables used during compilation of a C function. */
14172 pop_f_function_context ()
14174 struct f_function *p = f_function_chain;
14177 /* Bring back all the labels that were shadowed. */
14178 for (link = shadowed_labels; link; link = TREE_CHAIN (link))
14179 if (DECL_NAME (TREE_VALUE (link)) != 0)
14180 IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)))
14181 = TREE_VALUE (link);
14183 if (current_function_decl != error_mark_node
14184 && DECL_SAVED_INSNS (current_function_decl) == 0)
14186 /* Stop pointing to the local nodes about to be freed. */
14187 /* But DECL_INITIAL must remain nonzero so we know this was an actual
14188 function definition. */
14189 DECL_INITIAL (current_function_decl) = error_mark_node;
14190 DECL_ARGUMENTS (current_function_decl) = 0;
14193 pop_function_context ();
14195 f_function_chain = p->next;
14197 named_labels = p->named_labels;
14198 shadowed_labels = p->shadowed_labels;
14199 current_binding_level = p->binding_level;
14204 /* Save and reinitialize the variables
14205 used during compilation of a C function. */
14208 push_f_function_context ()
14210 struct f_function *p
14211 = (struct f_function *) xmalloc (sizeof (struct f_function));
14213 push_function_context ();
14215 p->next = f_function_chain;
14216 f_function_chain = p;
14218 p->named_labels = named_labels;
14219 p->shadowed_labels = shadowed_labels;
14220 p->binding_level = current_binding_level;
14224 push_parm_decl (tree parm)
14226 int old_immediate_size_expand = immediate_size_expand;
14228 /* Don't try computing parm sizes now -- wait till fn is called. */
14230 immediate_size_expand = 0;
14232 /* Fill in arg stuff. */
14234 DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
14235 DECL_ARG_TYPE_AS_WRITTEN (parm) = TREE_TYPE (parm);
14236 TREE_READONLY (parm) = 1; /* All implementation args are read-only. */
14238 parm = pushdecl (parm);
14240 immediate_size_expand = old_immediate_size_expand;
14242 finish_decl (parm, NULL_TREE, FALSE);
14245 /* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL, if appropriate. */
14248 pushdecl_top_level (x)
14252 register struct binding_level *b = current_binding_level;
14253 register tree f = current_function_decl;
14255 current_binding_level = global_binding_level;
14256 current_function_decl = NULL_TREE;
14258 current_binding_level = b;
14259 current_function_decl = f;
14263 /* Store the list of declarations of the current level.
14264 This is done for the parameter declarations of a function being defined,
14265 after they are modified in the light of any missing parameters. */
14271 return current_binding_level->names = decls;
14274 /* Store the parameter declarations into the current function declaration.
14275 This is called after parsing the parameter declarations, before
14276 digesting the body of the function.
14278 For an old-style definition, modify the function's type
14279 to specify at least the number of arguments. */
14282 store_parm_decls (int is_main_program UNUSED)
14284 register tree fndecl = current_function_decl;
14286 if (fndecl == error_mark_node)
14289 /* This is a chain of PARM_DECLs from old-style parm declarations. */
14290 DECL_ARGUMENTS (fndecl) = storedecls (nreverse (getdecls ()));
14292 /* Initialize the RTL code for the function. */
14294 init_function_start (fndecl, input_filename, lineno);
14296 /* Set up parameters and prepare for return, for the function. */
14298 expand_function_start (fndecl, 0);
14302 start_decl (tree decl, bool is_top_level)
14305 bool at_top_level = (current_binding_level == global_binding_level);
14306 bool top_level = is_top_level || at_top_level;
14308 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
14310 assert (!is_top_level || !at_top_level);
14312 if (DECL_INITIAL (decl) != NULL_TREE)
14314 assert (DECL_INITIAL (decl) == error_mark_node);
14315 assert (!DECL_EXTERNAL (decl));
14317 else if (top_level)
14318 assert ((TREE_STATIC (decl) == 1) || DECL_EXTERNAL (decl) == 1);
14320 /* For Fortran, we by default put things in .common when possible. */
14321 DECL_COMMON (decl) = 1;
14323 /* Add this decl to the current binding level. TEM may equal DECL or it may
14324 be a previous decl of the same name. */
14326 tem = pushdecl_top_level (decl);
14328 tem = pushdecl (decl);
14330 /* For a local variable, define the RTL now. */
14332 /* But not if this is a duplicate decl and we preserved the rtl from the
14333 previous one (which may or may not happen). */
14334 && DECL_RTL (tem) == 0)
14336 if (TYPE_SIZE (TREE_TYPE (tem)) != 0)
14338 else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
14339 && DECL_INITIAL (tem) != 0)
14346 /* Create the FUNCTION_DECL for a function definition.
14347 DECLSPECS and DECLARATOR are the parts of the declaration;
14348 they describe the function's name and the type it returns,
14349 but twisted together in a fashion that parallels the syntax of C.
14351 This function creates a binding context for the function body
14352 as well as setting up the FUNCTION_DECL in current_function_decl.
14354 Returns 1 on success. If the DECLARATOR is not suitable for a function
14355 (it defines a datum instead), we return 0, which tells
14356 yyparse to report a parse error.
14358 NESTED is nonzero for a function nested within another function. */
14361 start_function (tree name, tree type, int nested, int public)
14365 int old_immediate_size_expand = immediate_size_expand;
14368 shadowed_labels = 0;
14370 /* Don't expand any sizes in the return type of the function. */
14371 immediate_size_expand = 0;
14376 assert (current_function_decl != NULL_TREE);
14377 assert (DECL_CONTEXT (current_function_decl) == NULL_TREE);
14381 assert (current_function_decl == NULL_TREE);
14384 if (TREE_CODE (type) == ERROR_MARK)
14385 decl1 = current_function_decl = error_mark_node;
14388 decl1 = build_decl (FUNCTION_DECL,
14391 TREE_PUBLIC (decl1) = public ? 1 : 0;
14393 DECL_INLINE (decl1) = 1;
14394 TREE_STATIC (decl1) = 1;
14395 DECL_EXTERNAL (decl1) = 0;
14397 announce_function (decl1);
14399 /* Make the init_value nonzero so pushdecl knows this is not tentative.
14400 error_mark_node is replaced below (in poplevel) with the BLOCK. */
14401 DECL_INITIAL (decl1) = error_mark_node;
14403 /* Record the decl so that the function name is defined. If we already have
14404 a decl for this name, and it is a FUNCTION_DECL, use the old decl. */
14406 current_function_decl = pushdecl (decl1);
14410 ffecom_outer_function_decl_ = current_function_decl;
14413 current_binding_level->prep_state = 2;
14415 if (TREE_CODE (current_function_decl) != ERROR_MARK)
14417 make_decl_rtl (current_function_decl, NULL);
14419 restype = TREE_TYPE (TREE_TYPE (current_function_decl));
14420 DECL_RESULT (current_function_decl)
14421 = build_decl (RESULT_DECL, NULL_TREE, restype);
14424 if (!nested && (TREE_CODE (current_function_decl) != ERROR_MARK))
14425 TREE_ADDRESSABLE (current_function_decl) = 1;
14427 immediate_size_expand = old_immediate_size_expand;
14430 /* Here are the public functions the GNU back end needs. */
14433 convert (type, expr)
14436 register tree e = expr;
14437 register enum tree_code code = TREE_CODE (type);
14439 if (type == TREE_TYPE (e)
14440 || TREE_CODE (e) == ERROR_MARK)
14442 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
14443 return fold (build1 (NOP_EXPR, type, e));
14444 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
14445 || code == ERROR_MARK)
14446 return error_mark_node;
14447 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
14449 assert ("void value not ignored as it ought to be" == NULL);
14450 return error_mark_node;
14452 if (code == VOID_TYPE)
14453 return build1 (CONVERT_EXPR, type, e);
14454 if ((code != RECORD_TYPE)
14455 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
14456 e = ffecom_1 (REALPART_EXPR, TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e))),
14458 if (code == INTEGER_TYPE || code == ENUMERAL_TYPE)
14459 return fold (convert_to_integer (type, e));
14460 if (code == POINTER_TYPE)
14461 return fold (convert_to_pointer (type, e));
14462 if (code == REAL_TYPE)
14463 return fold (convert_to_real (type, e));
14464 if (code == COMPLEX_TYPE)
14465 return fold (convert_to_complex (type, e));
14466 if (code == RECORD_TYPE)
14467 return fold (ffecom_convert_to_complex_ (type, e));
14469 assert ("conversion to non-scalar type requested" == NULL);
14470 return error_mark_node;
14473 /* integrate_decl_tree calls this function, but since we don't use the
14474 DECL_LANG_SPECIFIC field, this is a no-op. */
14477 copy_lang_decl (node)
14482 /* Return the list of declarations of the current level.
14483 Note that this list is in reverse order unless/until
14484 you nreverse it; and when you do nreverse it, you must
14485 store the result back using `storedecls' or you will lose. */
14490 return current_binding_level->names;
14493 /* Nonzero if we are currently in the global binding level. */
14496 global_bindings_p ()
14498 return current_binding_level == global_binding_level;
14501 /* Print an error message for invalid use of an incomplete type.
14502 VALUE is the expression that was used (or 0 if that isn't known)
14503 and TYPE is the type that was invalid. */
14506 incomplete_type_error (value, type)
14510 if (TREE_CODE (type) == ERROR_MARK)
14513 assert ("incomplete type?!?" == NULL);
14516 /* Mark ARG for GC. */
14518 mark_binding_level (void *arg)
14520 struct binding_level *level = *(struct binding_level **) arg;
14524 ggc_mark_tree (level->names);
14525 ggc_mark_tree (level->blocks);
14526 ggc_mark_tree (level->this_block);
14527 level = level->level_chain;
14532 init_decl_processing ()
14534 static tree *const tree_roots[] = {
14535 ¤t_function_decl,
14537 &ffecom_tree_fun_type_void,
14538 &ffecom_integer_zero_node,
14539 &ffecom_integer_one_node,
14540 &ffecom_tree_subr_type,
14541 &ffecom_tree_ptr_to_subr_type,
14542 &ffecom_tree_blockdata_type,
14543 &ffecom_tree_xargc_,
14544 &ffecom_f2c_integer_type_node,
14545 &ffecom_f2c_ptr_to_integer_type_node,
14546 &ffecom_f2c_address_type_node,
14547 &ffecom_f2c_real_type_node,
14548 &ffecom_f2c_ptr_to_real_type_node,
14549 &ffecom_f2c_doublereal_type_node,
14550 &ffecom_f2c_complex_type_node,
14551 &ffecom_f2c_doublecomplex_type_node,
14552 &ffecom_f2c_longint_type_node,
14553 &ffecom_f2c_logical_type_node,
14554 &ffecom_f2c_flag_type_node,
14555 &ffecom_f2c_ftnlen_type_node,
14556 &ffecom_f2c_ftnlen_zero_node,
14557 &ffecom_f2c_ftnlen_one_node,
14558 &ffecom_f2c_ftnlen_two_node,
14559 &ffecom_f2c_ptr_to_ftnlen_type_node,
14560 &ffecom_f2c_ftnint_type_node,
14561 &ffecom_f2c_ptr_to_ftnint_type_node,
14562 &ffecom_outer_function_decl_,
14563 &ffecom_previous_function_decl_,
14564 &ffecom_which_entrypoint_decl_,
14565 &ffecom_float_zero_,
14566 &ffecom_float_half_,
14567 &ffecom_double_zero_,
14568 &ffecom_double_half_,
14569 &ffecom_func_result_,
14570 &ffecom_func_length_,
14571 &ffecom_multi_type_node_,
14572 &ffecom_multi_retval_,
14580 /* Record our roots. */
14581 for (i = 0; i < ARRAY_SIZE (tree_roots); i++)
14582 ggc_add_tree_root (tree_roots[i], 1);
14583 ggc_add_tree_root (&ffecom_tree_type[0][0],
14584 FFEINFO_basictype*FFEINFO_kindtype);
14585 ggc_add_tree_root (&ffecom_tree_fun_type[0][0],
14586 FFEINFO_basictype*FFEINFO_kindtype);
14587 ggc_add_tree_root (&ffecom_tree_ptr_to_fun_type[0][0],
14588 FFEINFO_basictype*FFEINFO_kindtype);
14589 ggc_add_tree_root (ffecom_gfrt_, FFECOM_gfrt);
14590 ggc_add_root (¤t_binding_level, 1, sizeof current_binding_level,
14591 mark_binding_level);
14592 ggc_add_root (&free_binding_level, 1, sizeof current_binding_level,
14593 mark_binding_level);
14594 ggc_add_root (&tracker_head, 1, sizeof tracker_head, mark_tracker_head);
14600 init_parse (filename)
14601 const char *filename;
14603 /* Open input file. */
14604 if (filename == 0 || !strcmp (filename, "-"))
14607 filename = "stdin";
14610 finput = fopen (filename, "r");
14612 pfatal_with_name (filename);
14614 #ifdef IO_BUFFER_SIZE
14615 setvbuf (finput, (char *) xmalloc (IO_BUFFER_SIZE), _IOFBF, IO_BUFFER_SIZE);
14618 /* Make identifier nodes long enough for the language-specific slots. */
14619 set_identifier_size (sizeof (struct lang_identifier));
14620 decl_printable_name = lang_printable_name;
14622 print_error_function = lang_print_error_function;
14634 /* Delete the node BLOCK from the current binding level.
14635 This is used for the block inside a stmt expr ({...})
14636 so that the block can be reinserted where appropriate. */
14639 delete_block (block)
14643 if (current_binding_level->blocks == block)
14644 current_binding_level->blocks = TREE_CHAIN (block);
14645 for (t = current_binding_level->blocks; t;)
14647 if (TREE_CHAIN (t) == block)
14648 TREE_CHAIN (t) = TREE_CHAIN (block);
14650 t = TREE_CHAIN (t);
14652 TREE_CHAIN (block) = NULL;
14653 /* Clear TREE_USED which is always set by poplevel.
14654 The flag is set again if insert_block is called. */
14655 TREE_USED (block) = 0;
14659 insert_block (block)
14662 TREE_USED (block) = 1;
14663 current_binding_level->blocks
14664 = chainon (current_binding_level->blocks, block);
14667 /* Each front end provides its own. */
14668 static void ffe_init PARAMS ((void));
14669 static void ffe_finish PARAMS ((void));
14670 static void ffe_init_options PARAMS ((void));
14672 struct lang_hooks lang_hooks = {ffe_init,
14676 NULL /* post_options */};
14678 /* used by print-tree.c */
14681 lang_print_xnode (file, node, indent)
14691 ffe_terminate_0 ();
14693 if (ffe_is_ffedebug ())
14694 malloc_pool_display (malloc_pool_image ());
14703 /* Return the typed-based alias set for T, which may be an expression
14704 or a type. Return -1 if we don't do anything special. */
14707 lang_get_alias_set (t)
14708 tree t ATTRIBUTE_UNUSED;
14710 /* We do not wish to use alias-set based aliasing at all. Used in the
14711 extreme (every object with its own set, with equivalences recorded)
14712 it might be helpful, but there are problems when it comes to inlining.
14713 We get on ok with flag_argument_noalias, and alias-set aliasing does
14714 currently limit how stack slots can be reused, which is a lose. */
14719 ffe_init_options ()
14721 /* Set default options for Fortran. */
14722 flag_move_all_movables = 1;
14723 flag_reduce_all_givs = 1;
14724 flag_argument_noalias = 2;
14725 flag_errno_math = 0;
14726 flag_complex_divide_method = 1;
14732 /* If the file is output from cpp, it should contain a first line
14733 `# 1 "real-filename"', and the current design of gcc (toplev.c
14734 in particular and the way it sets up information relied on by
14735 INCLUDE) requires that we read this now, and store the
14736 "real-filename" info in master_input_filename. Ask the lexer
14737 to try doing this. */
14738 ffelex_hash_kludge (finput);
14742 mark_addressable (exp)
14745 register tree x = exp;
14747 switch (TREE_CODE (x))
14750 case COMPONENT_REF:
14752 x = TREE_OPERAND (x, 0);
14756 TREE_ADDRESSABLE (x) = 1;
14763 if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x)
14764 && DECL_NONLOCAL (x))
14766 if (TREE_PUBLIC (x))
14768 assert ("address of global register var requested" == NULL);
14771 assert ("address of register variable requested" == NULL);
14773 else if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x))
14775 if (TREE_PUBLIC (x))
14777 assert ("address of global register var requested" == NULL);
14780 assert ("address of register var requested" == NULL);
14782 put_var_into_stack (x);
14785 case FUNCTION_DECL:
14786 TREE_ADDRESSABLE (x) = 1;
14787 #if 0 /* poplevel deals with this now. */
14788 if (DECL_CONTEXT (x) == 0)
14789 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;
14797 /* If DECL has a cleanup, build and return that cleanup here.
14798 This is a callback called by expand_expr. */
14801 maybe_build_cleanup (decl)
14804 /* There are no cleanups in Fortran. */
14808 /* Exit a binding level.
14809 Pop the level off, and restore the state of the identifier-decl mappings
14810 that were in effect when this level was entered.
14812 If KEEP is nonzero, this level had explicit declarations, so
14813 and create a "block" (a BLOCK node) for the level
14814 to record its declarations and subblocks for symbol table output.
14816 If FUNCTIONBODY is nonzero, this level is the body of a function,
14817 so create a block as if KEEP were set and also clear out all
14820 If REVERSE is nonzero, reverse the order of decls before putting
14821 them into the BLOCK. */
14824 poplevel (keep, reverse, functionbody)
14829 register tree link;
14830 /* The chain of decls was accumulated in reverse order.
14831 Put it into forward order, just for cleanliness. */
14833 tree subblocks = current_binding_level->blocks;
14836 int block_previously_created;
14838 /* Get the decls in the order they were written.
14839 Usually current_binding_level->names is in reverse order.
14840 But parameter decls were previously put in forward order. */
14843 current_binding_level->names
14844 = decls = nreverse (current_binding_level->names);
14846 decls = current_binding_level->names;
14848 /* Output any nested inline functions within this block
14849 if they weren't already output. */
14851 for (decl = decls; decl; decl = TREE_CHAIN (decl))
14852 if (TREE_CODE (decl) == FUNCTION_DECL
14853 && ! TREE_ASM_WRITTEN (decl)
14854 && DECL_INITIAL (decl) != 0
14855 && TREE_ADDRESSABLE (decl))
14857 /* If this decl was copied from a file-scope decl
14858 on account of a block-scope extern decl,
14859 propagate TREE_ADDRESSABLE to the file-scope decl.
14861 DECL_ABSTRACT_ORIGIN can be set to itself if warn_return_type is
14862 true, since then the decl goes through save_for_inline_copying. */
14863 if (DECL_ABSTRACT_ORIGIN (decl) != 0
14864 && DECL_ABSTRACT_ORIGIN (decl) != decl)
14865 TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
14866 else if (DECL_SAVED_INSNS (decl) != 0)
14868 push_function_context ();
14869 output_inline_function (decl);
14870 pop_function_context ();
14874 /* If there were any declarations or structure tags in that level,
14875 or if this level is a function body,
14876 create a BLOCK to record them for the life of this function. */
14879 block_previously_created = (current_binding_level->this_block != 0);
14880 if (block_previously_created)
14881 block = current_binding_level->this_block;
14882 else if (keep || functionbody)
14883 block = make_node (BLOCK);
14886 BLOCK_VARS (block) = decls;
14887 BLOCK_SUBBLOCKS (block) = subblocks;
14890 /* In each subblock, record that this is its superior. */
14892 for (link = subblocks; link; link = TREE_CHAIN (link))
14893 BLOCK_SUPERCONTEXT (link) = block;
14895 /* Clear out the meanings of the local variables of this level. */
14897 for (link = decls; link; link = TREE_CHAIN (link))
14899 if (DECL_NAME (link) != 0)
14901 /* If the ident. was used or addressed via a local extern decl,
14902 don't forget that fact. */
14903 if (DECL_EXTERNAL (link))
14905 if (TREE_USED (link))
14906 TREE_USED (DECL_NAME (link)) = 1;
14907 if (TREE_ADDRESSABLE (link))
14908 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1;
14910 IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = 0;
14914 /* If the level being exited is the top level of a function,
14915 check over all the labels, and clear out the current
14916 (function local) meanings of their names. */
14920 /* If this is the top level block of a function,
14921 the vars are the function's parameters.
14922 Don't leave them in the BLOCK because they are
14923 found in the FUNCTION_DECL instead. */
14925 BLOCK_VARS (block) = 0;
14928 /* Pop the current level, and free the structure for reuse. */
14931 register struct binding_level *level = current_binding_level;
14932 current_binding_level = current_binding_level->level_chain;
14934 level->level_chain = free_binding_level;
14935 free_binding_level = level;
14938 /* Dispose of the block that we just made inside some higher level. */
14940 && current_function_decl != error_mark_node)
14941 DECL_INITIAL (current_function_decl) = block;
14944 if (!block_previously_created)
14945 current_binding_level->blocks
14946 = chainon (current_binding_level->blocks, block);
14948 /* If we did not make a block for the level just exited,
14949 any blocks made for inner levels
14950 (since they cannot be recorded as subblocks in that level)
14951 must be carried forward so they will later become subblocks
14952 of something else. */
14953 else if (subblocks)
14954 current_binding_level->blocks
14955 = chainon (current_binding_level->blocks, subblocks);
14958 TREE_USED (block) = 1;
14963 print_lang_decl (file, node, indent)
14971 print_lang_identifier (file, node, indent)
14976 print_node (file, "global", IDENTIFIER_GLOBAL_VALUE (node), indent + 4);
14977 print_node (file, "local", IDENTIFIER_LOCAL_VALUE (node), indent + 4);
14981 print_lang_statistics ()
14986 print_lang_type (file, node, indent)
14993 /* Record a decl-node X as belonging to the current lexical scope.
14994 Check for errors (such as an incompatible declaration for the same
14995 name already seen in the same scope).
14997 Returns either X or an old decl for the same name.
14998 If an old decl is returned, it may have been smashed
14999 to agree with what X says. */
15006 register tree name = DECL_NAME (x);
15007 register struct binding_level *b = current_binding_level;
15009 if ((TREE_CODE (x) == FUNCTION_DECL)
15010 && (DECL_INITIAL (x) == 0)
15011 && DECL_EXTERNAL (x))
15012 DECL_CONTEXT (x) = NULL_TREE;
15014 DECL_CONTEXT (x) = current_function_decl;
15018 if (IDENTIFIER_INVENTED (name))
15021 DECL_ARTIFICIAL (x) = 1;
15023 DECL_IN_SYSTEM_HEADER (x) = 1;
15026 t = lookup_name_current_level (name);
15028 assert ((t == NULL_TREE) || (DECL_CONTEXT (x) == NULL_TREE));
15030 /* Don't push non-parms onto list for parms until we understand
15031 why we're doing this and whether it works. */
15033 assert ((b == global_binding_level)
15034 || !ffecom_transform_only_dummies_
15035 || TREE_CODE (x) == PARM_DECL);
15037 if ((t != NULL_TREE) && duplicate_decls (x, t))
15040 /* If we are processing a typedef statement, generate a whole new
15041 ..._TYPE node (which will be just an variant of the existing
15042 ..._TYPE node with identical properties) and then install the
15043 TYPE_DECL node generated to represent the typedef name as the
15044 TYPE_NAME of this brand new (duplicate) ..._TYPE node.
15046 The whole point here is to end up with a situation where each and every
15047 ..._TYPE node the compiler creates will be uniquely associated with
15048 AT MOST one node representing a typedef name. This way, even though
15049 the compiler substitutes corresponding ..._TYPE nodes for TYPE_DECL
15050 (i.e. "typedef name") nodes very early on, later parts of the
15051 compiler can always do the reverse translation and get back the
15052 corresponding typedef name. For example, given:
15054 typedef struct S MY_TYPE; MY_TYPE object;
15056 Later parts of the compiler might only know that `object' was of type
15057 `struct S' if it were not for code just below. With this code
15058 however, later parts of the compiler see something like:
15060 struct S' == struct S typedef struct S' MY_TYPE; struct S' object;
15062 And they can then deduce (from the node for type struct S') that the
15063 original object declaration was:
15067 Being able to do this is important for proper support of protoize, and
15068 also for generating precise symbolic debugging information which
15069 takes full account of the programmer's (typedef) vocabulary.
15071 Obviously, we don't want to generate a duplicate ..._TYPE node if the
15072 TYPE_DECL node that we are now processing really represents a
15073 standard built-in type.
15075 Since all standard types are effectively declared at line zero in the
15076 source file, we can easily check to see if we are working on a
15077 standard type by checking the current value of lineno. */
15079 if (TREE_CODE (x) == TYPE_DECL)
15081 if (DECL_SOURCE_LINE (x) == 0)
15083 if (TYPE_NAME (TREE_TYPE (x)) == 0)
15084 TYPE_NAME (TREE_TYPE (x)) = x;
15086 else if (TREE_TYPE (x) != error_mark_node)
15088 tree tt = TREE_TYPE (x);
15090 tt = build_type_copy (tt);
15091 TYPE_NAME (tt) = x;
15092 TREE_TYPE (x) = tt;
15096 /* This name is new in its binding level. Install the new declaration
15098 if (b == global_binding_level)
15099 IDENTIFIER_GLOBAL_VALUE (name) = x;
15101 IDENTIFIER_LOCAL_VALUE (name) = x;
15104 /* Put decls on list in reverse order. We will reverse them later if
15106 TREE_CHAIN (x) = b->names;
15112 /* Nonzero if the current level needs to have a BLOCK made. */
15119 for (decl = current_binding_level->names;
15121 decl = TREE_CHAIN (decl))
15123 if (TREE_USED (decl) || TREE_CODE (decl) != VAR_DECL
15124 || (DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl)))
15125 /* Currently, there aren't supposed to be non-artificial names
15126 at other than the top block for a function -- they're
15127 believed to always be temps. But it's wise to check anyway. */
15133 /* Enter a new binding level.
15134 If TAG_TRANSPARENT is nonzero, do so only for the name space of variables,
15135 not for that of tags. */
15138 pushlevel (tag_transparent)
15139 int tag_transparent;
15141 register struct binding_level *newlevel = NULL_BINDING_LEVEL;
15143 assert (! tag_transparent);
15145 if (current_binding_level == global_binding_level)
15150 /* Reuse or create a struct for this binding level. */
15152 if (free_binding_level)
15154 newlevel = free_binding_level;
15155 free_binding_level = free_binding_level->level_chain;
15159 newlevel = make_binding_level ();
15162 /* Add this level to the front of the chain (stack) of levels that
15165 *newlevel = clear_binding_level;
15166 newlevel->level_chain = current_binding_level;
15167 current_binding_level = newlevel;
15170 /* Set the BLOCK node for the innermost scope
15171 (the one we are currently in). */
15175 register tree block;
15177 current_binding_level->this_block = block;
15180 /* ~~gcc/tree.h *should* declare this, because toplev.c references it. */
15182 /* Can't 'yydebug' a front end not generated by yacc/bison! */
15185 set_yydebug (value)
15189 fprintf (stderr, "warning: no yacc/bison-generated output to debug!\n");
15193 signed_or_unsigned_type (unsignedp, type)
15199 if (! INTEGRAL_TYPE_P (type))
15201 if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node))
15202 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15203 if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
15204 return unsignedp ? unsigned_type_node : integer_type_node;
15205 if (TYPE_PRECISION (type) == TYPE_PRECISION (short_integer_type_node))
15206 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15207 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_integer_type_node))
15208 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15209 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_long_integer_type_node))
15210 return (unsignedp ? long_long_unsigned_type_node
15211 : long_long_integer_type_node);
15213 type2 = type_for_size (TYPE_PRECISION (type), unsignedp);
15214 if (type2 == NULL_TREE)
15224 tree type1 = TYPE_MAIN_VARIANT (type);
15225 ffeinfoKindtype kt;
15228 if (type1 == unsigned_char_type_node || type1 == char_type_node)
15229 return signed_char_type_node;
15230 if (type1 == unsigned_type_node)
15231 return integer_type_node;
15232 if (type1 == short_unsigned_type_node)
15233 return short_integer_type_node;
15234 if (type1 == long_unsigned_type_node)
15235 return long_integer_type_node;
15236 if (type1 == long_long_unsigned_type_node)
15237 return long_long_integer_type_node;
15238 #if 0 /* gcc/c-* files only */
15239 if (type1 == unsigned_intDI_type_node)
15240 return intDI_type_node;
15241 if (type1 == unsigned_intSI_type_node)
15242 return intSI_type_node;
15243 if (type1 == unsigned_intHI_type_node)
15244 return intHI_type_node;
15245 if (type1 == unsigned_intQI_type_node)
15246 return intQI_type_node;
15249 type2 = type_for_size (TYPE_PRECISION (type1), 0);
15250 if (type2 != NULL_TREE)
15253 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15255 type2 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
15257 if (type1 == type2)
15258 return ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15264 /* Prepare expr to be an argument of a TRUTH_NOT_EXPR,
15265 or validate its data type for an `if' or `while' statement or ?..: exp.
15267 This preparation consists of taking the ordinary
15268 representation of an expression expr and producing a valid tree
15269 boolean expression describing whether expr is nonzero. We could
15270 simply always do build_binary_op (NE_EXPR, expr, integer_zero_node, 1),
15271 but we optimize comparisons, &&, ||, and !.
15273 The resulting type should always be `integer_type_node'. */
15276 truthvalue_conversion (expr)
15279 if (TREE_CODE (expr) == ERROR_MARK)
15282 #if 0 /* This appears to be wrong for C++. */
15283 /* These really should return error_mark_node after 2.4 is stable.
15284 But not all callers handle ERROR_MARK properly. */
15285 switch (TREE_CODE (TREE_TYPE (expr)))
15288 error ("struct type value used where scalar is required");
15289 return integer_zero_node;
15292 error ("union type value used where scalar is required");
15293 return integer_zero_node;
15296 error ("array type value used where scalar is required");
15297 return integer_zero_node;
15304 switch (TREE_CODE (expr))
15306 /* It is simpler and generates better code to have only TRUTH_*_EXPR
15307 or comparison expressions as truth values at this level. */
15309 case COMPONENT_REF:
15310 /* A one-bit unsigned bit-field is already acceptable. */
15311 if (1 == TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (expr, 1)))
15312 && TREE_UNSIGNED (TREE_OPERAND (expr, 1)))
15318 /* It is simpler and generates better code to have only TRUTH_*_EXPR
15319 or comparison expressions as truth values at this level. */
15321 if (integer_zerop (TREE_OPERAND (expr, 1)))
15322 return build_unary_op (TRUTH_NOT_EXPR, TREE_OPERAND (expr, 0), 0);
15324 case NE_EXPR: case LE_EXPR: case GE_EXPR: case LT_EXPR: case GT_EXPR:
15325 case TRUTH_ANDIF_EXPR:
15326 case TRUTH_ORIF_EXPR:
15327 case TRUTH_AND_EXPR:
15328 case TRUTH_OR_EXPR:
15329 case TRUTH_XOR_EXPR:
15330 TREE_TYPE (expr) = integer_type_node;
15337 return integer_zerop (expr) ? integer_zero_node : integer_one_node;
15340 return real_zerop (expr) ? integer_zero_node : integer_one_node;
15343 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 0)))
15344 return build (COMPOUND_EXPR, integer_type_node,
15345 TREE_OPERAND (expr, 0), integer_one_node);
15347 return integer_one_node;
15350 return ffecom_2 ((TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
15351 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
15353 truthvalue_conversion (TREE_OPERAND (expr, 0)),
15354 truthvalue_conversion (TREE_OPERAND (expr, 1)));
15360 /* These don't change whether an object is non-zero or zero. */
15361 return truthvalue_conversion (TREE_OPERAND (expr, 0));
15365 /* These don't change whether an object is zero or non-zero, but
15366 we can't ignore them if their second arg has side-effects. */
15367 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
15368 return build (COMPOUND_EXPR, integer_type_node, TREE_OPERAND (expr, 1),
15369 truthvalue_conversion (TREE_OPERAND (expr, 0)));
15371 return truthvalue_conversion (TREE_OPERAND (expr, 0));
15374 /* Distribute the conversion into the arms of a COND_EXPR. */
15375 return fold (build (COND_EXPR, integer_type_node, TREE_OPERAND (expr, 0),
15376 truthvalue_conversion (TREE_OPERAND (expr, 1)),
15377 truthvalue_conversion (TREE_OPERAND (expr, 2))));
15380 /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
15381 since that affects how `default_conversion' will behave. */
15382 if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE
15383 || TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE)
15385 /* fall through... */
15387 /* If this is widening the argument, we can ignore it. */
15388 if (TYPE_PRECISION (TREE_TYPE (expr))
15389 >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))
15390 return truthvalue_conversion (TREE_OPERAND (expr, 0));
15394 /* With IEEE arithmetic, x - x may not equal 0, so we can't optimize
15396 if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
15397 && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE)
15399 /* fall through... */
15401 /* This and MINUS_EXPR can be changed into a comparison of the
15403 if (TREE_TYPE (TREE_OPERAND (expr, 0))
15404 == TREE_TYPE (TREE_OPERAND (expr, 1)))
15405 return ffecom_2 (NE_EXPR, integer_type_node,
15406 TREE_OPERAND (expr, 0),
15407 TREE_OPERAND (expr, 1));
15408 return ffecom_2 (NE_EXPR, integer_type_node,
15409 TREE_OPERAND (expr, 0),
15410 fold (build1 (NOP_EXPR,
15411 TREE_TYPE (TREE_OPERAND (expr, 0)),
15412 TREE_OPERAND (expr, 1))));
15415 if (integer_onep (TREE_OPERAND (expr, 1)))
15420 #if 0 /* No such thing in Fortran. */
15421 if (warn_parentheses && C_EXP_ORIGINAL_CODE (expr) == MODIFY_EXPR)
15422 warning ("suggest parentheses around assignment used as truth value");
15430 if (TREE_CODE (TREE_TYPE (expr)) == COMPLEX_TYPE)
15432 ((TREE_SIDE_EFFECTS (expr)
15433 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
15435 truthvalue_conversion (ffecom_1 (REALPART_EXPR,
15436 TREE_TYPE (TREE_TYPE (expr)),
15438 truthvalue_conversion (ffecom_1 (IMAGPART_EXPR,
15439 TREE_TYPE (TREE_TYPE (expr)),
15442 return ffecom_2 (NE_EXPR, integer_type_node,
15444 convert (TREE_TYPE (expr), integer_zero_node));
15448 type_for_mode (mode, unsignedp)
15449 enum machine_mode mode;
15456 if (mode == TYPE_MODE (integer_type_node))
15457 return unsignedp ? unsigned_type_node : integer_type_node;
15459 if (mode == TYPE_MODE (signed_char_type_node))
15460 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15462 if (mode == TYPE_MODE (short_integer_type_node))
15463 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15465 if (mode == TYPE_MODE (long_integer_type_node))
15466 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15468 if (mode == TYPE_MODE (long_long_integer_type_node))
15469 return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
15471 #if HOST_BITS_PER_WIDE_INT >= 64
15472 if (mode == TYPE_MODE (intTI_type_node))
15473 return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
15476 if (mode == TYPE_MODE (float_type_node))
15477 return float_type_node;
15479 if (mode == TYPE_MODE (double_type_node))
15480 return double_type_node;
15482 if (mode == TYPE_MODE (build_pointer_type (char_type_node)))
15483 return build_pointer_type (char_type_node);
15485 if (mode == TYPE_MODE (build_pointer_type (integer_type_node)))
15486 return build_pointer_type (integer_type_node);
15488 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
15489 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
15491 if (((t = ffecom_tree_type[i][j]) != NULL_TREE)
15492 && (mode == TYPE_MODE (t)))
15494 if ((i == FFEINFO_basictypeINTEGER) && unsignedp)
15495 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][j];
15505 type_for_size (bits, unsignedp)
15509 ffeinfoKindtype kt;
15512 if (bits == TYPE_PRECISION (integer_type_node))
15513 return unsignedp ? unsigned_type_node : integer_type_node;
15515 if (bits == TYPE_PRECISION (signed_char_type_node))
15516 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15518 if (bits == TYPE_PRECISION (short_integer_type_node))
15519 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15521 if (bits == TYPE_PRECISION (long_integer_type_node))
15522 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15524 if (bits == TYPE_PRECISION (long_long_integer_type_node))
15525 return (unsignedp ? long_long_unsigned_type_node
15526 : long_long_integer_type_node);
15528 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15530 type_node = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15532 if ((type_node != NULL_TREE) && (bits == TYPE_PRECISION (type_node)))
15533 return unsignedp ? ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt]
15541 unsigned_type (type)
15544 tree type1 = TYPE_MAIN_VARIANT (type);
15545 ffeinfoKindtype kt;
15548 if (type1 == signed_char_type_node || type1 == char_type_node)
15549 return unsigned_char_type_node;
15550 if (type1 == integer_type_node)
15551 return unsigned_type_node;
15552 if (type1 == short_integer_type_node)
15553 return short_unsigned_type_node;
15554 if (type1 == long_integer_type_node)
15555 return long_unsigned_type_node;
15556 if (type1 == long_long_integer_type_node)
15557 return long_long_unsigned_type_node;
15558 #if 0 /* gcc/c-* files only */
15559 if (type1 == intDI_type_node)
15560 return unsigned_intDI_type_node;
15561 if (type1 == intSI_type_node)
15562 return unsigned_intSI_type_node;
15563 if (type1 == intHI_type_node)
15564 return unsigned_intHI_type_node;
15565 if (type1 == intQI_type_node)
15566 return unsigned_intQI_type_node;
15569 type2 = type_for_size (TYPE_PRECISION (type1), 1);
15570 if (type2 != NULL_TREE)
15573 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15575 type2 = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15577 if (type1 == type2)
15578 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
15586 union tree_node *t ATTRIBUTE_UNUSED;
15588 if (TREE_CODE (t) == IDENTIFIER_NODE)
15590 struct lang_identifier *i = (struct lang_identifier *) t;
15591 ggc_mark_tree (IDENTIFIER_GLOBAL_VALUE (i));
15592 ggc_mark_tree (IDENTIFIER_LOCAL_VALUE (i));
15593 ggc_mark_tree (IDENTIFIER_LABEL_VALUE (i));
15595 else if (TYPE_P (t) && TYPE_LANG_SPECIFIC (t))
15596 ggc_mark (TYPE_LANG_SPECIFIC (t));
15599 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
15601 #if FFECOM_GCC_INCLUDE
15603 /* From gcc/cccp.c, the code to handle -I. */
15605 /* Skip leading "./" from a directory name.
15606 This may yield the empty string, which represents the current directory. */
15608 static const char *
15609 skip_redundant_dir_prefix (const char *dir)
15611 while (dir[0] == '.' && dir[1] == '/')
15612 for (dir += 2; *dir == '/'; dir++)
15614 if (dir[0] == '.' && !dir[1])
15619 /* The file_name_map structure holds a mapping of file names for a
15620 particular directory. This mapping is read from the file named
15621 FILE_NAME_MAP_FILE in that directory. Such a file can be used to
15622 map filenames on a file system with severe filename restrictions,
15623 such as DOS. The format of the file name map file is just a series
15624 of lines with two tokens on each line. The first token is the name
15625 to map, and the second token is the actual name to use. */
15627 struct file_name_map
15629 struct file_name_map *map_next;
15634 #define FILE_NAME_MAP_FILE "header.gcc"
15636 /* Current maximum length of directory names in the search path
15637 for include files. (Altered as we get more of them.) */
15639 static int max_include_len = 0;
15641 struct file_name_list
15643 struct file_name_list *next;
15645 /* Mapping of file names for this directory. */
15646 struct file_name_map *name_map;
15647 /* Non-zero if name_map is valid. */
15651 static struct file_name_list *include = NULL; /* First dir to search */
15652 static struct file_name_list *last_include = NULL; /* Last in chain */
15654 /* I/O buffer structure.
15655 The `fname' field is nonzero for source files and #include files
15656 and for the dummy text used for -D and -U.
15657 It is zero for rescanning results of macro expansion
15658 and for expanding macro arguments. */
15659 #define INPUT_STACK_MAX 400
15660 static struct file_buf {
15662 /* Filename specified with #line command. */
15663 const char *nominal_fname;
15664 /* Record where in the search path this file was found.
15665 For #include_next. */
15666 struct file_name_list *dir;
15668 ffewhereColumn column;
15669 } instack[INPUT_STACK_MAX];
15671 static int last_error_tick = 0; /* Incremented each time we print it. */
15672 static int input_file_stack_tick = 0; /* Incremented when status changes. */
15674 /* Current nesting level of input sources.
15675 `instack[indepth]' is the level currently being read. */
15676 static int indepth = -1;
15678 typedef struct file_buf FILE_BUF;
15680 typedef unsigned char U_CHAR;
15682 /* table to tell if char can be part of a C identifier. */
15683 U_CHAR is_idchar[256];
15684 /* table to tell if char can be first char of a c identifier. */
15685 U_CHAR is_idstart[256];
15686 /* table to tell if c is horizontal space. */
15687 U_CHAR is_hor_space[256];
15688 /* table to tell if c is horizontal or vertical space. */
15689 static U_CHAR is_space[256];
15691 #define SKIP_WHITE_SPACE(p) do { while (is_hor_space[*p]) p++; } while (0)
15692 #define SKIP_ALL_WHITE_SPACE(p) do { while (is_space[*p]) p++; } while (0)
15694 /* Nonzero means -I- has been seen,
15695 so don't look for #include "foo" the source-file directory. */
15696 static int ignore_srcdir;
15698 #ifndef INCLUDE_LEN_FUDGE
15699 #define INCLUDE_LEN_FUDGE 0
15702 static void append_include_chain (struct file_name_list *first,
15703 struct file_name_list *last);
15704 static FILE *open_include_file (char *filename,
15705 struct file_name_list *searchptr);
15706 static void print_containing_files (ffebadSeverity sev);
15707 static const char *skip_redundant_dir_prefix (const char *);
15708 static char *read_filename_string (int ch, FILE *f);
15709 static struct file_name_map *read_name_map (const char *dirname);
15711 /* Append a chain of `struct file_name_list's
15712 to the end of the main include chain.
15713 FIRST is the beginning of the chain to append, and LAST is the end. */
15716 append_include_chain (first, last)
15717 struct file_name_list *first, *last;
15719 struct file_name_list *dir;
15721 if (!first || !last)
15727 last_include->next = first;
15729 for (dir = first; ; dir = dir->next) {
15730 int len = strlen (dir->fname) + INCLUDE_LEN_FUDGE;
15731 if (len > max_include_len)
15732 max_include_len = len;
15738 last_include = last;
15741 /* Try to open include file FILENAME. SEARCHPTR is the directory
15742 being tried from the include file search path. This function maps
15743 filenames on file systems based on information read by
15747 open_include_file (filename, searchptr)
15749 struct file_name_list *searchptr;
15751 register struct file_name_map *map;
15752 register char *from;
15755 if (searchptr && ! searchptr->got_name_map)
15757 searchptr->name_map = read_name_map (searchptr->fname
15758 ? searchptr->fname : ".");
15759 searchptr->got_name_map = 1;
15762 /* First check the mapping for the directory we are using. */
15763 if (searchptr && searchptr->name_map)
15766 if (searchptr->fname)
15767 from += strlen (searchptr->fname) + 1;
15768 for (map = searchptr->name_map; map; map = map->map_next)
15770 if (! strcmp (map->map_from, from))
15772 /* Found a match. */
15773 return fopen (map->map_to, "r");
15778 /* Try to find a mapping file for the particular directory we are
15779 looking in. Thus #include <sys/types.h> will look up sys/types.h
15780 in /usr/include/header.gcc and look up types.h in
15781 /usr/include/sys/header.gcc. */
15782 p = strrchr (filename, '/');
15783 #ifdef DIR_SEPARATOR
15784 if (! p) p = strrchr (filename, DIR_SEPARATOR);
15786 char *tmp = strrchr (filename, DIR_SEPARATOR);
15787 if (tmp != NULL && tmp > p) p = tmp;
15793 && searchptr->fname
15794 && strlen (searchptr->fname) == (size_t) (p - filename)
15795 && ! strncmp (searchptr->fname, filename, (int) (p - filename)))
15797 /* FILENAME is in SEARCHPTR, which we've already checked. */
15798 return fopen (filename, "r");
15804 map = read_name_map (".");
15808 dir = (char *) xmalloc (p - filename + 1);
15809 memcpy (dir, filename, p - filename);
15810 dir[p - filename] = '\0';
15812 map = read_name_map (dir);
15815 for (; map; map = map->map_next)
15816 if (! strcmp (map->map_from, from))
15817 return fopen (map->map_to, "r");
15819 return fopen (filename, "r");
15822 /* Print the file names and line numbers of the #include
15823 commands which led to the current file. */
15826 print_containing_files (ffebadSeverity sev)
15828 FILE_BUF *ip = NULL;
15834 /* If stack of files hasn't changed since we last printed
15835 this info, don't repeat it. */
15836 if (last_error_tick == input_file_stack_tick)
15839 for (i = indepth; i >= 0; i--)
15840 if (instack[i].fname != NULL) {
15845 /* Give up if we don't find a source file. */
15849 /* Find the other, outer source files. */
15850 for (i--; i >= 0; i--)
15851 if (instack[i].fname != NULL)
15857 str1 = "In file included";
15869 ffebad_start_msg ("%A from %B at %0%C", sev);
15870 ffebad_here (0, ip->line, ip->column);
15871 ffebad_string (str1);
15872 ffebad_string (ip->nominal_fname);
15873 ffebad_string (str2);
15877 /* Record we have printed the status as of this time. */
15878 last_error_tick = input_file_stack_tick;
15881 /* Read a space delimited string of unlimited length from a stdio
15885 read_filename_string (ch, f)
15893 set = alloc = xmalloc (len + 1);
15894 if (! is_space[ch])
15897 while ((ch = getc (f)) != EOF && ! is_space[ch])
15899 if (set - alloc == len)
15902 alloc = xrealloc (alloc, len + 1);
15903 set = alloc + len / 2;
15913 /* Read the file name map file for DIRNAME. */
15915 static struct file_name_map *
15916 read_name_map (dirname)
15917 const char *dirname;
15919 /* This structure holds a linked list of file name maps, one per
15921 struct file_name_map_list
15923 struct file_name_map_list *map_list_next;
15924 char *map_list_name;
15925 struct file_name_map *map_list_map;
15927 static struct file_name_map_list *map_list;
15928 register struct file_name_map_list *map_list_ptr;
15932 int separator_needed;
15934 dirname = skip_redundant_dir_prefix (dirname);
15936 for (map_list_ptr = map_list; map_list_ptr;
15937 map_list_ptr = map_list_ptr->map_list_next)
15938 if (! strcmp (map_list_ptr->map_list_name, dirname))
15939 return map_list_ptr->map_list_map;
15941 map_list_ptr = ((struct file_name_map_list *)
15942 xmalloc (sizeof (struct file_name_map_list)));
15943 map_list_ptr->map_list_name = xstrdup (dirname);
15944 map_list_ptr->map_list_map = NULL;
15946 dirlen = strlen (dirname);
15947 separator_needed = dirlen != 0 && dirname[dirlen - 1] != '/';
15948 name = (char *) xmalloc (dirlen + strlen (FILE_NAME_MAP_FILE) + 2);
15949 strcpy (name, dirname);
15950 name[dirlen] = '/';
15951 strcpy (name + dirlen + separator_needed, FILE_NAME_MAP_FILE);
15952 f = fopen (name, "r");
15955 map_list_ptr->map_list_map = NULL;
15960 while ((ch = getc (f)) != EOF)
15963 struct file_name_map *ptr;
15967 from = read_filename_string (ch, f);
15968 while ((ch = getc (f)) != EOF && is_hor_space[ch])
15970 to = read_filename_string (ch, f);
15972 ptr = ((struct file_name_map *)
15973 xmalloc (sizeof (struct file_name_map)));
15974 ptr->map_from = from;
15976 /* Make the real filename absolute. */
15981 ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
15982 strcpy (ptr->map_to, dirname);
15983 ptr->map_to[dirlen] = '/';
15984 strcpy (ptr->map_to + dirlen + separator_needed, to);
15988 ptr->map_next = map_list_ptr->map_list_map;
15989 map_list_ptr->map_list_map = ptr;
15991 while ((ch = getc (f)) != '\n')
15998 map_list_ptr->map_list_next = map_list;
15999 map_list = map_list_ptr;
16001 return map_list_ptr->map_list_map;
16005 ffecom_file_ (const char *name)
16009 /* Do partial setup of input buffer for the sake of generating
16010 early #line directives (when -g is in effect). */
16012 fp = &instack[++indepth];
16013 memset ((char *) fp, 0, sizeof (FILE_BUF));
16016 fp->nominal_fname = fp->fname = name;
16019 /* Initialize syntactic classifications of characters. */
16022 ffecom_initialize_char_syntax_ ()
16027 * Set up is_idchar and is_idstart tables. These should be
16028 * faster than saying (is_alpha (c) || c == '_'), etc.
16029 * Set up these things before calling any routines tthat
16032 for (i = 'a'; i <= 'z'; i++) {
16033 is_idchar[i - 'a' + 'A'] = 1;
16035 is_idstart[i - 'a' + 'A'] = 1;
16038 for (i = '0'; i <= '9'; i++)
16040 is_idchar['_'] = 1;
16041 is_idstart['_'] = 1;
16043 /* horizontal space table */
16044 is_hor_space[' '] = 1;
16045 is_hor_space['\t'] = 1;
16046 is_hor_space['\v'] = 1;
16047 is_hor_space['\f'] = 1;
16048 is_hor_space['\r'] = 1;
16051 is_space['\t'] = 1;
16052 is_space['\v'] = 1;
16053 is_space['\f'] = 1;
16054 is_space['\n'] = 1;
16055 is_space['\r'] = 1;
16059 ffecom_close_include_ (FILE *f)
16064 input_file_stack_tick++;
16066 ffewhere_line_kill (instack[indepth].line);
16067 ffewhere_column_kill (instack[indepth].column);
16071 ffecom_decode_include_option_ (char *spec)
16073 struct file_name_list *dirtmp;
16075 if (! ignore_srcdir && !strcmp (spec, "-"))
16079 dirtmp = (struct file_name_list *)
16080 xmalloc (sizeof (struct file_name_list));
16081 dirtmp->next = 0; /* New one goes on the end */
16083 dirtmp->fname = spec;
16085 fatal ("Directory name must immediately follow -I option with no intervening spaces, as in `-Idir', not `-I dir'");
16086 dirtmp->got_name_map = 0;
16087 append_include_chain (dirtmp, dirtmp);
16092 /* Open INCLUDEd file. */
16095 ffecom_open_include_ (char *name, ffewhereLine l, ffewhereColumn c)
16098 size_t flen = strlen (fbeg);
16099 struct file_name_list *search_start = include; /* Chain of dirs to search */
16100 struct file_name_list dsp[1]; /* First in chain, if #include "..." */
16101 struct file_name_list *searchptr = 0;
16102 char *fname; /* Dynamically allocated fname buffer */
16109 dsp[0].fname = NULL;
16111 /* If -I- was specified, don't search current dir, only spec'd ones. */
16112 if (!ignore_srcdir)
16114 for (fp = &instack[indepth]; fp >= instack; fp--)
16120 if ((nam = fp->nominal_fname) != NULL)
16122 /* Found a named file. Figure out dir of the file,
16123 and put it in front of the search list. */
16124 dsp[0].next = search_start;
16125 search_start = dsp;
16127 ep = strrchr (nam, '/');
16128 #ifdef DIR_SEPARATOR
16129 if (ep == NULL) ep = strrchr (nam, DIR_SEPARATOR);
16131 char *tmp = strrchr (nam, DIR_SEPARATOR);
16132 if (tmp != NULL && tmp > ep) ep = tmp;
16136 ep = strrchr (nam, ']');
16137 if (ep == NULL) ep = strrchr (nam, '>');
16138 if (ep == NULL) ep = strrchr (nam, ':');
16139 if (ep != NULL) ep++;
16144 dsp[0].fname = (char *) xmalloc (n + 1);
16145 strncpy (dsp[0].fname, nam, n);
16146 dsp[0].fname[n] = '\0';
16147 if (n + INCLUDE_LEN_FUDGE > max_include_len)
16148 max_include_len = n + INCLUDE_LEN_FUDGE;
16151 dsp[0].fname = NULL; /* Current directory */
16152 dsp[0].got_name_map = 0;
16158 /* Allocate this permanently, because it gets stored in the definitions
16160 fname = xmalloc (max_include_len + flen + 4);
16161 /* + 2 above for slash and terminating null. */
16162 /* + 2 added for '.h' on VMS (to support '#include filename') (NOT USED
16165 /* If specified file name is absolute, just open it. */
16168 #ifdef DIR_SEPARATOR
16169 || *fbeg == DIR_SEPARATOR
16173 strncpy (fname, (char *) fbeg, flen);
16175 f = open_include_file (fname, NULL_PTR);
16181 /* Search directory path, trying to open the file.
16182 Copy each filename tried into FNAME. */
16184 for (searchptr = search_start; searchptr; searchptr = searchptr->next)
16186 if (searchptr->fname)
16188 /* The empty string in a search path is ignored.
16189 This makes it possible to turn off entirely
16190 a standard piece of the list. */
16191 if (searchptr->fname[0] == 0)
16193 strcpy (fname, skip_redundant_dir_prefix (searchptr->fname));
16194 if (fname[0] && fname[strlen (fname) - 1] != '/')
16195 strcat (fname, "/");
16196 fname[strlen (fname) + flen] = 0;
16201 strncat (fname, fbeg, flen);
16203 /* Change this 1/2 Unix 1/2 VMS file specification into a
16204 full VMS file specification */
16205 if (searchptr->fname && (searchptr->fname[0] != 0))
16207 /* Fix up the filename */
16208 hack_vms_include_specification (fname);
16212 /* This is a normal VMS filespec, so use it unchanged. */
16213 strncpy (fname, (char *) fbeg, flen);
16215 #if 0 /* Not for g77. */
16216 /* if it's '#include filename', add the missing .h */
16217 if (strchr (fname, '.') == NULL)
16218 strcat (fname, ".h");
16222 f = open_include_file (fname, searchptr);
16224 if (f == NULL && errno == EACCES)
16226 print_containing_files (FFEBAD_severityWARNING);
16227 ffebad_start_msg ("At %0, INCLUDE file %A exists, but is not readable",
16228 FFEBAD_severityWARNING);
16229 ffebad_string (fname);
16230 ffebad_here (0, l, c);
16241 /* A file that was not found. */
16243 strncpy (fname, (char *) fbeg, flen);
16245 print_containing_files (ffebad_severity (FFEBAD_OPEN_INCLUDE));
16246 ffebad_start (FFEBAD_OPEN_INCLUDE);
16247 ffebad_here (0, l, c);
16248 ffebad_string (fname);
16252 if (dsp[0].fname != NULL)
16253 free (dsp[0].fname);
16258 if (indepth >= (INPUT_STACK_MAX - 1))
16260 print_containing_files (FFEBAD_severityFATAL);
16261 ffebad_start_msg ("At %0, INCLUDE nesting too deep",
16262 FFEBAD_severityFATAL);
16263 ffebad_string (fname);
16264 ffebad_here (0, l, c);
16269 instack[indepth].line = ffewhere_line_use (l);
16270 instack[indepth].column = ffewhere_column_use (c);
16272 fp = &instack[indepth + 1];
16273 memset ((char *) fp, 0, sizeof (FILE_BUF));
16274 fp->nominal_fname = fp->fname = fname;
16275 fp->dir = searchptr;
16278 input_file_stack_tick++;
16282 #endif /* FFECOM_GCC_INCLUDE */
16284 /**INDENT* (Do not reformat this comment even with -fca option.)
16285 Data-gathering files: Given the source file listed below, compiled with
16286 f2c I obtained the output file listed after that, and from the output
16287 file I derived the above code.
16289 -------- (begin input file to f2c)
16295 double precision D1,D2
16297 call getem(A1,A2,C1,C2,I1,I2,R1,R2,D1,D2)
16324 c FFEINTRIN_impACOS
16325 call fooR(ACOS(R1))
16326 c FFEINTRIN_impAIMAG
16327 call fooR(AIMAG(C1))
16328 c FFEINTRIN_impAINT
16329 call fooR(AINT(R1))
16330 c FFEINTRIN_impALOG
16331 call fooR(ALOG(R1))
16332 c FFEINTRIN_impALOG10
16333 call fooR(ALOG10(R1))
16334 c FFEINTRIN_impAMAX0
16335 call fooR(AMAX0(I1,I2))
16336 c FFEINTRIN_impAMAX1
16337 call fooR(AMAX1(R1,R2))
16338 c FFEINTRIN_impAMIN0
16339 call fooR(AMIN0(I1,I2))
16340 c FFEINTRIN_impAMIN1
16341 call fooR(AMIN1(R1,R2))
16342 c FFEINTRIN_impAMOD
16343 call fooR(AMOD(R1,R2))
16344 c FFEINTRIN_impANINT
16345 call fooR(ANINT(R1))
16346 c FFEINTRIN_impASIN
16347 call fooR(ASIN(R1))
16348 c FFEINTRIN_impATAN
16349 call fooR(ATAN(R1))
16350 c FFEINTRIN_impATAN2
16351 call fooR(ATAN2(R1,R2))
16352 c FFEINTRIN_impCABS
16353 call fooR(CABS(C1))
16354 c FFEINTRIN_impCCOS
16355 call fooC(CCOS(C1))
16356 c FFEINTRIN_impCEXP
16357 call fooC(CEXP(C1))
16358 c FFEINTRIN_impCHAR
16359 call fooA(CHAR(I1))
16360 c FFEINTRIN_impCLOG
16361 call fooC(CLOG(C1))
16362 c FFEINTRIN_impCONJG
16363 call fooC(CONJG(C1))
16366 c FFEINTRIN_impCOSH
16367 call fooR(COSH(R1))
16368 c FFEINTRIN_impCSIN
16369 call fooC(CSIN(C1))
16370 c FFEINTRIN_impCSQRT
16371 call fooC(CSQRT(C1))
16372 c FFEINTRIN_impDABS
16373 call fooD(DABS(D1))
16374 c FFEINTRIN_impDACOS
16375 call fooD(DACOS(D1))
16376 c FFEINTRIN_impDASIN
16377 call fooD(DASIN(D1))
16378 c FFEINTRIN_impDATAN
16379 call fooD(DATAN(D1))
16380 c FFEINTRIN_impDATAN2
16381 call fooD(DATAN2(D1,D2))
16382 c FFEINTRIN_impDCOS
16383 call fooD(DCOS(D1))
16384 c FFEINTRIN_impDCOSH
16385 call fooD(DCOSH(D1))
16386 c FFEINTRIN_impDDIM
16387 call fooD(DDIM(D1,D2))
16388 c FFEINTRIN_impDEXP
16389 call fooD(DEXP(D1))
16391 call fooR(DIM(R1,R2))
16392 c FFEINTRIN_impDINT
16393 call fooD(DINT(D1))
16394 c FFEINTRIN_impDLOG
16395 call fooD(DLOG(D1))
16396 c FFEINTRIN_impDLOG10
16397 call fooD(DLOG10(D1))
16398 c FFEINTRIN_impDMAX1
16399 call fooD(DMAX1(D1,D2))
16400 c FFEINTRIN_impDMIN1
16401 call fooD(DMIN1(D1,D2))
16402 c FFEINTRIN_impDMOD
16403 call fooD(DMOD(D1,D2))
16404 c FFEINTRIN_impDNINT
16405 call fooD(DNINT(D1))
16406 c FFEINTRIN_impDPROD
16407 call fooD(DPROD(R1,R2))
16408 c FFEINTRIN_impDSIGN
16409 call fooD(DSIGN(D1,D2))
16410 c FFEINTRIN_impDSIN
16411 call fooD(DSIN(D1))
16412 c FFEINTRIN_impDSINH
16413 call fooD(DSINH(D1))
16414 c FFEINTRIN_impDSQRT
16415 call fooD(DSQRT(D1))
16416 c FFEINTRIN_impDTAN
16417 call fooD(DTAN(D1))
16418 c FFEINTRIN_impDTANH
16419 call fooD(DTANH(D1))
16422 c FFEINTRIN_impIABS
16423 call fooI(IABS(I1))
16424 c FFEINTRIN_impICHAR
16425 call fooI(ICHAR(A1))
16426 c FFEINTRIN_impIDIM
16427 call fooI(IDIM(I1,I2))
16428 c FFEINTRIN_impIDNINT
16429 call fooI(IDNINT(D1))
16430 c FFEINTRIN_impINDEX
16431 call fooI(INDEX(A1,A2))
16432 c FFEINTRIN_impISIGN
16433 call fooI(ISIGN(I1,I2))
16437 call fooL(LGE(A1,A2))
16439 call fooL(LGT(A1,A2))
16441 call fooL(LLE(A1,A2))
16443 call fooL(LLT(A1,A2))
16444 c FFEINTRIN_impMAX0
16445 call fooI(MAX0(I1,I2))
16446 c FFEINTRIN_impMAX1
16447 call fooI(MAX1(R1,R2))
16448 c FFEINTRIN_impMIN0
16449 call fooI(MIN0(I1,I2))
16450 c FFEINTRIN_impMIN1
16451 call fooI(MIN1(R1,R2))
16453 call fooI(MOD(I1,I2))
16454 c FFEINTRIN_impNINT
16455 call fooI(NINT(R1))
16456 c FFEINTRIN_impSIGN
16457 call fooR(SIGN(R1,R2))
16460 c FFEINTRIN_impSINH
16461 call fooR(SINH(R1))
16462 c FFEINTRIN_impSQRT
16463 call fooR(SQRT(R1))
16466 c FFEINTRIN_impTANH
16467 call fooR(TANH(R1))
16468 c FFEINTRIN_imp_CMPLX_C
16469 call fooC(cmplx(C1,C2))
16470 c FFEINTRIN_imp_CMPLX_D
16471 call fooZ(cmplx(D1,D2))
16472 c FFEINTRIN_imp_CMPLX_I
16473 call fooC(cmplx(I1,I2))
16474 c FFEINTRIN_imp_CMPLX_R
16475 call fooC(cmplx(R1,R2))
16476 c FFEINTRIN_imp_DBLE_C
16477 call fooD(dble(C1))
16478 c FFEINTRIN_imp_DBLE_D
16479 call fooD(dble(D1))
16480 c FFEINTRIN_imp_DBLE_I
16481 call fooD(dble(I1))
16482 c FFEINTRIN_imp_DBLE_R
16483 call fooD(dble(R1))
16484 c FFEINTRIN_imp_INT_C
16486 c FFEINTRIN_imp_INT_D
16488 c FFEINTRIN_imp_INT_I
16490 c FFEINTRIN_imp_INT_R
16492 c FFEINTRIN_imp_REAL_C
16493 call fooR(real(C1))
16494 c FFEINTRIN_imp_REAL_D
16495 call fooR(real(D1))
16496 c FFEINTRIN_imp_REAL_I
16497 call fooR(real(I1))
16498 c FFEINTRIN_imp_REAL_R
16499 call fooR(real(R1))
16501 c FFEINTRIN_imp_INT_D:
16503 c FFEINTRIN_specIDINT
16504 call fooI(IDINT(D1))
16506 c FFEINTRIN_imp_INT_R:
16508 c FFEINTRIN_specIFIX
16509 call fooI(IFIX(R1))
16510 c FFEINTRIN_specINT
16513 c FFEINTRIN_imp_REAL_D:
16515 c FFEINTRIN_specSNGL
16516 call fooR(SNGL(D1))
16518 c FFEINTRIN_imp_REAL_I:
16520 c FFEINTRIN_specFLOAT
16521 call fooR(FLOAT(I1))
16522 c FFEINTRIN_specREAL
16523 call fooR(REAL(I1))
16526 -------- (end input file to f2c)
16528 -------- (begin output from providing above input file as input to:
16529 -------- `f2c | gcc -E -C - | sed -e "s:/[*]*://:g" -e "s:[*]*[/]://:g" \
16530 -------- -e "s:^#.*$::g"')
16532 // -- translated by f2c (version 19950223).
16533 You must link the resulting object file with the libraries:
16534 -lf2c -lm (in that order)
16538 // f2c.h -- Standard Fortran to C header file //
16540 /// barf [ba:rf] 2. "He suggested using FORTRAN, and everybody barfed."
16542 - From The Shogakukan DICTIONARY OF NEW ENGLISH (Second edition) //
16547 // F2C_INTEGER will normally be `int' but would be `long' on 16-bit systems //
16548 // we assume short, float are OK //
16549 typedef long int // long int // integer;
16550 typedef char *address;
16551 typedef short int shortint;
16552 typedef float real;
16553 typedef double doublereal;
16554 typedef struct { real r, i; } complex;
16555 typedef struct { doublereal r, i; } doublecomplex;
16556 typedef long int // long int // logical;
16557 typedef short int shortlogical;
16558 typedef char logical1;
16559 typedef char integer1;
16560 // typedef long long longint; // // system-dependent //
16565 // Extern is for use with -E //
16579 typedef long int // int or long int // flag;
16580 typedef long int // int or long int // ftnlen;
16581 typedef long int // int or long int // ftnint;
16584 //external read, write//
16593 //internal read, write//
16623 //rewind, backspace, endfile//
16635 ftnint *inex; //parameters in standard's order//
16661 union Multitype { // for multiple entry points //
16672 typedef union Multitype Multitype;
16674 typedef long Long; // No longer used; formerly in Namelist //
16676 struct Vardesc { // for Namelist //
16682 typedef struct Vardesc Vardesc;
16689 typedef struct Namelist Namelist;
16698 // procedure parameter types for -A and -C++ //
16703 typedef int // Unknown procedure type // (*U_fp)();
16704 typedef shortint (*J_fp)();
16705 typedef integer (*I_fp)();
16706 typedef real (*R_fp)();
16707 typedef doublereal (*D_fp)(), (*E_fp)();
16708 typedef // Complex // void (*C_fp)();
16709 typedef // Double Complex // void (*Z_fp)();
16710 typedef logical (*L_fp)();
16711 typedef shortlogical (*K_fp)();
16712 typedef // Character // void (*H_fp)();
16713 typedef // Subroutine // int (*S_fp)();
16715 // E_fp is for real functions when -R is not specified //
16716 typedef void C_f; // complex function //
16717 typedef void H_f; // character function //
16718 typedef void Z_f; // double complex function //
16719 typedef doublereal E_f; // real function with -R not specified //
16721 // undef any lower-case symbols that your C compiler predefines, e.g.: //
16724 // (No such symbols should be defined in a strict ANSI C compiler.
16725 We can avoid trouble with f2c-translated code by using
16726 gcc -ansi [-traditional].) //
16750 // Main program // MAIN__()
16752 // System generated locals //
16755 doublereal d__1, d__2;
16757 doublecomplex z__1, z__2, z__3;
16761 // Builtin functions //
16764 double pow_ri(), pow_di();
16768 double acos(), r_imag(), r_int(), log(), r_lg10(), r_mod(), r_nint(),
16769 asin(), atan(), atan2(), c_abs();
16770 void c_cos(), c_exp(), c_log(), r_cnjg();
16771 double cos(), cosh();
16772 void c_sin(), c_sqrt();
16773 double d_dim(), exp(), r_dim(), d_int(), d_lg10(), d_mod(), d_nint(),
16774 d_sign(), sin(), sinh(), sqrt(), tan(), tanh();
16775 integer i_dim(), i_dnnt(), i_indx(), i_sign(), i_len();
16776 logical l_ge(), l_gt(), l_le(), l_lt();
16780 // Local variables //
16781 extern // Subroutine // int fooa_(), fooc_(), food_(), fooi_(), foor_(),
16782 fool_(), fooz_(), getem_();
16783 static char a1[10], a2[10];
16784 static complex c1, c2;
16785 static doublereal d1, d2;
16786 static integer i1, i2;
16787 static real r1, r2;
16790 getem_(a1, a2, &c1, &c2, &i1, &i2, &r1, &r2, &d1, &d2, 10L, 10L);
16798 d__1 = (doublereal) i1;
16799 q__1.r = c1.r / d__1, q__1.i = c1.i / d__1;
16809 c_div(&q__1, &c1, &c2);
16811 q__1.r = c1.r / r1, q__1.i = c1.i / r1;
16813 z__1.r = c1.r / d1, z__1.i = c1.i / d1;
16816 i__1 = pow_ii(&i1, &i2);
16818 r__1 = pow_ri(&r1, &i1);
16820 d__1 = pow_di(&d1, &i1);
16822 pow_ci(&q__1, &c1, &i1);
16824 d__1 = (doublereal) r1;
16825 d__2 = (doublereal) r2;
16826 r__1 = pow_dd(&d__1, &d__2);
16828 d__2 = (doublereal) r1;
16829 d__1 = pow_dd(&d__2, &d1);
16831 d__1 = pow_dd(&d1, &d2);
16833 d__2 = (doublereal) r1;
16834 d__1 = pow_dd(&d1, &d__2);
16836 z__2.r = c1.r, z__2.i = c1.i;
16837 z__3.r = c2.r, z__3.i = c2.i;
16838 pow_zz(&z__1, &z__2, &z__3);
16839 q__1.r = z__1.r, q__1.i = z__1.i;
16841 z__2.r = c1.r, z__2.i = c1.i;
16842 z__3.r = r1, z__3.i = 0.;
16843 pow_zz(&z__1, &z__2, &z__3);
16844 q__1.r = z__1.r, q__1.i = z__1.i;
16846 z__2.r = c1.r, z__2.i = c1.i;
16847 z__3.r = d1, z__3.i = 0.;
16848 pow_zz(&z__1, &z__2, &z__3);
16850 // FFEINTRIN_impABS //
16851 r__1 = (doublereal)(( r1 ) >= 0 ? ( r1 ) : -( r1 )) ;
16853 // FFEINTRIN_impACOS //
16856 // FFEINTRIN_impAIMAG //
16857 r__1 = r_imag(&c1);
16859 // FFEINTRIN_impAINT //
16862 // FFEINTRIN_impALOG //
16865 // FFEINTRIN_impALOG10 //
16866 r__1 = r_lg10(&r1);
16868 // FFEINTRIN_impAMAX0 //
16869 r__1 = (real) (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
16871 // FFEINTRIN_impAMAX1 //
16872 r__1 = (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
16874 // FFEINTRIN_impAMIN0 //
16875 r__1 = (real) (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
16877 // FFEINTRIN_impAMIN1 //
16878 r__1 = (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
16880 // FFEINTRIN_impAMOD //
16881 r__1 = r_mod(&r1, &r2);
16883 // FFEINTRIN_impANINT //
16884 r__1 = r_nint(&r1);
16886 // FFEINTRIN_impASIN //
16889 // FFEINTRIN_impATAN //
16892 // FFEINTRIN_impATAN2 //
16893 r__1 = atan2(r1, r2);
16895 // FFEINTRIN_impCABS //
16898 // FFEINTRIN_impCCOS //
16901 // FFEINTRIN_impCEXP //
16904 // FFEINTRIN_impCHAR //
16905 *(unsigned char *)&ch__1[0] = i1;
16907 // FFEINTRIN_impCLOG //
16910 // FFEINTRIN_impCONJG //
16911 r_cnjg(&q__1, &c1);
16913 // FFEINTRIN_impCOS //
16916 // FFEINTRIN_impCOSH //
16919 // FFEINTRIN_impCSIN //
16922 // FFEINTRIN_impCSQRT //
16923 c_sqrt(&q__1, &c1);
16925 // FFEINTRIN_impDABS //
16926 d__1 = (( d1 ) >= 0 ? ( d1 ) : -( d1 )) ;
16928 // FFEINTRIN_impDACOS //
16931 // FFEINTRIN_impDASIN //
16934 // FFEINTRIN_impDATAN //
16937 // FFEINTRIN_impDATAN2 //
16938 d__1 = atan2(d1, d2);
16940 // FFEINTRIN_impDCOS //
16943 // FFEINTRIN_impDCOSH //
16946 // FFEINTRIN_impDDIM //
16947 d__1 = d_dim(&d1, &d2);
16949 // FFEINTRIN_impDEXP //
16952 // FFEINTRIN_impDIM //
16953 r__1 = r_dim(&r1, &r2);
16955 // FFEINTRIN_impDINT //
16958 // FFEINTRIN_impDLOG //
16961 // FFEINTRIN_impDLOG10 //
16962 d__1 = d_lg10(&d1);
16964 // FFEINTRIN_impDMAX1 //
16965 d__1 = (( d1 ) >= ( d2 ) ? ( d1 ) : ( d2 )) ;
16967 // FFEINTRIN_impDMIN1 //
16968 d__1 = (( d1 ) <= ( d2 ) ? ( d1 ) : ( d2 )) ;
16970 // FFEINTRIN_impDMOD //
16971 d__1 = d_mod(&d1, &d2);
16973 // FFEINTRIN_impDNINT //
16974 d__1 = d_nint(&d1);
16976 // FFEINTRIN_impDPROD //
16977 d__1 = (doublereal) r1 * r2;
16979 // FFEINTRIN_impDSIGN //
16980 d__1 = d_sign(&d1, &d2);
16982 // FFEINTRIN_impDSIN //
16985 // FFEINTRIN_impDSINH //
16988 // FFEINTRIN_impDSQRT //
16991 // FFEINTRIN_impDTAN //
16994 // FFEINTRIN_impDTANH //
16997 // FFEINTRIN_impEXP //
17000 // FFEINTRIN_impIABS //
17001 i__1 = (( i1 ) >= 0 ? ( i1 ) : -( i1 )) ;
17003 // FFEINTRIN_impICHAR //
17004 i__1 = *(unsigned char *)a1;
17006 // FFEINTRIN_impIDIM //
17007 i__1 = i_dim(&i1, &i2);
17009 // FFEINTRIN_impIDNINT //
17010 i__1 = i_dnnt(&d1);
17012 // FFEINTRIN_impINDEX //
17013 i__1 = i_indx(a1, a2, 10L, 10L);
17015 // FFEINTRIN_impISIGN //
17016 i__1 = i_sign(&i1, &i2);
17018 // FFEINTRIN_impLEN //
17019 i__1 = i_len(a1, 10L);
17021 // FFEINTRIN_impLGE //
17022 L__1 = l_ge(a1, a2, 10L, 10L);
17024 // FFEINTRIN_impLGT //
17025 L__1 = l_gt(a1, a2, 10L, 10L);
17027 // FFEINTRIN_impLLE //
17028 L__1 = l_le(a1, a2, 10L, 10L);
17030 // FFEINTRIN_impLLT //
17031 L__1 = l_lt(a1, a2, 10L, 10L);
17033 // FFEINTRIN_impMAX0 //
17034 i__1 = (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
17036 // FFEINTRIN_impMAX1 //
17037 i__1 = (integer) (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
17039 // FFEINTRIN_impMIN0 //
17040 i__1 = (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
17042 // FFEINTRIN_impMIN1 //
17043 i__1 = (integer) (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
17045 // FFEINTRIN_impMOD //
17048 // FFEINTRIN_impNINT //
17049 i__1 = i_nint(&r1);
17051 // FFEINTRIN_impSIGN //
17052 r__1 = r_sign(&r1, &r2);
17054 // FFEINTRIN_impSIN //
17057 // FFEINTRIN_impSINH //
17060 // FFEINTRIN_impSQRT //
17063 // FFEINTRIN_impTAN //
17066 // FFEINTRIN_impTANH //
17069 // FFEINTRIN_imp_CMPLX_C //
17072 q__1.r = r__1, q__1.i = r__2;
17074 // FFEINTRIN_imp_CMPLX_D //
17075 z__1.r = d1, z__1.i = d2;
17077 // FFEINTRIN_imp_CMPLX_I //
17080 q__1.r = r__1, q__1.i = r__2;
17082 // FFEINTRIN_imp_CMPLX_R //
17083 q__1.r = r1, q__1.i = r2;
17085 // FFEINTRIN_imp_DBLE_C //
17086 d__1 = (doublereal) c1.r;
17088 // FFEINTRIN_imp_DBLE_D //
17091 // FFEINTRIN_imp_DBLE_I //
17092 d__1 = (doublereal) i1;
17094 // FFEINTRIN_imp_DBLE_R //
17095 d__1 = (doublereal) r1;
17097 // FFEINTRIN_imp_INT_C //
17098 i__1 = (integer) c1.r;
17100 // FFEINTRIN_imp_INT_D //
17101 i__1 = (integer) d1;
17103 // FFEINTRIN_imp_INT_I //
17106 // FFEINTRIN_imp_INT_R //
17107 i__1 = (integer) r1;
17109 // FFEINTRIN_imp_REAL_C //
17112 // FFEINTRIN_imp_REAL_D //
17115 // FFEINTRIN_imp_REAL_I //
17118 // FFEINTRIN_imp_REAL_R //
17122 // FFEINTRIN_imp_INT_D: //
17124 // FFEINTRIN_specIDINT //
17125 i__1 = (integer) d1;
17128 // FFEINTRIN_imp_INT_R: //
17130 // FFEINTRIN_specIFIX //
17131 i__1 = (integer) r1;
17133 // FFEINTRIN_specINT //
17134 i__1 = (integer) r1;
17137 // FFEINTRIN_imp_REAL_D: //
17139 // FFEINTRIN_specSNGL //
17143 // FFEINTRIN_imp_REAL_I: //
17145 // FFEINTRIN_specFLOAT //
17148 // FFEINTRIN_specREAL //
17154 -------- (end output file from f2c)