1 /* com.c -- Implementation File (module.c template V1.0)
2 Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000
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):
58 yes = suspend_momentary ();
59 if (is_nested) push_f_function_context ();
60 start_function (get_identifier ("function_name"), function_type,
61 is_nested, is_public);
62 // for each arg, build PARM_DECL and call push_parm_decl (decl) with it;
63 store_parm_decls (is_main_program);
64 ffecom_start_compstmt ();
65 // for stmts and decls inside function, do appropriate things;
66 ffecom_end_compstmt ();
67 finish_function (is_nested);
68 if (is_nested) pop_f_function_context ();
69 if (is_nested) resume_momentary (yes);
75 yes = suspend_momentary ();
76 // fill in external, public, static, &c for decl, and
77 // set DECL_INITIAL to error_mark_node if going to initialize
78 // set is_top_level TRUE only if not at top level and decl
79 // must go in top level (i.e. not within current function decl context)
80 d = start_decl (decl, is_top_level);
81 init = ...; // if have initializer
82 finish_decl (d, init, is_top_level);
83 resume_momentary (yes);
90 #if FFECOM_targetCURRENT == FFECOM_targetGCC
95 #include "output.j" /* Must follow tree.j so TREE_CODE is defined! */
98 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
100 #define FFECOM_GCC_INCLUDE 1 /* Enable -I. */
102 /* BEGIN stuff from gcc/cccp.c. */
104 /* The following symbols should be autoconfigured:
111 In the mean time, we'll get by with approximations based
112 on existing GCC configuration symbols. */
115 # ifndef HAVE_STDLIB_H
116 # define HAVE_STDLIB_H 1
118 # ifndef HAVE_UNISTD_H
119 # define HAVE_UNISTD_H 1
121 # ifndef STDC_HEADERS
122 # define STDC_HEADERS 1
124 #endif /* defined (POSIX) */
126 #if defined (POSIX) || (defined (USG) && !defined (VMS))
127 # ifndef HAVE_FCNTL_H
128 # define HAVE_FCNTL_H 1
135 # if TIME_WITH_SYS_TIME
136 # include <sys/time.h>
140 # include <sys/time.h>
145 # include <sys/resource.h>
152 /* This defines "errno" properly for VMS, and gives us EACCES. */
165 /* VMS-specific definitions */
168 #define O_RDONLY 0 /* Open arg for Read/Only */
169 #define O_WRONLY 1 /* Open arg for Write/Only */
170 #define read(fd,buf,size) VMS_read (fd,buf,size)
171 #define write(fd,buf,size) VMS_write (fd,buf,size)
172 #define open(fname,mode,prot) VMS_open (fname,mode,prot)
173 #define fopen(fname,mode) VMS_fopen (fname,mode)
174 #define freopen(fname,mode,ofile) VMS_freopen (fname,mode,ofile)
175 #define strncat(dst,src,cnt) VMS_strncat (dst,src,cnt)
176 #define fstat(fd,stbuf) VMS_fstat (fd,stbuf)
177 static int VMS_fstat (), VMS_stat ();
178 static char * VMS_strncat ();
179 static int VMS_read ();
180 static int VMS_write ();
181 static int VMS_open ();
182 static FILE * VMS_fopen ();
183 static FILE * VMS_freopen ();
184 static void hack_vms_include_specification ();
185 typedef struct { unsigned :16, :16, :16; } vms_ino_t;
186 #define ino_t vms_ino_t
187 #define INCLUDE_LEN_FUDGE 10 /* leave room for VMS syntax conversion */
189 #define BSTRING /* VMS/GCC supplies the bstring routines */
190 #endif /* __GNUC__ */
197 /* END stuff from gcc/cccp.c. */
199 #define FFECOM_DETERMINE_TYPES 1 /* for com.h */
216 /* Externals defined here. */
218 #if FFECOM_targetCURRENT == FFECOM_targetGCC
220 /* ~~gcc/tree.h *should* declare this, because toplev.c and dwarfout.c
223 const char * const language_string = "GNU F77";
225 /* Stream for reading from the input file. */
228 /* These definitions parallel those in c-decl.c so that code from that
229 module can be used pretty much as is. Much of these defs aren't
230 otherwise used, i.e. by g77 code per se, except some of them are used
231 to build some of them that are. The ones that are global (i.e. not
232 "static") are those that ste.c and such might use (directly
233 or by using com macros that reference them in their definitions). */
235 tree string_type_node;
237 /* The rest of these are inventions for g77, though there might be
238 similar things in the C front end. As they are found, these
239 inventions should be renamed to be canonical. Note that only
240 the ones currently required to be global are so. */
242 static tree ffecom_tree_fun_type_void;
244 tree ffecom_integer_type_node; /* Abbrev for _tree_type[blah][blah]. */
245 tree ffecom_integer_zero_node; /* Like *_*_* with g77's integer type. */
246 tree ffecom_integer_one_node; /* " */
247 tree ffecom_tree_type[FFEINFO_basictype][FFEINFO_kindtype];
249 /* _fun_type things are the f2c-specific versions. For -fno-f2c,
250 just use build_function_type and build_pointer_type on the
251 appropriate _tree_type array element. */
253 static tree ffecom_tree_fun_type[FFEINFO_basictype][FFEINFO_kindtype];
254 static tree ffecom_tree_ptr_to_fun_type[FFEINFO_basictype][FFEINFO_kindtype];
255 static tree ffecom_tree_subr_type;
256 static tree ffecom_tree_ptr_to_subr_type;
257 static tree ffecom_tree_blockdata_type;
259 static tree ffecom_tree_xargc_;
261 ffecomSymbol ffecom_symbol_null_
270 ffeinfoKindtype ffecom_pointer_kind_ = FFEINFO_basictypeNONE;
271 ffeinfoKindtype ffecom_label_kind_ = FFEINFO_basictypeNONE;
273 int ffecom_f2c_typecode_[FFEINFO_basictype][FFEINFO_kindtype];
274 tree ffecom_f2c_integer_type_node;
275 tree ffecom_f2c_ptr_to_integer_type_node;
276 tree ffecom_f2c_address_type_node;
277 tree ffecom_f2c_real_type_node;
278 tree ffecom_f2c_ptr_to_real_type_node;
279 tree ffecom_f2c_doublereal_type_node;
280 tree ffecom_f2c_complex_type_node;
281 tree ffecom_f2c_doublecomplex_type_node;
282 tree ffecom_f2c_longint_type_node;
283 tree ffecom_f2c_logical_type_node;
284 tree ffecom_f2c_flag_type_node;
285 tree ffecom_f2c_ftnlen_type_node;
286 tree ffecom_f2c_ftnlen_zero_node;
287 tree ffecom_f2c_ftnlen_one_node;
288 tree ffecom_f2c_ftnlen_two_node;
289 tree ffecom_f2c_ptr_to_ftnlen_type_node;
290 tree ffecom_f2c_ftnint_type_node;
291 tree ffecom_f2c_ptr_to_ftnint_type_node;
292 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
294 /* Simple definitions and enumerations. */
296 #ifndef FFECOM_sizeMAXSTACKITEM
297 #define FFECOM_sizeMAXSTACKITEM 32*1024 /* Keep user-declared things
298 larger than this # bytes
299 off stack if possible. */
302 /* For systems that have large enough stacks, they should define
303 this to 0, and here, for ease of use later on, we just undefine
306 #if FFECOM_sizeMAXSTACKITEM == 0
307 #undef FFECOM_sizeMAXSTACKITEM
313 FFECOM_rttypeVOIDSTAR_, /* C's `void *' type. */
314 FFECOM_rttypeFTNINT_, /* f2c's `ftnint' type. */
315 FFECOM_rttypeINTEGER_, /* f2c's `integer' type. */
316 FFECOM_rttypeLONGINT_, /* f2c's `longint' type. */
317 FFECOM_rttypeLOGICAL_, /* f2c's `logical' type. */
318 FFECOM_rttypeREAL_F2C_, /* f2c's `real' returned as `double'. */
319 FFECOM_rttypeREAL_GNU_, /* `real' returned as such. */
320 FFECOM_rttypeCOMPLEX_F2C_, /* f2c's `complex' returned via 1st arg. */
321 FFECOM_rttypeCOMPLEX_GNU_, /* f2c's `complex' returned directly. */
322 FFECOM_rttypeDOUBLE_, /* C's `double' type. */
323 FFECOM_rttypeDOUBLEREAL_, /* f2c's `doublereal' type. */
324 FFECOM_rttypeDBLCMPLX_F2C_, /* f2c's `doublecomplex' returned via 1st arg. */
325 FFECOM_rttypeDBLCMPLX_GNU_, /* f2c's `doublecomplex' returned directly. */
326 FFECOM_rttypeCHARACTER_, /* f2c `char *'/`ftnlen' pair. */
330 /* Internal typedefs. */
332 #if FFECOM_targetCURRENT == FFECOM_targetGCC
333 typedef struct _ffecom_concat_list_ ffecomConcatList_;
334 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
336 /* Private include files. */
339 /* Internal structure definitions. */
341 #if FFECOM_targetCURRENT == FFECOM_targetGCC
342 struct _ffecom_concat_list_
347 ffetargetCharacterSize minlen;
348 ffetargetCharacterSize maxlen;
350 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
352 /* Static functions (internal). */
354 #if FFECOM_targetCURRENT == FFECOM_targetGCC
355 static tree ffecom_arglist_expr_ (const char *argstring, ffebld args);
356 static tree ffecom_widest_expr_type_ (ffebld list);
357 static bool ffecom_overlap_ (tree dest_decl, tree dest_offset,
358 tree dest_size, tree source_tree,
359 ffebld source, bool scalar_arg);
360 static bool ffecom_args_overlapping_ (tree dest_tree, ffebld dest,
361 tree args, tree callee_commons,
363 static tree ffecom_build_f2c_string_ (int i, const char *s);
364 static tree ffecom_call_ (tree fn, ffeinfoKindtype kt,
365 bool is_f2c_complex, tree type,
366 tree args, tree dest_tree,
367 ffebld dest, bool *dest_used,
368 tree callee_commons, bool scalar_args, tree hook);
369 static tree ffecom_call_binop_ (tree fn, ffeinfoKindtype kt,
370 bool is_f2c_complex, tree type,
371 ffebld left, ffebld right,
372 tree dest_tree, ffebld dest,
373 bool *dest_used, tree callee_commons,
374 bool scalar_args, tree hook);
375 static void ffecom_char_args_x_ (tree *xitem, tree *length,
376 ffebld expr, bool with_null);
377 static tree ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy);
378 static tree ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s);
379 static ffecomConcatList_
380 ffecom_concat_list_gather_ (ffecomConcatList_ catlist,
382 ffetargetCharacterSize max);
383 static void ffecom_concat_list_kill_ (ffecomConcatList_ catlist);
384 static ffecomConcatList_ ffecom_concat_list_new_ (ffebld expr,
385 ffetargetCharacterSize max);
386 static void ffecom_debug_kludge_ (tree aggr, const char *aggr_type,
387 ffesymbol member, tree member_type,
388 ffetargetOffset offset);
389 static void ffecom_do_entry_ (ffesymbol fn, int entrynum);
390 static tree ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
391 bool *dest_used, bool assignp, bool widenp);
392 static tree ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
393 ffebld dest, bool *dest_used);
394 static tree ffecom_expr_power_integer_ (ffebld expr);
395 static void ffecom_expr_transform_ (ffebld expr);
396 static void ffecom_f2c_make_type_ (tree *type, int tcode, const char *name);
397 static void ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size,
399 static ffeglobal ffecom_finish_global_ (ffeglobal global);
400 static ffesymbol ffecom_finish_symbol_transform_ (ffesymbol s);
401 static tree ffecom_get_appended_identifier_ (char us, const char *text);
402 static tree ffecom_get_external_identifier_ (ffesymbol s);
403 static tree ffecom_get_identifier_ (const char *text);
404 static tree ffecom_gen_sfuncdef_ (ffesymbol s,
407 static const char *ffecom_gfrt_args_ (ffecomGfrt ix);
408 static tree ffecom_gfrt_tree_ (ffecomGfrt ix);
409 static tree ffecom_init_zero_ (tree decl);
410 static tree ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg,
412 static tree ffecom_intrinsic_len_ (ffebld expr);
413 static void ffecom_let_char_ (tree dest_tree,
415 ffetargetCharacterSize dest_size,
417 static void ffecom_make_gfrt_ (ffecomGfrt ix);
418 static void ffecom_member_phase1_ (ffestorag mst, ffestorag st);
419 static void ffecom_member_phase2_ (ffestorag mst, ffestorag st);
420 static void ffecom_prepare_let_char_ (ffetargetCharacterSize dest_size,
422 static void ffecom_push_dummy_decls_ (ffebld dumlist,
424 static void ffecom_start_progunit_ (void);
425 static ffesymbol ffecom_sym_transform_ (ffesymbol s);
426 static ffesymbol ffecom_sym_transform_assign_ (ffesymbol s);
427 static void ffecom_transform_common_ (ffesymbol s);
428 static void ffecom_transform_equiv_ (ffestorag st);
429 static tree ffecom_transform_namelist_ (ffesymbol s);
430 static void ffecom_tree_canonize_ptr_ (tree *decl, tree *offset,
432 static void ffecom_tree_canonize_ref_ (tree *decl, tree *offset,
433 tree *size, tree tree);
434 static tree ffecom_tree_divide_ (tree tree_type, tree left, tree right,
435 tree dest_tree, ffebld dest,
436 bool *dest_used, tree hook);
437 static tree ffecom_type_localvar_ (ffesymbol s,
440 static tree ffecom_type_namelist_ (void);
441 static tree ffecom_type_vardesc_ (void);
442 static tree ffecom_vardesc_ (ffebld expr);
443 static tree ffecom_vardesc_array_ (ffesymbol s);
444 static tree ffecom_vardesc_dims_ (ffesymbol s);
445 static tree ffecom_convert_narrow_ (tree type, tree expr);
446 static tree ffecom_convert_widen_ (tree type, tree expr);
447 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
449 /* These are static functions that parallel those found in the C front
450 end and thus have the same names. */
452 #if FFECOM_targetCURRENT == FFECOM_targetGCC
453 static tree bison_rule_compstmt_ (void);
454 static void bison_rule_pushlevel_ (void);
455 static void delete_block (tree block);
456 static int duplicate_decls (tree newdecl, tree olddecl);
457 static void finish_decl (tree decl, tree init, bool is_top_level);
458 static void finish_function (int nested);
459 static const char *lang_printable_name (tree decl, int v);
460 static tree lookup_name_current_level (tree name);
461 static struct binding_level *make_binding_level (void);
462 static void pop_f_function_context (void);
463 static void push_f_function_context (void);
464 static void push_parm_decl (tree parm);
465 static tree pushdecl_top_level (tree decl);
466 static int kept_level_p (void);
467 static tree storedecls (tree decls);
468 static void store_parm_decls (int is_main_program);
469 static tree start_decl (tree decl, bool is_top_level);
470 static void start_function (tree name, tree type, int nested, int public);
471 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
472 #if FFECOM_GCC_INCLUDE
473 static void ffecom_file_ (const char *name);
474 static void ffecom_initialize_char_syntax_ (void);
475 static void ffecom_close_include_ (FILE *f);
476 static int ffecom_decode_include_option_ (char *spec);
477 static FILE *ffecom_open_include_ (char *name, ffewhereLine l,
479 #endif /* FFECOM_GCC_INCLUDE */
481 /* Static objects accessed by functions in this module. */
483 static ffesymbol ffecom_primary_entry_ = NULL;
484 static ffesymbol ffecom_nested_entry_ = NULL;
485 static ffeinfoKind ffecom_primary_entry_kind_;
486 static bool ffecom_primary_entry_is_proc_;
487 #if FFECOM_targetCURRENT == FFECOM_targetGCC
488 static tree ffecom_outer_function_decl_;
489 static tree ffecom_previous_function_decl_;
490 static tree ffecom_which_entrypoint_decl_;
491 static tree ffecom_float_zero_ = NULL_TREE;
492 static tree ffecom_float_half_ = NULL_TREE;
493 static tree ffecom_double_zero_ = NULL_TREE;
494 static tree ffecom_double_half_ = NULL_TREE;
495 static tree ffecom_func_result_;/* For functions. */
496 static tree ffecom_func_length_;/* For CHARACTER fns. */
497 static ffebld ffecom_list_blockdata_;
498 static ffebld ffecom_list_common_;
499 static ffebld ffecom_master_arglist_;
500 static ffeinfoBasictype ffecom_master_bt_;
501 static ffeinfoKindtype ffecom_master_kt_;
502 static ffetargetCharacterSize ffecom_master_size_;
503 static int ffecom_num_fns_ = 0;
504 static int ffecom_num_entrypoints_ = 0;
505 static bool ffecom_is_altreturning_ = FALSE;
506 static tree ffecom_multi_type_node_;
507 static tree ffecom_multi_retval_;
509 ffecom_multi_fields_[FFEINFO_basictype][FFEINFO_kindtype];
510 static bool ffecom_member_namelisted_; /* _member_phase1_ namelisted? */
511 static bool ffecom_doing_entry_ = FALSE;
512 static bool ffecom_transform_only_dummies_ = FALSE;
513 static int ffecom_typesize_pointer_;
514 static int ffecom_typesize_integer1_;
516 /* Holds pointer-to-function expressions. */
518 static tree ffecom_gfrt_[FFECOM_gfrt]
521 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) NULL_TREE,
522 #include "com-rt.def"
526 /* Holds the external names of the functions. */
528 static const char *ffecom_gfrt_name_[FFECOM_gfrt]
531 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) NAME,
532 #include "com-rt.def"
536 /* Whether the function returns. */
538 static bool ffecom_gfrt_volatile_[FFECOM_gfrt]
541 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) VOLATILE,
542 #include "com-rt.def"
546 /* Whether the function returns type complex. */
548 static bool ffecom_gfrt_complex_[FFECOM_gfrt]
551 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) COMPLEX,
552 #include "com-rt.def"
556 /* Type code for the function return value. */
558 static ffecomRttype_ ffecom_gfrt_type_[FFECOM_gfrt]
561 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) TYPE,
562 #include "com-rt.def"
566 /* String of codes for the function's arguments. */
568 static const char *ffecom_gfrt_argstring_[FFECOM_gfrt]
571 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) ARGS,
572 #include "com-rt.def"
575 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
577 /* Internal macros. */
579 #if FFECOM_targetCURRENT == FFECOM_targetGCC
581 /* We let tm.h override the types used here, to handle trivial differences
582 such as the choice of unsigned int or long unsigned int for size_t.
583 When machines start needing nontrivial differences in the size type,
584 it would be best to do something here to figure out automatically
585 from other information what type to use. */
588 #define SIZE_TYPE "long unsigned int"
591 #define ffecom_concat_list_count_(catlist) ((catlist).count)
592 #define ffecom_concat_list_expr_(catlist,i) ((catlist).exprs[(i)])
593 #define ffecom_concat_list_maxlen_(catlist) ((catlist).maxlen)
594 #define ffecom_concat_list_minlen_(catlist) ((catlist).minlen)
596 #define ffecom_char_args_(i,l,e) ffecom_char_args_x_((i),(l),(e),FALSE)
597 #define ffecom_char_args_with_null_(i,l,e) ffecom_char_args_x_((i),(l),(e),TRUE)
599 /* For each binding contour we allocate a binding_level structure
600 * which records the names defined in that contour.
603 * 1) one for each function definition,
604 * where internal declarations of the parameters appear.
606 * The current meaning of a name can be found by searching the levels from
607 * the current one out to the global one.
610 /* Note that the information in the `names' component of the global contour
611 is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers. */
615 /* A chain of _DECL nodes for all variables, constants, functions,
616 and typedef types. These are in the reverse of the order supplied.
620 /* For each level (except not the global one),
621 a chain of BLOCK nodes for all the levels
622 that were entered and exited one level down. */
625 /* The BLOCK node for this level, if one has been preallocated.
626 If 0, the BLOCK is allocated (if needed) when the level is popped. */
629 /* The binding level which this one is contained in (inherits from). */
630 struct binding_level *level_chain;
632 /* 0: no ffecom_prepare_* functions called at this level yet;
633 1: ffecom_prepare* functions called, except not ffecom_prepare_end;
634 2: ffecom_prepare_end called. */
638 #define NULL_BINDING_LEVEL (struct binding_level *) NULL
640 /* The binding level currently in effect. */
642 static struct binding_level *current_binding_level;
644 /* A chain of binding_level structures awaiting reuse. */
646 static struct binding_level *free_binding_level;
648 /* The outermost binding level, for names of file scope.
649 This is created when the compiler is started and exists
650 through the entire run. */
652 static struct binding_level *global_binding_level;
654 /* Binding level structures are initialized by copying this one. */
656 static struct binding_level clear_binding_level
658 {NULL, NULL, NULL, NULL_BINDING_LEVEL, 0};
660 /* Language-dependent contents of an identifier. */
662 struct lang_identifier
664 struct tree_identifier ignore;
665 tree global_value, local_value, label_value;
669 /* Macros for access to language-specific slots in an identifier. */
670 /* Each of these slots contains a DECL node or null. */
672 /* This represents the value which the identifier has in the
673 file-scope namespace. */
674 #define IDENTIFIER_GLOBAL_VALUE(NODE) \
675 (((struct lang_identifier *)(NODE))->global_value)
676 /* This represents the value which the identifier has in the current
678 #define IDENTIFIER_LOCAL_VALUE(NODE) \
679 (((struct lang_identifier *)(NODE))->local_value)
680 /* This represents the value which the identifier has as a label in
681 the current label scope. */
682 #define IDENTIFIER_LABEL_VALUE(NODE) \
683 (((struct lang_identifier *)(NODE))->label_value)
684 /* This is nonzero if the identifier was "made up" by g77 code. */
685 #define IDENTIFIER_INVENTED(NODE) \
686 (((struct lang_identifier *)(NODE))->invented)
688 /* In identifiers, C uses the following fields in a special way:
689 TREE_PUBLIC to record that there was a previous local extern decl.
690 TREE_USED to record that such a decl was used.
691 TREE_ADDRESSABLE to record that the address of such a decl was used. */
693 /* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
694 that have names. Here so we can clear out their names' definitions
695 at the end of the function. */
697 static tree named_labels;
699 /* A list of LABEL_DECLs from outer contexts that are currently shadowed. */
701 static tree shadowed_labels;
703 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
705 /* Return the subscript expression, modified to do range-checking.
707 `array' is the array to be checked against.
708 `element' is the subscript expression to check.
709 `dim' is the dimension number (starting at 0).
710 `total_dims' is the total number of dimensions (0 for CHARACTER substring).
714 ffecom_subscript_check_ (tree array, tree element, int dim, int total_dims,
715 const char *array_name)
717 tree low = TYPE_MIN_VALUE (TYPE_DOMAIN (array));
718 tree high = TYPE_MAX_VALUE (TYPE_DOMAIN (array));
723 if (element == error_mark_node)
726 if (TREE_TYPE (low) != TREE_TYPE (element))
728 if (TYPE_PRECISION (TREE_TYPE (low))
729 > TYPE_PRECISION (TREE_TYPE (element)))
730 element = convert (TREE_TYPE (low), element);
733 low = convert (TREE_TYPE (element), low);
735 high = convert (TREE_TYPE (element), high);
739 element = ffecom_save_tree (element);
740 cond = ffecom_2 (LE_EXPR, integer_type_node,
745 cond = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
747 ffecom_2 (LE_EXPR, integer_type_node,
764 var = xmalloc (strlen (array_name) + 20);
765 sprintf (var, "%s[%s-substring]",
767 dim ? "end" : "start");
768 len = strlen (var) + 1;
769 arg1 = build_string (len, var);
774 len = strlen (array_name) + 1;
775 arg1 = build_string (len, array_name);
779 var = xmalloc (strlen (array_name) + 40);
780 sprintf (var, "%s[subscript-%d-of-%d]",
782 dim + 1, total_dims);
783 len = strlen (var) + 1;
784 arg1 = build_string (len, var);
790 = build_type_variant (build_array_type (char_type_node,
794 build_int_2 (len, 0))),
796 TREE_CONSTANT (arg1) = 1;
797 TREE_STATIC (arg1) = 1;
798 arg1 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg1)),
801 /* s_rnge adds one to the element to print it, so bias against
802 that -- want to print a faithful *subscript* value. */
803 arg2 = convert (ffecom_f2c_ftnint_type_node,
804 ffecom_2 (MINUS_EXPR,
807 convert (TREE_TYPE (element),
810 proc = xmalloc ((len = strlen (input_filename)
811 + IDENTIFIER_LENGTH (DECL_NAME (current_function_decl))
814 sprintf (&proc[0], "%s/%s",
816 IDENTIFIER_POINTER (DECL_NAME (current_function_decl)));
817 arg3 = build_string (len, proc);
822 = build_type_variant (build_array_type (char_type_node,
826 build_int_2 (len, 0))),
828 TREE_CONSTANT (arg3) = 1;
829 TREE_STATIC (arg3) = 1;
830 arg3 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg3)),
833 arg4 = convert (ffecom_f2c_ftnint_type_node,
834 build_int_2 (lineno, 0));
836 arg1 = build_tree_list (NULL_TREE, arg1);
837 arg2 = build_tree_list (NULL_TREE, arg2);
838 arg3 = build_tree_list (NULL_TREE, arg3);
839 arg4 = build_tree_list (NULL_TREE, arg4);
840 TREE_CHAIN (arg3) = arg4;
841 TREE_CHAIN (arg2) = arg3;
842 TREE_CHAIN (arg1) = arg2;
846 die = ffecom_call_gfrt (FFECOM_gfrtRANGE,
848 TREE_SIDE_EFFECTS (die) = 1;
850 element = ffecom_3 (COND_EXPR,
859 /* Return the computed element of an array reference.
861 `item' is NULL_TREE, or the transformed pointer to the array.
862 `expr' is the original opARRAYREF expression, which is transformed
863 if `item' is NULL_TREE.
864 `want_ptr' is non-zero if a pointer to the element, instead of
865 the element itself, is to be returned. */
868 ffecom_arrayref_ (tree item, ffebld expr, int want_ptr)
870 ffebld dims[FFECOM_dimensionsMAX];
873 int flatten = ffe_is_flatten_arrays ();
879 const char *array_name;
883 if (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER)
884 array_name = ffesymbol_text (ffebld_symter (ffebld_left (expr)));
886 array_name = "[expr?]";
888 /* Build up ARRAY_REFs in reverse order (since we're column major
889 here in Fortran land). */
891 for (i = 0, list = ffebld_right (expr);
893 ++i, list = ffebld_trail (list))
895 dims[i] = ffebld_head (list);
896 type = ffeinfo_type (ffebld_basictype (dims[i]),
897 ffebld_kindtype (dims[i]));
899 && ffecom_typesize_pointer_ > ffecom_typesize_integer1_
900 && ffetype_size (type) > ffecom_typesize_integer1_)
901 /* E.g. ARRAY(INDEX), given INTEGER*8 INDEX, on a system with 64-bit
902 pointers and 32-bit integers. Do the full 64-bit pointer
903 arithmetic, for codes using arrays for nonstandard heap-like
910 need_ptr = want_ptr || flatten;
915 item = ffecom_ptr_to_expr (ffebld_left (expr));
917 item = ffecom_expr (ffebld_left (expr));
919 if (item == error_mark_node)
922 if (ffeinfo_where (ffebld_info (expr)) == FFEINFO_whereFLEETING
923 && ! mark_addressable (item))
924 return error_mark_node;
927 if (item == error_mark_node)
934 for (--i, array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
936 --i, array = TYPE_MAIN_VARIANT (TREE_TYPE (array)))
938 min = TYPE_MIN_VALUE (TYPE_DOMAIN (array));
939 element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
940 if (flag_bounds_check)
941 element = ffecom_subscript_check_ (array, element, i, total_dims,
943 if (element == error_mark_node)
946 /* Widen integral arithmetic as desired while preserving
948 tree_type = TREE_TYPE (element);
949 tree_type_x = tree_type;
951 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
952 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
953 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
955 if (TREE_TYPE (min) != tree_type_x)
956 min = convert (tree_type_x, min);
957 if (TREE_TYPE (element) != tree_type_x)
958 element = convert (tree_type_x, element);
960 item = ffecom_2 (PLUS_EXPR,
961 build_pointer_type (TREE_TYPE (array)),
963 size_binop (MULT_EXPR,
964 size_in_bytes (TREE_TYPE (array)),
966 fold (build (MINUS_EXPR,
972 item = ffecom_1 (INDIRECT_REF,
973 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))),
983 array = TYPE_MAIN_VARIANT (TREE_TYPE (item));
985 element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
986 if (flag_bounds_check)
987 element = ffecom_subscript_check_ (array, element, i, total_dims,
989 if (element == error_mark_node)
992 /* Widen integral arithmetic as desired while preserving
994 tree_type = TREE_TYPE (element);
995 tree_type_x = tree_type;
997 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
998 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
999 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
1001 element = convert (tree_type_x, element);
1003 item = ffecom_2 (ARRAY_REF,
1004 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))),
1013 /* This is like gcc's stabilize_reference -- in fact, most of the code
1014 comes from that -- but it handles the situation where the reference
1015 is going to have its subparts picked at, and it shouldn't change
1016 (or trigger extra invocations of functions in the subtrees) due to
1017 this. save_expr is a bit overzealous, because we don't need the
1018 entire thing calculated and saved like a temp. So, for DECLs, no
1019 change is needed, because these are stable aggregates, and ARRAY_REF
1020 and such might well be stable too, but for things like calculations,
1021 we do need to calculate a snapshot of a value before picking at it. */
1023 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1025 ffecom_stabilize_aggregate_ (tree ref)
1028 enum tree_code code = TREE_CODE (ref);
1035 /* No action is needed in this case. */
1041 case FIX_TRUNC_EXPR:
1042 case FIX_FLOOR_EXPR:
1043 case FIX_ROUND_EXPR:
1045 result = build_nt (code, stabilize_reference (TREE_OPERAND (ref, 0)));
1049 result = build_nt (INDIRECT_REF,
1050 stabilize_reference_1 (TREE_OPERAND (ref, 0)));
1054 result = build_nt (COMPONENT_REF,
1055 stabilize_reference (TREE_OPERAND (ref, 0)),
1056 TREE_OPERAND (ref, 1));
1060 result = build_nt (BIT_FIELD_REF,
1061 stabilize_reference (TREE_OPERAND (ref, 0)),
1062 stabilize_reference_1 (TREE_OPERAND (ref, 1)),
1063 stabilize_reference_1 (TREE_OPERAND (ref, 2)));
1067 result = build_nt (ARRAY_REF,
1068 stabilize_reference (TREE_OPERAND (ref, 0)),
1069 stabilize_reference_1 (TREE_OPERAND (ref, 1)));
1073 result = build_nt (COMPOUND_EXPR,
1074 stabilize_reference_1 (TREE_OPERAND (ref, 0)),
1075 stabilize_reference (TREE_OPERAND (ref, 1)));
1079 result = build1 (INDIRECT_REF, TREE_TYPE (ref),
1080 save_expr (build1 (ADDR_EXPR,
1081 build_pointer_type (TREE_TYPE (ref)),
1087 return save_expr (ref);
1090 return error_mark_node;
1093 TREE_TYPE (result) = TREE_TYPE (ref);
1094 TREE_READONLY (result) = TREE_READONLY (ref);
1095 TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (ref);
1096 TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (ref);
1102 /* A rip-off of gcc's convert.c convert_to_complex function,
1103 reworked to handle complex implemented as C structures
1104 (RECORD_TYPE with two fields, real and imaginary `r' and `i'). */
1106 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1108 ffecom_convert_to_complex_ (tree type, tree expr)
1110 register enum tree_code form = TREE_CODE (TREE_TYPE (expr));
1113 assert (TREE_CODE (type) == RECORD_TYPE);
1115 subtype = TREE_TYPE (TYPE_FIELDS (type));
1117 if (form == REAL_TYPE || form == INTEGER_TYPE || form == ENUMERAL_TYPE)
1119 expr = convert (subtype, expr);
1120 return ffecom_2 (COMPLEX_EXPR, type, expr,
1121 convert (subtype, integer_zero_node));
1124 if (form == RECORD_TYPE)
1126 tree elt_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr)));
1127 if (TYPE_MAIN_VARIANT (elt_type) == TYPE_MAIN_VARIANT (subtype))
1131 expr = save_expr (expr);
1132 return ffecom_2 (COMPLEX_EXPR,
1135 ffecom_1 (REALPART_EXPR,
1136 TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))),
1139 ffecom_1 (IMAGPART_EXPR,
1140 TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))),
1145 if (form == POINTER_TYPE || form == REFERENCE_TYPE)
1146 error ("pointer value used where a complex was expected");
1148 error ("aggregate value used where a complex was expected");
1150 return ffecom_2 (COMPLEX_EXPR, type,
1151 convert (subtype, integer_zero_node),
1152 convert (subtype, integer_zero_node));
1156 /* Like gcc's convert(), but crashes if widening might happen. */
1158 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1160 ffecom_convert_narrow_ (type, expr)
1163 register tree e = expr;
1164 register enum tree_code code = TREE_CODE (type);
1166 if (type == TREE_TYPE (e)
1167 || TREE_CODE (e) == ERROR_MARK)
1169 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
1170 return fold (build1 (NOP_EXPR, type, e));
1171 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
1172 || code == ERROR_MARK)
1173 return error_mark_node;
1174 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
1176 assert ("void value not ignored as it ought to be" == NULL);
1177 return error_mark_node;
1179 assert (code != VOID_TYPE);
1180 if ((code != RECORD_TYPE)
1181 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
1182 assert ("converting COMPLEX to REAL" == NULL);
1183 assert (code != ENUMERAL_TYPE);
1184 if (code == INTEGER_TYPE)
1186 assert ((TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE
1187 && TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)))
1188 || (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
1189 && (TYPE_PRECISION (type)
1190 == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (e))))));
1191 return fold (convert_to_integer (type, e));
1193 if (code == POINTER_TYPE)
1195 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
1196 return fold (convert_to_pointer (type, e));
1198 if (code == REAL_TYPE)
1200 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
1201 assert (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)));
1202 return fold (convert_to_real (type, e));
1204 if (code == COMPLEX_TYPE)
1206 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
1207 assert (TYPE_PRECISION (TREE_TYPE (type)) <= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
1208 return fold (convert_to_complex (type, e));
1210 if (code == RECORD_TYPE)
1212 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
1213 /* Check that at least the first field name agrees. */
1214 assert (DECL_NAME (TYPE_FIELDS (type))
1215 == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e))));
1216 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1217 <= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
1218 if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1219 == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))))
1221 return fold (ffecom_convert_to_complex_ (type, e));
1224 assert ("conversion to non-scalar type requested" == NULL);
1225 return error_mark_node;
1229 /* Like gcc's convert(), but crashes if narrowing might happen. */
1231 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1233 ffecom_convert_widen_ (type, expr)
1236 register tree e = expr;
1237 register enum tree_code code = TREE_CODE (type);
1239 if (type == TREE_TYPE (e)
1240 || TREE_CODE (e) == ERROR_MARK)
1242 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
1243 return fold (build1 (NOP_EXPR, type, e));
1244 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
1245 || code == ERROR_MARK)
1246 return error_mark_node;
1247 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
1249 assert ("void value not ignored as it ought to be" == NULL);
1250 return error_mark_node;
1252 assert (code != VOID_TYPE);
1253 if ((code != RECORD_TYPE)
1254 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
1255 assert ("narrowing COMPLEX to REAL" == NULL);
1256 assert (code != ENUMERAL_TYPE);
1257 if (code == INTEGER_TYPE)
1259 assert ((TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE
1260 && TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)))
1261 || (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
1262 && (TYPE_PRECISION (type)
1263 == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (e))))));
1264 return fold (convert_to_integer (type, e));
1266 if (code == POINTER_TYPE)
1268 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
1269 return fold (convert_to_pointer (type, e));
1271 if (code == REAL_TYPE)
1273 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
1274 assert (TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)));
1275 return fold (convert_to_real (type, e));
1277 if (code == COMPLEX_TYPE)
1279 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
1280 assert (TYPE_PRECISION (TREE_TYPE (type)) >= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
1281 return fold (convert_to_complex (type, e));
1283 if (code == RECORD_TYPE)
1285 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
1286 /* Check that at least the first field name agrees. */
1287 assert (DECL_NAME (TYPE_FIELDS (type))
1288 == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e))));
1289 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1290 >= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
1291 if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1292 == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))))
1294 return fold (ffecom_convert_to_complex_ (type, e));
1297 assert ("conversion to non-scalar type requested" == NULL);
1298 return error_mark_node;
1302 /* Handles making a COMPLEX type, either the standard
1303 (but buggy?) gbe way, or the safer (but less elegant?)
1306 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1308 ffecom_make_complex_type_ (tree subtype)
1314 if (ffe_is_emulate_complex ())
1316 type = make_node (RECORD_TYPE);
1317 realfield = ffecom_decl_field (type, NULL_TREE, "r", subtype);
1318 imagfield = ffecom_decl_field (type, realfield, "i", subtype);
1319 TYPE_FIELDS (type) = realfield;
1324 type = make_node (COMPLEX_TYPE);
1325 TREE_TYPE (type) = subtype;
1333 /* Chooses either the gbe or the f2c way to build a
1334 complex constant. */
1336 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1338 ffecom_build_complex_constant_ (tree type, tree realpart, tree imagpart)
1342 if (ffe_is_emulate_complex ())
1344 bothparts = build_tree_list (TYPE_FIELDS (type), realpart);
1345 TREE_CHAIN (bothparts) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), imagpart);
1346 bothparts = build (CONSTRUCTOR, type, NULL_TREE, bothparts);
1350 bothparts = build_complex (type, realpart, imagpart);
1357 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1359 ffecom_arglist_expr_ (const char *c, ffebld expr)
1362 tree *plist = &list;
1363 tree trail = NULL_TREE; /* Append char length args here. */
1364 tree *ptrail = &trail;
1369 tree wanted = NULL_TREE;
1370 static char zed[] = "0";
1375 while (expr != NULL)
1398 wanted = ffecom_f2c_complex_type_node;
1402 wanted = ffecom_f2c_doublereal_type_node;
1406 wanted = ffecom_f2c_doublecomplex_type_node;
1410 wanted = ffecom_f2c_real_type_node;
1414 wanted = ffecom_f2c_integer_type_node;
1418 wanted = ffecom_f2c_longint_type_node;
1422 assert ("bad argstring code" == NULL);
1428 exprh = ffebld_head (expr);
1432 if ((wanted == NULL_TREE)
1435 (ffecom_tree_type[ffeinfo_basictype (ffebld_info (exprh))]
1436 [ffeinfo_kindtype (ffebld_info (exprh))])
1437 == TYPE_MODE (wanted))))
1439 = build_tree_list (NULL_TREE,
1440 ffecom_arg_ptr_to_expr (exprh,
1444 item = ffecom_arg_expr (exprh, &length);
1445 item = ffecom_convert_widen_ (wanted, item);
1448 item = ffecom_1 (ADDR_EXPR,
1449 build_pointer_type (TREE_TYPE (item)),
1453 = build_tree_list (NULL_TREE,
1457 plist = &TREE_CHAIN (*plist);
1458 expr = ffebld_trail (expr);
1459 if (length != NULL_TREE)
1461 *ptrail = build_tree_list (NULL_TREE, length);
1462 ptrail = &TREE_CHAIN (*ptrail);
1466 /* We've run out of args in the call; if the implementation expects
1467 more, supply null pointers for them, which the implementation can
1468 check to see if an arg was omitted. */
1470 while (*c != '\0' && *c != '0')
1475 assert ("missing arg to run-time routine!" == NULL);
1490 assert ("bad arg string code" == NULL);
1494 = build_tree_list (NULL_TREE,
1496 plist = &TREE_CHAIN (*plist);
1505 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1507 ffecom_widest_expr_type_ (ffebld list)
1510 ffebld widest = NULL;
1512 ffetype widest_type = NULL;
1515 for (; list != NULL; list = ffebld_trail (list))
1517 item = ffebld_head (list);
1520 if ((widest != NULL)
1521 && (ffeinfo_basictype (ffebld_info (item))
1522 != ffeinfo_basictype (ffebld_info (widest))))
1524 type = ffeinfo_type (ffeinfo_basictype (ffebld_info (item)),
1525 ffeinfo_kindtype (ffebld_info (item)));
1526 if ((widest == FFEINFO_kindtypeNONE)
1527 || (ffetype_size (type)
1528 > ffetype_size (widest_type)))
1535 assert (widest != NULL);
1536 t = ffecom_tree_type[ffeinfo_basictype (ffebld_info (widest))]
1537 [ffeinfo_kindtype (ffebld_info (widest))];
1538 assert (t != NULL_TREE);
1543 /* Check whether a partial overlap between two expressions is possible.
1545 Can *starting* to write a portion of expr1 change the value
1546 computed (perhaps already, *partially*) by expr2?
1548 Currently, this is a concern only for a COMPLEX expr1. But if it
1549 isn't in COMMON or local EQUIVALENCE, since we don't support
1550 aliasing of arguments, it isn't a concern. */
1553 ffecom_possible_partial_overlap_ (ffebld expr1, ffebld expr2 ATTRIBUTE_UNUSED)
1558 switch (ffebld_op (expr1))
1560 case FFEBLD_opSYMTER:
1561 sym = ffebld_symter (expr1);
1564 case FFEBLD_opARRAYREF:
1565 if (ffebld_op (ffebld_left (expr1)) != FFEBLD_opSYMTER)
1567 sym = ffebld_symter (ffebld_left (expr1));
1574 if (ffesymbol_where (sym) != FFEINFO_whereCOMMON
1575 && (ffesymbol_where (sym) != FFEINFO_whereLOCAL
1576 || ! (st = ffesymbol_storage (sym))
1577 || ! ffestorag_parent (st)))
1580 /* It's in COMMON or local EQUIVALENCE. */
1585 /* Check whether dest and source might overlap. ffebld versions of these
1586 might or might not be passed, will be NULL if not.
1588 The test is really whether source_tree is modifiable and, if modified,
1589 might overlap destination such that the value(s) in the destination might
1590 change before it is finally modified. dest_* are the canonized
1591 destination itself. */
1593 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1595 ffecom_overlap_ (tree dest_decl, tree dest_offset, tree dest_size,
1596 tree source_tree, ffebld source UNUSED,
1604 if (source_tree == NULL_TREE)
1607 switch (TREE_CODE (source_tree))
1610 case IDENTIFIER_NODE:
1621 case TRUNC_DIV_EXPR:
1623 case FLOOR_DIV_EXPR:
1624 case ROUND_DIV_EXPR:
1625 case TRUNC_MOD_EXPR:
1627 case FLOOR_MOD_EXPR:
1628 case ROUND_MOD_EXPR:
1630 case EXACT_DIV_EXPR:
1631 case FIX_TRUNC_EXPR:
1633 case FIX_FLOOR_EXPR:
1634 case FIX_ROUND_EXPR:
1649 case BIT_ANDTC_EXPR:
1651 case TRUTH_ANDIF_EXPR:
1652 case TRUTH_ORIF_EXPR:
1653 case TRUTH_AND_EXPR:
1655 case TRUTH_XOR_EXPR:
1656 case TRUTH_NOT_EXPR:
1672 return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1673 TREE_OPERAND (source_tree, 1), NULL,
1677 return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1678 TREE_OPERAND (source_tree, 0), NULL,
1683 case NON_LVALUE_EXPR:
1685 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1688 ffecom_tree_canonize_ptr_ (&source_decl, &source_offset,
1690 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1695 ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1696 TREE_OPERAND (source_tree, 1), NULL,
1698 || ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1699 TREE_OPERAND (source_tree, 2), NULL,
1704 ffecom_tree_canonize_ref_ (&source_decl, &source_offset,
1706 TREE_OPERAND (source_tree, 0));
1710 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1713 source_decl = source_tree;
1714 source_offset = bitsize_zero_node;
1715 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1719 case REFERENCE_EXPR:
1720 case PREDECREMENT_EXPR:
1721 case PREINCREMENT_EXPR:
1722 case POSTDECREMENT_EXPR:
1723 case POSTINCREMENT_EXPR:
1731 /* Come here when source_decl, source_offset, and source_size filled
1732 in appropriately. */
1734 if (source_decl == NULL_TREE)
1735 return FALSE; /* No decl involved, so no overlap. */
1737 if (source_decl != dest_decl)
1738 return FALSE; /* Different decl, no overlap. */
1740 if (TREE_CODE (dest_size) == ERROR_MARK)
1741 return TRUE; /* Assignment into entire assumed-size
1742 array? Shouldn't happen.... */
1744 t = ffecom_2 (LE_EXPR, integer_type_node,
1745 ffecom_2 (PLUS_EXPR, TREE_TYPE (dest_offset),
1747 convert (TREE_TYPE (dest_offset),
1749 convert (TREE_TYPE (dest_offset),
1752 if (integer_onep (t))
1753 return FALSE; /* Destination precedes source. */
1756 || (source_size == NULL_TREE)
1757 || (TREE_CODE (source_size) == ERROR_MARK)
1758 || integer_zerop (source_size))
1759 return TRUE; /* No way to tell if dest follows source. */
1761 t = ffecom_2 (LE_EXPR, integer_type_node,
1762 ffecom_2 (PLUS_EXPR, TREE_TYPE (source_offset),
1764 convert (TREE_TYPE (source_offset),
1766 convert (TREE_TYPE (source_offset),
1769 if (integer_onep (t))
1770 return FALSE; /* Destination follows source. */
1772 return TRUE; /* Destination and source overlap. */
1776 /* Check whether dest might overlap any of a list of arguments or is
1777 in a COMMON area the callee might know about (and thus modify). */
1779 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1781 ffecom_args_overlapping_ (tree dest_tree, ffebld dest UNUSED,
1782 tree args, tree callee_commons,
1790 ffecom_tree_canonize_ref_ (&dest_decl, &dest_offset, &dest_size,
1793 if (dest_decl == NULL_TREE)
1794 return FALSE; /* Seems unlikely! */
1796 /* If the decl cannot be determined reliably, or if its in COMMON
1797 and the callee isn't known to not futz with COMMON via other
1798 means, overlap might happen. */
1800 if ((TREE_CODE (dest_decl) == ERROR_MARK)
1801 || ((callee_commons != NULL_TREE)
1802 && TREE_PUBLIC (dest_decl)))
1805 for (; args != NULL_TREE; args = TREE_CHAIN (args))
1807 if (((arg = TREE_VALUE (args)) != NULL_TREE)
1808 && ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1809 arg, NULL, scalar_args))
1817 /* Build a string for a variable name as used by NAMELIST. This means that
1818 if we're using the f2c library, we build an uppercase string, since
1821 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1823 ffecom_build_f2c_string_ (int i, const char *s)
1825 if (!ffe_is_f2c_library ())
1826 return build_string (i, s);
1835 if (((size_t) i) > ARRAY_SIZE (space))
1836 tmp = malloc_new_ks (malloc_pool_image (), "f2c_string", i);
1840 for (p = s, q = tmp; *p != '\0'; ++p, ++q)
1841 *q = ffesrc_toupper (*p);
1844 t = build_string (i, tmp);
1846 if (((size_t) i) > ARRAY_SIZE (space))
1847 malloc_kill_ks (malloc_pool_image (), tmp, i);
1854 /* Returns CALL_EXPR or equivalent with given type (pass NULL_TREE for
1855 type to just get whatever the function returns), handling the
1856 f2c value-returning convention, if required, by prepending
1857 to the arglist a pointer to a temporary to receive the return value. */
1859 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1861 ffecom_call_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1862 tree type, tree args, tree dest_tree,
1863 ffebld dest, bool *dest_used, tree callee_commons,
1864 bool scalar_args, tree hook)
1869 if (dest_used != NULL)
1874 if ((dest_used == NULL)
1876 || (ffeinfo_basictype (ffebld_info (dest))
1877 != FFEINFO_basictypeCOMPLEX)
1878 || (ffeinfo_kindtype (ffebld_info (dest)) != kt)
1879 || ((type != NULL_TREE) && (TREE_TYPE (dest_tree) != type))
1880 || ffecom_args_overlapping_ (dest_tree, dest, args,
1885 tempvar = ffecom_make_tempvar (ffecom_tree_type
1886 [FFEINFO_basictypeCOMPLEX][kt],
1887 FFETARGET_charactersizeNONE,
1897 tempvar = dest_tree;
1902 = build_tree_list (NULL_TREE,
1903 ffecom_1 (ADDR_EXPR,
1904 build_pointer_type (TREE_TYPE (tempvar)),
1906 TREE_CHAIN (item) = args;
1908 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1911 if (tempvar != dest_tree)
1912 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item, tempvar);
1915 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1918 if ((type != NULL_TREE) && (TREE_TYPE (item) != type))
1919 item = ffecom_convert_narrow_ (type, item);
1925 /* Given two arguments, transform them and make a call to the given
1926 function via ffecom_call_. */
1928 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1930 ffecom_call_binop_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1931 tree type, ffebld left, ffebld right,
1932 tree dest_tree, ffebld dest, bool *dest_used,
1933 tree callee_commons, bool scalar_args, tree hook)
1940 left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
1941 right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
1943 left_tree = build_tree_list (NULL_TREE, left_tree);
1944 right_tree = build_tree_list (NULL_TREE, right_tree);
1945 TREE_CHAIN (left_tree) = right_tree;
1947 if (left_length != NULL_TREE)
1949 left_length = build_tree_list (NULL_TREE, left_length);
1950 TREE_CHAIN (right_tree) = left_length;
1953 if (right_length != NULL_TREE)
1955 right_length = build_tree_list (NULL_TREE, right_length);
1956 if (left_length != NULL_TREE)
1957 TREE_CHAIN (left_length) = right_length;
1959 TREE_CHAIN (right_tree) = right_length;
1962 return ffecom_call_ (fn, kt, is_f2c_complex, type, left_tree,
1963 dest_tree, dest, dest_used, callee_commons,
1968 /* Return ptr/length args for char subexpression
1970 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
1971 subexpressions by constructing the appropriate trees for the ptr-to-
1972 character-text and length-of-character-text arguments in a calling
1975 Note that if with_null is TRUE, and the expression is an opCONTER,
1976 a null byte is appended to the string. */
1978 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1980 ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
1984 ffetargetCharacter1 val;
1985 ffetargetCharacterSize newlen;
1987 switch (ffebld_op (expr))
1989 case FFEBLD_opCONTER:
1990 val = ffebld_constant_character1 (ffebld_conter (expr));
1991 newlen = ffetarget_length_character1 (val);
1994 /* Begin FFETARGET-NULL-KLUDGE. */
1998 *length = build_int_2 (newlen, 0);
1999 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2000 high = build_int_2 (newlen, 0);
2001 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
2002 item = build_string (newlen,
2003 ffetarget_text_character1 (val));
2004 /* End FFETARGET-NULL-KLUDGE. */
2006 = build_type_variant
2010 (ffecom_f2c_ftnlen_type_node,
2011 ffecom_f2c_ftnlen_one_node,
2014 TREE_CONSTANT (item) = 1;
2015 TREE_STATIC (item) = 1;
2016 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
2020 case FFEBLD_opSYMTER:
2022 ffesymbol s = ffebld_symter (expr);
2024 item = ffesymbol_hook (s).decl_tree;
2025 if (item == NULL_TREE)
2027 s = ffecom_sym_transform_ (s);
2028 item = ffesymbol_hook (s).decl_tree;
2030 if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
2032 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
2033 *length = ffesymbol_hook (s).length_tree;
2036 *length = build_int_2 (ffesymbol_size (s), 0);
2037 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2040 else if (item == error_mark_node)
2041 *length = error_mark_node;
2043 /* FFEINFO_kindFUNCTION. */
2044 *length = NULL_TREE;
2045 if (!ffesymbol_hook (s).addr
2046 && (item != error_mark_node))
2047 item = ffecom_1 (ADDR_EXPR,
2048 build_pointer_type (TREE_TYPE (item)),
2053 case FFEBLD_opARRAYREF:
2055 ffecom_char_args_ (&item, length, ffebld_left (expr));
2057 if (item == error_mark_node || *length == error_mark_node)
2059 item = *length = error_mark_node;
2063 item = ffecom_arrayref_ (item, expr, 1);
2067 case FFEBLD_opSUBSTR:
2071 ffebld thing = ffebld_right (expr);
2074 const char *char_name;
2078 assert (ffebld_op (thing) == FFEBLD_opITEM);
2079 start = ffebld_head (thing);
2080 thing = ffebld_trail (thing);
2081 assert (ffebld_trail (thing) == NULL);
2082 end = ffebld_head (thing);
2084 /* Determine name for pretty-printing range-check errors. */
2085 for (left_symter = ffebld_left (expr);
2086 left_symter && ffebld_op (left_symter) == FFEBLD_opARRAYREF;
2087 left_symter = ffebld_left (left_symter))
2089 if (ffebld_op (left_symter) == FFEBLD_opSYMTER)
2090 char_name = ffesymbol_text (ffebld_symter (left_symter));
2092 char_name = "[expr?]";
2094 ffecom_char_args_ (&item, length, ffebld_left (expr));
2096 if (item == error_mark_node || *length == error_mark_node)
2098 item = *length = error_mark_node;
2102 array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
2104 /* ~~~~Handle INTEGER*8 start/end, a la FFEBLD_opARRAYREF. */
2112 end_tree = ffecom_expr (end);
2113 if (flag_bounds_check)
2114 end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
2116 end_tree = convert (ffecom_f2c_ftnlen_type_node,
2119 if (end_tree == error_mark_node)
2121 item = *length = error_mark_node;
2130 start_tree = ffecom_expr (start);
2131 if (flag_bounds_check)
2132 start_tree = ffecom_subscript_check_ (array, start_tree, 0, 0,
2134 start_tree = convert (ffecom_f2c_ftnlen_type_node,
2137 if (start_tree == error_mark_node)
2139 item = *length = error_mark_node;
2143 start_tree = ffecom_save_tree (start_tree);
2145 item = ffecom_2 (PLUS_EXPR, TREE_TYPE (item),
2147 ffecom_2 (MINUS_EXPR,
2148 TREE_TYPE (start_tree),
2150 ffecom_f2c_ftnlen_one_node));
2154 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
2155 ffecom_f2c_ftnlen_one_node,
2156 ffecom_2 (MINUS_EXPR,
2157 ffecom_f2c_ftnlen_type_node,
2163 end_tree = ffecom_expr (end);
2164 if (flag_bounds_check)
2165 end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
2167 end_tree = convert (ffecom_f2c_ftnlen_type_node,
2170 if (end_tree == error_mark_node)
2172 item = *length = error_mark_node;
2176 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
2177 ffecom_f2c_ftnlen_one_node,
2178 ffecom_2 (MINUS_EXPR,
2179 ffecom_f2c_ftnlen_type_node,
2180 end_tree, start_tree));
2186 case FFEBLD_opFUNCREF:
2188 ffesymbol s = ffebld_symter (ffebld_left (expr));
2191 ffetargetCharacterSize size = ffeinfo_size (ffebld_info (expr));
2194 if (size == FFETARGET_charactersizeNONE)
2195 /* ~~Kludge alert! This should someday be fixed. */
2198 *length = build_int_2 (size, 0);
2199 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2201 if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
2202 == FFEINFO_whereINTRINSIC)
2206 /* Invocation of an intrinsic returning CHARACTER*1. */
2207 item = ffecom_expr_intrinsic_ (expr, NULL_TREE,
2211 ix = ffeintrin_gfrt_direct (ffebld_symter_implementation (ffebld_left (expr)));
2212 assert (ix != FFECOM_gfrt);
2213 item = ffecom_gfrt_tree_ (ix);
2218 item = ffesymbol_hook (s).decl_tree;
2219 if (item == NULL_TREE)
2221 s = ffecom_sym_transform_ (s);
2222 item = ffesymbol_hook (s).decl_tree;
2224 if (item == error_mark_node)
2226 item = *length = error_mark_node;
2230 if (!ffesymbol_hook (s).addr)
2231 item = ffecom_1_fn (item);
2235 tempvar = ffecom_push_tempvar (char_type_node, size, -1, TRUE);
2237 tempvar = ffebld_nonter_hook (expr);
2240 tempvar = ffecom_1 (ADDR_EXPR,
2241 build_pointer_type (TREE_TYPE (tempvar)),
2244 args = build_tree_list (NULL_TREE, tempvar);
2246 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT) /* Sfunc args by value. */
2247 TREE_CHAIN (args) = ffecom_list_expr (ffebld_right (expr));
2250 TREE_CHAIN (args) = build_tree_list (NULL_TREE, *length);
2251 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
2253 TREE_CHAIN (TREE_CHAIN (args))
2254 = ffecom_arglist_expr_ (ffecom_gfrt_args_ (ix),
2255 ffebld_right (expr));
2259 TREE_CHAIN (TREE_CHAIN (args))
2260 = ffecom_list_ptr_to_expr (ffebld_right (expr));
2264 item = ffecom_3s (CALL_EXPR,
2265 TREE_TYPE (TREE_TYPE (TREE_TYPE (item))),
2266 item, args, NULL_TREE);
2267 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item,
2272 case FFEBLD_opCONVERT:
2274 ffecom_char_args_ (&item, length, ffebld_left (expr));
2276 if (item == error_mark_node || *length == error_mark_node)
2278 item = *length = error_mark_node;
2282 if ((ffebld_size_known (ffebld_left (expr))
2283 == FFETARGET_charactersizeNONE)
2284 || (ffebld_size_known (ffebld_left (expr)) < (ffebld_size (expr))))
2285 { /* Possible blank-padding needed, copy into
2292 tempvar = ffecom_make_tempvar (char_type_node,
2293 ffebld_size (expr), -1);
2295 tempvar = ffebld_nonter_hook (expr);
2298 tempvar = ffecom_1 (ADDR_EXPR,
2299 build_pointer_type (TREE_TYPE (tempvar)),
2302 newlen = build_int_2 (ffebld_size (expr), 0);
2303 TREE_TYPE (newlen) = ffecom_f2c_ftnlen_type_node;
2305 args = build_tree_list (NULL_TREE, tempvar);
2306 TREE_CHAIN (args) = build_tree_list (NULL_TREE, item);
2307 TREE_CHAIN (TREE_CHAIN (args)) = build_tree_list (NULL_TREE, newlen);
2308 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (args)))
2309 = build_tree_list (NULL_TREE, *length);
2311 item = ffecom_call_gfrt (FFECOM_gfrtCOPY, args, NULL_TREE);
2312 TREE_SIDE_EFFECTS (item) = 1;
2313 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), fold (item),
2318 { /* Just truncate the length. */
2319 *length = build_int_2 (ffebld_size (expr), 0);
2320 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2325 assert ("bad op for single char arg expr" == NULL);
2334 /* Check the size of the type to be sure it doesn't overflow the
2335 "portable" capacities of the compiler back end. `dummy' types
2336 can generally overflow the normal sizes as long as the computations
2337 themselves don't overflow. A particular target of the back end
2338 must still enforce its size requirements, though, and the back
2339 end takes care of this in stor-layout.c. */
2341 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2343 ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy)
2345 if (TREE_CODE (type) == ERROR_MARK)
2348 if (TYPE_SIZE (type) == NULL_TREE)
2351 if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
2354 if ((tree_int_cst_sgn (TYPE_SIZE (type)) < 0)
2355 || (!dummy && (((TREE_INT_CST_HIGH (TYPE_SIZE (type)) != 0))
2356 || TREE_OVERFLOW (TYPE_SIZE (type)))))
2358 ffebad_start (FFEBAD_ARRAY_LARGE);
2359 ffebad_string (ffesymbol_text (s));
2360 ffebad_here (0, ffesymbol_where_line (s), ffesymbol_where_column (s));
2363 return error_mark_node;
2370 /* Builds a length argument (PARM_DECL). Also wraps type in an array type
2371 where the dimension info is (1:size) where <size> is ffesymbol_size(s) if
2372 known, length_arg if not known (FFETARGET_charactersizeNONE). */
2374 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2376 ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s)
2378 ffetargetCharacterSize sz = ffesymbol_size (s);
2383 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
2384 tlen = NULL_TREE; /* A statement function, no length passed. */
2387 if (ffesymbol_where (s) == FFEINFO_whereDUMMY)
2388 tlen = ffecom_get_invented_identifier ("__g77_length_%s",
2389 ffesymbol_text (s));
2391 tlen = ffecom_get_invented_identifier ("__g77_%s", "length");
2392 tlen = build_decl (PARM_DECL, tlen, ffecom_f2c_ftnlen_type_node);
2394 DECL_ARTIFICIAL (tlen) = 1;
2398 if (sz == FFETARGET_charactersizeNONE)
2400 assert (tlen != NULL_TREE);
2401 highval = variable_size (tlen);
2405 highval = build_int_2 (sz, 0);
2406 TREE_TYPE (highval) = ffecom_f2c_ftnlen_type_node;
2409 type = build_array_type (type,
2410 build_range_type (ffecom_f2c_ftnlen_type_node,
2411 ffecom_f2c_ftnlen_one_node,
2419 /* ffecom_concat_list_gather_ -- Gather list of concatenated string exprs
2421 ffecomConcatList_ catlist;
2422 ffebld expr; // expr of CHARACTER basictype.
2423 ffetargetCharacterSize max; // max chars to gather or _...NONE if no max
2424 catlist = ffecom_concat_list_gather_(catlist,expr,max);
2426 Scans expr for character subexpressions, updates and returns catlist
2429 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2430 static ffecomConcatList_
2431 ffecom_concat_list_gather_ (ffecomConcatList_ catlist, ffebld expr,
2432 ffetargetCharacterSize max)
2434 ffetargetCharacterSize sz;
2436 recurse: /* :::::::::::::::::::: */
2441 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen >= max))
2442 return catlist; /* Don't append any more items. */
2444 switch (ffebld_op (expr))
2446 case FFEBLD_opCONTER:
2447 case FFEBLD_opSYMTER:
2448 case FFEBLD_opARRAYREF:
2449 case FFEBLD_opFUNCREF:
2450 case FFEBLD_opSUBSTR:
2451 case FFEBLD_opCONVERT: /* Callers should strip this off beforehand
2452 if they don't need to preserve it. */
2453 if (catlist.count == catlist.max)
2454 { /* Make a (larger) list. */
2458 newmax = (catlist.max == 0) ? 8 : catlist.max * 2;
2459 newx = malloc_new_ks (malloc_pool_image (), "catlist",
2460 newmax * sizeof (newx[0]));
2461 if (catlist.max != 0)
2463 memcpy (newx, catlist.exprs, catlist.max * sizeof (newx[0]));
2464 malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2465 catlist.max * sizeof (newx[0]));
2467 catlist.max = newmax;
2468 catlist.exprs = newx;
2470 if ((sz = ffebld_size_known (expr)) != FFETARGET_charactersizeNONE)
2471 catlist.minlen += sz;
2473 ++catlist.minlen; /* Not true for F90; can be 0 length. */
2474 if ((sz = ffebld_size_max (expr)) == FFETARGET_charactersizeNONE)
2475 catlist.maxlen = sz;
2477 catlist.maxlen += sz;
2478 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen > max))
2479 { /* This item overlaps (or is beyond) the end
2480 of the destination. */
2481 switch (ffebld_op (expr))
2483 case FFEBLD_opCONTER:
2484 case FFEBLD_opSYMTER:
2485 case FFEBLD_opARRAYREF:
2486 case FFEBLD_opFUNCREF:
2487 case FFEBLD_opSUBSTR:
2488 /* ~~Do useful truncations here. */
2492 assert ("op changed or inconsistent switches!" == NULL);
2496 catlist.exprs[catlist.count++] = expr;
2499 case FFEBLD_opPAREN:
2500 expr = ffebld_left (expr);
2501 goto recurse; /* :::::::::::::::::::: */
2503 case FFEBLD_opCONCATENATE:
2504 catlist = ffecom_concat_list_gather_ (catlist, ffebld_left (expr), max);
2505 expr = ffebld_right (expr);
2506 goto recurse; /* :::::::::::::::::::: */
2508 #if 0 /* Breaks passing small actual arg to larger
2509 dummy arg of sfunc */
2510 case FFEBLD_opCONVERT:
2511 expr = ffebld_left (expr);
2513 ffetargetCharacterSize cmax;
2515 cmax = catlist.len + ffebld_size_known (expr);
2517 if ((max == FFETARGET_charactersizeNONE) || (max > cmax))
2520 goto recurse; /* :::::::::::::::::::: */
2527 assert ("bad op in _gather_" == NULL);
2533 /* ffecom_concat_list_kill_ -- Kill list of concatenated string exprs
2535 ffecomConcatList_ catlist;
2536 ffecom_concat_list_kill_(catlist);
2538 Anything allocated within the list info is deallocated. */
2540 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2542 ffecom_concat_list_kill_ (ffecomConcatList_ catlist)
2544 if (catlist.max != 0)
2545 malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2546 catlist.max * sizeof (catlist.exprs[0]));
2550 /* Make list of concatenated string exprs.
2552 Returns a flattened list of concatenated subexpressions given a
2553 tree of such expressions. */
2555 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2556 static ffecomConcatList_
2557 ffecom_concat_list_new_ (ffebld expr, ffetargetCharacterSize max)
2559 ffecomConcatList_ catlist;
2561 catlist.maxlen = catlist.minlen = catlist.max = catlist.count = 0;
2562 return ffecom_concat_list_gather_ (catlist, expr, max);
2567 /* Provide some kind of useful info on member of aggregate area,
2568 since current g77/gcc technology does not provide debug info
2569 on these members. */
2571 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2573 ffecom_debug_kludge_ (tree aggr, const char *aggr_type, ffesymbol member,
2574 tree member_type UNUSED, ffetargetOffset offset)
2584 for (type_id = member_type;
2585 TREE_CODE (type_id) != IDENTIFIER_NODE;
2588 switch (TREE_CODE (type_id))
2592 type_id = TYPE_NAME (type_id);
2597 type_id = TREE_TYPE (type_id);
2601 assert ("no IDENTIFIER_NODE for type!" == NULL);
2602 type_id = error_mark_node;
2608 if (ffecom_transform_only_dummies_
2609 || !ffe_is_debug_kludge ())
2610 return; /* Can't do this yet, maybe later. */
2613 + strlen (aggr_type)
2614 + IDENTIFIER_LENGTH (DECL_NAME (aggr));
2616 + IDENTIFIER_LENGTH (type_id);
2619 if (((size_t) len) >= ARRAY_SIZE (space))
2620 buff = malloc_new_ks (malloc_pool_image (), "debug_kludge", len + 1);
2624 sprintf (&buff[0], "At (%s) `%s' plus %ld bytes",
2626 IDENTIFIER_POINTER (DECL_NAME (aggr)),
2629 value = build_string (len, buff);
2631 = build_type_variant (build_array_type (char_type_node,
2635 build_int_2 (strlen (buff), 0))),
2637 decl = build_decl (VAR_DECL,
2638 ffecom_get_identifier_ (ffesymbol_text (member)),
2640 TREE_CONSTANT (decl) = 1;
2641 TREE_STATIC (decl) = 1;
2642 DECL_INITIAL (decl) = error_mark_node;
2643 DECL_IN_SYSTEM_HEADER (decl) = 1; /* Don't let -Wunused complain. */
2644 decl = start_decl (decl, FALSE);
2645 finish_decl (decl, value, FALSE);
2647 if (buff != &space[0])
2648 malloc_kill_ks (malloc_pool_image (), buff, len + 1);
2652 /* ffecom_do_entry_ -- Do compilation of a particular entrypoint
2654 ffesymbol fn; // the SUBROUTINE, FUNCTION, or ENTRY symbol itself
2655 int i; // entry# for this entrypoint (used by master fn)
2656 ffecom_do_entrypoint_(s,i);
2658 Makes a public entry point that calls our private master fn (already
2661 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2663 ffecom_do_entry_ (ffesymbol fn, int entrynum)
2666 tree type; /* Type of function. */
2667 tree multi_retval; /* Var holding return value (union). */
2668 tree result; /* Var holding result. */
2669 ffeinfoBasictype bt;
2673 bool charfunc; /* All entry points return same type
2675 bool cmplxfunc; /* Use f2c way of returning COMPLEX. */
2676 bool multi; /* Master fn has multiple return types. */
2677 bool altreturning = FALSE; /* This entry point has alternate returns. */
2679 int old_lineno = lineno;
2680 const char *old_input_filename = input_filename;
2682 input_filename = ffesymbol_where_filename (fn);
2683 lineno = ffesymbol_where_filelinenum (fn);
2685 /* c-parse.y indeed does call suspend_momentary and not only ignores the
2686 return value, but also never calls resume_momentary, when starting an
2687 outer function (see "fndef:", "setspecs:", and so on). So g77 does the
2688 same thing. It shouldn't be a problem since start_function calls
2689 temporary_allocation, but it might be necessary. If it causes a problem
2690 here, then maybe there's a bug lurking in gcc. NOTE: This identical
2691 comment appears twice in thist file. */
2693 suspend_momentary ();
2695 ffecom_doing_entry_ = TRUE; /* Don't bother with array dimensions. */
2697 switch (ffecom_primary_entry_kind_)
2699 case FFEINFO_kindFUNCTION:
2701 /* Determine actual return type for function. */
2703 gt = FFEGLOBAL_typeFUNC;
2704 bt = ffesymbol_basictype (fn);
2705 kt = ffesymbol_kindtype (fn);
2706 if (bt == FFEINFO_basictypeNONE)
2708 ffeimplic_establish_symbol (fn);
2709 if (ffesymbol_funcresult (fn) != NULL)
2710 ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
2711 bt = ffesymbol_basictype (fn);
2712 kt = ffesymbol_kindtype (fn);
2715 if (bt == FFEINFO_basictypeCHARACTER)
2716 charfunc = TRUE, cmplxfunc = FALSE;
2717 else if ((bt == FFEINFO_basictypeCOMPLEX)
2718 && ffesymbol_is_f2c (fn))
2719 charfunc = FALSE, cmplxfunc = TRUE;
2721 charfunc = cmplxfunc = FALSE;
2724 type = ffecom_tree_fun_type_void;
2725 else if (ffesymbol_is_f2c (fn))
2726 type = ffecom_tree_fun_type[bt][kt];
2728 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
2730 if ((type == NULL_TREE)
2731 || (TREE_TYPE (type) == NULL_TREE))
2732 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */
2734 multi = (ffecom_master_bt_ == FFEINFO_basictypeNONE);
2737 case FFEINFO_kindSUBROUTINE:
2738 gt = FFEGLOBAL_typeSUBR;
2739 bt = FFEINFO_basictypeNONE;
2740 kt = FFEINFO_kindtypeNONE;
2741 if (ffecom_is_altreturning_)
2742 { /* Am _I_ altreturning? */
2743 for (item = ffesymbol_dummyargs (fn);
2745 item = ffebld_trail (item))
2747 if (ffebld_op (ffebld_head (item)) == FFEBLD_opSTAR)
2749 altreturning = TRUE;
2754 type = ffecom_tree_subr_type;
2756 type = ffecom_tree_fun_type_void;
2759 type = ffecom_tree_fun_type_void;
2766 assert ("say what??" == NULL);
2768 case FFEINFO_kindANY:
2769 gt = FFEGLOBAL_typeANY;
2770 bt = FFEINFO_basictypeNONE;
2771 kt = FFEINFO_kindtypeNONE;
2772 type = error_mark_node;
2779 /* build_decl uses the current lineno and input_filename to set the decl
2780 source info. So, I've putzed with ffestd and ffeste code to update that
2781 source info to point to the appropriate statement just before calling
2782 ffecom_do_entrypoint (which calls this fn). */
2784 start_function (ffecom_get_external_identifier_ (fn),
2786 0, /* nested/inline */
2787 1); /* TREE_PUBLIC */
2789 if (((g = ffesymbol_global (fn)) != NULL)
2790 && ((ffeglobal_type (g) == gt)
2791 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
2793 ffeglobal_set_hook (g, current_function_decl);
2796 /* Reset args in master arg list so they get retransitioned. */
2798 for (item = ffecom_master_arglist_;
2800 item = ffebld_trail (item))
2805 arg = ffebld_head (item);
2806 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2807 continue; /* Alternate return or some such thing. */
2808 s = ffebld_symter (arg);
2809 ffesymbol_hook (s).decl_tree = NULL_TREE;
2810 ffesymbol_hook (s).length_tree = NULL_TREE;
2813 /* Build dummy arg list for this entry point. */
2815 yes = suspend_momentary ();
2817 if (charfunc || cmplxfunc)
2818 { /* Prepend arg for where result goes. */
2823 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
2825 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
2827 result = ffecom_get_invented_identifier ("__g77_%s", "result");
2829 /* Make length arg _and_ enhance type info for CHAR arg itself. */
2832 length = ffecom_char_enhance_arg_ (&type, fn);
2834 length = NULL_TREE; /* Not ref'd if !charfunc. */
2836 type = build_pointer_type (type);
2837 result = build_decl (PARM_DECL, result, type);
2839 push_parm_decl (result);
2840 ffecom_func_result_ = result;
2844 push_parm_decl (length);
2845 ffecom_func_length_ = length;
2849 result = DECL_RESULT (current_function_decl);
2851 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (fn), FALSE);
2853 resume_momentary (yes);
2855 store_parm_decls (0);
2857 ffecom_start_compstmt ();
2858 /* Disallow temp vars at this level. */
2859 current_binding_level->prep_state = 2;
2861 /* Make local var to hold return type for multi-type master fn. */
2865 yes = suspend_momentary ();
2867 multi_retval = ffecom_get_invented_identifier ("__g77_%s",
2869 multi_retval = build_decl (VAR_DECL, multi_retval,
2870 ffecom_multi_type_node_);
2871 multi_retval = start_decl (multi_retval, FALSE);
2872 finish_decl (multi_retval, NULL_TREE, FALSE);
2874 resume_momentary (yes);
2877 multi_retval = NULL_TREE; /* Not actually ref'd if !multi. */
2879 /* Here we emit the actual code for the entry point. */
2885 tree arglist = NULL_TREE;
2886 tree *plist = &arglist;
2892 /* Prepare actual arg list based on master arg list. */
2894 for (list = ffecom_master_arglist_;
2896 list = ffebld_trail (list))
2898 arg = ffebld_head (list);
2899 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2901 s = ffebld_symter (arg);
2902 if (ffesymbol_hook (s).decl_tree == NULL_TREE
2903 || ffesymbol_hook (s).decl_tree == error_mark_node)
2904 actarg = null_pointer_node; /* We don't have this arg. */
2906 actarg = ffesymbol_hook (s).decl_tree;
2907 *plist = build_tree_list (NULL_TREE, actarg);
2908 plist = &TREE_CHAIN (*plist);
2911 /* This code appends the length arguments for character
2912 variables/arrays. */
2914 for (list = ffecom_master_arglist_;
2916 list = ffebld_trail (list))
2918 arg = ffebld_head (list);
2919 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2921 s = ffebld_symter (arg);
2922 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
2923 continue; /* Only looking for CHARACTER arguments. */
2924 if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
2925 continue; /* Only looking for variables and arrays. */
2926 if (ffesymbol_hook (s).length_tree == NULL_TREE
2927 || ffesymbol_hook (s).length_tree == error_mark_node)
2928 actarg = ffecom_f2c_ftnlen_zero_node; /* We don't have this arg. */
2930 actarg = ffesymbol_hook (s).length_tree;
2931 *plist = build_tree_list (NULL_TREE, actarg);
2932 plist = &TREE_CHAIN (*plist);
2935 /* Prepend character-value return info to actual arg list. */
2939 prepend = build_tree_list (NULL_TREE, ffecom_func_result_);
2940 TREE_CHAIN (prepend)
2941 = build_tree_list (NULL_TREE, ffecom_func_length_);
2942 TREE_CHAIN (TREE_CHAIN (prepend)) = arglist;
2946 /* Prepend multi-type return value to actual arg list. */
2951 = build_tree_list (NULL_TREE,
2952 ffecom_1 (ADDR_EXPR,
2953 build_pointer_type (TREE_TYPE (multi_retval)),
2955 TREE_CHAIN (prepend) = arglist;
2959 /* Prepend my entry-point number to the actual arg list. */
2961 prepend = build_tree_list (NULL_TREE, build_int_2 (entrynum, 0));
2962 TREE_CHAIN (prepend) = arglist;
2965 /* Build the call to the master function. */
2967 master_fn = ffecom_1_fn (ffecom_previous_function_decl_);
2968 call = ffecom_3s (CALL_EXPR,
2969 TREE_TYPE (TREE_TYPE (TREE_TYPE (master_fn))),
2970 master_fn, arglist, NULL_TREE);
2972 /* Decide whether the master function is a function or subroutine, and
2973 handle the return value for my entry point. */
2975 if (charfunc || ((ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
2978 expand_expr_stmt (call);
2979 expand_null_return ();
2981 else if (multi && cmplxfunc)
2983 expand_expr_stmt (call);
2985 = ffecom_1 (INDIRECT_REF,
2986 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
2988 result = ffecom_modify (NULL_TREE, result,
2989 ffecom_2 (COMPONENT_REF, TREE_TYPE (result),
2991 ffecom_multi_fields_[bt][kt]));
2992 expand_expr_stmt (result);
2993 expand_null_return ();
2997 expand_expr_stmt (call);
2999 = ffecom_modify (NULL_TREE, result,
3000 convert (TREE_TYPE (result),
3001 ffecom_2 (COMPONENT_REF,
3002 ffecom_tree_type[bt][kt],
3004 ffecom_multi_fields_[bt][kt])));
3005 expand_return (result);
3010 = ffecom_1 (INDIRECT_REF,
3011 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
3013 result = ffecom_modify (NULL_TREE, result, call);
3014 expand_expr_stmt (result);
3015 expand_null_return ();
3019 result = ffecom_modify (NULL_TREE,
3021 convert (TREE_TYPE (result),
3023 expand_return (result);
3029 ffecom_end_compstmt ();
3031 finish_function (0);
3033 lineno = old_lineno;
3034 input_filename = old_input_filename;
3036 ffecom_doing_entry_ = FALSE;
3040 /* Transform expr into gcc tree with possible destination
3042 Recursive descent on expr while making corresponding tree nodes and
3043 attaching type info and such. If destination supplied and compatible
3044 with temporary that would be made in certain cases, temporary isn't
3045 made, destination used instead, and dest_used flag set TRUE. */
3047 #if FFECOM_targetCURRENT == FFECOM_targetGCC
3049 ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
3050 bool *dest_used, bool assignp, bool widenp)
3055 ffeinfoBasictype bt;
3058 tree dt; /* decl_tree for an ffesymbol. */
3059 tree tree_type, tree_type_x;
3062 enum tree_code code;
3064 assert (expr != NULL);
3066 if (dest_used != NULL)
3069 bt = ffeinfo_basictype (ffebld_info (expr));
3070 kt = ffeinfo_kindtype (ffebld_info (expr));
3071 tree_type = ffecom_tree_type[bt][kt];
3073 /* Widen integral arithmetic as desired while preserving signedness. */
3074 tree_type_x = NULL_TREE;
3075 if (widenp && tree_type
3076 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
3077 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
3078 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
3080 switch (ffebld_op (expr))
3082 case FFEBLD_opACCTER:
3085 ffebit bits = ffebld_accter_bits (expr);
3086 ffetargetOffset source_offset = 0;
3087 ffetargetOffset dest_offset = ffebld_accter_pad (expr);
3090 assert (dest_offset == 0
3091 || (bt == FFEINFO_basictypeCHARACTER
3092 && kt == FFEINFO_kindtypeCHARACTER1));
3097 ffebldConstantUnion cu;
3100 ffebldConstantArray ca = ffebld_accter (expr);
3102 ffebit_test (bits, source_offset, &value, &length);
3108 for (i = 0; i < length; ++i)
3110 cu = ffebld_constantarray_get (ca, bt, kt,
3113 t = ffecom_constantunion (&cu, bt, kt, tree_type);
3116 && dest_offset != 0)
3117 purpose = build_int_2 (dest_offset, 0);
3119 purpose = NULL_TREE;
3121 if (list == NULL_TREE)
3122 list = item = build_tree_list (purpose, t);
3125 TREE_CHAIN (item) = build_tree_list (purpose, t);
3126 item = TREE_CHAIN (item);
3130 source_offset += length;
3131 dest_offset += length;
3135 item = build_int_2 ((ffebld_accter_size (expr)
3136 + ffebld_accter_pad (expr)) - 1, 0);
3137 ffebit_kill (ffebld_accter_bits (expr));
3138 TREE_TYPE (item) = ffecom_integer_type_node;
3142 build_range_type (ffecom_integer_type_node,
3143 ffecom_integer_zero_node,
3145 list = build (CONSTRUCTOR, item, NULL_TREE, list);
3146 TREE_CONSTANT (list) = 1;
3147 TREE_STATIC (list) = 1;
3150 case FFEBLD_opARRTER:
3155 if (ffebld_arrter_pad (expr) == 0)
3159 assert (bt == FFEINFO_basictypeCHARACTER
3160 && kt == FFEINFO_kindtypeCHARACTER1);
3162 /* Becomes PURPOSE first time through loop. */
3163 item = build_int_2 (ffebld_arrter_pad (expr), 0);
3166 for (i = 0; i < ffebld_arrter_size (expr); ++i)
3168 ffebldConstantUnion cu
3169 = ffebld_constantarray_get (ffebld_arrter (expr), bt, kt, i);
3171 t = ffecom_constantunion (&cu, bt, kt, tree_type);
3173 if (list == NULL_TREE)
3174 /* Assume item is PURPOSE first time through loop. */
3175 list = item = build_tree_list (item, t);
3178 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
3179 item = TREE_CHAIN (item);
3184 item = build_int_2 ((ffebld_arrter_size (expr)
3185 + ffebld_arrter_pad (expr)) - 1, 0);
3186 TREE_TYPE (item) = ffecom_integer_type_node;
3190 build_range_type (ffecom_integer_type_node,
3191 ffecom_integer_zero_node,
3193 list = build (CONSTRUCTOR, item, NULL_TREE, list);
3194 TREE_CONSTANT (list) = 1;
3195 TREE_STATIC (list) = 1;
3198 case FFEBLD_opCONTER:
3199 assert (ffebld_conter_pad (expr) == 0);
3201 = ffecom_constantunion (&ffebld_constant_union (ffebld_conter (expr)),
3205 case FFEBLD_opSYMTER:
3206 if ((ffebld_symter_generic (expr) != FFEINTRIN_genNONE)
3207 || (ffebld_symter_specific (expr) != FFEINTRIN_specNONE))
3208 return ffecom_ptr_to_expr (expr); /* Same as %REF(intrinsic). */
3209 s = ffebld_symter (expr);
3210 t = ffesymbol_hook (s).decl_tree;
3213 { /* ASSIGN'ed-label expr. */
3214 if (ffe_is_ugly_assign ())
3216 /* User explicitly wants ASSIGN'ed variables to be at the same
3217 memory address as the variables when used in non-ASSIGN
3218 contexts. That can make old, arcane, non-standard code
3219 work, but don't try to do it when a pointer wouldn't fit
3220 in the normal variable (take other approach, and warn,
3225 s = ffecom_sym_transform_ (s);
3226 t = ffesymbol_hook (s).decl_tree;
3227 assert (t != NULL_TREE);
3230 if (t == error_mark_node)
3233 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (t)))
3234 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
3236 if (ffesymbol_hook (s).addr)
3237 t = ffecom_1 (INDIRECT_REF,
3238 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
3242 if (ffesymbol_hook (s).assign_tree == NULL_TREE)
3244 ffebad_start_msg ("ASSIGN'ed label cannot fit into `%A' at %0 -- using wider sibling",
3245 FFEBAD_severityWARNING);
3246 ffebad_string (ffesymbol_text (s));
3247 ffebad_here (0, ffesymbol_where_line (s),
3248 ffesymbol_where_column (s));
3253 /* Don't use the normal variable's tree for ASSIGN, though mark
3254 it as in the system header (housekeeping). Use an explicit,
3255 specially created sibling that is known to be wide enough
3256 to hold pointers to labels. */
3259 && TREE_CODE (t) == VAR_DECL)
3260 DECL_IN_SYSTEM_HEADER (t) = 1; /* Don't let -Wunused complain. */
3262 t = ffesymbol_hook (s).assign_tree;
3265 s = ffecom_sym_transform_assign_ (s);
3266 t = ffesymbol_hook (s).assign_tree;
3267 assert (t != NULL_TREE);
3274 s = ffecom_sym_transform_ (s);
3275 t = ffesymbol_hook (s).decl_tree;
3276 assert (t != NULL_TREE);
3278 if (ffesymbol_hook (s).addr)
3279 t = ffecom_1 (INDIRECT_REF,
3280 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
3284 case FFEBLD_opARRAYREF:
3285 return ffecom_arrayref_ (NULL_TREE, expr, 0);
3287 case FFEBLD_opUPLUS:
3288 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3289 return ffecom_1 (NOP_EXPR, tree_type, left);
3291 case FFEBLD_opPAREN:
3292 /* ~~~Make sure Fortran rules respected here */
3293 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3294 return ffecom_1 (NOP_EXPR, tree_type, left);
3296 case FFEBLD_opUMINUS:
3297 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3300 tree_type = tree_type_x;
3301 left = convert (tree_type, left);
3303 return ffecom_1 (NEGATE_EXPR, tree_type, left);
3306 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3307 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3310 tree_type = tree_type_x;
3311 left = convert (tree_type, left);
3312 right = convert (tree_type, right);
3314 return ffecom_2 (PLUS_EXPR, tree_type, left, right);
3316 case FFEBLD_opSUBTRACT:
3317 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3318 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3321 tree_type = tree_type_x;
3322 left = convert (tree_type, left);
3323 right = convert (tree_type, right);
3325 return ffecom_2 (MINUS_EXPR, tree_type, left, right);
3327 case FFEBLD_opMULTIPLY:
3328 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3329 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3332 tree_type = tree_type_x;
3333 left = convert (tree_type, left);
3334 right = convert (tree_type, right);
3336 return ffecom_2 (MULT_EXPR, tree_type, left, right);
3338 case FFEBLD_opDIVIDE:
3339 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3340 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3343 tree_type = tree_type_x;
3344 left = convert (tree_type, left);
3345 right = convert (tree_type, right);
3347 return ffecom_tree_divide_ (tree_type, left, right,
3348 dest_tree, dest, dest_used,
3349 ffebld_nonter_hook (expr));
3351 case FFEBLD_opPOWER:
3353 ffebld left = ffebld_left (expr);
3354 ffebld right = ffebld_right (expr);
3356 ffeinfoKindtype rtkt;
3357 ffeinfoKindtype ltkt;
3359 switch (ffeinfo_basictype (ffebld_info (right)))
3361 case FFEINFO_basictypeINTEGER:
3364 item = ffecom_expr_power_integer_ (expr);
3365 if (item != NULL_TREE)
3369 rtkt = FFEINFO_kindtypeINTEGER1;
3370 switch (ffeinfo_basictype (ffebld_info (left)))
3372 case FFEINFO_basictypeINTEGER:
3373 if ((ffeinfo_kindtype (ffebld_info (left))
3374 == FFEINFO_kindtypeINTEGER4)
3375 || (ffeinfo_kindtype (ffebld_info (right))
3376 == FFEINFO_kindtypeINTEGER4))
3378 code = FFECOM_gfrtPOW_QQ;
3379 ltkt = FFEINFO_kindtypeINTEGER4;
3380 rtkt = FFEINFO_kindtypeINTEGER4;
3384 code = FFECOM_gfrtPOW_II;
3385 ltkt = FFEINFO_kindtypeINTEGER1;
3389 case FFEINFO_basictypeREAL:
3390 if (ffeinfo_kindtype (ffebld_info (left))
3391 == FFEINFO_kindtypeREAL1)
3393 code = FFECOM_gfrtPOW_RI;
3394 ltkt = FFEINFO_kindtypeREAL1;
3398 code = FFECOM_gfrtPOW_DI;
3399 ltkt = FFEINFO_kindtypeREAL2;
3403 case FFEINFO_basictypeCOMPLEX:
3404 if (ffeinfo_kindtype (ffebld_info (left))
3405 == FFEINFO_kindtypeREAL1)
3407 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */
3408 ltkt = FFEINFO_kindtypeREAL1;
3412 code = FFECOM_gfrtPOW_ZI; /* Overlapping result okay. */
3413 ltkt = FFEINFO_kindtypeREAL2;
3418 assert ("bad pow_*i" == NULL);
3419 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */
3420 ltkt = FFEINFO_kindtypeREAL1;
3423 if (ffeinfo_kindtype (ffebld_info (left)) != ltkt)
3424 left = ffeexpr_convert (left, NULL, NULL,
3425 ffeinfo_basictype (ffebld_info (left)),
3427 FFETARGET_charactersizeNONE,
3428 FFEEXPR_contextLET);
3429 if (ffeinfo_kindtype (ffebld_info (right)) != rtkt)
3430 right = ffeexpr_convert (right, NULL, NULL,
3431 FFEINFO_basictypeINTEGER,
3433 FFETARGET_charactersizeNONE,
3434 FFEEXPR_contextLET);
3437 case FFEINFO_basictypeREAL:
3438 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3439 left = ffeexpr_convert (left, NULL, NULL, FFEINFO_basictypeREAL,
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_basictypeREAL,
3447 FFEINFO_kindtypeREALDOUBLE, 0,
3448 FFETARGET_charactersizeNONE,
3449 FFEEXPR_contextLET);
3450 code = FFECOM_gfrtPOW_DD;
3453 case FFEINFO_basictypeCOMPLEX:
3454 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3455 left = ffeexpr_convert (left, NULL, NULL,
3456 FFEINFO_basictypeCOMPLEX,
3457 FFEINFO_kindtypeREALDOUBLE, 0,
3458 FFETARGET_charactersizeNONE,
3459 FFEEXPR_contextLET);
3460 if (ffeinfo_kindtype (ffebld_info (right))
3461 == FFEINFO_kindtypeREAL1)
3462 right = ffeexpr_convert (right, NULL, NULL,
3463 FFEINFO_basictypeCOMPLEX,
3464 FFEINFO_kindtypeREALDOUBLE, 0,
3465 FFETARGET_charactersizeNONE,
3466 FFEEXPR_contextLET);
3467 code = FFECOM_gfrtPOW_ZZ; /* Overlapping result okay. */
3471 assert ("bad pow_x*" == NULL);
3472 code = FFECOM_gfrtPOW_II;
3475 return ffecom_call_binop_ (ffecom_gfrt_tree_ (code),
3476 ffecom_gfrt_kindtype (code),
3477 (ffe_is_f2c_library ()
3478 && ffecom_gfrt_complex_[code]),
3479 tree_type, left, right,
3480 dest_tree, dest, dest_used,
3482 ffebld_nonter_hook (expr));
3488 case FFEINFO_basictypeLOGICAL:
3489 item = ffecom_truth_value_invert (ffecom_expr (ffebld_left (expr)));
3490 return convert (tree_type, item);
3492 case FFEINFO_basictypeINTEGER:
3493 return ffecom_1 (BIT_NOT_EXPR, tree_type,
3494 ffecom_expr (ffebld_left (expr)));
3497 assert ("NOT bad basictype" == NULL);
3499 case FFEINFO_basictypeANY:
3500 return error_mark_node;
3504 case FFEBLD_opFUNCREF:
3505 assert (ffeinfo_basictype (ffebld_info (expr))
3506 != FFEINFO_basictypeCHARACTER);
3508 case FFEBLD_opSUBRREF:
3509 if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
3510 == FFEINFO_whereINTRINSIC)
3511 { /* Invocation of an intrinsic. */
3512 item = ffecom_expr_intrinsic_ (expr, dest_tree, dest,
3516 s = ffebld_symter (ffebld_left (expr));
3517 dt = ffesymbol_hook (s).decl_tree;
3518 if (dt == NULL_TREE)
3520 s = ffecom_sym_transform_ (s);
3521 dt = ffesymbol_hook (s).decl_tree;
3523 if (dt == error_mark_node)
3526 if (ffesymbol_hook (s).addr)
3529 item = ffecom_1_fn (dt);
3531 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
3532 args = ffecom_list_expr (ffebld_right (expr));
3534 args = ffecom_list_ptr_to_expr (ffebld_right (expr));
3536 if (args == error_mark_node)
3537 return error_mark_node;
3539 item = ffecom_call_ (item, kt,
3540 ffesymbol_is_f2c (s)
3541 && (bt == FFEINFO_basictypeCOMPLEX)
3542 && (ffesymbol_where (s)
3543 != FFEINFO_whereCONSTANT),
3546 dest_tree, dest, dest_used,
3547 error_mark_node, FALSE,
3548 ffebld_nonter_hook (expr));
3549 TREE_SIDE_EFFECTS (item) = 1;
3555 case FFEINFO_basictypeLOGICAL:
3557 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3558 ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3559 ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3560 return convert (tree_type, item);
3562 case FFEINFO_basictypeINTEGER:
3563 return ffecom_2 (BIT_AND_EXPR, tree_type,
3564 ffecom_expr (ffebld_left (expr)),
3565 ffecom_expr (ffebld_right (expr)));
3568 assert ("AND bad basictype" == NULL);
3570 case FFEINFO_basictypeANY:
3571 return error_mark_node;
3578 case FFEINFO_basictypeLOGICAL:
3580 = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
3581 ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3582 ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3583 return convert (tree_type, item);
3585 case FFEINFO_basictypeINTEGER:
3586 return ffecom_2 (BIT_IOR_EXPR, tree_type,
3587 ffecom_expr (ffebld_left (expr)),
3588 ffecom_expr (ffebld_right (expr)));
3591 assert ("OR bad basictype" == NULL);
3593 case FFEINFO_basictypeANY:
3594 return error_mark_node;
3602 case FFEINFO_basictypeLOGICAL:
3604 = ffecom_2 (NE_EXPR, integer_type_node,
3605 ffecom_expr (ffebld_left (expr)),
3606 ffecom_expr (ffebld_right (expr)));
3607 return convert (tree_type, ffecom_truth_value (item));
3609 case FFEINFO_basictypeINTEGER:
3610 return ffecom_2 (BIT_XOR_EXPR, tree_type,
3611 ffecom_expr (ffebld_left (expr)),
3612 ffecom_expr (ffebld_right (expr)));
3615 assert ("XOR/NEQV bad basictype" == NULL);
3617 case FFEINFO_basictypeANY:
3618 return error_mark_node;
3625 case FFEINFO_basictypeLOGICAL:
3627 = ffecom_2 (EQ_EXPR, integer_type_node,
3628 ffecom_expr (ffebld_left (expr)),
3629 ffecom_expr (ffebld_right (expr)));
3630 return convert (tree_type, ffecom_truth_value (item));
3632 case FFEINFO_basictypeINTEGER:
3634 ffecom_1 (BIT_NOT_EXPR, tree_type,
3635 ffecom_2 (BIT_XOR_EXPR, tree_type,
3636 ffecom_expr (ffebld_left (expr)),
3637 ffecom_expr (ffebld_right (expr))));
3640 assert ("EQV bad basictype" == NULL);
3642 case FFEINFO_basictypeANY:
3643 return error_mark_node;
3647 case FFEBLD_opCONVERT:
3648 if (ffebld_op (ffebld_left (expr)) == FFEBLD_opANY)
3649 return error_mark_node;
3653 case FFEINFO_basictypeLOGICAL:
3654 case FFEINFO_basictypeINTEGER:
3655 case FFEINFO_basictypeREAL:
3656 return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3658 case FFEINFO_basictypeCOMPLEX:
3659 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3661 case FFEINFO_basictypeINTEGER:
3662 case FFEINFO_basictypeLOGICAL:
3663 case FFEINFO_basictypeREAL:
3664 item = ffecom_expr (ffebld_left (expr));
3665 if (item == error_mark_node)
3666 return error_mark_node;
3667 /* convert() takes care of converting to the subtype first,
3668 at least in gcc-2.7.2. */
3669 item = convert (tree_type, item);
3672 case FFEINFO_basictypeCOMPLEX:
3673 return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3676 assert ("CONVERT COMPLEX bad basictype" == NULL);
3678 case FFEINFO_basictypeANY:
3679 return error_mark_node;
3684 assert ("CONVERT bad basictype" == NULL);
3686 case FFEINFO_basictypeANY:
3687 return error_mark_node;
3693 goto relational; /* :::::::::::::::::::: */
3697 goto relational; /* :::::::::::::::::::: */
3701 goto relational; /* :::::::::::::::::::: */
3705 goto relational; /* :::::::::::::::::::: */
3709 goto relational; /* :::::::::::::::::::: */
3714 relational: /* :::::::::::::::::::: */
3715 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3717 case FFEINFO_basictypeLOGICAL:
3718 case FFEINFO_basictypeINTEGER:
3719 case FFEINFO_basictypeREAL:
3720 item = ffecom_2 (code, integer_type_node,
3721 ffecom_expr (ffebld_left (expr)),
3722 ffecom_expr (ffebld_right (expr)));
3723 return convert (tree_type, item);
3725 case FFEINFO_basictypeCOMPLEX:
3726 assert (code == EQ_EXPR || code == NE_EXPR);
3729 tree arg1 = ffecom_expr (ffebld_left (expr));
3730 tree arg2 = ffecom_expr (ffebld_right (expr));
3732 if (arg1 == error_mark_node || arg2 == error_mark_node)
3733 return error_mark_node;
3735 arg1 = ffecom_save_tree (arg1);
3736 arg2 = ffecom_save_tree (arg2);
3738 if (TREE_CODE (TREE_TYPE (arg1)) == COMPLEX_TYPE)
3740 real_type = TREE_TYPE (TREE_TYPE (arg1));
3741 assert (real_type == TREE_TYPE (TREE_TYPE (arg2)));
3745 real_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg1)));
3746 assert (real_type == TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg2))));
3750 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3751 ffecom_2 (EQ_EXPR, integer_type_node,
3752 ffecom_1 (REALPART_EXPR, real_type, arg1),
3753 ffecom_1 (REALPART_EXPR, real_type, arg2)),
3754 ffecom_2 (EQ_EXPR, integer_type_node,
3755 ffecom_1 (IMAGPART_EXPR, real_type, arg1),
3756 ffecom_1 (IMAGPART_EXPR, real_type,
3758 if (code == EQ_EXPR)
3759 item = ffecom_truth_value (item);
3761 item = ffecom_truth_value_invert (item);
3762 return convert (tree_type, item);
3765 case FFEINFO_basictypeCHARACTER:
3767 ffebld left = ffebld_left (expr);
3768 ffebld right = ffebld_right (expr);
3774 /* f2c run-time functions do the implicit blank-padding for us,
3775 so we don't usually have to implement blank-padding ourselves.
3776 (The exception is when we pass an argument to a separately
3777 compiled statement function -- if we know the arg is not the
3778 same length as the dummy, we must truncate or extend it. If
3779 we "inline" statement functions, that necessity goes away as
3782 Strip off the CONVERT operators that blank-pad. (Truncation by
3783 CONVERT shouldn't happen here, but it can happen in
3786 while (ffebld_op (left) == FFEBLD_opCONVERT)
3787 left = ffebld_left (left);
3788 while (ffebld_op (right) == FFEBLD_opCONVERT)
3789 right = ffebld_left (right);
3791 left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
3792 right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
3794 if (left_tree == error_mark_node || left_length == error_mark_node
3795 || right_tree == error_mark_node
3796 || right_length == error_mark_node)
3797 return error_mark_node;
3799 if ((ffebld_size_known (left) == 1)
3800 && (ffebld_size_known (right) == 1))
3803 = ffecom_1 (INDIRECT_REF,
3804 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3807 = ffecom_1 (INDIRECT_REF,
3808 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3812 = ffecom_2 (code, integer_type_node,
3813 ffecom_2 (ARRAY_REF,
3814 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3817 ffecom_2 (ARRAY_REF,
3818 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3824 item = build_tree_list (NULL_TREE, left_tree);
3825 TREE_CHAIN (item) = build_tree_list (NULL_TREE, right_tree);
3826 TREE_CHAIN (TREE_CHAIN (item)) = build_tree_list (NULL_TREE,
3828 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
3829 = build_tree_list (NULL_TREE, right_length);
3830 item = ffecom_call_gfrt (FFECOM_gfrtCMP, item, NULL_TREE);
3831 item = ffecom_2 (code, integer_type_node,
3833 convert (TREE_TYPE (item),
3834 integer_zero_node));
3836 item = convert (tree_type, item);
3842 assert ("relational bad basictype" == NULL);
3844 case FFEINFO_basictypeANY:
3845 return error_mark_node;
3849 case FFEBLD_opPERCENT_LOC:
3850 item = ffecom_arg_ptr_to_expr (ffebld_left (expr), &list);
3851 return convert (tree_type, item);
3855 case FFEBLD_opBOUNDS:
3856 case FFEBLD_opREPEAT:
3857 case FFEBLD_opLABTER:
3858 case FFEBLD_opLABTOK:
3859 case FFEBLD_opIMPDO:
3860 case FFEBLD_opCONCATENATE:
3861 case FFEBLD_opSUBSTR:
3863 assert ("bad op" == NULL);
3866 return error_mark_node;
3870 assert ("didn't think anything got here anymore!!" == NULL);
3872 switch (ffebld_arity (expr))
3875 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3876 TREE_OPERAND (item, 1) = ffecom_expr (ffebld_right (expr));
3877 if (TREE_OPERAND (item, 0) == error_mark_node
3878 || TREE_OPERAND (item, 1) == error_mark_node)
3879 return error_mark_node;
3883 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3884 if (TREE_OPERAND (item, 0) == error_mark_node)
3885 return error_mark_node;
3897 /* Returns the tree that does the intrinsic invocation.
3899 Note: this function applies only to intrinsics returning
3900 CHARACTER*1 or non-CHARACTER results, and to intrinsic
3903 #if FFECOM_targetCURRENT == FFECOM_targetGCC
3905 ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
3906 ffebld dest, bool *dest_used)
3909 tree saved_expr1; /* For those who need it. */
3910 tree saved_expr2; /* For those who need it. */
3911 ffeinfoBasictype bt;
3915 tree real_type; /* REAL type corresponding to COMPLEX. */
3917 ffebld list = ffebld_right (expr); /* List of (some) args. */
3918 ffebld arg1; /* For handy reference. */
3921 ffeintrinImp codegen_imp;
3924 assert (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER);
3926 if (dest_used != NULL)
3929 bt = ffeinfo_basictype (ffebld_info (expr));
3930 kt = ffeinfo_kindtype (ffebld_info (expr));
3931 tree_type = ffecom_tree_type[bt][kt];
3935 arg1 = ffebld_head (list);
3936 if (arg1 != NULL && ffebld_op (arg1) == FFEBLD_opANY)
3937 return error_mark_node;
3938 if ((list = ffebld_trail (list)) != NULL)
3940 arg2 = ffebld_head (list);
3941 if (arg2 != NULL && ffebld_op (arg2) == FFEBLD_opANY)
3942 return error_mark_node;
3943 if ((list = ffebld_trail (list)) != NULL)
3945 arg3 = ffebld_head (list);
3946 if (arg3 != NULL && ffebld_op (arg3) == FFEBLD_opANY)
3947 return error_mark_node;
3956 arg1 = arg2 = arg3 = NULL;
3958 /* <list> ends up at the opITEM of the 3rd arg, or NULL if there are < 3
3959 args. This is used by the MAX/MIN expansions. */
3962 arg1_type = ffecom_tree_type
3963 [ffeinfo_basictype (ffebld_info (arg1))]
3964 [ffeinfo_kindtype (ffebld_info (arg1))];
3966 arg1_type = NULL_TREE; /* Really not needed, but might catch bugs
3969 /* There are several ways for each of the cases in the following switch
3970 statements to exit (from simplest to use to most complicated):
3972 break; (when expr_tree == NULL)
3974 A standard call is made to the specific intrinsic just as if it had been
3975 passed in as a dummy procedure and called as any old procedure. This
3976 method can produce slower code but in some cases it's the easiest way for
3977 now. However, if a (presumably faster) direct call is available,
3978 that is used, so this is the easiest way in many more cases now.
3980 gfrt = FFECOM_gfrtWHATEVER;
3983 gfrt contains the gfrt index of a library function to call, passing the
3984 argument(s) by value rather than by reference. Used when a more
3985 careful choice of library function is needed than that provided
3986 by the vanilla `break;'.
3990 The expr_tree has been completely set up and is ready to be returned
3991 as is. No further actions are taken. Use this when the tree is not
3992 in the simple form for one of the arity_n labels. */
3994 /* For info on how the switch statement cases were written, see the files
3995 enclosed in comments below the switch statement. */
3997 codegen_imp = ffebld_symter_implementation (ffebld_left (expr));
3998 gfrt = ffeintrin_gfrt_direct (codegen_imp);
3999 if (gfrt == FFECOM_gfrt)
4000 gfrt = ffeintrin_gfrt_indirect (codegen_imp);
4002 switch (codegen_imp)
4004 case FFEINTRIN_impABS:
4005 case FFEINTRIN_impCABS:
4006 case FFEINTRIN_impCDABS:
4007 case FFEINTRIN_impDABS:
4008 case FFEINTRIN_impIABS:
4009 if (ffeinfo_basictype (ffebld_info (arg1))
4010 == FFEINFO_basictypeCOMPLEX)
4012 if (kt == FFEINFO_kindtypeREAL1)
4013 gfrt = FFECOM_gfrtCABS;
4014 else if (kt == FFEINFO_kindtypeREAL2)
4015 gfrt = FFECOM_gfrtCDABS;
4018 return ffecom_1 (ABS_EXPR, tree_type,
4019 convert (tree_type, ffecom_expr (arg1)));
4021 case FFEINTRIN_impACOS:
4022 case FFEINTRIN_impDACOS:
4025 case FFEINTRIN_impAIMAG:
4026 case FFEINTRIN_impDIMAG:
4027 case FFEINTRIN_impIMAGPART:
4028 if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
4029 arg1_type = TREE_TYPE (arg1_type);
4031 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
4035 ffecom_1 (IMAGPART_EXPR, arg1_type,
4036 ffecom_expr (arg1)));
4038 case FFEINTRIN_impAINT:
4039 case FFEINTRIN_impDINT:
4041 /* ~~Someday implement FIX_TRUNC_EXPR yielding same type as arg. */
4042 return ffecom_1 (FIX_TRUNC_EXPR, tree_type, ffecom_expr (arg1));
4043 #else /* in the meantime, must use floor to avoid range problems with ints */
4044 /* r__1 = r1 >= 0 ? floor(r1) : -floor(-r1); */
4045 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4048 ffecom_3 (COND_EXPR, double_type_node,
4050 (ffecom_2 (GE_EXPR, integer_type_node,
4053 ffecom_float_zero_))),
4054 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4055 build_tree_list (NULL_TREE,
4056 convert (double_type_node,
4059 ffecom_1 (NEGATE_EXPR, double_type_node,
4060 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4061 build_tree_list (NULL_TREE,
4062 convert (double_type_node,
4063 ffecom_1 (NEGATE_EXPR,
4071 case FFEINTRIN_impANINT:
4072 case FFEINTRIN_impDNINT:
4073 #if 0 /* This way of doing it won't handle real
4074 numbers of large magnitudes. */
4075 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4076 expr_tree = convert (tree_type,
4077 convert (integer_type_node,
4078 ffecom_3 (COND_EXPR, tree_type,
4083 ffecom_float_zero_)),
4084 ffecom_2 (PLUS_EXPR,
4087 ffecom_float_half_),
4088 ffecom_2 (MINUS_EXPR,
4091 ffecom_float_half_))));
4093 #else /* So we instead call floor. */
4094 /* r__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1) */
4095 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4098 ffecom_3 (COND_EXPR, double_type_node,
4100 (ffecom_2 (GE_EXPR, integer_type_node,
4103 ffecom_float_zero_))),
4104 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4105 build_tree_list (NULL_TREE,
4106 convert (double_type_node,
4107 ffecom_2 (PLUS_EXPR,
4111 ffecom_float_half_)))),
4113 ffecom_1 (NEGATE_EXPR, double_type_node,
4114 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4115 build_tree_list (NULL_TREE,
4116 convert (double_type_node,
4117 ffecom_2 (MINUS_EXPR,
4120 ffecom_float_half_),
4127 case FFEINTRIN_impASIN:
4128 case FFEINTRIN_impDASIN:
4129 case FFEINTRIN_impATAN:
4130 case FFEINTRIN_impDATAN:
4131 case FFEINTRIN_impATAN2:
4132 case FFEINTRIN_impDATAN2:
4135 case FFEINTRIN_impCHAR:
4136 case FFEINTRIN_impACHAR:
4138 tempvar = ffecom_make_tempvar (char_type_node, 1, -1);
4140 tempvar = ffebld_nonter_hook (expr);
4144 tree tmv = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (tempvar)));
4146 expr_tree = ffecom_modify (tmv,
4147 ffecom_2 (ARRAY_REF, tmv, tempvar,
4149 convert (tmv, ffecom_expr (arg1)));
4151 expr_tree = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar),
4154 expr_tree = ffecom_1 (ADDR_EXPR,
4155 build_pointer_type (TREE_TYPE (expr_tree)),
4159 case FFEINTRIN_impCMPLX:
4160 case FFEINTRIN_impDCMPLX:
4163 convert (tree_type, ffecom_expr (arg1));
4165 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
4167 ffecom_2 (COMPLEX_EXPR, tree_type,
4168 convert (real_type, ffecom_expr (arg1)),
4170 ffecom_expr (arg2)));
4172 case FFEINTRIN_impCOMPLEX:
4174 ffecom_2 (COMPLEX_EXPR, tree_type,
4176 ffecom_expr (arg2));
4178 case FFEINTRIN_impCONJG:
4179 case FFEINTRIN_impDCONJG:
4183 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
4184 arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4186 ffecom_2 (COMPLEX_EXPR, tree_type,
4187 ffecom_1 (REALPART_EXPR, real_type, arg1_tree),
4188 ffecom_1 (NEGATE_EXPR, real_type,
4189 ffecom_1 (IMAGPART_EXPR, real_type, arg1_tree)));
4192 case FFEINTRIN_impCOS:
4193 case FFEINTRIN_impCCOS:
4194 case FFEINTRIN_impCDCOS:
4195 case FFEINTRIN_impDCOS:
4196 if (bt == FFEINFO_basictypeCOMPLEX)
4198 if (kt == FFEINFO_kindtypeREAL1)
4199 gfrt = FFECOM_gfrtCCOS; /* Overlapping result okay. */
4200 else if (kt == FFEINFO_kindtypeREAL2)
4201 gfrt = FFECOM_gfrtCDCOS; /* Overlapping result okay. */
4205 case FFEINTRIN_impCOSH:
4206 case FFEINTRIN_impDCOSH:
4209 case FFEINTRIN_impDBLE:
4210 case FFEINTRIN_impDFLOAT:
4211 case FFEINTRIN_impDREAL:
4212 case FFEINTRIN_impFLOAT:
4213 case FFEINTRIN_impIDINT:
4214 case FFEINTRIN_impIFIX:
4215 case FFEINTRIN_impINT2:
4216 case FFEINTRIN_impINT8:
4217 case FFEINTRIN_impINT:
4218 case FFEINTRIN_impLONG:
4219 case FFEINTRIN_impREAL:
4220 case FFEINTRIN_impSHORT:
4221 case FFEINTRIN_impSNGL:
4222 return convert (tree_type, ffecom_expr (arg1));
4224 case FFEINTRIN_impDIM:
4225 case FFEINTRIN_impDDIM:
4226 case FFEINTRIN_impIDIM:
4227 saved_expr1 = ffecom_save_tree (convert (tree_type,
4228 ffecom_expr (arg1)));
4229 saved_expr2 = ffecom_save_tree (convert (tree_type,
4230 ffecom_expr (arg2)));
4232 ffecom_3 (COND_EXPR, tree_type,
4234 (ffecom_2 (GT_EXPR, integer_type_node,
4237 ffecom_2 (MINUS_EXPR, tree_type,
4240 convert (tree_type, ffecom_float_zero_));
4242 case FFEINTRIN_impDPROD:
4244 ffecom_2 (MULT_EXPR, tree_type,
4245 convert (tree_type, ffecom_expr (arg1)),
4246 convert (tree_type, ffecom_expr (arg2)));
4248 case FFEINTRIN_impEXP:
4249 case FFEINTRIN_impCDEXP:
4250 case FFEINTRIN_impCEXP:
4251 case FFEINTRIN_impDEXP:
4252 if (bt == FFEINFO_basictypeCOMPLEX)
4254 if (kt == FFEINFO_kindtypeREAL1)
4255 gfrt = FFECOM_gfrtCEXP; /* Overlapping result okay. */
4256 else if (kt == FFEINFO_kindtypeREAL2)
4257 gfrt = FFECOM_gfrtCDEXP; /* Overlapping result okay. */
4261 case FFEINTRIN_impICHAR:
4262 case FFEINTRIN_impIACHAR:
4263 #if 0 /* The simple approach. */
4264 ffecom_char_args_ (&expr_tree, &saved_expr1 /* Ignored */ , arg1);
4266 = ffecom_1 (INDIRECT_REF,
4267 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
4270 = ffecom_2 (ARRAY_REF,
4271 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
4274 return convert (tree_type, expr_tree);
4275 #else /* The more interesting (and more optimal) approach. */
4276 expr_tree = ffecom_intrinsic_ichar_ (tree_type, arg1, &saved_expr1);
4277 expr_tree = ffecom_3 (COND_EXPR, tree_type,
4280 convert (tree_type, integer_zero_node));
4284 case FFEINTRIN_impINDEX:
4287 case FFEINTRIN_impLEN:
4289 break; /* The simple approach. */
4291 return ffecom_intrinsic_len_ (arg1); /* The more optimal approach. */
4294 case FFEINTRIN_impLGE:
4295 case FFEINTRIN_impLGT:
4296 case FFEINTRIN_impLLE:
4297 case FFEINTRIN_impLLT:
4300 case FFEINTRIN_impLOG:
4301 case FFEINTRIN_impALOG:
4302 case FFEINTRIN_impCDLOG:
4303 case FFEINTRIN_impCLOG:
4304 case FFEINTRIN_impDLOG:
4305 if (bt == FFEINFO_basictypeCOMPLEX)
4307 if (kt == FFEINFO_kindtypeREAL1)
4308 gfrt = FFECOM_gfrtCLOG; /* Overlapping result okay. */
4309 else if (kt == FFEINFO_kindtypeREAL2)
4310 gfrt = FFECOM_gfrtCDLOG; /* Overlapping result okay. */
4314 case FFEINTRIN_impLOG10:
4315 case FFEINTRIN_impALOG10:
4316 case FFEINTRIN_impDLOG10:
4317 if (gfrt != FFECOM_gfrt)
4318 break; /* Already picked one, stick with it. */
4320 if (kt == FFEINFO_kindtypeREAL1)
4321 gfrt = FFECOM_gfrtALOG10;
4322 else if (kt == FFEINFO_kindtypeREAL2)
4323 gfrt = FFECOM_gfrtDLOG10;
4326 case FFEINTRIN_impMAX:
4327 case FFEINTRIN_impAMAX0:
4328 case FFEINTRIN_impAMAX1:
4329 case FFEINTRIN_impDMAX1:
4330 case FFEINTRIN_impMAX0:
4331 case FFEINTRIN_impMAX1:
4332 if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4333 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4335 arg1_type = tree_type;
4336 expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4337 convert (arg1_type, ffecom_expr (arg1)),
4338 convert (arg1_type, ffecom_expr (arg2)));
4339 for (; list != NULL; list = ffebld_trail (list))
4341 if ((ffebld_head (list) == NULL)
4342 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4344 expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4347 ffecom_expr (ffebld_head (list))));
4349 return convert (tree_type, expr_tree);
4351 case FFEINTRIN_impMIN:
4352 case FFEINTRIN_impAMIN0:
4353 case FFEINTRIN_impAMIN1:
4354 case FFEINTRIN_impDMIN1:
4355 case FFEINTRIN_impMIN0:
4356 case FFEINTRIN_impMIN1:
4357 if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4358 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4360 arg1_type = tree_type;
4361 expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4362 convert (arg1_type, ffecom_expr (arg1)),
4363 convert (arg1_type, ffecom_expr (arg2)));
4364 for (; list != NULL; list = ffebld_trail (list))
4366 if ((ffebld_head (list) == NULL)
4367 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4369 expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4372 ffecom_expr (ffebld_head (list))));
4374 return convert (tree_type, expr_tree);
4376 case FFEINTRIN_impMOD:
4377 case FFEINTRIN_impAMOD:
4378 case FFEINTRIN_impDMOD:
4379 if (bt != FFEINFO_basictypeREAL)
4380 return ffecom_2 (TRUNC_MOD_EXPR, tree_type,
4381 convert (tree_type, ffecom_expr (arg1)),
4382 convert (tree_type, ffecom_expr (arg2)));
4384 if (kt == FFEINFO_kindtypeREAL1)
4385 gfrt = FFECOM_gfrtAMOD;
4386 else if (kt == FFEINFO_kindtypeREAL2)
4387 gfrt = FFECOM_gfrtDMOD;
4390 case FFEINTRIN_impNINT:
4391 case FFEINTRIN_impIDNINT:
4393 /* ~~Ideally FIX_ROUND_EXPR would be implemented, but it ain't yet. */
4394 return ffecom_1 (FIX_ROUND_EXPR, tree_type, ffecom_expr (arg1));
4396 /* i__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1); */
4397 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4399 convert (ffecom_integer_type_node,
4400 ffecom_3 (COND_EXPR, arg1_type,
4402 (ffecom_2 (GE_EXPR, integer_type_node,
4405 ffecom_float_zero_))),
4406 ffecom_2 (PLUS_EXPR, arg1_type,
4409 ffecom_float_half_)),
4410 ffecom_2 (MINUS_EXPR, arg1_type,
4413 ffecom_float_half_))));
4416 case FFEINTRIN_impSIGN:
4417 case FFEINTRIN_impDSIGN:
4418 case FFEINTRIN_impISIGN:
4420 tree arg2_tree = ffecom_expr (arg2);
4424 (ffecom_1 (ABS_EXPR, tree_type,
4426 ffecom_expr (arg1))));
4428 = ffecom_3 (COND_EXPR, tree_type,
4430 (ffecom_2 (GE_EXPR, integer_type_node,
4432 convert (TREE_TYPE (arg2_tree),
4433 integer_zero_node))),
4435 ffecom_1 (NEGATE_EXPR, tree_type, saved_expr1));
4436 /* Make sure SAVE_EXPRs get referenced early enough. */
4438 = ffecom_2 (COMPOUND_EXPR, tree_type,
4439 convert (void_type_node, saved_expr1),
4444 case FFEINTRIN_impSIN:
4445 case FFEINTRIN_impCDSIN:
4446 case FFEINTRIN_impCSIN:
4447 case FFEINTRIN_impDSIN:
4448 if (bt == FFEINFO_basictypeCOMPLEX)
4450 if (kt == FFEINFO_kindtypeREAL1)
4451 gfrt = FFECOM_gfrtCSIN; /* Overlapping result okay. */
4452 else if (kt == FFEINFO_kindtypeREAL2)
4453 gfrt = FFECOM_gfrtCDSIN; /* Overlapping result okay. */
4457 case FFEINTRIN_impSINH:
4458 case FFEINTRIN_impDSINH:
4461 case FFEINTRIN_impSQRT:
4462 case FFEINTRIN_impCDSQRT:
4463 case FFEINTRIN_impCSQRT:
4464 case FFEINTRIN_impDSQRT:
4465 if (bt == FFEINFO_basictypeCOMPLEX)
4467 if (kt == FFEINFO_kindtypeREAL1)
4468 gfrt = FFECOM_gfrtCSQRT; /* Overlapping result okay. */
4469 else if (kt == FFEINFO_kindtypeREAL2)
4470 gfrt = FFECOM_gfrtCDSQRT; /* Overlapping result okay. */
4474 case FFEINTRIN_impTAN:
4475 case FFEINTRIN_impDTAN:
4476 case FFEINTRIN_impTANH:
4477 case FFEINTRIN_impDTANH:
4480 case FFEINTRIN_impREALPART:
4481 if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
4482 arg1_type = TREE_TYPE (arg1_type);
4484 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
4488 ffecom_1 (REALPART_EXPR, arg1_type,
4489 ffecom_expr (arg1)));
4491 case FFEINTRIN_impIAND:
4492 case FFEINTRIN_impAND:
4493 return ffecom_2 (BIT_AND_EXPR, tree_type,
4495 ffecom_expr (arg1)),
4497 ffecom_expr (arg2)));
4499 case FFEINTRIN_impIOR:
4500 case FFEINTRIN_impOR:
4501 return ffecom_2 (BIT_IOR_EXPR, tree_type,
4503 ffecom_expr (arg1)),
4505 ffecom_expr (arg2)));
4507 case FFEINTRIN_impIEOR:
4508 case FFEINTRIN_impXOR:
4509 return ffecom_2 (BIT_XOR_EXPR, tree_type,
4511 ffecom_expr (arg1)),
4513 ffecom_expr (arg2)));
4515 case FFEINTRIN_impLSHIFT:
4516 return ffecom_2 (LSHIFT_EXPR, tree_type,
4518 convert (integer_type_node,
4519 ffecom_expr (arg2)));
4521 case FFEINTRIN_impRSHIFT:
4522 return ffecom_2 (RSHIFT_EXPR, tree_type,
4524 convert (integer_type_node,
4525 ffecom_expr (arg2)));
4527 case FFEINTRIN_impNOT:
4528 return ffecom_1 (BIT_NOT_EXPR, tree_type, ffecom_expr (arg1));
4530 case FFEINTRIN_impBIT_SIZE:
4531 return convert (tree_type, TYPE_SIZE (arg1_type));
4533 case FFEINTRIN_impBTEST:
4535 ffetargetLogical1 true;
4536 ffetargetLogical1 false;
4540 ffetarget_logical1 (&true, TRUE);
4541 ffetarget_logical1 (&false, FALSE);
4543 true_tree = convert (tree_type, integer_one_node);
4545 true_tree = convert (tree_type, build_int_2 (true, 0));
4547 false_tree = convert (tree_type, integer_zero_node);
4549 false_tree = convert (tree_type, build_int_2 (false, 0));
4552 ffecom_3 (COND_EXPR, tree_type,
4554 (ffecom_2 (EQ_EXPR, integer_type_node,
4555 ffecom_2 (BIT_AND_EXPR, arg1_type,
4557 ffecom_2 (LSHIFT_EXPR, arg1_type,
4560 convert (integer_type_node,
4561 ffecom_expr (arg2)))),
4563 integer_zero_node))),
4568 case FFEINTRIN_impIBCLR:
4570 ffecom_2 (BIT_AND_EXPR, tree_type,
4572 ffecom_1 (BIT_NOT_EXPR, tree_type,
4573 ffecom_2 (LSHIFT_EXPR, tree_type,
4576 convert (integer_type_node,
4577 ffecom_expr (arg2)))));
4579 case FFEINTRIN_impIBITS:
4581 tree arg3_tree = ffecom_save_tree (convert (integer_type_node,
4582 ffecom_expr (arg3)));
4584 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4587 = ffecom_2 (BIT_AND_EXPR, tree_type,
4588 ffecom_2 (RSHIFT_EXPR, tree_type,
4590 convert (integer_type_node,
4591 ffecom_expr (arg2))),
4593 ffecom_2 (RSHIFT_EXPR, uns_type,
4594 ffecom_1 (BIT_NOT_EXPR,
4597 integer_zero_node)),
4598 ffecom_2 (MINUS_EXPR,
4600 TYPE_SIZE (uns_type),
4602 #if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4604 = ffecom_3 (COND_EXPR, tree_type,
4606 (ffecom_2 (NE_EXPR, integer_type_node,
4608 integer_zero_node)),
4610 convert (tree_type, integer_zero_node));
4615 case FFEINTRIN_impIBSET:
4617 ffecom_2 (BIT_IOR_EXPR, tree_type,
4619 ffecom_2 (LSHIFT_EXPR, tree_type,
4620 convert (tree_type, integer_one_node),
4621 convert (integer_type_node,
4622 ffecom_expr (arg2))));
4624 case FFEINTRIN_impISHFT:
4626 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4627 tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4628 ffecom_expr (arg2)));
4630 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4633 = ffecom_3 (COND_EXPR, tree_type,
4635 (ffecom_2 (GE_EXPR, integer_type_node,
4637 integer_zero_node)),
4638 ffecom_2 (LSHIFT_EXPR, tree_type,
4642 ffecom_2 (RSHIFT_EXPR, uns_type,
4643 convert (uns_type, arg1_tree),
4644 ffecom_1 (NEGATE_EXPR,
4647 #if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4649 = ffecom_3 (COND_EXPR, tree_type,
4651 (ffecom_2 (NE_EXPR, integer_type_node,
4653 TYPE_SIZE (uns_type))),
4655 convert (tree_type, integer_zero_node));
4657 /* Make sure SAVE_EXPRs get referenced early enough. */
4659 = ffecom_2 (COMPOUND_EXPR, tree_type,
4660 convert (void_type_node, arg1_tree),
4661 ffecom_2 (COMPOUND_EXPR, tree_type,
4662 convert (void_type_node, arg2_tree),
4667 case FFEINTRIN_impISHFTC:
4669 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4670 tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4671 ffecom_expr (arg2)));
4672 tree arg3_tree = (arg3 == NULL) ? TYPE_SIZE (tree_type)
4673 : ffecom_save_tree (convert (integer_type_node, ffecom_expr (arg3)));
4679 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4682 = ffecom_2 (LSHIFT_EXPR, tree_type,
4683 ffecom_1 (BIT_NOT_EXPR, tree_type,
4684 convert (tree_type, integer_zero_node)),
4686 #if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4688 = ffecom_3 (COND_EXPR, tree_type,
4690 (ffecom_2 (NE_EXPR, integer_type_node,
4692 TYPE_SIZE (uns_type))),
4694 convert (tree_type, integer_zero_node));
4696 mask_arg1 = ffecom_save_tree (mask_arg1);
4698 = ffecom_2 (BIT_AND_EXPR, tree_type,
4700 ffecom_1 (BIT_NOT_EXPR, tree_type,
4702 masked_arg1 = ffecom_save_tree (masked_arg1);
4704 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4706 ffecom_2 (RSHIFT_EXPR, uns_type,
4707 convert (uns_type, masked_arg1),
4708 ffecom_1 (NEGATE_EXPR,
4711 ffecom_2 (LSHIFT_EXPR, tree_type,
4713 ffecom_2 (PLUS_EXPR, integer_type_node,
4717 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4718 ffecom_2 (LSHIFT_EXPR, tree_type,
4722 ffecom_2 (RSHIFT_EXPR, uns_type,
4723 convert (uns_type, masked_arg1),
4724 ffecom_2 (MINUS_EXPR,
4729 = ffecom_3 (COND_EXPR, tree_type,
4731 (ffecom_2 (LT_EXPR, integer_type_node,
4733 integer_zero_node)),
4737 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4738 ffecom_2 (BIT_AND_EXPR, tree_type,
4741 ffecom_2 (BIT_AND_EXPR, tree_type,
4742 ffecom_1 (BIT_NOT_EXPR, tree_type,
4746 = ffecom_3 (COND_EXPR, tree_type,
4748 (ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
4749 ffecom_2 (EQ_EXPR, integer_type_node,
4754 ffecom_2 (EQ_EXPR, integer_type_node,
4756 integer_zero_node))),
4759 /* Make sure SAVE_EXPRs get referenced early enough. */
4761 = ffecom_2 (COMPOUND_EXPR, tree_type,
4762 convert (void_type_node, arg1_tree),
4763 ffecom_2 (COMPOUND_EXPR, tree_type,
4764 convert (void_type_node, arg2_tree),
4765 ffecom_2 (COMPOUND_EXPR, tree_type,
4766 convert (void_type_node,
4768 ffecom_2 (COMPOUND_EXPR, tree_type,
4769 convert (void_type_node,
4773 = ffecom_2 (COMPOUND_EXPR, tree_type,
4774 convert (void_type_node,
4780 case FFEINTRIN_impLOC:
4782 tree arg1_tree = ffecom_expr (arg1);
4785 = convert (tree_type,
4786 ffecom_1 (ADDR_EXPR,
4787 build_pointer_type (TREE_TYPE (arg1_tree)),
4792 case FFEINTRIN_impMVBITS:
4797 ffebld arg4 = ffebld_head (ffebld_trail (list));
4800 ffebld arg5 = ffebld_head (ffebld_trail (ffebld_trail (list)));
4804 tree arg5_plus_arg3;
4806 arg2_tree = convert (integer_type_node,
4807 ffecom_expr (arg2));
4808 arg3_tree = ffecom_save_tree (convert (integer_type_node,
4809 ffecom_expr (arg3)));
4810 arg4_tree = ffecom_expr_rw (NULL_TREE, arg4);
4811 arg4_type = TREE_TYPE (arg4_tree);
4813 arg1_tree = ffecom_save_tree (convert (arg4_type,
4814 ffecom_expr (arg1)));
4816 arg5_tree = ffecom_save_tree (convert (integer_type_node,
4817 ffecom_expr (arg5)));
4820 = ffecom_2 (LSHIFT_EXPR, arg4_type,
4821 ffecom_2 (BIT_AND_EXPR, arg4_type,
4822 ffecom_2 (RSHIFT_EXPR, arg4_type,
4825 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4826 ffecom_2 (LSHIFT_EXPR, arg4_type,
4827 ffecom_1 (BIT_NOT_EXPR,
4831 integer_zero_node)),
4835 = ffecom_save_tree (ffecom_2 (PLUS_EXPR, arg4_type,
4839 = ffecom_2 (LSHIFT_EXPR, arg4_type,
4840 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4842 integer_zero_node)),
4844 #if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4846 = ffecom_3 (COND_EXPR, arg4_type,
4848 (ffecom_2 (NE_EXPR, integer_type_node,
4850 convert (TREE_TYPE (arg5_plus_arg3),
4851 TYPE_SIZE (arg4_type)))),
4853 convert (arg4_type, integer_zero_node));
4856 = ffecom_2 (BIT_AND_EXPR, arg4_type,
4858 ffecom_2 (BIT_IOR_EXPR, arg4_type,
4860 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4861 ffecom_2 (LSHIFT_EXPR, arg4_type,
4862 ffecom_1 (BIT_NOT_EXPR,
4866 integer_zero_node)),
4869 = ffecom_2 (BIT_IOR_EXPR, arg4_type,
4872 #if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4874 = ffecom_3 (COND_EXPR, arg4_type,
4876 (ffecom_2 (NE_EXPR, integer_type_node,
4878 convert (TREE_TYPE (arg3_tree),
4879 integer_zero_node))),
4883 = ffecom_3 (COND_EXPR, arg4_type,
4885 (ffecom_2 (NE_EXPR, integer_type_node,
4887 convert (TREE_TYPE (arg3_tree),
4888 TYPE_SIZE (arg4_type)))),
4893 = ffecom_2s (MODIFY_EXPR, void_type_node,
4896 /* Make sure SAVE_EXPRs get referenced early enough. */
4898 = ffecom_2 (COMPOUND_EXPR, void_type_node,
4900 ffecom_2 (COMPOUND_EXPR, void_type_node,
4902 ffecom_2 (COMPOUND_EXPR, void_type_node,
4904 ffecom_2 (COMPOUND_EXPR, void_type_node,
4908 = ffecom_2 (COMPOUND_EXPR, void_type_node,
4915 case FFEINTRIN_impDERF:
4916 case FFEINTRIN_impERF:
4917 case FFEINTRIN_impDERFC:
4918 case FFEINTRIN_impERFC:
4921 case FFEINTRIN_impIARGC:
4922 /* extern int xargc; i__1 = xargc - 1; */
4923 expr_tree = ffecom_2 (MINUS_EXPR, TREE_TYPE (ffecom_tree_xargc_),
4925 convert (TREE_TYPE (ffecom_tree_xargc_),
4929 case FFEINTRIN_impSIGNAL_func:
4930 case FFEINTRIN_impSIGNAL_subr:
4936 arg1_tree = convert (ffecom_f2c_integer_type_node,
4937 ffecom_expr (arg1));
4938 arg1_tree = ffecom_1 (ADDR_EXPR,
4939 build_pointer_type (TREE_TYPE (arg1_tree)),
4942 /* Pass procedure as a pointer to it, anything else by value. */
4943 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
4944 arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
4946 arg2_tree = ffecom_ptr_to_expr (arg2);
4947 arg2_tree = convert (TREE_TYPE (null_pointer_node),
4951 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
4953 arg3_tree = NULL_TREE;
4955 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4956 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4957 TREE_CHAIN (arg1_tree) = arg2_tree;
4960 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4961 ffecom_gfrt_kindtype (gfrt),
4963 ((codegen_imp == FFEINTRIN_impSIGNAL_subr) ?
4967 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
4968 ffebld_nonter_hook (expr));
4970 if (arg3_tree != NULL_TREE)
4972 = ffecom_modify (NULL_TREE, arg3_tree,
4973 convert (TREE_TYPE (arg3_tree),
4978 case FFEINTRIN_impALARM:
4984 arg1_tree = convert (ffecom_f2c_integer_type_node,
4985 ffecom_expr (arg1));
4986 arg1_tree = ffecom_1 (ADDR_EXPR,
4987 build_pointer_type (TREE_TYPE (arg1_tree)),
4990 /* Pass procedure as a pointer to it, anything else by value. */
4991 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
4992 arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
4994 arg2_tree = ffecom_ptr_to_expr (arg2);
4995 arg2_tree = convert (TREE_TYPE (null_pointer_node),
4999 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5001 arg3_tree = NULL_TREE;
5003 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5004 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5005 TREE_CHAIN (arg1_tree) = arg2_tree;
5008 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5009 ffecom_gfrt_kindtype (gfrt),
5013 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5014 ffebld_nonter_hook (expr));
5016 if (arg3_tree != NULL_TREE)
5018 = ffecom_modify (NULL_TREE, arg3_tree,
5019 convert (TREE_TYPE (arg3_tree),
5024 case FFEINTRIN_impCHDIR_subr:
5025 case FFEINTRIN_impFDATE_subr:
5026 case FFEINTRIN_impFGET_subr:
5027 case FFEINTRIN_impFPUT_subr:
5028 case FFEINTRIN_impGETCWD_subr:
5029 case FFEINTRIN_impHOSTNM_subr:
5030 case FFEINTRIN_impSYSTEM_subr:
5031 case FFEINTRIN_impUNLINK_subr:
5033 tree arg1_len = integer_zero_node;
5037 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5040 arg2_tree = ffecom_expr_w (NULL_TREE, arg2);
5042 arg2_tree = NULL_TREE;
5044 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5045 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5046 TREE_CHAIN (arg1_tree) = arg1_len;
5049 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5050 ffecom_gfrt_kindtype (gfrt),
5054 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5055 ffebld_nonter_hook (expr));
5057 if (arg2_tree != NULL_TREE)
5059 = ffecom_modify (NULL_TREE, arg2_tree,
5060 convert (TREE_TYPE (arg2_tree),
5065 case FFEINTRIN_impEXIT:
5069 expr_tree = build_tree_list (NULL_TREE,
5070 ffecom_1 (ADDR_EXPR,
5072 (ffecom_integer_type_node),
5073 integer_zero_node));
5076 ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5077 ffecom_gfrt_kindtype (gfrt),
5081 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5082 ffebld_nonter_hook (expr));
5084 case FFEINTRIN_impFLUSH:
5086 gfrt = FFECOM_gfrtFLUSH;
5088 gfrt = FFECOM_gfrtFLUSH1;
5091 case FFEINTRIN_impCHMOD_subr:
5092 case FFEINTRIN_impLINK_subr:
5093 case FFEINTRIN_impRENAME_subr:
5094 case FFEINTRIN_impSYMLNK_subr:
5096 tree arg1_len = integer_zero_node;
5098 tree arg2_len = integer_zero_node;
5102 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5103 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
5105 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5107 arg3_tree = NULL_TREE;
5109 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5110 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5111 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5112 arg2_len = build_tree_list (NULL_TREE, arg2_len);
5113 TREE_CHAIN (arg1_tree) = arg2_tree;
5114 TREE_CHAIN (arg2_tree) = arg1_len;
5115 TREE_CHAIN (arg1_len) = arg2_len;
5116 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5117 ffecom_gfrt_kindtype (gfrt),
5121 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5122 ffebld_nonter_hook (expr));
5123 if (arg3_tree != NULL_TREE)
5124 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5125 convert (TREE_TYPE (arg3_tree),
5130 case FFEINTRIN_impLSTAT_subr:
5131 case FFEINTRIN_impSTAT_subr:
5133 tree arg1_len = integer_zero_node;
5138 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5140 arg2_tree = ffecom_ptr_to_expr (arg2);
5143 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5145 arg3_tree = NULL_TREE;
5147 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5148 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5149 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5150 TREE_CHAIN (arg1_tree) = arg2_tree;
5151 TREE_CHAIN (arg2_tree) = arg1_len;
5152 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5153 ffecom_gfrt_kindtype (gfrt),
5157 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5158 ffebld_nonter_hook (expr));
5159 if (arg3_tree != NULL_TREE)
5160 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5161 convert (TREE_TYPE (arg3_tree),
5166 case FFEINTRIN_impFGETC_subr:
5167 case FFEINTRIN_impFPUTC_subr:
5171 tree arg2_len = integer_zero_node;
5174 arg1_tree = convert (ffecom_f2c_integer_type_node,
5175 ffecom_expr (arg1));
5176 arg1_tree = ffecom_1 (ADDR_EXPR,
5177 build_pointer_type (TREE_TYPE (arg1_tree)),
5180 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
5181 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5183 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5184 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5185 arg2_len = build_tree_list (NULL_TREE, arg2_len);
5186 TREE_CHAIN (arg1_tree) = arg2_tree;
5187 TREE_CHAIN (arg2_tree) = arg2_len;
5189 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5190 ffecom_gfrt_kindtype (gfrt),
5194 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5195 ffebld_nonter_hook (expr));
5196 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5197 convert (TREE_TYPE (arg3_tree),
5202 case FFEINTRIN_impFSTAT_subr:
5208 arg1_tree = convert (ffecom_f2c_integer_type_node,
5209 ffecom_expr (arg1));
5210 arg1_tree = ffecom_1 (ADDR_EXPR,
5211 build_pointer_type (TREE_TYPE (arg1_tree)),
5214 arg2_tree = convert (ffecom_f2c_ptr_to_integer_type_node,
5215 ffecom_ptr_to_expr (arg2));
5218 arg3_tree = NULL_TREE;
5220 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5222 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5223 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5224 TREE_CHAIN (arg1_tree) = arg2_tree;
5225 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5226 ffecom_gfrt_kindtype (gfrt),
5230 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5231 ffebld_nonter_hook (expr));
5232 if (arg3_tree != NULL_TREE) {
5233 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5234 convert (TREE_TYPE (arg3_tree),
5240 case FFEINTRIN_impKILL_subr:
5246 arg1_tree = convert (ffecom_f2c_integer_type_node,
5247 ffecom_expr (arg1));
5248 arg1_tree = ffecom_1 (ADDR_EXPR,
5249 build_pointer_type (TREE_TYPE (arg1_tree)),
5252 arg2_tree = convert (ffecom_f2c_integer_type_node,
5253 ffecom_expr (arg2));
5254 arg2_tree = ffecom_1 (ADDR_EXPR,
5255 build_pointer_type (TREE_TYPE (arg2_tree)),
5259 arg3_tree = NULL_TREE;
5261 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5263 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5264 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5265 TREE_CHAIN (arg1_tree) = arg2_tree;
5266 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5267 ffecom_gfrt_kindtype (gfrt),
5271 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5272 ffebld_nonter_hook (expr));
5273 if (arg3_tree != NULL_TREE) {
5274 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5275 convert (TREE_TYPE (arg3_tree),
5281 case FFEINTRIN_impCTIME_subr:
5282 case FFEINTRIN_impTTYNAM_subr:
5284 tree arg1_len = integer_zero_node;
5288 arg1_tree = ffecom_arg_ptr_to_expr (arg2, &arg1_len);
5290 arg2_tree = convert (((codegen_imp == FFEINTRIN_impCTIME_subr) ?
5291 ffecom_f2c_longint_type_node :
5292 ffecom_f2c_integer_type_node),
5293 ffecom_expr (arg1));
5294 arg2_tree = ffecom_1 (ADDR_EXPR,
5295 build_pointer_type (TREE_TYPE (arg2_tree)),
5298 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5299 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5300 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5301 TREE_CHAIN (arg1_len) = arg2_tree;
5302 TREE_CHAIN (arg1_tree) = arg1_len;
5305 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5306 ffecom_gfrt_kindtype (gfrt),
5310 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5311 ffebld_nonter_hook (expr));
5312 TREE_SIDE_EFFECTS (expr_tree) = 1;
5316 case FFEINTRIN_impIRAND:
5317 case FFEINTRIN_impRAND:
5318 /* Arg defaults to 0 (normal random case) */
5323 arg1_tree = ffecom_integer_zero_node;
5325 arg1_tree = ffecom_expr (arg1);
5326 arg1_tree = convert (ffecom_f2c_integer_type_node,
5328 arg1_tree = ffecom_1 (ADDR_EXPR,
5329 build_pointer_type (TREE_TYPE (arg1_tree)),
5331 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5333 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5334 ffecom_gfrt_kindtype (gfrt),
5336 ((codegen_imp == FFEINTRIN_impIRAND) ?
5337 ffecom_f2c_integer_type_node :
5338 ffecom_f2c_real_type_node),
5340 dest_tree, dest, dest_used,
5342 ffebld_nonter_hook (expr));
5346 case FFEINTRIN_impFTELL_subr:
5347 case FFEINTRIN_impUMASK_subr:
5352 arg1_tree = convert (ffecom_f2c_integer_type_node,
5353 ffecom_expr (arg1));
5354 arg1_tree = ffecom_1 (ADDR_EXPR,
5355 build_pointer_type (TREE_TYPE (arg1_tree)),
5359 arg2_tree = NULL_TREE;
5361 arg2_tree = ffecom_expr_w (NULL_TREE, arg2);
5363 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5364 ffecom_gfrt_kindtype (gfrt),
5367 build_tree_list (NULL_TREE, arg1_tree),
5368 NULL_TREE, NULL, NULL, NULL_TREE,
5370 ffebld_nonter_hook (expr));
5371 if (arg2_tree != NULL_TREE) {
5372 expr_tree = ffecom_modify (NULL_TREE, arg2_tree,
5373 convert (TREE_TYPE (arg2_tree),
5379 case FFEINTRIN_impCPU_TIME:
5380 case FFEINTRIN_impSECOND_subr:
5384 arg1_tree = ffecom_expr_w (NULL_TREE, arg1);
5387 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5388 ffecom_gfrt_kindtype (gfrt),
5392 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5393 ffebld_nonter_hook (expr));
5396 = ffecom_modify (NULL_TREE, arg1_tree,
5397 convert (TREE_TYPE (arg1_tree),
5402 case FFEINTRIN_impDTIME_subr:
5403 case FFEINTRIN_impETIME_subr:
5408 result_tree = ffecom_expr_w (NULL_TREE, arg2);
5410 arg1_tree = ffecom_ptr_to_expr (arg1);
5412 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5413 ffecom_gfrt_kindtype (gfrt),
5416 build_tree_list (NULL_TREE, arg1_tree),
5417 NULL_TREE, NULL, NULL, NULL_TREE,
5419 ffebld_nonter_hook (expr));
5420 expr_tree = ffecom_modify (NULL_TREE, result_tree,
5421 convert (TREE_TYPE (result_tree),
5426 /* Straightforward calls of libf2c routines: */
5427 case FFEINTRIN_impABORT:
5428 case FFEINTRIN_impACCESS:
5429 case FFEINTRIN_impBESJ0:
5430 case FFEINTRIN_impBESJ1:
5431 case FFEINTRIN_impBESJN:
5432 case FFEINTRIN_impBESY0:
5433 case FFEINTRIN_impBESY1:
5434 case FFEINTRIN_impBESYN:
5435 case FFEINTRIN_impCHDIR_func:
5436 case FFEINTRIN_impCHMOD_func:
5437 case FFEINTRIN_impDATE:
5438 case FFEINTRIN_impDATE_AND_TIME:
5439 case FFEINTRIN_impDBESJ0:
5440 case FFEINTRIN_impDBESJ1:
5441 case FFEINTRIN_impDBESJN:
5442 case FFEINTRIN_impDBESY0:
5443 case FFEINTRIN_impDBESY1:
5444 case FFEINTRIN_impDBESYN:
5445 case FFEINTRIN_impDTIME_func:
5446 case FFEINTRIN_impETIME_func:
5447 case FFEINTRIN_impFGETC_func:
5448 case FFEINTRIN_impFGET_func:
5449 case FFEINTRIN_impFNUM:
5450 case FFEINTRIN_impFPUTC_func:
5451 case FFEINTRIN_impFPUT_func:
5452 case FFEINTRIN_impFSEEK:
5453 case FFEINTRIN_impFSTAT_func:
5454 case FFEINTRIN_impFTELL_func:
5455 case FFEINTRIN_impGERROR:
5456 case FFEINTRIN_impGETARG:
5457 case FFEINTRIN_impGETCWD_func:
5458 case FFEINTRIN_impGETENV:
5459 case FFEINTRIN_impGETGID:
5460 case FFEINTRIN_impGETLOG:
5461 case FFEINTRIN_impGETPID:
5462 case FFEINTRIN_impGETUID:
5463 case FFEINTRIN_impGMTIME:
5464 case FFEINTRIN_impHOSTNM_func:
5465 case FFEINTRIN_impIDATE_unix:
5466 case FFEINTRIN_impIDATE_vxt:
5467 case FFEINTRIN_impIERRNO:
5468 case FFEINTRIN_impISATTY:
5469 case FFEINTRIN_impITIME:
5470 case FFEINTRIN_impKILL_func:
5471 case FFEINTRIN_impLINK_func:
5472 case FFEINTRIN_impLNBLNK:
5473 case FFEINTRIN_impLSTAT_func:
5474 case FFEINTRIN_impLTIME:
5475 case FFEINTRIN_impMCLOCK8:
5476 case FFEINTRIN_impMCLOCK:
5477 case FFEINTRIN_impPERROR:
5478 case FFEINTRIN_impRENAME_func:
5479 case FFEINTRIN_impSECNDS:
5480 case FFEINTRIN_impSECOND_func:
5481 case FFEINTRIN_impSLEEP:
5482 case FFEINTRIN_impSRAND:
5483 case FFEINTRIN_impSTAT_func:
5484 case FFEINTRIN_impSYMLNK_func:
5485 case FFEINTRIN_impSYSTEM_CLOCK:
5486 case FFEINTRIN_impSYSTEM_func:
5487 case FFEINTRIN_impTIME8:
5488 case FFEINTRIN_impTIME_unix:
5489 case FFEINTRIN_impTIME_vxt:
5490 case FFEINTRIN_impUMASK_func:
5491 case FFEINTRIN_impUNLINK_func:
5494 case FFEINTRIN_impCTIME_func: /* CHARACTER functions not handled here. */
5495 case FFEINTRIN_impFDATE_func: /* CHARACTER functions not handled here. */
5496 case FFEINTRIN_impTTYNAM_func: /* CHARACTER functions not handled here. */
5497 case FFEINTRIN_impNONE:
5498 case FFEINTRIN_imp: /* Hush up gcc warning. */
5499 fprintf (stderr, "No %s implementation.\n",
5500 ffeintrin_name_implementation (ffebld_symter_implementation (ffebld_left (expr))));
5501 assert ("unimplemented intrinsic" == NULL);
5502 return error_mark_node;
5505 assert (gfrt != FFECOM_gfrt); /* Must have an implementation! */
5507 expr_tree = ffecom_arglist_expr_ (ffecom_gfrt_args_ (gfrt),
5508 ffebld_right (expr));
5510 return ffecom_call_ (ffecom_gfrt_tree_ (gfrt), ffecom_gfrt_kindtype (gfrt),
5511 (ffe_is_f2c_library () && ffecom_gfrt_complex_[gfrt]),
5513 expr_tree, dest_tree, dest, dest_used,
5515 ffebld_nonter_hook (expr));
5517 /* See bottom of this file for f2c transforms used to determine
5518 many of the above implementations. The info seems to confuse
5519 Emacs's C mode indentation, which is why it's been moved to
5520 the bottom of this source file. */
5524 /* For power (exponentiation) where right-hand operand is type INTEGER,
5525 generate in-line code to do it the fast way (which, if the operand
5526 is a constant, might just mean a series of multiplies). */
5528 #if FFECOM_targetCURRENT == FFECOM_targetGCC
5530 ffecom_expr_power_integer_ (ffebld expr)
5532 tree l = ffecom_expr (ffebld_left (expr));
5533 tree r = ffecom_expr (ffebld_right (expr));
5534 tree ltype = TREE_TYPE (l);
5535 tree rtype = TREE_TYPE (r);
5536 tree result = NULL_TREE;
5538 if (l == error_mark_node
5539 || r == error_mark_node)
5540 return error_mark_node;
5542 if (TREE_CODE (r) == INTEGER_CST)
5544 int sgn = tree_int_cst_sgn (r);
5547 return convert (ltype, integer_one_node);
5549 if ((TREE_CODE (ltype) == INTEGER_TYPE)
5552 /* Reciprocal of integer is either 0, -1, or 1, so after
5553 calculating that (which we leave to the back end to do
5554 or not do optimally), don't bother with any multiplying. */
5556 result = ffecom_tree_divide_ (ltype,
5557 convert (ltype, integer_one_node),
5559 NULL_TREE, NULL, NULL, NULL_TREE);
5560 r = ffecom_1 (NEGATE_EXPR,
5563 if ((TREE_INT_CST_LOW (r) & 1) == 0)
5564 result = ffecom_1 (ABS_EXPR, rtype,
5568 /* Generate appropriate series of multiplies, preceded
5569 by divide if the exponent is negative. */
5575 l = ffecom_tree_divide_ (ltype,
5576 convert (ltype, integer_one_node),
5578 NULL_TREE, NULL, NULL,
5579 ffebld_nonter_hook (expr));
5580 r = ffecom_1 (NEGATE_EXPR, rtype, r);
5581 assert (TREE_CODE (r) == INTEGER_CST);
5583 if (tree_int_cst_sgn (r) < 0)
5584 { /* The "most negative" number. */
5585 r = ffecom_1 (NEGATE_EXPR, rtype,
5586 ffecom_2 (RSHIFT_EXPR, rtype,
5590 l = ffecom_2 (MULT_EXPR, ltype,
5598 if (TREE_INT_CST_LOW (r) & 1)
5600 if (result == NULL_TREE)
5603 result = ffecom_2 (MULT_EXPR, ltype,
5608 r = ffecom_2 (RSHIFT_EXPR, rtype,
5611 if (integer_zerop (r))
5613 assert (TREE_CODE (r) == INTEGER_CST);
5616 l = ffecom_2 (MULT_EXPR, ltype,
5623 /* Though rhs isn't a constant, in-line code cannot be expanded
5624 while transforming dummies
5625 because the back end cannot be easily convinced to generate
5626 stores (MODIFY_EXPR), handle temporaries, and so on before
5627 all the appropriate rtx's have been generated for things like
5628 dummy args referenced in rhs -- which doesn't happen until
5629 store_parm_decls() is called (expand_function_start, I believe,
5630 does the actual rtx-stuffing of PARM_DECLs).
5632 So, in this case, let the caller generate the call to the
5633 run-time-library function to evaluate the power for us. */
5635 if (ffecom_transform_only_dummies_)
5638 /* Right-hand operand not a constant, expand in-line code to figure
5639 out how to do the multiplies, &c.
5641 The returned expression is expressed this way in GNU C, where l and
5644 ({ typeof (r) rtmp = r;
5645 typeof (l) ltmp = l;
5652 if ((basetypeof (l) == basetypeof (int))
5655 result = ((typeof (l)) 1) / ltmp;
5656 if ((ltmp < 0) && (((-rtmp) & 1) == 0))
5662 if ((basetypeof (l) != basetypeof (int))
5665 ltmp = ((typeof (l)) 1) / ltmp;
5669 rtmp = -(rtmp >> 1);
5677 if ((rtmp >>= 1) == 0)
5686 Note that some of the above is compile-time collapsable, such as
5687 the first part of the if statements that checks the base type of
5688 l against int. The if statements are phrased that way to suggest
5689 an easy way to generate the if/else constructs here, knowing that
5690 the back end should (and probably does) eliminate the resulting
5691 dead code (either the int case or the non-int case), something
5692 it couldn't do without the redundant phrasing, requiring explicit
5693 dead-code elimination here, which would be kind of difficult to
5700 tree basetypeof_l_is_int;
5705 = build_int_2 ((TREE_CODE (ltype) == INTEGER_TYPE), 0);
5707 se = expand_start_stmt_expr ();
5709 ffecom_start_compstmt ();
5712 rtmp = ffecom_make_tempvar ("power_r", rtype,
5713 FFETARGET_charactersizeNONE, -1);
5714 ltmp = ffecom_make_tempvar ("power_l", ltype,
5715 FFETARGET_charactersizeNONE, -1);
5716 result = ffecom_make_tempvar ("power_res", ltype,
5717 FFETARGET_charactersizeNONE, -1);
5718 if (TREE_CODE (ltype) == COMPLEX_TYPE
5719 || TREE_CODE (ltype) == RECORD_TYPE)
5720 divide = ffecom_make_tempvar ("power_div", ltype,
5721 FFETARGET_charactersizeNONE, -1);
5728 hook = ffebld_nonter_hook (expr);
5730 assert (TREE_CODE (hook) == TREE_VEC);
5731 assert (TREE_VEC_LENGTH (hook) == 4);
5732 rtmp = TREE_VEC_ELT (hook, 0);
5733 ltmp = TREE_VEC_ELT (hook, 1);
5734 result = TREE_VEC_ELT (hook, 2);
5735 divide = TREE_VEC_ELT (hook, 3);
5736 if (TREE_CODE (ltype) == COMPLEX_TYPE
5737 || TREE_CODE (ltype) == RECORD_TYPE)
5744 expand_expr_stmt (ffecom_modify (void_type_node,
5747 expand_expr_stmt (ffecom_modify (void_type_node,
5750 expand_start_cond (ffecom_truth_value
5751 (ffecom_2 (EQ_EXPR, integer_type_node,
5753 convert (rtype, integer_zero_node))),
5755 expand_expr_stmt (ffecom_modify (void_type_node,
5757 convert (ltype, integer_one_node)));
5758 expand_start_else ();
5759 if (! integer_zerop (basetypeof_l_is_int))
5761 expand_start_cond (ffecom_2 (LT_EXPR, integer_type_node,
5764 integer_zero_node)),
5766 expand_expr_stmt (ffecom_modify (void_type_node,
5770 convert (ltype, integer_one_node),
5772 NULL_TREE, NULL, NULL,
5774 expand_start_cond (ffecom_truth_value
5775 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
5776 ffecom_2 (LT_EXPR, integer_type_node,
5779 integer_zero_node)),
5780 ffecom_2 (EQ_EXPR, integer_type_node,
5781 ffecom_2 (BIT_AND_EXPR,
5783 ffecom_1 (NEGATE_EXPR,
5789 integer_zero_node)))),
5791 expand_expr_stmt (ffecom_modify (void_type_node,
5793 ffecom_1 (NEGATE_EXPR,
5797 expand_start_else ();
5799 expand_expr_stmt (ffecom_modify (void_type_node,
5801 convert (ltype, integer_one_node)));
5802 expand_start_cond (ffecom_truth_value
5803 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
5804 ffecom_truth_value_invert
5805 (basetypeof_l_is_int),
5806 ffecom_2 (LT_EXPR, integer_type_node,
5809 integer_zero_node)))),
5811 expand_expr_stmt (ffecom_modify (void_type_node,
5815 convert (ltype, integer_one_node),
5817 NULL_TREE, NULL, NULL,
5819 expand_expr_stmt (ffecom_modify (void_type_node,
5821 ffecom_1 (NEGATE_EXPR, rtype,
5823 expand_start_cond (ffecom_truth_value
5824 (ffecom_2 (LT_EXPR, integer_type_node,
5826 convert (rtype, integer_zero_node))),
5828 expand_expr_stmt (ffecom_modify (void_type_node,
5830 ffecom_1 (NEGATE_EXPR, rtype,
5831 ffecom_2 (RSHIFT_EXPR,
5834 integer_one_node))));
5835 expand_expr_stmt (ffecom_modify (void_type_node,
5837 ffecom_2 (MULT_EXPR, ltype,
5842 expand_start_loop (1);
5843 expand_start_cond (ffecom_truth_value
5844 (ffecom_2 (BIT_AND_EXPR, rtype,
5846 convert (rtype, integer_one_node))),
5848 expand_expr_stmt (ffecom_modify (void_type_node,
5850 ffecom_2 (MULT_EXPR, ltype,
5854 expand_exit_loop_if_false (NULL,
5856 (ffecom_modify (rtype,
5858 ffecom_2 (RSHIFT_EXPR,
5861 integer_one_node))));
5862 expand_expr_stmt (ffecom_modify (void_type_node,
5864 ffecom_2 (MULT_EXPR, ltype,
5869 if (!integer_zerop (basetypeof_l_is_int))
5871 expand_expr_stmt (result);
5873 t = ffecom_end_compstmt ();
5875 result = expand_end_stmt_expr (se);
5877 /* This code comes from c-parse.in, after its expand_end_stmt_expr. */
5879 if (TREE_CODE (t) == BLOCK)
5881 /* Make a BIND_EXPR for the BLOCK already made. */
5882 result = build (BIND_EXPR, TREE_TYPE (result),
5883 NULL_TREE, result, t);
5884 /* Remove the block from the tree at this point.
5885 It gets put back at the proper place
5886 when the BIND_EXPR is expanded. */
5897 /* ffecom_expr_transform_ -- Transform symbols in expr
5899 ffebld expr; // FFE expression.
5900 ffecom_expr_transform_ (expr);
5902 Recursive descent on expr while transforming any untransformed SYMTERs. */
5904 #if FFECOM_targetCURRENT == FFECOM_targetGCC
5906 ffecom_expr_transform_ (ffebld expr)
5911 tail_recurse: /* :::::::::::::::::::: */
5916 switch (ffebld_op (expr))
5918 case FFEBLD_opSYMTER:
5919 s = ffebld_symter (expr);
5920 t = ffesymbol_hook (s).decl_tree;
5921 if ((t == NULL_TREE)
5922 && ((ffesymbol_kind (s) != FFEINFO_kindNONE)
5923 || ((ffesymbol_where (s) != FFEINFO_whereNONE)
5924 && (ffesymbol_where (s) != FFEINFO_whereINTRINSIC))))
5926 s = ffecom_sym_transform_ (s);
5927 t = ffesymbol_hook (s).decl_tree; /* Sfunc expr non-dummy,
5930 break; /* Ok if (t == NULL) here. */
5933 ffecom_expr_transform_ (ffebld_head (expr));
5934 expr = ffebld_trail (expr);
5935 goto tail_recurse; /* :::::::::::::::::::: */
5941 switch (ffebld_arity (expr))
5944 ffecom_expr_transform_ (ffebld_left (expr));
5945 expr = ffebld_right (expr);
5946 goto tail_recurse; /* :::::::::::::::::::: */
5949 expr = ffebld_left (expr);
5950 goto tail_recurse; /* :::::::::::::::::::: */
5960 /* Make a type based on info in live f2c.h file. */
5962 #if FFECOM_targetCURRENT == FFECOM_targetGCC
5964 ffecom_f2c_make_type_ (tree *type, int tcode, const char *name)
5968 case FFECOM_f2ccodeCHAR:
5969 *type = make_signed_type (CHAR_TYPE_SIZE);
5972 case FFECOM_f2ccodeSHORT:
5973 *type = make_signed_type (SHORT_TYPE_SIZE);
5976 case FFECOM_f2ccodeINT:
5977 *type = make_signed_type (INT_TYPE_SIZE);
5980 case FFECOM_f2ccodeLONG:
5981 *type = make_signed_type (LONG_TYPE_SIZE);
5984 case FFECOM_f2ccodeLONGLONG:
5985 *type = make_signed_type (LONG_LONG_TYPE_SIZE);
5988 case FFECOM_f2ccodeCHARPTR:
5989 *type = build_pointer_type (DEFAULT_SIGNED_CHAR
5990 ? signed_char_type_node
5991 : unsigned_char_type_node);
5994 case FFECOM_f2ccodeFLOAT:
5995 *type = make_node (REAL_TYPE);
5996 TYPE_PRECISION (*type) = FLOAT_TYPE_SIZE;
5997 layout_type (*type);
6000 case FFECOM_f2ccodeDOUBLE:
6001 *type = make_node (REAL_TYPE);
6002 TYPE_PRECISION (*type) = DOUBLE_TYPE_SIZE;
6003 layout_type (*type);
6006 case FFECOM_f2ccodeLONGDOUBLE:
6007 *type = make_node (REAL_TYPE);
6008 TYPE_PRECISION (*type) = LONG_DOUBLE_TYPE_SIZE;
6009 layout_type (*type);
6012 case FFECOM_f2ccodeTWOREALS:
6013 *type = ffecom_make_complex_type_ (ffecom_f2c_real_type_node);
6016 case FFECOM_f2ccodeTWODOUBLEREALS:
6017 *type = ffecom_make_complex_type_ (ffecom_f2c_doublereal_type_node);
6021 assert ("unexpected FFECOM_f2ccodeXYZZY!" == NULL);
6022 *type = error_mark_node;
6026 pushdecl (build_decl (TYPE_DECL,
6027 ffecom_get_invented_identifier ("__g77_f2c_%s", name),
6032 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6033 /* Set the f2c list-directed-I/O code for whatever (integral) type has the
6037 ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size,
6043 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
6044 if ((t = ffecom_tree_type[bt][j]) != NULL_TREE
6045 && compare_tree_int (TYPE_SIZE (t), size) == 0)
6047 assert (code != -1);
6048 ffecom_f2c_typecode_[bt][j] = code;
6054 /* Finish up globals after doing all program units in file
6056 Need to handle only uninitialized COMMON areas. */
6058 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6060 ffecom_finish_global_ (ffeglobal global)
6066 if (ffeglobal_type (global) != FFEGLOBAL_typeCOMMON)
6069 if (ffeglobal_common_init (global))
6072 cbt = ffeglobal_hook (global);
6073 if ((cbt == NULL_TREE)
6074 || !ffeglobal_common_have_size (global))
6075 return global; /* No need to make common, never ref'd. */
6077 suspend_momentary ();
6079 DECL_EXTERNAL (cbt) = 0;
6081 /* Give the array a size now. */
6083 size = build_int_2 ((ffeglobal_common_size (global)
6084 + ffeglobal_common_pad (global)) - 1,
6087 cbtype = TREE_TYPE (cbt);
6088 TYPE_DOMAIN (cbtype) = build_range_type (integer_type_node,
6091 if (!TREE_TYPE (size))
6092 TREE_TYPE (size) = TYPE_DOMAIN (cbtype);
6093 layout_type (cbtype);
6095 cbt = start_decl (cbt, FALSE);
6096 assert (cbt == ffeglobal_hook (global));
6098 finish_decl (cbt, NULL_TREE, FALSE);
6104 /* Finish up any untransformed symbols. */
6106 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6108 ffecom_finish_symbol_transform_ (ffesymbol s)
6110 if ((s == NULL) || (TREE_CODE (current_function_decl) == ERROR_MARK))
6113 /* It's easy to know to transform an untransformed symbol, to make sure
6114 we put out debugging info for it. But COMMON variables, unlike
6115 EQUIVALENCE ones, aren't given declarations in addition to the
6116 tree expressions that specify offsets, because COMMON variables
6117 can be referenced in the outer scope where only dummy arguments
6118 (PARM_DECLs) should really be seen. To be safe, just don't do any
6119 VAR_DECLs for COMMON variables when we transform them for real
6120 use, and therefore we do all the VAR_DECL creating here. */
6122 if (ffesymbol_hook (s).decl_tree == NULL_TREE)
6124 if (ffesymbol_kind (s) != FFEINFO_kindNONE
6125 || (ffesymbol_where (s) != FFEINFO_whereNONE
6126 && ffesymbol_where (s) != FFEINFO_whereINTRINSIC
6127 && ffesymbol_where (s) != FFEINFO_whereDUMMY))
6128 /* Not transformed, and not CHARACTER*(*), and not a dummy
6129 argument, which can happen only if the entry point names
6130 it "rides in on" are all invalidated for other reasons. */
6131 s = ffecom_sym_transform_ (s);
6134 if ((ffesymbol_where (s) == FFEINFO_whereCOMMON)
6135 && (ffesymbol_hook (s).decl_tree != error_mark_node))
6137 int yes = suspend_momentary ();
6139 /* This isn't working, at least for dbxout. The .s file looks
6140 okay to me (burley), but in gdb 4.9 at least, the variables
6141 appear to reside somewhere outside of the common area, so
6142 it doesn't make sense to mislead anyone by generating the info
6143 on those variables until this is fixed. NOTE: Same problem
6144 with EQUIVALENCE, sadly...see similar #if later. */
6145 ffecom_member_phase2_ (ffesymbol_storage (ffesymbol_common (s)),
6146 ffesymbol_storage (s));
6148 resume_momentary (yes);
6155 /* Append underscore(s) to name before calling get_identifier. "us"
6156 is nonzero if the name already contains an underscore and thus
6157 needs two underscores appended. */
6159 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6161 ffecom_get_appended_identifier_ (char us, const char *name)
6167 newname = xmalloc ((i = strlen (name)) + 1
6168 + ffe_is_underscoring ()
6170 memcpy (newname, name, i);
6172 newname[i + us] = '_';
6173 newname[i + 1 + us] = '\0';
6174 id = get_identifier (newname);
6182 /* Decide whether to append underscore to name before calling
6185 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6187 ffecom_get_external_identifier_ (ffesymbol s)
6190 const char *name = ffesymbol_text (s);
6192 /* If name is a built-in name, just return it as is. */
6194 if (!ffe_is_underscoring ()
6195 || (strcmp (name, FFETARGET_nameBLANK_COMMON) == 0)
6196 #if FFETARGET_isENFORCED_MAIN_NAME
6197 || (strcmp (name, FFETARGET_nameENFORCED_NAME) == 0)
6199 || (strcmp (name, FFETARGET_nameUNNAMED_MAIN) == 0)
6201 || (strcmp (name, FFETARGET_nameUNNAMED_BLOCK_DATA) == 0))
6202 return get_identifier (name);
6204 us = ffe_is_second_underscore ()
6205 ? (strchr (name, '_') != NULL)
6208 return ffecom_get_appended_identifier_ (us, name);
6212 /* Decide whether to append underscore to internal name before calling
6215 This is for non-external, top-function-context names only. Transform
6216 identifier so it doesn't conflict with the transformed result
6217 of using a _different_ external name. E.g. if "CALL FOO" is
6218 transformed into "FOO_();", then the variable in "FOO_ = 3"
6219 must be transformed into something that does not conflict, since
6220 these two things should be independent.
6222 The transformation is as follows. If the name does not contain
6223 an underscore, there is no possible conflict, so just return.
6224 If the name does contain an underscore, then transform it just
6225 like we transform an external identifier. */
6227 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6229 ffecom_get_identifier_ (const char *name)
6231 /* If name does not contain an underscore, just return it as is. */
6233 if (!ffe_is_underscoring ()
6234 || (strchr (name, '_') == NULL))
6235 return get_identifier (name);
6237 return ffecom_get_appended_identifier_ (ffe_is_second_underscore (),
6242 /* ffecom_gen_sfuncdef_ -- Generate definition of statement function
6245 ffesymbol s; // kindFUNCTION, whereIMMEDIATE.
6246 t = ffecom_gen_sfuncdef_(s,ffesymbol_basictype(s),
6247 ffesymbol_kindtype(s));
6249 Call after setting up containing function and getting trees for all
6252 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6254 ffecom_gen_sfuncdef_ (ffesymbol s, ffeinfoBasictype bt, ffeinfoKindtype kt)
6256 ffebld expr = ffesymbol_sfexpr (s);
6260 bool charfunc = (bt == FFEINFO_basictypeCHARACTER);
6261 static bool recurse = FALSE;
6263 int old_lineno = lineno;
6264 const char *old_input_filename = input_filename;
6266 ffecom_nested_entry_ = s;
6268 /* For now, we don't have a handy pointer to where the sfunc is actually
6269 defined, though that should be easy to add to an ffesymbol. (The
6270 token/where info available might well point to the place where the type
6271 of the sfunc is declared, especially if that precedes the place where
6272 the sfunc itself is defined, which is typically the case.) We should
6273 put out a null pointer rather than point somewhere wrong, but I want to
6274 see how it works at this point. */
6276 input_filename = ffesymbol_where_filename (s);
6277 lineno = ffesymbol_where_filelinenum (s);
6279 /* Pretransform the expression so any newly discovered things belong to the
6280 outer program unit, not to the statement function. */
6282 ffecom_expr_transform_ (expr);
6284 /* Make sure no recursive invocation of this fn (a specific case of failing
6285 to pretransform an sfunc's expression, i.e. where its expression
6286 references another untransformed sfunc) happens. */
6291 yes = suspend_momentary ();
6293 push_f_function_context ();
6296 type = void_type_node;
6299 type = ffecom_tree_type[bt][kt];
6300 if (type == NULL_TREE)
6301 type = integer_type_node; /* _sym_exec_transition reports
6305 start_function (ffecom_get_identifier_ (ffesymbol_text (s)),
6306 build_function_type (type, NULL_TREE),
6307 1, /* nested/inline */
6308 0); /* TREE_PUBLIC */
6310 /* We don't worry about COMPLEX return values here, because this is
6311 entirely internal to our code, and gcc has the ability to return COMPLEX
6312 directly as a value. */
6314 yes = suspend_momentary ();
6317 { /* Prepend arg for where result goes. */
6320 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
6322 result = ffecom_get_invented_identifier ("__g77_%s", "result");
6324 ffecom_char_enhance_arg_ (&type, s); /* Ignore returned length. */
6326 type = build_pointer_type (type);
6327 result = build_decl (PARM_DECL, result, type);
6329 push_parm_decl (result);
6332 result = NULL_TREE; /* Not ref'd if !charfunc. */
6334 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (s), TRUE);
6336 resume_momentary (yes);
6338 store_parm_decls (0);
6340 ffecom_start_compstmt ();
6346 ffetargetCharacterSize sz = ffesymbol_size (s);
6349 result_length = build_int_2 (sz, 0);
6350 TREE_TYPE (result_length) = ffecom_f2c_ftnlen_type_node;
6352 ffecom_prepare_let_char_ (sz, expr);
6354 ffecom_prepare_end ();
6356 ffecom_let_char_ (result, result_length, sz, expr);
6357 expand_null_return ();
6361 ffecom_prepare_expr (expr);
6363 ffecom_prepare_end ();
6365 expand_return (ffecom_modify (NULL_TREE,
6366 DECL_RESULT (current_function_decl),
6367 ffecom_expr (expr)));
6373 ffecom_end_compstmt ();
6375 func = current_function_decl;
6376 finish_function (1);
6378 pop_f_function_context ();
6380 resume_momentary (yes);
6384 lineno = old_lineno;
6385 input_filename = old_input_filename;
6387 ffecom_nested_entry_ = NULL;
6394 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6396 ffecom_gfrt_args_ (ffecomGfrt ix)
6398 return ffecom_gfrt_argstring_[ix];
6402 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6404 ffecom_gfrt_tree_ (ffecomGfrt ix)
6406 if (ffecom_gfrt_[ix] == NULL_TREE)
6407 ffecom_make_gfrt_ (ix);
6409 return ffecom_1 (ADDR_EXPR,
6410 build_pointer_type (TREE_TYPE (ffecom_gfrt_[ix])),
6415 /* Return initialize-to-zero expression for this VAR_DECL. */
6417 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6418 /* A somewhat evil way to prevent the garbage collector
6419 from collecting 'tree' structures. */
6420 #define NUM_TRACKED_CHUNK 63
6421 static struct tree_ggc_tracker
6423 struct tree_ggc_tracker *next;
6424 tree trees[NUM_TRACKED_CHUNK];
6425 } *tracker_head = NULL;
6428 mark_tracker_head (void *arg)
6430 struct tree_ggc_tracker *head;
6433 for (head = * (struct tree_ggc_tracker **) arg;
6438 for (i = 0; i < NUM_TRACKED_CHUNK; i++)
6439 ggc_mark_tree (head->trees[i]);
6444 ffecom_save_tree_forever (tree t)
6447 if (tracker_head != NULL)
6448 for (i = 0; i < NUM_TRACKED_CHUNK; i++)
6449 if (tracker_head->trees[i] == NULL)
6451 tracker_head->trees[i] = t;
6456 /* Need to allocate a new block. */
6457 struct tree_ggc_tracker *old_head = tracker_head;
6459 tracker_head = ggc_alloc (sizeof (*tracker_head));
6460 tracker_head->next = old_head;
6461 tracker_head->trees[0] = t;
6462 for (i = 1; i < NUM_TRACKED_CHUNK; i++)
6463 tracker_head->trees[i] = NULL;
6468 ffecom_init_zero_ (tree decl)
6471 int incremental = TREE_STATIC (decl);
6472 tree type = TREE_TYPE (decl);
6476 make_decl_rtl (decl, NULL, TREE_PUBLIC (decl) ? 1 : 0);
6477 assemble_variable (decl, TREE_PUBLIC (decl) ? 1 : 0, 0, 1);
6482 if ((TREE_CODE (type) != ARRAY_TYPE)
6483 && (TREE_CODE (type) != RECORD_TYPE)
6484 && (TREE_CODE (type) != UNION_TYPE)
6486 init = convert (type, integer_zero_node);
6487 else if (!incremental)
6489 int momentary = suspend_momentary ();
6491 init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
6492 TREE_CONSTANT (init) = 1;
6493 TREE_STATIC (init) = 1;
6495 resume_momentary (momentary);
6499 int momentary = suspend_momentary ();
6501 assemble_zeros (int_size_in_bytes (type));
6502 init = error_mark_node;
6504 resume_momentary (momentary);
6507 pop_momentary_nofree ();
6513 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6515 ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg,
6521 switch (ffebld_op (arg))
6523 case FFEBLD_opCONTER: /* For F90, check 0-length. */
6524 if (ffetarget_length_character1
6525 (ffebld_constant_character1
6526 (ffebld_conter (arg))) == 0)
6528 *maybe_tree = integer_zero_node;
6529 return convert (tree_type, integer_zero_node);
6532 *maybe_tree = integer_one_node;
6533 expr_tree = build_int_2 (*ffetarget_text_character1
6534 (ffebld_constant_character1
6535 (ffebld_conter (arg))),
6537 TREE_TYPE (expr_tree) = tree_type;
6540 case FFEBLD_opSYMTER:
6541 case FFEBLD_opARRAYREF:
6542 case FFEBLD_opFUNCREF:
6543 case FFEBLD_opSUBSTR:
6544 ffecom_char_args_ (&expr_tree, &length_tree, arg);
6546 if ((expr_tree == error_mark_node)
6547 || (length_tree == error_mark_node))
6549 *maybe_tree = error_mark_node;
6550 return error_mark_node;
6553 if (integer_zerop (length_tree))
6555 *maybe_tree = integer_zero_node;
6556 return convert (tree_type, integer_zero_node);
6560 = ffecom_1 (INDIRECT_REF,
6561 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
6564 = ffecom_2 (ARRAY_REF,
6565 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
6568 expr_tree = convert (tree_type, expr_tree);
6570 if (TREE_CODE (length_tree) == INTEGER_CST)
6571 *maybe_tree = integer_one_node;
6572 else /* Must check length at run time. */
6574 = ffecom_truth_value
6575 (ffecom_2 (GT_EXPR, integer_type_node,
6577 ffecom_f2c_ftnlen_zero_node));
6580 case FFEBLD_opPAREN:
6581 case FFEBLD_opCONVERT:
6582 if (ffeinfo_size (ffebld_info (arg)) == 0)
6584 *maybe_tree = integer_zero_node;
6585 return convert (tree_type, integer_zero_node);
6587 return ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
6590 case FFEBLD_opCONCATENATE:
6597 expr_left = ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
6599 expr_right = ffecom_intrinsic_ichar_ (tree_type, ffebld_right (arg),
6601 *maybe_tree = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
6604 expr_tree = ffecom_3 (COND_EXPR, tree_type,
6612 assert ("bad op in ICHAR" == NULL);
6613 return error_mark_node;
6618 /* ffecom_intrinsic_len_ -- Return length info for char arg (LEN())
6622 length_arg = ffecom_intrinsic_len_ (expr);
6624 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
6625 subexpressions by constructing the appropriate tree for the
6626 length-of-character-text argument in a calling sequence. */
6628 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6630 ffecom_intrinsic_len_ (ffebld expr)
6632 ffetargetCharacter1 val;
6635 switch (ffebld_op (expr))
6637 case FFEBLD_opCONTER:
6638 val = ffebld_constant_character1 (ffebld_conter (expr));
6639 length = build_int_2 (ffetarget_length_character1 (val), 0);
6640 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6643 case FFEBLD_opSYMTER:
6645 ffesymbol s = ffebld_symter (expr);
6648 item = ffesymbol_hook (s).decl_tree;
6649 if (item == NULL_TREE)
6651 s = ffecom_sym_transform_ (s);
6652 item = ffesymbol_hook (s).decl_tree;
6654 if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
6656 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
6657 length = ffesymbol_hook (s).length_tree;
6660 length = build_int_2 (ffesymbol_size (s), 0);
6661 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6664 else if (item == error_mark_node)
6665 length = error_mark_node;
6666 else /* FFEINFO_kindFUNCTION: */
6671 case FFEBLD_opARRAYREF:
6672 length = ffecom_intrinsic_len_ (ffebld_left (expr));
6675 case FFEBLD_opSUBSTR:
6679 ffebld thing = ffebld_right (expr);
6683 assert (ffebld_op (thing) == FFEBLD_opITEM);
6684 start = ffebld_head (thing);
6685 thing = ffebld_trail (thing);
6686 assert (ffebld_trail (thing) == NULL);
6687 end = ffebld_head (thing);
6689 length = ffecom_intrinsic_len_ (ffebld_left (expr));
6691 if (length == error_mark_node)
6700 length = convert (ffecom_f2c_ftnlen_type_node,
6706 start_tree = convert (ffecom_f2c_ftnlen_type_node,
6707 ffecom_expr (start));
6709 if (start_tree == error_mark_node)
6711 length = error_mark_node;
6717 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6718 ffecom_f2c_ftnlen_one_node,
6719 ffecom_2 (MINUS_EXPR,
6720 ffecom_f2c_ftnlen_type_node,
6726 end_tree = convert (ffecom_f2c_ftnlen_type_node,
6729 if (end_tree == error_mark_node)
6731 length = error_mark_node;
6735 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6736 ffecom_f2c_ftnlen_one_node,
6737 ffecom_2 (MINUS_EXPR,
6738 ffecom_f2c_ftnlen_type_node,
6739 end_tree, start_tree));
6745 case FFEBLD_opCONCATENATE:
6747 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6748 ffecom_intrinsic_len_ (ffebld_left (expr)),
6749 ffecom_intrinsic_len_ (ffebld_right (expr)));
6752 case FFEBLD_opFUNCREF:
6753 case FFEBLD_opCONVERT:
6754 length = build_int_2 (ffebld_size (expr), 0);
6755 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6759 assert ("bad op for single char arg expr" == NULL);
6760 length = ffecom_f2c_ftnlen_zero_node;
6764 assert (length != NULL_TREE);
6770 /* Handle CHARACTER assignments.
6772 Generates code to do the assignment. Used by ordinary assignment
6773 statement handler ffecom_let_stmt and by statement-function
6774 handler to generate code for a statement function. */
6776 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6778 ffecom_let_char_ (tree dest_tree, tree dest_length,
6779 ffetargetCharacterSize dest_size, ffebld source)
6781 ffecomConcatList_ catlist;
6786 if ((dest_tree == error_mark_node)
6787 || (dest_length == error_mark_node))
6790 assert (dest_tree != NULL_TREE);
6791 assert (dest_length != NULL_TREE);
6793 /* Source might be an opCONVERT, which just means it is a different size
6794 than the destination. Since the underlying implementation here handles
6795 that (directly or via the s_copy or s_cat run-time-library functions),
6796 we don't need the "convenience" of an opCONVERT that tells us to
6797 truncate or blank-pad, particularly since the resulting implementation
6798 would probably be slower than otherwise. */
6800 while (ffebld_op (source) == FFEBLD_opCONVERT)
6801 source = ffebld_left (source);
6803 catlist = ffecom_concat_list_new_ (source, dest_size);
6804 switch (ffecom_concat_list_count_ (catlist))
6806 case 0: /* Shouldn't happen, but in case it does... */
6807 ffecom_concat_list_kill_ (catlist);
6808 source_tree = null_pointer_node;
6809 source_length = ffecom_f2c_ftnlen_zero_node;
6810 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6811 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
6812 TREE_CHAIN (TREE_CHAIN (expr_tree))
6813 = build_tree_list (NULL_TREE, dest_length);
6814 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6815 = build_tree_list (NULL_TREE, source_length);
6817 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree, NULL_TREE);
6818 TREE_SIDE_EFFECTS (expr_tree) = 1;
6820 expand_expr_stmt (expr_tree);
6824 case 1: /* The (fairly) easy case. */
6825 ffecom_char_args_ (&source_tree, &source_length,
6826 ffecom_concat_list_expr_ (catlist, 0));
6827 ffecom_concat_list_kill_ (catlist);
6828 assert (source_tree != NULL_TREE);
6829 assert (source_length != NULL_TREE);
6831 if ((source_tree == error_mark_node)
6832 || (source_length == error_mark_node))
6838 = ffecom_1 (INDIRECT_REF,
6839 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6843 = ffecom_2 (ARRAY_REF,
6844 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6849 = ffecom_1 (INDIRECT_REF,
6850 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6854 = ffecom_2 (ARRAY_REF,
6855 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6860 expr_tree = ffecom_modify (void_type_node, dest_tree, source_tree);
6862 expand_expr_stmt (expr_tree);
6867 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6868 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
6869 TREE_CHAIN (TREE_CHAIN (expr_tree))
6870 = build_tree_list (NULL_TREE, dest_length);
6871 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6872 = build_tree_list (NULL_TREE, source_length);
6874 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree, NULL_TREE);
6875 TREE_SIDE_EFFECTS (expr_tree) = 1;
6877 expand_expr_stmt (expr_tree);
6881 default: /* Must actually concatenate things. */
6885 /* Heavy-duty concatenation. */
6888 int count = ffecom_concat_list_count_ (catlist);
6900 = ffecom_push_tempvar (ffecom_f2c_ftnlen_type_node,
6901 FFETARGET_charactersizeNONE, count, TRUE);
6902 item_array = items = ffecom_push_tempvar (ffecom_f2c_address_type_node,
6903 FFETARGET_charactersizeNONE,
6909 hook = ffebld_nonter_hook (source);
6911 assert (TREE_CODE (hook) == TREE_VEC);
6912 assert (TREE_VEC_LENGTH (hook) == 2);
6913 length_array = lengths = TREE_VEC_ELT (hook, 0);
6914 item_array = items = TREE_VEC_ELT (hook, 1);
6918 for (i = 0; i < count; ++i)
6920 ffecom_char_args_ (&citem, &clength,
6921 ffecom_concat_list_expr_ (catlist, i));
6922 if ((citem == error_mark_node)
6923 || (clength == error_mark_node))
6925 ffecom_concat_list_kill_ (catlist);
6930 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
6931 ffecom_modify (void_type_node,
6932 ffecom_2 (ARRAY_REF,
6933 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
6935 build_int_2 (i, 0)),
6939 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
6940 ffecom_modify (void_type_node,
6941 ffecom_2 (ARRAY_REF,
6942 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
6944 build_int_2 (i, 0)),
6949 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6950 TREE_CHAIN (expr_tree)
6951 = build_tree_list (NULL_TREE,
6952 ffecom_1 (ADDR_EXPR,
6953 build_pointer_type (TREE_TYPE (items)),
6955 TREE_CHAIN (TREE_CHAIN (expr_tree))
6956 = build_tree_list (NULL_TREE,
6957 ffecom_1 (ADDR_EXPR,
6958 build_pointer_type (TREE_TYPE (lengths)),
6960 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6963 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
6964 convert (ffecom_f2c_ftnlen_type_node,
6965 build_int_2 (count, 0))));
6966 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree))))
6967 = build_tree_list (NULL_TREE, dest_length);
6969 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCAT, expr_tree, NULL_TREE);
6970 TREE_SIDE_EFFECTS (expr_tree) = 1;
6972 expand_expr_stmt (expr_tree);
6975 ffecom_concat_list_kill_ (catlist);
6979 /* ffecom_make_gfrt_ -- Make initial info for run-time routine
6982 ffecom_make_gfrt_(ix);
6984 Assumes gfrt_[ix] is NULL_TREE, and replaces it with the FUNCTION_DECL
6985 for the indicated run-time routine (ix). */
6987 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6989 ffecom_make_gfrt_ (ffecomGfrt ix)
6994 switch (ffecom_gfrt_type_[ix])
6996 case FFECOM_rttypeVOID_:
6997 ttype = void_type_node;
7000 case FFECOM_rttypeVOIDSTAR_:
7001 ttype = TREE_TYPE (null_pointer_node); /* `void *'. */
7004 case FFECOM_rttypeFTNINT_:
7005 ttype = ffecom_f2c_ftnint_type_node;
7008 case FFECOM_rttypeINTEGER_:
7009 ttype = ffecom_f2c_integer_type_node;
7012 case FFECOM_rttypeLONGINT_:
7013 ttype = ffecom_f2c_longint_type_node;
7016 case FFECOM_rttypeLOGICAL_:
7017 ttype = ffecom_f2c_logical_type_node;
7020 case FFECOM_rttypeREAL_F2C_:
7021 ttype = double_type_node;
7024 case FFECOM_rttypeREAL_GNU_:
7025 ttype = float_type_node;
7028 case FFECOM_rttypeCOMPLEX_F2C_:
7029 ttype = void_type_node;
7032 case FFECOM_rttypeCOMPLEX_GNU_:
7033 ttype = ffecom_f2c_complex_type_node;
7036 case FFECOM_rttypeDOUBLE_:
7037 ttype = double_type_node;
7040 case FFECOM_rttypeDOUBLEREAL_:
7041 ttype = ffecom_f2c_doublereal_type_node;
7044 case FFECOM_rttypeDBLCMPLX_F2C_:
7045 ttype = void_type_node;
7048 case FFECOM_rttypeDBLCMPLX_GNU_:
7049 ttype = ffecom_f2c_doublecomplex_type_node;
7052 case FFECOM_rttypeCHARACTER_:
7053 ttype = void_type_node;
7058 assert ("bad rttype" == NULL);
7062 ttype = build_function_type (ttype, NULL_TREE);
7063 t = build_decl (FUNCTION_DECL,
7064 get_identifier (ffecom_gfrt_name_[ix]),
7066 DECL_EXTERNAL (t) = 1;
7067 TREE_PUBLIC (t) = 1;
7068 TREE_THIS_VOLATILE (t) = ffecom_gfrt_volatile_[ix] ? 1 : 0;
7070 t = start_decl (t, TRUE);
7072 finish_decl (t, NULL_TREE, TRUE);
7074 ffecom_gfrt_[ix] = t;
7078 /* Phase 1 pass over each member of a COMMON/EQUIVALENCE group. */
7080 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7082 ffecom_member_phase1_ (ffestorag mst UNUSED, ffestorag st)
7084 ffesymbol s = ffestorag_symbol (st);
7086 if (ffesymbol_namelisted (s))
7087 ffecom_member_namelisted_ = TRUE;
7091 /* Phase 2 pass over each member of a COMMON/EQUIVALENCE group. Declare
7092 the member so debugger will see it. Otherwise nobody should be
7093 referencing the member. */
7095 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7097 ffecom_member_phase2_ (ffestorag mst, ffestorag st)
7105 || ((mt = ffestorag_hook (mst)) == NULL)
7106 || (mt == error_mark_node))
7110 || ((s = ffestorag_symbol (st)) == NULL))
7113 type = ffecom_type_localvar_ (s,
7114 ffesymbol_basictype (s),
7115 ffesymbol_kindtype (s));
7116 if (type == error_mark_node)
7119 t = build_decl (VAR_DECL,
7120 ffecom_get_identifier_ (ffesymbol_text (s)),
7123 TREE_STATIC (t) = TREE_STATIC (mt);
7124 DECL_INITIAL (t) = NULL_TREE;
7125 TREE_ASM_WRITTEN (t) = 1;
7128 = gen_rtx (MEM, TYPE_MODE (type),
7129 plus_constant (XEXP (DECL_RTL (mt), 0),
7130 ffestorag_modulo (mst)
7131 + ffestorag_offset (st)
7132 - ffestorag_offset (mst)));
7134 t = start_decl (t, FALSE);
7136 finish_decl (t, NULL_TREE, FALSE);
7140 /* Prepare source expression for assignment into a destination perhaps known
7141 to be of a specific size. */
7144 ffecom_prepare_let_char_ (ffetargetCharacterSize dest_size, ffebld source)
7146 ffecomConcatList_ catlist;
7151 tree tempvar = NULL_TREE;
7153 while (ffebld_op (source) == FFEBLD_opCONVERT)
7154 source = ffebld_left (source);
7156 catlist = ffecom_concat_list_new_ (source, dest_size);
7157 count = ffecom_concat_list_count_ (catlist);
7162 = ffecom_make_tempvar ("let_char_len", ffecom_f2c_ftnlen_type_node,
7163 FFETARGET_charactersizeNONE, count);
7165 = ffecom_make_tempvar ("let_char_item", ffecom_f2c_address_type_node,
7166 FFETARGET_charactersizeNONE, count);
7168 tempvar = make_tree_vec (2);
7169 TREE_VEC_ELT (tempvar, 0) = ltmp;
7170 TREE_VEC_ELT (tempvar, 1) = itmp;
7173 for (i = 0; i < count; ++i)
7174 ffecom_prepare_arg_ptr_to_expr (ffecom_concat_list_expr_ (catlist, i));
7176 ffecom_concat_list_kill_ (catlist);
7180 ffebld_nonter_set_hook (source, tempvar);
7181 current_binding_level->prep_state = 1;
7185 /* ffecom_push_dummy_decls_ -- Transform dummy args, push parm decls in order
7187 Ignores STAR (alternate-return) dummies. All other get exec-transitioned
7188 (which generates their trees) and then their trees get push_parm_decl'd.
7190 The second arg is TRUE if the dummies are for a statement function, in
7191 which case lengths are not pushed for character arguments (since they are
7192 always known by both the caller and the callee, though the code allows
7193 for someday permitting CHAR*(*) stmtfunc dummies). */
7195 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7197 ffecom_push_dummy_decls_ (ffebld dummy_list, bool stmtfunc)
7204 ffecom_transform_only_dummies_ = TRUE;
7206 /* First push the parms corresponding to actual dummy "contents". */
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. */
7220 assert (ffebld_op (dummy) == FFEBLD_opSYMTER);
7221 s = ffebld_symter (dummy);
7222 parm = ffesymbol_hook (s).decl_tree;
7223 if (parm == NULL_TREE)
7225 s = ffecom_sym_transform_ (s);
7226 parm = ffesymbol_hook (s).decl_tree;
7227 assert (parm != NULL_TREE);
7229 if (parm != error_mark_node)
7230 push_parm_decl (parm);
7233 /* Then, for CHARACTER dummies, push the parms giving their lengths. */
7235 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
7237 dummy = ffebld_head (dumlist);
7238 switch (ffebld_op (dummy))
7242 continue; /* Forget alternate returns, they mean
7248 s = ffebld_symter (dummy);
7249 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
7250 continue; /* Only looking for CHARACTER arguments. */
7251 if (stmtfunc && (ffesymbol_size (s) != FFETARGET_charactersizeNONE))
7252 continue; /* Stmtfunc arg with known size needs no
7254 if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
7255 continue; /* Only looking for variables and arrays. */
7256 parm = ffesymbol_hook (s).length_tree;
7257 assert (parm != NULL_TREE);
7258 if (parm != error_mark_node)
7259 push_parm_decl (parm);
7262 ffecom_transform_only_dummies_ = FALSE;
7266 /* ffecom_start_progunit_ -- Beginning of program unit
7268 Does GNU back end stuff necessary to teach it about the start of its
7269 equivalent of a Fortran program unit. */
7271 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7273 ffecom_start_progunit_ ()
7275 ffesymbol fn = ffecom_primary_entry_;
7277 tree id; /* Identifier (name) of function. */
7278 tree type; /* Type of function. */
7279 tree result; /* Result of function. */
7280 ffeinfoBasictype bt;
7284 ffeglobalType egt = FFEGLOBAL_type;
7287 bool altentries = (ffecom_num_entrypoints_ != 0);
7290 && (ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
7291 && (ffecom_master_bt_ == FFEINFO_basictypeNONE);
7292 bool main_program = FALSE;
7293 int old_lineno = lineno;
7294 const char *old_input_filename = input_filename;
7297 assert (fn != NULL);
7298 assert (ffesymbol_hook (fn).decl_tree == NULL_TREE);
7300 input_filename = ffesymbol_where_filename (fn);
7301 lineno = ffesymbol_where_filelinenum (fn);
7303 /* c-parse.y indeed does call suspend_momentary and not only ignores the
7304 return value, but also never calls resume_momentary, when starting an
7305 outer function (see "fndef:", "setspecs:", and so on). So g77 does the
7306 same thing. It shouldn't be a problem since start_function calls
7307 temporary_allocation, but it might be necessary. If it causes a problem
7308 here, then maybe there's a bug lurking in gcc. NOTE: This identical
7309 comment appears twice in thist file. */
7311 suspend_momentary ();
7313 switch (ffecom_primary_entry_kind_)
7315 case FFEINFO_kindPROGRAM:
7316 main_program = TRUE;
7317 gt = FFEGLOBAL_typeMAIN;
7318 bt = FFEINFO_basictypeNONE;
7319 kt = FFEINFO_kindtypeNONE;
7320 type = ffecom_tree_fun_type_void;
7325 case FFEINFO_kindBLOCKDATA:
7326 gt = FFEGLOBAL_typeBDATA;
7327 bt = FFEINFO_basictypeNONE;
7328 kt = FFEINFO_kindtypeNONE;
7329 type = ffecom_tree_fun_type_void;
7334 case FFEINFO_kindFUNCTION:
7335 gt = FFEGLOBAL_typeFUNC;
7336 egt = FFEGLOBAL_typeEXT;
7337 bt = ffesymbol_basictype (fn);
7338 kt = ffesymbol_kindtype (fn);
7339 if (bt == FFEINFO_basictypeNONE)
7341 ffeimplic_establish_symbol (fn);
7342 if (ffesymbol_funcresult (fn) != NULL)
7343 ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
7344 bt = ffesymbol_basictype (fn);
7345 kt = ffesymbol_kindtype (fn);
7349 charfunc = cmplxfunc = FALSE;
7350 else if (bt == FFEINFO_basictypeCHARACTER)
7351 charfunc = TRUE, cmplxfunc = FALSE;
7352 else if ((bt == FFEINFO_basictypeCOMPLEX)
7353 && ffesymbol_is_f2c (fn)
7355 charfunc = FALSE, cmplxfunc = TRUE;
7357 charfunc = cmplxfunc = FALSE;
7359 if (multi || charfunc)
7360 type = ffecom_tree_fun_type_void;
7361 else if (ffesymbol_is_f2c (fn) && !altentries)
7362 type = ffecom_tree_fun_type[bt][kt];
7364 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
7366 if ((type == NULL_TREE)
7367 || (TREE_TYPE (type) == NULL_TREE))
7368 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */
7371 case FFEINFO_kindSUBROUTINE:
7372 gt = FFEGLOBAL_typeSUBR;
7373 egt = FFEGLOBAL_typeEXT;
7374 bt = FFEINFO_basictypeNONE;
7375 kt = FFEINFO_kindtypeNONE;
7376 if (ffecom_is_altreturning_)
7377 type = ffecom_tree_subr_type;
7379 type = ffecom_tree_fun_type_void;
7385 assert ("say what??" == NULL);
7387 case FFEINFO_kindANY:
7388 gt = FFEGLOBAL_typeANY;
7389 bt = FFEINFO_basictypeNONE;
7390 kt = FFEINFO_kindtypeNONE;
7391 type = error_mark_node;
7399 id = ffecom_get_invented_identifier ("__g77_masterfun_%s",
7400 ffesymbol_text (fn));
7402 #if FFETARGET_isENFORCED_MAIN
7403 else if (main_program)
7404 id = get_identifier (FFETARGET_nameENFORCED_MAIN_NAME);
7407 id = ffecom_get_external_identifier_ (fn);
7411 0, /* nested/inline */
7412 !altentries); /* TREE_PUBLIC */
7414 TREE_USED (current_function_decl) = 1; /* Avoid spurious warning if altentries. */
7417 && ((g = ffesymbol_global (fn)) != NULL)
7418 && ((ffeglobal_type (g) == gt)
7419 || (ffeglobal_type (g) == egt)))
7421 ffeglobal_set_hook (g, current_function_decl);
7424 yes = suspend_momentary ();
7426 /* Arg handling needs exec-transitioned ffesymbols to work with. But
7427 exec-transitioning needs current_function_decl to be filled in. So we
7428 do these things in two phases. */
7431 { /* 1st arg identifies which entrypoint. */
7432 ffecom_which_entrypoint_decl_
7433 = build_decl (PARM_DECL,
7434 ffecom_get_invented_identifier ("__g77_%s",
7435 "which_entrypoint"),
7437 push_parm_decl (ffecom_which_entrypoint_decl_);
7443 { /* Arg for result (return value). */
7448 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
7450 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
7452 type = ffecom_multi_type_node_;
7454 result = ffecom_get_invented_identifier ("__g77_%s", "result");
7456 /* Make length arg _and_ enhance type info for CHAR arg itself. */
7459 length = ffecom_char_enhance_arg_ (&type, fn);
7461 length = NULL_TREE; /* Not ref'd if !charfunc. */
7463 type = build_pointer_type (type);
7464 result = build_decl (PARM_DECL, result, type);
7466 push_parm_decl (result);
7468 ffecom_multi_retval_ = result;
7470 ffecom_func_result_ = result;
7474 push_parm_decl (length);
7475 ffecom_func_length_ = length;
7479 if (ffecom_primary_entry_is_proc_)
7482 arglist = ffecom_master_arglist_;
7484 arglist = ffesymbol_dummyargs (fn);
7485 ffecom_push_dummy_decls_ (arglist, FALSE);
7488 resume_momentary (yes);
7490 if (TREE_CODE (current_function_decl) != ERROR_MARK)
7491 store_parm_decls (main_program ? 1 : 0);
7493 ffecom_start_compstmt ();
7494 /* Disallow temp vars at this level. */
7495 current_binding_level->prep_state = 2;
7497 lineno = old_lineno;
7498 input_filename = old_input_filename;
7500 /* This handles any symbols still untransformed, in case -g specified.
7501 This used to be done in ffecom_finish_progunit, but it turns out to
7502 be necessary to do it here so that statement functions are
7503 expanded before code. But don't bother for BLOCK DATA. */
7505 if (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
7506 ffesymbol_drive (ffecom_finish_symbol_transform_);
7510 /* ffecom_sym_transform_ -- Transform FFE sym into backend sym
7513 ffecom_sym_transform_(s);
7515 The ffesymbol_hook info for s is updated with appropriate backend info
7518 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7520 ffecom_sym_transform_ (ffesymbol s)
7522 tree t; /* Transformed thingy. */
7523 tree tlen; /* Length if CHAR*(*). */
7524 bool addr; /* Is t the address of the thingy? */
7525 ffeinfoBasictype bt;
7529 int old_lineno = lineno;
7530 const char *old_input_filename = input_filename;
7532 /* Must ensure special ASSIGN variables are declared at top of outermost
7533 block, else they'll end up in the innermost block when their first
7534 ASSIGN is seen, which leaves them out of scope when they're the
7535 subject of a GOTO or I/O statement.
7537 We make this variable even if -fugly-assign. Just let it go unused,
7538 in case it turns out there are cases where we really want to use this
7539 variable anyway (e.g. ASSIGN to INTEGER*2 variable). */
7541 if (! ffecom_transform_only_dummies_
7542 && ffesymbol_assigned (s)
7543 && ! ffesymbol_hook (s).assign_tree)
7544 s = ffecom_sym_transform_assign_ (s);
7546 if (ffesymbol_sfdummyparent (s) == NULL)
7548 input_filename = ffesymbol_where_filename (s);
7549 lineno = ffesymbol_where_filelinenum (s);
7553 ffesymbol sf = ffesymbol_sfdummyparent (s);
7555 input_filename = ffesymbol_where_filename (sf);
7556 lineno = ffesymbol_where_filelinenum (sf);
7559 bt = ffeinfo_basictype (ffebld_info (s));
7560 kt = ffeinfo_kindtype (ffebld_info (s));
7566 switch (ffesymbol_kind (s))
7568 case FFEINFO_kindNONE:
7569 switch (ffesymbol_where (s))
7571 case FFEINFO_whereDUMMY: /* Subroutine or function. */
7572 assert (ffecom_transform_only_dummies_);
7574 /* Before 0.4, this could be ENTITY/DUMMY, but see
7575 ffestu_sym_end_transition -- no longer true (in particular, if
7576 it could be an ENTITY, it _will_ be made one, so that
7577 possibility won't come through here). So we never make length
7578 arg for CHARACTER type. */
7580 t = build_decl (PARM_DECL,
7581 ffecom_get_identifier_ (ffesymbol_text (s)),
7582 ffecom_tree_ptr_to_subr_type);
7584 DECL_ARTIFICIAL (t) = 1;
7589 case FFEINFO_whereGLOBAL: /* Subroutine or function. */
7590 assert (!ffecom_transform_only_dummies_);
7592 if (((g = ffesymbol_global (s)) != NULL)
7593 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
7594 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
7595 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
7596 && (ffeglobal_hook (g) != NULL_TREE)
7597 && ffe_is_globals ())
7599 t = ffeglobal_hook (g);
7603 t = build_decl (FUNCTION_DECL,
7604 ffecom_get_external_identifier_ (s),
7605 ffecom_tree_subr_type); /* Assume subr. */
7606 DECL_EXTERNAL (t) = 1;
7607 TREE_PUBLIC (t) = 1;
7609 t = start_decl (t, FALSE);
7610 finish_decl (t, NULL_TREE, FALSE);
7613 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
7614 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
7615 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
7616 ffeglobal_set_hook (g, t);
7618 ffecom_save_tree_forever (t);
7623 assert ("NONE where unexpected" == NULL);
7625 case FFEINFO_whereANY:
7630 case FFEINFO_kindENTITY:
7631 switch (ffeinfo_where (ffesymbol_info (s)))
7634 case FFEINFO_whereCONSTANT:
7635 /* ~~Debugging info needed? */
7636 assert (!ffecom_transform_only_dummies_);
7637 t = error_mark_node; /* Shouldn't ever see this in expr. */
7640 case FFEINFO_whereLOCAL:
7641 assert (!ffecom_transform_only_dummies_);
7644 ffestorag st = ffesymbol_storage (s);
7648 && (ffestorag_size (st) == 0))
7650 t = error_mark_node;
7654 yes = suspend_momentary ();
7655 type = ffecom_type_localvar_ (s, bt, kt);
7656 resume_momentary (yes);
7658 if (type == error_mark_node)
7660 t = error_mark_node;
7665 && (ffestorag_parent (st) != NULL))
7666 { /* Child of EQUIVALENCE parent. */
7670 ffetargetOffset offset;
7672 est = ffestorag_parent (st);
7673 ffecom_transform_equiv_ (est);
7675 et = ffestorag_hook (est);
7676 assert (et != NULL_TREE);
7678 if (! TREE_STATIC (et))
7679 put_var_into_stack (et);
7681 yes = suspend_momentary ();
7683 offset = ffestorag_modulo (est)
7684 + ffestorag_offset (ffesymbol_storage (s))
7685 - ffestorag_offset (est);
7687 ffecom_debug_kludge_ (et, "EQUIVALENCE", s, type, offset);
7689 /* (t_type *) (((char *) &et) + offset) */
7691 t = convert (string_type_node, /* (char *) */
7692 ffecom_1 (ADDR_EXPR,
7693 build_pointer_type (TREE_TYPE (et)),
7695 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
7697 build_int_2 (offset, 0));
7698 t = convert (build_pointer_type (type),
7700 TREE_CONSTANT (t) = staticp (et);
7704 resume_momentary (yes);
7709 bool init = ffesymbol_is_init (s);
7711 yes = suspend_momentary ();
7713 t = build_decl (VAR_DECL,
7714 ffecom_get_identifier_ (ffesymbol_text (s)),
7718 || ffesymbol_namelisted (s)
7719 #ifdef FFECOM_sizeMAXSTACKITEM
7721 && (ffestorag_size (st) > FFECOM_sizeMAXSTACKITEM))
7723 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
7724 && (ffecom_primary_entry_kind_
7725 != FFEINFO_kindBLOCKDATA)
7726 && (ffesymbol_is_save (s) || ffe_is_saveall ())))
7727 TREE_STATIC (t) = !ffesymbol_attr (s, FFESYMBOL_attrADJUSTABLE);
7729 TREE_STATIC (t) = 0; /* No need to make static. */
7731 if (init || ffe_is_init_local_zero ())
7732 DECL_INITIAL (t) = error_mark_node;
7734 /* Keep -Wunused from complaining about var if it
7735 is used as sfunc arg or DATA implied-DO. */
7736 if (ffesymbol_attrs (s) & FFESYMBOL_attrsSFARG)
7737 DECL_IN_SYSTEM_HEADER (t) = 1;
7739 t = start_decl (t, FALSE);
7743 if (ffesymbol_init (s) != NULL)
7744 initexpr = ffecom_expr (ffesymbol_init (s));
7746 initexpr = ffecom_init_zero_ (t);
7748 else if (ffe_is_init_local_zero ())
7749 initexpr = ffecom_init_zero_ (t);
7751 initexpr = NULL_TREE; /* Not ref'd if !init. */
7753 finish_decl (t, initexpr, FALSE);
7755 if (st != NULL && DECL_SIZE (t) != error_mark_node)
7757 assert (TREE_CODE (DECL_SIZE_UNIT (t)) == INTEGER_CST);
7758 assert (0 == compare_tree_int (DECL_SIZE_UNIT (t),
7759 ffestorag_size (st)));
7762 resume_momentary (yes);
7767 case FFEINFO_whereRESULT:
7768 assert (!ffecom_transform_only_dummies_);
7770 if (bt == FFEINFO_basictypeCHARACTER)
7771 { /* Result is already in list of dummies, use
7773 t = ffecom_func_result_;
7774 tlen = ffecom_func_length_;
7778 if ((ffecom_num_entrypoints_ == 0)
7779 && (bt == FFEINFO_basictypeCOMPLEX)
7780 && (ffesymbol_is_f2c (ffecom_primary_entry_)))
7781 { /* Result is already in list of dummies, use
7783 t = ffecom_func_result_;
7787 if (ffecom_func_result_ != NULL_TREE)
7789 t = ffecom_func_result_;
7792 if ((ffecom_num_entrypoints_ != 0)
7793 && (ffecom_master_bt_ == FFEINFO_basictypeNONE))
7795 yes = suspend_momentary ();
7797 assert (ffecom_multi_retval_ != NULL_TREE);
7798 t = ffecom_1 (INDIRECT_REF, ffecom_multi_type_node_,
7799 ffecom_multi_retval_);
7800 t = ffecom_2 (COMPONENT_REF, ffecom_tree_type[bt][kt],
7801 t, ffecom_multi_fields_[bt][kt]);
7803 resume_momentary (yes);
7807 yes = suspend_momentary ();
7809 t = build_decl (VAR_DECL,
7810 ffecom_get_identifier_ (ffesymbol_text (s)),
7811 ffecom_tree_type[bt][kt]);
7812 TREE_STATIC (t) = 0; /* Put result on stack. */
7813 t = start_decl (t, FALSE);
7814 finish_decl (t, NULL_TREE, FALSE);
7816 ffecom_func_result_ = t;
7818 resume_momentary (yes);
7821 case FFEINFO_whereDUMMY:
7829 bool adjustable = FALSE; /* Conditionally adjustable? */
7831 type = ffecom_tree_type[bt][kt];
7832 if (ffesymbol_sfdummyparent (s) != NULL)
7834 if (current_function_decl == ffecom_outer_function_decl_)
7835 { /* Exec transition before sfunc
7836 context; get it later. */
7839 t = ffecom_get_identifier_ (ffesymbol_text
7840 (ffesymbol_sfdummyparent (s)));
7843 t = ffecom_get_identifier_ (ffesymbol_text (s));
7845 assert (ffecom_transform_only_dummies_);
7847 old_sizes = get_pending_sizes ();
7848 put_pending_sizes (old_sizes);
7850 if (bt == FFEINFO_basictypeCHARACTER)
7851 tlen = ffecom_char_enhance_arg_ (&type, s);
7852 type = ffecom_check_size_overflow_ (s, type, TRUE);
7854 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
7856 if (type == error_mark_node)
7859 dim = ffebld_head (dl);
7860 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
7861 if ((ffebld_left (dim) == NULL) || ffecom_doing_entry_)
7862 low = ffecom_integer_one_node;
7864 low = ffecom_expr (ffebld_left (dim));
7865 assert (ffebld_right (dim) != NULL);
7866 if ((ffebld_op (ffebld_right (dim)) == FFEBLD_opSTAR)
7867 || ffecom_doing_entry_)
7869 /* Used to just do high=low. But for ffecom_tree_
7870 canonize_ref_, it probably is important to correctly
7871 assess the size. E.g. given COMPLEX C(*),CFUNC and
7872 C(2)=CFUNC(C), overlap can happen, while it can't
7873 for, say, C(1)=CFUNC(C(2)). */
7874 /* Even more recently used to set to INT_MAX, but that
7875 broke when some overflow checking went into the back
7876 end. Now we just leave the upper bound unspecified. */
7880 high = ffecom_expr (ffebld_right (dim));
7882 /* Determine whether array is conditionally adjustable,
7883 to decide whether back-end magic is needed.
7885 Normally the front end uses the back-end function
7886 variable_size to wrap SAVE_EXPR's around expressions
7887 affecting the size/shape of an array so that the
7888 size/shape info doesn't change during execution
7889 of the compiled code even though variables and
7890 functions referenced in those expressions might.
7892 variable_size also makes sure those saved expressions
7893 get evaluated immediately upon entry to the
7894 compiled procedure -- the front end normally doesn't
7895 have to worry about that.
7897 However, there is a problem with this that affects
7898 g77's implementation of entry points, and that is
7899 that it is _not_ true that each invocation of the
7900 compiled procedure is permitted to evaluate
7901 array size/shape info -- because it is possible
7902 that, for some invocations, that info is invalid (in
7903 which case it is "promised" -- i.e. a violation of
7904 the Fortran standard -- that the compiled code
7905 won't reference the array or its size/shape
7906 during that particular invocation).
7908 To phrase this in C terms, consider this gcc function:
7910 void foo (int *n, float (*a)[*n])
7912 // a is "pointer to array ...", fyi.
7915 Suppose that, for some invocations, it is permitted
7916 for a caller of foo to do this:
7920 Now the _written_ code for foo can take such a call
7921 into account by either testing explicitly for whether
7922 (a == NULL) || (n == NULL) -- presumably it is
7923 not permitted to reference *a in various fashions
7924 if (n == NULL) I suppose -- or it can avoid it by
7925 looking at other info (other arguments, static/global
7928 However, this won't work in gcc 2.5.8 because it'll
7929 automatically emit the code to save the "*n"
7930 expression, which'll yield a NULL dereference for
7931 the "foo (NULL, NULL)" call, something the code
7932 for foo cannot prevent.
7934 g77 definitely needs to avoid executing such
7935 code anytime the pointer to the adjustable array
7936 is NULL, because even if its bounds expressions
7937 don't have any references to possible "absent"
7938 variables like "*n" -- say all variable references
7939 are to COMMON variables, i.e. global (though in C,
7940 local static could actually make sense) -- the
7941 expressions could yield other run-time problems
7942 for allowably "dead" values in those variables.
7944 For example, let's consider a more complicated
7950 void foo (float (*a)[i/j])
7955 The above is (essentially) quite valid for Fortran
7956 but, again, for a call like "foo (NULL);", it is
7957 permitted for i and j to be undefined when the
7958 call is made. If j happened to be zero, for
7959 example, emitting the code to evaluate "i/j"
7960 could result in a run-time error.
7962 Offhand, though I don't have my F77 or F90
7963 standards handy, it might even be valid for a
7964 bounds expression to contain a function reference,
7965 in which case I doubt it is permitted for an
7966 implementation to invoke that function in the
7967 Fortran case involved here (invocation of an
7968 alternate ENTRY point that doesn't have the adjustable
7969 array as one of its arguments).
7971 So, the code that the compiler would normally emit
7972 to preevaluate the size/shape info for an
7973 adjustable array _must not_ be executed at run time
7974 in certain cases. Specifically, for Fortran,
7975 the case is when the pointer to the adjustable
7976 array == NULL. (For gnu-ish C, it might be nice
7977 for the source code itself to specify an expression
7978 that, if TRUE, inhibits execution of the code. Or
7979 reverse the sense for elegance.)
7981 (Note that g77 could use a different test than NULL,
7982 actually, since it happens to always pass an
7983 integer to the called function that specifies which
7984 entry point is being invoked. Hmm, this might
7985 solve the next problem.)
7987 One way a user could, I suppose, write "foo" so
7988 it works is to insert COND_EXPR's for the
7989 size/shape info so the dangerous stuff isn't
7990 actually done, as in:
7992 void foo (int *n, float (*a)[(a == NULL) ? 0 : *n])
7997 The next problem is that the front end needs to
7998 be able to tell the back end about the array's
7999 decl _before_ it tells it about the conditional
8000 expression to inhibit evaluation of size/shape info,
8003 To solve this, the front end needs to be able
8004 to give the back end the expression to inhibit
8005 generation of the preevaluation code _after_
8006 it makes the decl for the adjustable array.
8008 Until then, the above example using the COND_EXPR
8009 doesn't pass muster with gcc because the "(a == NULL)"
8010 part has a reference to "a", which is still
8011 undefined at that point.
8013 g77 will therefore use a different mechanism in the
8017 && ((TREE_CODE (low) != INTEGER_CST)
8018 || (high && TREE_CODE (high) != INTEGER_CST)))
8021 #if 0 /* Old approach -- see below. */
8022 if (TREE_CODE (low) != INTEGER_CST)
8023 low = ffecom_3 (COND_EXPR, integer_type_node,
8024 ffecom_adjarray_passed_ (s),
8026 ffecom_integer_zero_node);
8028 if (high && TREE_CODE (high) != INTEGER_CST)
8029 high = ffecom_3 (COND_EXPR, integer_type_node,
8030 ffecom_adjarray_passed_ (s),
8032 ffecom_integer_zero_node);
8035 /* ~~~gcc/stor-layout.c (layout_type) should do this,
8036 probably. Fixes 950302-1.f. */
8038 if (TREE_CODE (low) != INTEGER_CST)
8039 low = variable_size (low);
8041 /* ~~~Similarly, this fixes dumb0.f. The C front end
8042 does this, which is why dumb0.c would work. */
8044 if (high && TREE_CODE (high) != INTEGER_CST)
8045 high = variable_size (high);
8050 build_range_type (ffecom_integer_type_node,
8052 type = ffecom_check_size_overflow_ (s, type, TRUE);
8055 if (type == error_mark_node)
8057 t = error_mark_node;
8061 if ((ffesymbol_sfdummyparent (s) == NULL)
8062 || (ffesymbol_basictype (s) == FFEINFO_basictypeCHARACTER))
8064 type = build_pointer_type (type);
8068 t = build_decl (PARM_DECL, t, type);
8070 DECL_ARTIFICIAL (t) = 1;
8073 /* If this arg is present in every entry point's list of
8074 dummy args, then we're done. */
8076 if (ffesymbol_numentries (s)
8077 == (ffecom_num_entrypoints_ + 1))
8082 /* If variable_size in stor-layout has been called during
8083 the above, then get_pending_sizes should have the
8084 yet-to-be-evaluated saved expressions pending.
8085 Make the whole lot of them get emitted, conditionally
8086 on whether the array decl ("t" above) is not NULL. */
8089 tree sizes = get_pending_sizes ();
8094 tem = TREE_CHAIN (tem))
8096 tree temv = TREE_VALUE (tem);
8102 = ffecom_2 (COMPOUND_EXPR,
8111 = ffecom_3 (COND_EXPR,
8118 convert (TREE_TYPE (sizes),
8119 integer_zero_node));
8120 sizes = ffecom_save_tree (sizes);
8123 = tree_cons (NULL_TREE, sizes, tem);
8127 put_pending_sizes (sizes);
8133 && (ffesymbol_numentries (s)
8134 != ffecom_num_entrypoints_ + 1))
8136 = ffecom_2 (NE_EXPR, integer_type_node,
8142 && (ffesymbol_numentries (s)
8143 != ffecom_num_entrypoints_ + 1))
8145 ffebad_start (FFEBAD_MISSING_ADJARRAY_UNSUPPORTED);
8146 ffebad_here (0, ffesymbol_where_line (s),
8147 ffesymbol_where_column (s));
8148 ffebad_string (ffesymbol_text (s));
8157 case FFEINFO_whereCOMMON:
8162 ffestorag st = ffesymbol_storage (s);
8166 cs = ffesymbol_common (s); /* The COMMON area itself. */
8167 if (st != NULL) /* Else not laid out. */
8169 ffecom_transform_common_ (cs);
8170 st = ffesymbol_storage (s);
8173 yes = suspend_momentary ();
8175 type = ffecom_type_localvar_ (s, bt, kt);
8177 cg = ffesymbol_global (cs); /* The global COMMON info. */
8179 || (ffeglobal_type (cg) != FFEGLOBAL_typeCOMMON))
8182 ct = ffeglobal_hook (cg); /* The common area's tree. */
8184 if ((ct == NULL_TREE)
8186 || (type == error_mark_node))
8187 t = error_mark_node;
8190 ffetargetOffset offset;
8193 cst = ffestorag_parent (st);
8194 assert (cst == ffesymbol_storage (cs));
8196 offset = ffestorag_modulo (cst)
8197 + ffestorag_offset (st)
8198 - ffestorag_offset (cst);
8200 ffecom_debug_kludge_ (ct, "COMMON", s, type, offset);
8202 /* (t_type *) (((char *) &ct) + offset) */
8204 t = convert (string_type_node, /* (char *) */
8205 ffecom_1 (ADDR_EXPR,
8206 build_pointer_type (TREE_TYPE (ct)),
8208 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
8210 build_int_2 (offset, 0));
8211 t = convert (build_pointer_type (type),
8213 TREE_CONSTANT (t) = 1;
8218 resume_momentary (yes);
8222 case FFEINFO_whereIMMEDIATE:
8223 case FFEINFO_whereGLOBAL:
8224 case FFEINFO_whereFLEETING:
8225 case FFEINFO_whereFLEETING_CADDR:
8226 case FFEINFO_whereFLEETING_IADDR:
8227 case FFEINFO_whereINTRINSIC:
8228 case FFEINFO_whereCONSTANT_SUBOBJECT:
8230 assert ("ENTITY where unheard of" == NULL);
8232 case FFEINFO_whereANY:
8233 t = error_mark_node;
8238 case FFEINFO_kindFUNCTION:
8239 switch (ffeinfo_where (ffesymbol_info (s)))
8241 case FFEINFO_whereLOCAL: /* Me. */
8242 assert (!ffecom_transform_only_dummies_);
8243 t = current_function_decl;
8246 case FFEINFO_whereGLOBAL:
8247 assert (!ffecom_transform_only_dummies_);
8249 if (((g = ffesymbol_global (s)) != NULL)
8250 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8251 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8252 && (ffeglobal_hook (g) != NULL_TREE)
8253 && ffe_is_globals ())
8255 t = ffeglobal_hook (g);
8259 if (ffesymbol_is_f2c (s)
8260 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
8261 t = ffecom_tree_fun_type[bt][kt];
8263 t = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
8265 t = build_decl (FUNCTION_DECL,
8266 ffecom_get_external_identifier_ (s),
8268 DECL_EXTERNAL (t) = 1;
8269 TREE_PUBLIC (t) = 1;
8271 t = start_decl (t, FALSE);
8272 finish_decl (t, NULL_TREE, FALSE);
8275 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8276 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8277 ffeglobal_set_hook (g, t);
8279 ffecom_save_tree_forever (t);
8283 case FFEINFO_whereDUMMY:
8284 assert (ffecom_transform_only_dummies_);
8286 if (ffesymbol_is_f2c (s)
8287 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
8288 t = ffecom_tree_ptr_to_fun_type[bt][kt];
8290 t = build_pointer_type
8291 (build_function_type (ffecom_tree_type[bt][kt], NULL_TREE));
8293 t = build_decl (PARM_DECL,
8294 ffecom_get_identifier_ (ffesymbol_text (s)),
8297 DECL_ARTIFICIAL (t) = 1;
8302 case FFEINFO_whereCONSTANT: /* Statement function. */
8303 assert (!ffecom_transform_only_dummies_);
8304 t = ffecom_gen_sfuncdef_ (s, bt, kt);
8307 case FFEINFO_whereINTRINSIC:
8308 assert (!ffecom_transform_only_dummies_);
8309 break; /* Let actual references generate their
8313 assert ("FUNCTION where unheard of" == NULL);
8315 case FFEINFO_whereANY:
8316 t = error_mark_node;
8321 case FFEINFO_kindSUBROUTINE:
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_whereGLOBAL:
8330 assert (!ffecom_transform_only_dummies_);
8332 if (((g = ffesymbol_global (s)) != NULL)
8333 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8334 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8335 && (ffeglobal_hook (g) != NULL_TREE)
8336 && ffe_is_globals ())
8338 t = ffeglobal_hook (g);
8342 t = build_decl (FUNCTION_DECL,
8343 ffecom_get_external_identifier_ (s),
8344 ffecom_tree_subr_type);
8345 DECL_EXTERNAL (t) = 1;
8346 TREE_PUBLIC (t) = 1;
8348 t = start_decl (t, FALSE);
8349 finish_decl (t, NULL_TREE, FALSE);
8352 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8353 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8354 ffeglobal_set_hook (g, t);
8356 ffecom_save_tree_forever (t);
8360 case FFEINFO_whereDUMMY:
8361 assert (ffecom_transform_only_dummies_);
8363 t = build_decl (PARM_DECL,
8364 ffecom_get_identifier_ (ffesymbol_text (s)),
8365 ffecom_tree_ptr_to_subr_type);
8367 DECL_ARTIFICIAL (t) = 1;
8372 case FFEINFO_whereINTRINSIC:
8373 assert (!ffecom_transform_only_dummies_);
8374 break; /* Let actual references generate their
8378 assert ("SUBROUTINE where unheard of" == NULL);
8380 case FFEINFO_whereANY:
8381 t = error_mark_node;
8386 case FFEINFO_kindPROGRAM:
8387 switch (ffeinfo_where (ffesymbol_info (s)))
8389 case FFEINFO_whereLOCAL: /* Me. */
8390 assert (!ffecom_transform_only_dummies_);
8391 t = current_function_decl;
8394 case FFEINFO_whereCOMMON:
8395 case FFEINFO_whereDUMMY:
8396 case FFEINFO_whereGLOBAL:
8397 case FFEINFO_whereRESULT:
8398 case FFEINFO_whereFLEETING:
8399 case FFEINFO_whereFLEETING_CADDR:
8400 case FFEINFO_whereFLEETING_IADDR:
8401 case FFEINFO_whereIMMEDIATE:
8402 case FFEINFO_whereINTRINSIC:
8403 case FFEINFO_whereCONSTANT:
8404 case FFEINFO_whereCONSTANT_SUBOBJECT:
8406 assert ("PROGRAM where unheard of" == NULL);
8408 case FFEINFO_whereANY:
8409 t = error_mark_node;
8414 case FFEINFO_kindBLOCKDATA:
8415 switch (ffeinfo_where (ffesymbol_info (s)))
8417 case FFEINFO_whereLOCAL: /* Me. */
8418 assert (!ffecom_transform_only_dummies_);
8419 t = current_function_decl;
8422 case FFEINFO_whereGLOBAL:
8423 assert (!ffecom_transform_only_dummies_);
8425 t = build_decl (FUNCTION_DECL,
8426 ffecom_get_external_identifier_ (s),
8427 ffecom_tree_blockdata_type);
8428 DECL_EXTERNAL (t) = 1;
8429 TREE_PUBLIC (t) = 1;
8431 t = start_decl (t, FALSE);
8432 finish_decl (t, NULL_TREE, FALSE);
8434 ffecom_save_tree_forever (t);
8438 case FFEINFO_whereCOMMON:
8439 case FFEINFO_whereDUMMY:
8440 case FFEINFO_whereRESULT:
8441 case FFEINFO_whereFLEETING:
8442 case FFEINFO_whereFLEETING_CADDR:
8443 case FFEINFO_whereFLEETING_IADDR:
8444 case FFEINFO_whereIMMEDIATE:
8445 case FFEINFO_whereINTRINSIC:
8446 case FFEINFO_whereCONSTANT:
8447 case FFEINFO_whereCONSTANT_SUBOBJECT:
8449 assert ("BLOCKDATA where unheard of" == NULL);
8451 case FFEINFO_whereANY:
8452 t = error_mark_node;
8457 case FFEINFO_kindCOMMON:
8458 switch (ffeinfo_where (ffesymbol_info (s)))
8460 case FFEINFO_whereLOCAL:
8461 assert (!ffecom_transform_only_dummies_);
8462 ffecom_transform_common_ (s);
8465 case FFEINFO_whereNONE:
8466 case FFEINFO_whereCOMMON:
8467 case FFEINFO_whereDUMMY:
8468 case FFEINFO_whereGLOBAL:
8469 case FFEINFO_whereRESULT:
8470 case FFEINFO_whereFLEETING:
8471 case FFEINFO_whereFLEETING_CADDR:
8472 case FFEINFO_whereFLEETING_IADDR:
8473 case FFEINFO_whereIMMEDIATE:
8474 case FFEINFO_whereINTRINSIC:
8475 case FFEINFO_whereCONSTANT:
8476 case FFEINFO_whereCONSTANT_SUBOBJECT:
8478 assert ("COMMON where unheard of" == NULL);
8480 case FFEINFO_whereANY:
8481 t = error_mark_node;
8486 case FFEINFO_kindCONSTRUCT:
8487 switch (ffeinfo_where (ffesymbol_info (s)))
8489 case FFEINFO_whereLOCAL:
8490 assert (!ffecom_transform_only_dummies_);
8493 case FFEINFO_whereNONE:
8494 case FFEINFO_whereCOMMON:
8495 case FFEINFO_whereDUMMY:
8496 case FFEINFO_whereGLOBAL:
8497 case FFEINFO_whereRESULT:
8498 case FFEINFO_whereFLEETING:
8499 case FFEINFO_whereFLEETING_CADDR:
8500 case FFEINFO_whereFLEETING_IADDR:
8501 case FFEINFO_whereIMMEDIATE:
8502 case FFEINFO_whereINTRINSIC:
8503 case FFEINFO_whereCONSTANT:
8504 case FFEINFO_whereCONSTANT_SUBOBJECT:
8506 assert ("CONSTRUCT where unheard of" == NULL);
8508 case FFEINFO_whereANY:
8509 t = error_mark_node;
8514 case FFEINFO_kindNAMELIST:
8515 switch (ffeinfo_where (ffesymbol_info (s)))
8517 case FFEINFO_whereLOCAL:
8518 assert (!ffecom_transform_only_dummies_);
8519 t = ffecom_transform_namelist_ (s);
8522 case FFEINFO_whereNONE:
8523 case FFEINFO_whereCOMMON:
8524 case FFEINFO_whereDUMMY:
8525 case FFEINFO_whereGLOBAL:
8526 case FFEINFO_whereRESULT:
8527 case FFEINFO_whereFLEETING:
8528 case FFEINFO_whereFLEETING_CADDR:
8529 case FFEINFO_whereFLEETING_IADDR:
8530 case FFEINFO_whereIMMEDIATE:
8531 case FFEINFO_whereINTRINSIC:
8532 case FFEINFO_whereCONSTANT:
8533 case FFEINFO_whereCONSTANT_SUBOBJECT:
8535 assert ("NAMELIST where unheard of" == NULL);
8537 case FFEINFO_whereANY:
8538 t = error_mark_node;
8544 assert ("kind unheard of" == NULL);
8546 case FFEINFO_kindANY:
8547 t = error_mark_node;
8551 ffesymbol_hook (s).decl_tree = t;
8552 ffesymbol_hook (s).length_tree = tlen;
8553 ffesymbol_hook (s).addr = addr;
8555 lineno = old_lineno;
8556 input_filename = old_input_filename;
8562 /* Transform into ASSIGNable symbol.
8564 Symbol has already been transformed, but for whatever reason, the
8565 resulting decl_tree has been deemed not usable for an ASSIGN target.
8566 (E.g. it isn't wide enough to hold a pointer.) So, here we invent
8567 another local symbol of type void * and stuff that in the assign_tree
8568 argument. The F77/F90 standards allow this implementation. */
8570 #if FFECOM_targetCURRENT == FFECOM_targetGCC
8572 ffecom_sym_transform_assign_ (ffesymbol s)
8574 tree t; /* Transformed thingy. */
8576 int old_lineno = lineno;
8577 const char *old_input_filename = input_filename;
8579 if (ffesymbol_sfdummyparent (s) == NULL)
8581 input_filename = ffesymbol_where_filename (s);
8582 lineno = ffesymbol_where_filelinenum (s);
8586 ffesymbol sf = ffesymbol_sfdummyparent (s);
8588 input_filename = ffesymbol_where_filename (sf);
8589 lineno = ffesymbol_where_filelinenum (sf);
8592 assert (!ffecom_transform_only_dummies_);
8594 yes = suspend_momentary ();
8596 t = build_decl (VAR_DECL,
8597 ffecom_get_invented_identifier ("__g77_ASSIGN_%s",
8598 ffesymbol_text (s)),
8599 TREE_TYPE (null_pointer_node));
8601 switch (ffesymbol_where (s))
8603 case FFEINFO_whereLOCAL:
8604 /* Unlike for regular vars, SAVE status is easy to determine for
8605 ASSIGNed vars, since there's no initialization, there's no
8606 effective storage association (so "SAVE J" does not apply to
8607 K even given "EQUIVALENCE (J,K)"), there's no size issue
8608 to worry about, etc. */
8609 if ((ffesymbol_is_save (s) || ffe_is_saveall ())
8610 && (ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
8611 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA))
8612 TREE_STATIC (t) = 1; /* SAVEd in proc, make static. */
8614 TREE_STATIC (t) = 0; /* No need to make static. */
8617 case FFEINFO_whereCOMMON:
8618 TREE_STATIC (t) = 1; /* Assume COMMONs always SAVEd. */
8621 case FFEINFO_whereDUMMY:
8622 /* Note that twinning a DUMMY means the caller won't see
8623 the ASSIGNed value. But both F77 and F90 allow implementations
8624 to do this, i.e. disallow Fortran code that would try and
8625 take advantage of actually putting a label into a variable
8626 via a dummy argument (or any other storage association, for
8628 TREE_STATIC (t) = 0;
8632 TREE_STATIC (t) = 0;
8636 t = start_decl (t, FALSE);
8637 finish_decl (t, NULL_TREE, FALSE);
8639 resume_momentary (yes);
8641 ffesymbol_hook (s).assign_tree = t;
8643 lineno = old_lineno;
8644 input_filename = old_input_filename;
8650 /* Implement COMMON area in back end.
8652 Because COMMON-based variables can be referenced in the dimension
8653 expressions of dummy (adjustable) arrays, and because dummies
8654 (in the gcc back end) need to be put in the outer binding level
8655 of a function (which has two binding levels, the outer holding
8656 the dummies and the inner holding the other vars), special care
8657 must be taken to handle COMMON areas.
8659 The current strategy is basically to always tell the back end about
8660 the COMMON area as a top-level external reference to just a block
8661 of storage of the master type of that area (e.g. integer, real,
8662 character, whatever -- not a structure). As a distinct action,
8663 if initial values are provided, tell the back end about the area
8664 as a top-level non-external (initialized) area and remember not to
8665 allow further initialization or expansion of the area. Meanwhile,
8666 if no initialization happens at all, tell the back end about
8667 the largest size we've seen declared so the space does get reserved.
8668 (This function doesn't handle all that stuff, but it does some
8669 of the important things.)
8671 Meanwhile, for COMMON variables themselves, just keep creating
8672 references like *((float *) (&common_area + offset)) each time
8673 we reference the variable. In other words, don't make a VAR_DECL
8674 or any kind of component reference (like we used to do before 0.4),
8675 though we might do that as well just for debugging purposes (and
8676 stuff the rtl with the appropriate offset expression). */
8678 #if FFECOM_targetCURRENT == FFECOM_targetGCC
8680 ffecom_transform_common_ (ffesymbol s)
8682 ffestorag st = ffesymbol_storage (s);
8683 ffeglobal g = ffesymbol_global (s);
8688 bool is_init = ffestorag_is_init (st);
8690 assert (st != NULL);
8693 || (ffeglobal_type (g) != FFEGLOBAL_typeCOMMON))
8696 /* First update the size of the area in global terms. */
8698 ffeglobal_size_common (s, ffestorag_size (st));
8700 if (!ffeglobal_common_init (g))
8701 is_init = FALSE; /* No explicit init, don't let erroneous joins init. */
8703 cbt = ffeglobal_hook (g);
8705 /* If we already have declared this common block for a previous program
8706 unit, and either we already initialized it or we don't have new
8707 initialization for it, just return what we have without changing it. */
8709 if ((cbt != NULL_TREE)
8711 || !DECL_EXTERNAL (cbt)))
8713 if (st->hook == NULL) ffestorag_set_hook (st, cbt);
8717 /* Process inits. */
8721 if (ffestorag_init (st) != NULL)
8725 /* Set the padding for the expression, so ffecom_expr
8726 knows to insert that many zeros. */
8727 switch (ffebld_op (sexp = ffestorag_init (st)))
8729 case FFEBLD_opCONTER:
8730 ffebld_conter_set_pad (sexp, ffestorag_modulo (st));
8733 case FFEBLD_opARRTER:
8734 ffebld_arrter_set_pad (sexp, ffestorag_modulo (st));
8737 case FFEBLD_opACCTER:
8738 ffebld_accter_set_pad (sexp, ffestorag_modulo (st));
8742 assert ("bad op for cmn init (pad)" == NULL);
8746 init = ffecom_expr (sexp);
8747 if (init == error_mark_node)
8748 { /* Hopefully the back end complained! */
8750 if (cbt != NULL_TREE)
8755 init = error_mark_node;
8760 /* cbtype must be permanently allocated! */
8762 /* Allocate the MAX of the areas so far, seen filewide. */
8763 high = build_int_2 ((ffeglobal_common_size (g)
8764 + ffeglobal_common_pad (g)) - 1, 0);
8765 TREE_TYPE (high) = ffecom_integer_type_node;
8768 cbtype = build_array_type (char_type_node,
8769 build_range_type (integer_type_node,
8773 cbtype = build_array_type (char_type_node, NULL_TREE);
8775 if (cbt == NULL_TREE)
8778 = build_decl (VAR_DECL,
8779 ffecom_get_external_identifier_ (s),
8781 TREE_STATIC (cbt) = 1;
8782 TREE_PUBLIC (cbt) = 1;
8787 TREE_TYPE (cbt) = cbtype;
8789 DECL_EXTERNAL (cbt) = init ? 0 : 1;
8790 DECL_INITIAL (cbt) = init ? error_mark_node : NULL_TREE;
8792 cbt = start_decl (cbt, TRUE);
8793 if (ffeglobal_hook (g) != NULL)
8794 assert (cbt == ffeglobal_hook (g));
8796 assert (!init || !DECL_EXTERNAL (cbt));
8798 /* Make sure that any type can live in COMMON and be referenced
8799 without getting a bus error. We could pick the most restrictive
8800 alignment of all entities actually placed in the COMMON, but
8801 this seems easy enough. */
8803 DECL_ALIGN (cbt) = BIGGEST_ALIGNMENT;
8805 if (is_init && (ffestorag_init (st) == NULL))
8806 init = ffecom_init_zero_ (cbt);
8808 finish_decl (cbt, init, TRUE);
8811 ffestorag_set_init (st, ffebld_new_any ());
8815 assert (DECL_SIZE_UNIT (cbt) != NULL_TREE);
8816 assert (TREE_CODE (DECL_SIZE_UNIT (cbt)) == INTEGER_CST);
8817 assert (0 == compare_tree_int (DECL_SIZE_UNIT (cbt),
8818 (ffeglobal_common_size (g)
8819 + ffeglobal_common_pad (g))));
8822 ffeglobal_set_hook (g, cbt);
8824 ffestorag_set_hook (st, cbt);
8826 ffecom_save_tree_forever (cbt);
8830 /* Make master area for local EQUIVALENCE. */
8832 #if FFECOM_targetCURRENT == FFECOM_targetGCC
8834 ffecom_transform_equiv_ (ffestorag eqst)
8840 bool is_init = ffestorag_is_init (eqst);
8843 assert (eqst != NULL);
8845 eqt = ffestorag_hook (eqst);
8847 if (eqt != NULL_TREE)
8850 /* Process inits. */
8854 if (ffestorag_init (eqst) != NULL)
8858 /* Set the padding for the expression, so ffecom_expr
8859 knows to insert that many zeros. */
8860 switch (ffebld_op (sexp = ffestorag_init (eqst)))
8862 case FFEBLD_opCONTER:
8863 ffebld_conter_set_pad (sexp, ffestorag_modulo (eqst));
8866 case FFEBLD_opARRTER:
8867 ffebld_arrter_set_pad (sexp, ffestorag_modulo (eqst));
8870 case FFEBLD_opACCTER:
8871 ffebld_accter_set_pad (sexp, ffestorag_modulo (eqst));
8875 assert ("bad op for eqv init (pad)" == NULL);
8879 init = ffecom_expr (sexp);
8880 if (init == error_mark_node)
8881 init = NULL_TREE; /* Hopefully the back end complained! */
8884 init = error_mark_node;
8886 else if (ffe_is_init_local_zero ())
8887 init = error_mark_node;
8891 ffecom_member_namelisted_ = FALSE;
8892 ffestorag_drive (ffestorag_list_equivs (eqst),
8893 &ffecom_member_phase1_,
8896 yes = suspend_momentary ();
8898 high = build_int_2 ((ffestorag_size (eqst)
8899 + ffestorag_modulo (eqst)) - 1, 0);
8900 TREE_TYPE (high) = ffecom_integer_type_node;
8902 eqtype = build_array_type (char_type_node,
8903 build_range_type (ffecom_integer_type_node,
8904 ffecom_integer_zero_node,
8907 eqt = build_decl (VAR_DECL,
8908 ffecom_get_invented_identifier ("__g77_equiv_%s",
8910 (ffestorag_symbol (eqst))),
8912 DECL_EXTERNAL (eqt) = 0;
8914 || ffecom_member_namelisted_
8915 #ifdef FFECOM_sizeMAXSTACKITEM
8916 || (ffestorag_size (eqst) > FFECOM_sizeMAXSTACKITEM)
8918 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
8919 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
8920 && (ffestorag_is_save (eqst) || ffe_is_saveall ())))
8921 TREE_STATIC (eqt) = 1;
8923 TREE_STATIC (eqt) = 0;
8924 TREE_PUBLIC (eqt) = 0;
8925 DECL_CONTEXT (eqt) = current_function_decl;
8927 DECL_INITIAL (eqt) = error_mark_node;
8929 DECL_INITIAL (eqt) = NULL_TREE;
8931 eqt = start_decl (eqt, FALSE);
8933 /* Make sure that any type can live in EQUIVALENCE and be referenced
8934 without getting a bus error. We could pick the most restrictive
8935 alignment of all entities actually placed in the EQUIVALENCE, but
8936 this seems easy enough. */
8938 DECL_ALIGN (eqt) = BIGGEST_ALIGNMENT;
8940 if ((!is_init && ffe_is_init_local_zero ())
8941 || (is_init && (ffestorag_init (eqst) == NULL)))
8942 init = ffecom_init_zero_ (eqt);
8944 finish_decl (eqt, init, FALSE);
8947 ffestorag_set_init (eqst, ffebld_new_any ());
8950 assert (TREE_CODE (DECL_SIZE_UNIT (eqt)) == INTEGER_CST);
8951 assert (0 == compare_tree_int (DECL_SIZE_UNIT (eqt),
8952 (ffestorag_size (eqst)
8953 + ffestorag_modulo (eqst))));
8956 ffestorag_set_hook (eqst, eqt);
8958 #ifdef SOMEONE_GETS_DEBUG_SUPPORT_WORKING
8959 ffestorag_drive (ffestorag_list_equivs (eqst),
8960 &ffecom_member_phase2_,
8964 resume_momentary (yes);
8968 /* Implement NAMELIST in back end. See f2c/format.c for more info. */
8970 #if FFECOM_targetCURRENT == FFECOM_targetGCC
8972 ffecom_transform_namelist_ (ffesymbol s)
8975 tree nmltype = ffecom_type_namelist_ ();
8984 static int mynumber = 0;
8986 yes = suspend_momentary ();
8988 nmlt = build_decl (VAR_DECL,
8989 ffecom_get_invented_identifier ("__g77_namelist_%d",
8992 TREE_STATIC (nmlt) = 1;
8993 DECL_INITIAL (nmlt) = error_mark_node;
8995 nmlt = start_decl (nmlt, FALSE);
8997 /* Process inits. */
8999 i = strlen (ffesymbol_text (s));
9001 high = build_int_2 (i, 0);
9002 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
9004 nameinit = ffecom_build_f2c_string_ (i + 1,
9005 ffesymbol_text (s));
9006 TREE_TYPE (nameinit)
9007 = build_type_variant
9010 build_range_type (ffecom_f2c_ftnlen_type_node,
9011 ffecom_f2c_ftnlen_one_node,
9014 TREE_CONSTANT (nameinit) = 1;
9015 TREE_STATIC (nameinit) = 1;
9016 nameinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (nameinit)),
9019 varsinit = ffecom_vardesc_array_ (s);
9020 varsinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (varsinit)),
9022 TREE_CONSTANT (varsinit) = 1;
9023 TREE_STATIC (varsinit) = 1;
9028 for (i = 0, b = ffesymbol_namelist (s); b != NULL; b = ffebld_trail (b))
9031 nvarsinit = build_int_2 (i, 0);
9032 TREE_TYPE (nvarsinit) = integer_type_node;
9033 TREE_CONSTANT (nvarsinit) = 1;
9034 TREE_STATIC (nvarsinit) = 1;
9036 nmlinits = build_tree_list ((field = TYPE_FIELDS (nmltype)), nameinit);
9037 TREE_CHAIN (nmlinits) = build_tree_list ((field = TREE_CHAIN (field)),
9039 TREE_CHAIN (TREE_CHAIN (nmlinits))
9040 = build_tree_list ((field = TREE_CHAIN (field)), nvarsinit);
9042 nmlinits = build (CONSTRUCTOR, nmltype, NULL_TREE, nmlinits);
9043 TREE_CONSTANT (nmlinits) = 1;
9044 TREE_STATIC (nmlinits) = 1;
9046 finish_decl (nmlt, nmlinits, FALSE);
9048 nmlt = ffecom_1 (ADDR_EXPR, build_pointer_type (nmltype), nmlt);
9050 resume_momentary (yes);
9057 /* A subroutine of ffecom_tree_canonize_ref_. The incoming tree is
9058 analyzed on the assumption it is calculating a pointer to be
9059 indirected through. It must return the proper decl and offset,
9060 taking into account different units of measurements for offsets. */
9062 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9064 ffecom_tree_canonize_ptr_ (tree *decl, tree *offset,
9067 switch (TREE_CODE (t))
9071 case NON_LVALUE_EXPR:
9072 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
9076 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
9077 if ((*decl == NULL_TREE)
9078 || (*decl == error_mark_node))
9081 if (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST)
9083 /* An offset into COMMON. */
9084 *offset = fold (build (PLUS_EXPR, TREE_TYPE (*offset),
9085 *offset, TREE_OPERAND (t, 1)));
9086 /* Convert offset (presumably in bytes) into canonical units
9087 (presumably bits). */
9088 *offset = size_binop (MULT_EXPR,
9089 convert (bitsizetype, *offset),
9090 TYPE_SIZE (TREE_TYPE (TREE_TYPE (t))));
9093 /* Not a COMMON reference, so an unrecognized pattern. */
9094 *decl = error_mark_node;
9099 *offset = bitsize_zero_node;
9103 if (TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL)
9105 /* A reference to COMMON. */
9106 *decl = TREE_OPERAND (t, 0);
9107 *offset = bitsize_zero_node;
9112 /* Not a COMMON reference, so an unrecognized pattern. */
9113 *decl = error_mark_node;
9119 /* Given a tree that is possibly intended for use as an lvalue, return
9120 information representing a canonical view of that tree as a decl, an
9121 offset into that decl, and a size for the lvalue.
9123 If there's no applicable decl, NULL_TREE is returned for the decl,
9124 and the other fields are left undefined.
9126 If the tree doesn't fit the recognizable forms, an ERROR_MARK node
9127 is returned for the decl, and the other fields are left undefined.
9129 Otherwise, the decl returned currently is either a VAR_DECL or a
9132 The offset returned is always valid, but of course not necessarily
9133 a constant, and not necessarily converted into the appropriate
9134 type, leaving that up to the caller (so as to avoid that overhead
9135 if the decls being looked at are different anyway).
9137 If the size cannot be determined (e.g. an adjustable array),
9138 an ERROR_MARK node is returned for the size. Otherwise, the
9139 size returned is valid, not necessarily a constant, and not
9140 necessarily converted into the appropriate type as with the
9143 Note that the offset and size expressions are expressed in the
9144 base storage units (usually bits) rather than in the units of
9145 the type of the decl, because two decls with different types
9146 might overlap but with apparently non-overlapping array offsets,
9147 whereas converting the array offsets to consistant offsets will
9148 reveal the overlap. */
9150 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9152 ffecom_tree_canonize_ref_ (tree *decl, tree *offset,
9155 /* The default path is to report a nonexistant decl. */
9161 switch (TREE_CODE (t))
9164 case IDENTIFIER_NODE:
9173 case TRUNC_DIV_EXPR:
9175 case FLOOR_DIV_EXPR:
9176 case ROUND_DIV_EXPR:
9177 case TRUNC_MOD_EXPR:
9179 case FLOOR_MOD_EXPR:
9180 case ROUND_MOD_EXPR:
9182 case EXACT_DIV_EXPR:
9183 case FIX_TRUNC_EXPR:
9185 case FIX_FLOOR_EXPR:
9186 case FIX_ROUND_EXPR:
9201 case BIT_ANDTC_EXPR:
9203 case TRUTH_ANDIF_EXPR:
9204 case TRUTH_ORIF_EXPR:
9205 case TRUTH_AND_EXPR:
9207 case TRUTH_XOR_EXPR:
9208 case TRUTH_NOT_EXPR:
9228 *offset = bitsize_zero_node;
9229 *size = TYPE_SIZE (TREE_TYPE (t));
9234 tree array = TREE_OPERAND (t, 0);
9235 tree element = TREE_OPERAND (t, 1);
9238 if ((array == NULL_TREE)
9239 || (element == NULL_TREE))
9241 *decl = error_mark_node;
9245 ffecom_tree_canonize_ref_ (decl, &init_offset, size,
9247 if ((*decl == NULL_TREE)
9248 || (*decl == error_mark_node))
9251 /* Calculate ((element - base) * NBBY) + init_offset. */
9252 *offset = fold (build (MINUS_EXPR, TREE_TYPE (element),
9254 TYPE_MIN_VALUE (TYPE_DOMAIN
9255 (TREE_TYPE (array)))));
9257 *offset = size_binop (MULT_EXPR,
9258 convert (bitsizetype, *offset),
9259 TYPE_SIZE (TREE_TYPE (TREE_TYPE (array))));
9261 *offset = size_binop (PLUS_EXPR, init_offset, *offset);
9263 *size = TYPE_SIZE (TREE_TYPE (t));
9269 /* Most of this code is to handle references to COMMON. And so
9270 far that is useful only for calling library functions, since
9271 external (user) functions might reference common areas. But
9272 even calling an external function, it's worthwhile to decode
9273 COMMON references because if not storing into COMMON, we don't
9274 want COMMON-based arguments to gratuitously force use of a
9277 *size = TYPE_SIZE (TREE_TYPE (t));
9279 ffecom_tree_canonize_ptr_ (decl, offset,
9280 TREE_OPERAND (t, 0));
9287 case NON_LVALUE_EXPR:
9290 case COND_EXPR: /* More cases than we can handle. */
9292 case REFERENCE_EXPR:
9293 case PREDECREMENT_EXPR:
9294 case PREINCREMENT_EXPR:
9295 case POSTDECREMENT_EXPR:
9296 case POSTINCREMENT_EXPR:
9299 *decl = error_mark_node;
9305 /* Do divide operation appropriate to type of operands. */
9307 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9309 ffecom_tree_divide_ (tree tree_type, tree left, tree right,
9310 tree dest_tree, ffebld dest, bool *dest_used,
9313 if ((left == error_mark_node)
9314 || (right == error_mark_node))
9315 return error_mark_node;
9317 switch (TREE_CODE (tree_type))
9320 return ffecom_2 (TRUNC_DIV_EXPR, tree_type,
9325 if (! optimize_size)
9326 return ffecom_2 (RDIV_EXPR, tree_type,
9332 if (TREE_TYPE (tree_type)
9333 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9334 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */
9336 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */
9338 left = ffecom_1 (ADDR_EXPR,
9339 build_pointer_type (TREE_TYPE (left)),
9341 left = build_tree_list (NULL_TREE, left);
9342 right = ffecom_1 (ADDR_EXPR,
9343 build_pointer_type (TREE_TYPE (right)),
9345 right = build_tree_list (NULL_TREE, right);
9346 TREE_CHAIN (left) = right;
9348 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9349 ffecom_gfrt_kindtype (ix),
9350 ffe_is_f2c_library (),
9353 dest_tree, dest, dest_used,
9354 NULL_TREE, TRUE, hook);
9362 if (TREE_TYPE (TYPE_FIELDS (tree_type))
9363 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9364 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */
9366 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */
9368 left = ffecom_1 (ADDR_EXPR,
9369 build_pointer_type (TREE_TYPE (left)),
9371 left = build_tree_list (NULL_TREE, left);
9372 right = ffecom_1 (ADDR_EXPR,
9373 build_pointer_type (TREE_TYPE (right)),
9375 right = build_tree_list (NULL_TREE, right);
9376 TREE_CHAIN (left) = right;
9378 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9379 ffecom_gfrt_kindtype (ix),
9380 ffe_is_f2c_library (),
9383 dest_tree, dest, dest_used,
9384 NULL_TREE, TRUE, hook);
9389 return ffecom_2 (RDIV_EXPR, tree_type,
9396 /* Build type info for non-dummy variable. */
9398 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9400 ffecom_type_localvar_ (ffesymbol s, ffeinfoBasictype bt,
9409 type = ffecom_tree_type[bt][kt];
9410 if (bt == FFEINFO_basictypeCHARACTER)
9412 hight = build_int_2 (ffesymbol_size (s), 0);
9413 TREE_TYPE (hight) = ffecom_f2c_ftnlen_type_node;
9418 build_range_type (ffecom_f2c_ftnlen_type_node,
9419 ffecom_f2c_ftnlen_one_node,
9421 type = ffecom_check_size_overflow_ (s, type, FALSE);
9424 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
9426 if (type == error_mark_node)
9429 dim = ffebld_head (dl);
9430 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
9432 if (ffebld_left (dim) == NULL)
9433 lowt = integer_one_node;
9435 lowt = ffecom_expr (ffebld_left (dim));
9437 if (TREE_CODE (lowt) != INTEGER_CST)
9438 lowt = variable_size (lowt);
9440 assert (ffebld_right (dim) != NULL);
9441 hight = ffecom_expr (ffebld_right (dim));
9443 if (TREE_CODE (hight) != INTEGER_CST)
9444 hight = variable_size (hight);
9446 type = build_array_type (type,
9447 build_range_type (ffecom_integer_type_node,
9449 type = ffecom_check_size_overflow_ (s, type, FALSE);
9456 /* Build Namelist type. */
9458 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9460 ffecom_type_namelist_ ()
9462 static tree type = NULL_TREE;
9464 if (type == NULL_TREE)
9466 static tree namefield, varsfield, nvarsfield;
9469 vardesctype = ffecom_type_vardesc_ ();
9471 type = make_node (RECORD_TYPE);
9473 vardesctype = build_pointer_type (build_pointer_type (vardesctype));
9475 namefield = ffecom_decl_field (type, NULL_TREE, "name",
9477 varsfield = ffecom_decl_field (type, namefield, "vars", vardesctype);
9478 nvarsfield = ffecom_decl_field (type, varsfield, "nvars",
9481 TYPE_FIELDS (type) = namefield;
9484 ggc_add_tree_root (&type, 1);
9492 /* Build Vardesc type. */
9494 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9496 ffecom_type_vardesc_ ()
9498 static tree type = NULL_TREE;
9499 static tree namefield, addrfield, dimsfield, typefield;
9501 if (type == NULL_TREE)
9503 type = make_node (RECORD_TYPE);
9505 namefield = ffecom_decl_field (type, NULL_TREE, "name",
9507 addrfield = ffecom_decl_field (type, namefield, "addr",
9509 dimsfield = ffecom_decl_field (type, addrfield, "dims",
9510 ffecom_f2c_ptr_to_ftnlen_type_node);
9511 typefield = ffecom_decl_field (type, dimsfield, "type",
9514 TYPE_FIELDS (type) = namefield;
9517 ggc_add_tree_root (&type, 1);
9525 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9527 ffecom_vardesc_ (ffebld expr)
9531 assert (ffebld_op (expr) == FFEBLD_opSYMTER);
9532 s = ffebld_symter (expr);
9534 if (ffesymbol_hook (s).vardesc_tree == NULL_TREE)
9537 tree vardesctype = ffecom_type_vardesc_ ();
9546 static int mynumber = 0;
9548 yes = suspend_momentary ();
9550 var = build_decl (VAR_DECL,
9551 ffecom_get_invented_identifier ("__g77_vardesc_%d",
9554 TREE_STATIC (var) = 1;
9555 DECL_INITIAL (var) = error_mark_node;
9557 var = start_decl (var, FALSE);
9559 /* Process inits. */
9561 nameinit = ffecom_build_f2c_string_ ((i = strlen (ffesymbol_text (s)))
9563 ffesymbol_text (s));
9564 TREE_TYPE (nameinit)
9565 = build_type_variant
9568 build_range_type (integer_type_node,
9570 build_int_2 (i, 0))),
9572 TREE_CONSTANT (nameinit) = 1;
9573 TREE_STATIC (nameinit) = 1;
9574 nameinit = ffecom_1 (ADDR_EXPR,
9575 build_pointer_type (TREE_TYPE (nameinit)),
9578 addrinit = ffecom_arg_ptr_to_expr (expr, &typeinit);
9580 dimsinit = ffecom_vardesc_dims_ (s);
9582 if (typeinit == NULL_TREE)
9584 ffeinfoBasictype bt = ffesymbol_basictype (s);
9585 ffeinfoKindtype kt = ffesymbol_kindtype (s);
9586 int tc = ffecom_f2c_typecode (bt, kt);
9589 typeinit = build_int_2 (tc, (tc < 0) ? -1 : 0);
9592 typeinit = ffecom_1 (NEGATE_EXPR, TREE_TYPE (typeinit), typeinit);
9594 varinits = build_tree_list ((field = TYPE_FIELDS (vardesctype)),
9596 TREE_CHAIN (varinits) = build_tree_list ((field = TREE_CHAIN (field)),
9598 TREE_CHAIN (TREE_CHAIN (varinits))
9599 = build_tree_list ((field = TREE_CHAIN (field)), dimsinit);
9600 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (varinits)))
9601 = build_tree_list ((field = TREE_CHAIN (field)), typeinit);
9603 varinits = build (CONSTRUCTOR, vardesctype, NULL_TREE, varinits);
9604 TREE_CONSTANT (varinits) = 1;
9605 TREE_STATIC (varinits) = 1;
9607 finish_decl (var, varinits, FALSE);
9609 var = ffecom_1 (ADDR_EXPR, build_pointer_type (vardesctype), var);
9611 resume_momentary (yes);
9613 ffesymbol_hook (s).vardesc_tree = var;
9616 return ffesymbol_hook (s).vardesc_tree;
9620 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9622 ffecom_vardesc_array_ (ffesymbol s)
9626 tree item = NULL_TREE;
9630 static int mynumber = 0;
9632 for (i = 0, list = NULL_TREE, b = ffesymbol_namelist (s);
9634 b = ffebld_trail (b), ++i)
9638 t = ffecom_vardesc_ (ffebld_head (b));
9640 if (list == NULL_TREE)
9641 list = item = build_tree_list (NULL_TREE, t);
9644 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
9645 item = TREE_CHAIN (item);
9649 yes = suspend_momentary ();
9651 item = build_array_type (build_pointer_type (ffecom_type_vardesc_ ()),
9652 build_range_type (integer_type_node,
9654 build_int_2 (i, 0)));
9655 list = build (CONSTRUCTOR, item, NULL_TREE, list);
9656 TREE_CONSTANT (list) = 1;
9657 TREE_STATIC (list) = 1;
9659 var = ffecom_get_invented_identifier ("__g77_vardesc_array_%d", mynumber++);
9660 var = build_decl (VAR_DECL, var, item);
9661 TREE_STATIC (var) = 1;
9662 DECL_INITIAL (var) = error_mark_node;
9663 var = start_decl (var, FALSE);
9664 finish_decl (var, list, FALSE);
9666 resume_momentary (yes);
9672 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9674 ffecom_vardesc_dims_ (ffesymbol s)
9676 if (ffesymbol_dims (s) == NULL)
9677 return convert (ffecom_f2c_ptr_to_ftnlen_type_node,
9685 tree item = NULL_TREE;
9690 tree baseoff = NULL_TREE;
9691 static int mynumber = 0;
9693 numdim = build_int_2 ((int) ffesymbol_rank (s), 0);
9694 TREE_TYPE (numdim) = ffecom_f2c_ftnlen_type_node;
9696 numelem = ffecom_expr (ffesymbol_arraysize (s));
9697 TREE_TYPE (numelem) = ffecom_f2c_ftnlen_type_node;
9700 backlist = NULL_TREE;
9701 for (b = ffesymbol_dims (s), e = ffesymbol_extents (s);
9703 b = ffebld_trail (b), e = ffebld_trail (e))
9709 if (ffebld_trail (b) == NULL)
9713 t = convert (ffecom_f2c_ftnlen_type_node,
9714 ffecom_expr (ffebld_head (e)));
9716 if (list == NULL_TREE)
9717 list = item = build_tree_list (NULL_TREE, t);
9720 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
9721 item = TREE_CHAIN (item);
9725 if (ffebld_left (ffebld_head (b)) == NULL)
9726 low = ffecom_integer_one_node;
9728 low = ffecom_expr (ffebld_left (ffebld_head (b)));
9729 low = convert (ffecom_f2c_ftnlen_type_node, low);
9731 back = build_tree_list (low, t);
9732 TREE_CHAIN (back) = backlist;
9736 for (item = backlist; item != NULL_TREE; item = TREE_CHAIN (item))
9738 if (TREE_VALUE (item) == NULL_TREE)
9739 baseoff = TREE_PURPOSE (item);
9741 baseoff = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
9742 TREE_PURPOSE (item),
9743 ffecom_2 (MULT_EXPR,
9744 ffecom_f2c_ftnlen_type_node,
9749 /* backlist now dead, along with all TREE_PURPOSEs on it. */
9751 baseoff = build_tree_list (NULL_TREE, baseoff);
9752 TREE_CHAIN (baseoff) = list;
9754 numelem = build_tree_list (NULL_TREE, numelem);
9755 TREE_CHAIN (numelem) = baseoff;
9757 numdim = build_tree_list (NULL_TREE, numdim);
9758 TREE_CHAIN (numdim) = numelem;
9760 yes = suspend_momentary ();
9762 item = build_array_type (ffecom_f2c_ftnlen_type_node,
9763 build_range_type (integer_type_node,
9766 ((int) ffesymbol_rank (s)
9768 list = build (CONSTRUCTOR, item, NULL_TREE, numdim);
9769 TREE_CONSTANT (list) = 1;
9770 TREE_STATIC (list) = 1;
9772 var = ffecom_get_invented_identifier ("__g77_dims_%d", mynumber++);
9773 var = build_decl (VAR_DECL, var, item);
9774 TREE_STATIC (var) = 1;
9775 DECL_INITIAL (var) = error_mark_node;
9776 var = start_decl (var, FALSE);
9777 finish_decl (var, list, FALSE);
9779 var = ffecom_1 (ADDR_EXPR, build_pointer_type (item), var);
9781 resume_momentary (yes);
9788 /* Essentially does a "fold (build1 (code, type, node))" while checking
9789 for certain housekeeping things.
9791 NOTE: for building an ADDR_EXPR around a FUNCTION_DECL, use
9792 ffecom_1_fn instead. */
9794 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9796 ffecom_1 (enum tree_code code, tree type, tree node)
9800 if ((node == error_mark_node)
9801 || (type == error_mark_node))
9802 return error_mark_node;
9804 if (code == ADDR_EXPR)
9806 if (!mark_addressable (node))
9807 assert ("can't mark_addressable this node!" == NULL);
9810 switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
9815 item = build (COMPONENT_REF, type, node, TYPE_FIELDS (TREE_TYPE (node)));
9819 item = build (COMPONENT_REF, type, node, TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (node))));
9824 if (TREE_CODE (type) != RECORD_TYPE)
9826 item = build1 (code, type, node);
9829 node = ffecom_stabilize_aggregate_ (node);
9830 realtype = TREE_TYPE (TYPE_FIELDS (type));
9832 ffecom_2 (COMPLEX_EXPR, type,
9833 ffecom_1 (NEGATE_EXPR, realtype,
9834 ffecom_1 (REALPART_EXPR, realtype,
9836 ffecom_1 (NEGATE_EXPR, realtype,
9837 ffecom_1 (IMAGPART_EXPR, realtype,
9842 item = build1 (code, type, node);
9846 if (TREE_SIDE_EFFECTS (node))
9847 TREE_SIDE_EFFECTS (item) = 1;
9848 if ((code == ADDR_EXPR) && staticp (node))
9849 TREE_CONSTANT (item) = 1;
9854 /* Like ffecom_1 (ADDR_EXPR, TREE_TYPE (node), node), except
9855 handles TREE_CODE (node) == FUNCTION_DECL. In particular,
9856 does not set TREE_ADDRESSABLE (because calling an inline
9857 function does not mean the function needs to be separately
9860 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9862 ffecom_1_fn (tree node)
9867 if (node == error_mark_node)
9868 return error_mark_node;
9870 type = build_type_variant (TREE_TYPE (node),
9871 TREE_READONLY (node),
9872 TREE_THIS_VOLATILE (node));
9873 item = build1 (ADDR_EXPR,
9874 build_pointer_type (type), node);
9875 if (TREE_SIDE_EFFECTS (node))
9876 TREE_SIDE_EFFECTS (item) = 1;
9878 TREE_CONSTANT (item) = 1;
9883 /* Essentially does a "fold (build (code, type, node1, node2))" while
9884 checking for certain housekeeping things. */
9886 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9888 ffecom_2 (enum tree_code code, tree type, tree node1,
9893 if ((node1 == error_mark_node)
9894 || (node2 == error_mark_node)
9895 || (type == error_mark_node))
9896 return error_mark_node;
9898 switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
9900 tree a, b, c, d, realtype;
9903 assert ("no CONJ_EXPR support yet" == NULL);
9904 return error_mark_node;
9907 item = build_tree_list (TYPE_FIELDS (type), node1);
9908 TREE_CHAIN (item) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), node2);
9909 item = build (CONSTRUCTOR, type, NULL_TREE, item);
9913 if (TREE_CODE (type) != RECORD_TYPE)
9915 item = build (code, type, node1, node2);
9918 node1 = ffecom_stabilize_aggregate_ (node1);
9919 node2 = ffecom_stabilize_aggregate_ (node2);
9920 realtype = TREE_TYPE (TYPE_FIELDS (type));
9922 ffecom_2 (COMPLEX_EXPR, type,
9923 ffecom_2 (PLUS_EXPR, realtype,
9924 ffecom_1 (REALPART_EXPR, realtype,
9926 ffecom_1 (REALPART_EXPR, realtype,
9928 ffecom_2 (PLUS_EXPR, realtype,
9929 ffecom_1 (IMAGPART_EXPR, realtype,
9931 ffecom_1 (IMAGPART_EXPR, realtype,
9936 if (TREE_CODE (type) != RECORD_TYPE)
9938 item = build (code, type, node1, node2);
9941 node1 = ffecom_stabilize_aggregate_ (node1);
9942 node2 = ffecom_stabilize_aggregate_ (node2);
9943 realtype = TREE_TYPE (TYPE_FIELDS (type));
9945 ffecom_2 (COMPLEX_EXPR, type,
9946 ffecom_2 (MINUS_EXPR, realtype,
9947 ffecom_1 (REALPART_EXPR, realtype,
9949 ffecom_1 (REALPART_EXPR, realtype,
9951 ffecom_2 (MINUS_EXPR, realtype,
9952 ffecom_1 (IMAGPART_EXPR, realtype,
9954 ffecom_1 (IMAGPART_EXPR, realtype,
9959 if (TREE_CODE (type) != RECORD_TYPE)
9961 item = build (code, type, node1, node2);
9964 node1 = ffecom_stabilize_aggregate_ (node1);
9965 node2 = ffecom_stabilize_aggregate_ (node2);
9966 realtype = TREE_TYPE (TYPE_FIELDS (type));
9967 a = save_expr (ffecom_1 (REALPART_EXPR, realtype,
9969 b = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
9971 c = save_expr (ffecom_1 (REALPART_EXPR, realtype,
9973 d = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
9976 ffecom_2 (COMPLEX_EXPR, type,
9977 ffecom_2 (MINUS_EXPR, realtype,
9978 ffecom_2 (MULT_EXPR, realtype,
9981 ffecom_2 (MULT_EXPR, realtype,
9984 ffecom_2 (PLUS_EXPR, realtype,
9985 ffecom_2 (MULT_EXPR, realtype,
9988 ffecom_2 (MULT_EXPR, realtype,
9994 if ((TREE_CODE (node1) != RECORD_TYPE)
9995 && (TREE_CODE (node2) != RECORD_TYPE))
9997 item = build (code, type, node1, node2);
10000 assert (TREE_CODE (node1) == RECORD_TYPE);
10001 assert (TREE_CODE (node2) == RECORD_TYPE);
10002 node1 = ffecom_stabilize_aggregate_ (node1);
10003 node2 = ffecom_stabilize_aggregate_ (node2);
10004 realtype = TREE_TYPE (TYPE_FIELDS (type));
10006 ffecom_2 (TRUTH_ANDIF_EXPR, type,
10007 ffecom_2 (code, type,
10008 ffecom_1 (REALPART_EXPR, realtype,
10010 ffecom_1 (REALPART_EXPR, realtype,
10012 ffecom_2 (code, type,
10013 ffecom_1 (IMAGPART_EXPR, realtype,
10015 ffecom_1 (IMAGPART_EXPR, realtype,
10020 if ((TREE_CODE (node1) != RECORD_TYPE)
10021 && (TREE_CODE (node2) != RECORD_TYPE))
10023 item = build (code, type, node1, node2);
10026 assert (TREE_CODE (node1) == RECORD_TYPE);
10027 assert (TREE_CODE (node2) == RECORD_TYPE);
10028 node1 = ffecom_stabilize_aggregate_ (node1);
10029 node2 = ffecom_stabilize_aggregate_ (node2);
10030 realtype = TREE_TYPE (TYPE_FIELDS (type));
10032 ffecom_2 (TRUTH_ORIF_EXPR, type,
10033 ffecom_2 (code, type,
10034 ffecom_1 (REALPART_EXPR, realtype,
10036 ffecom_1 (REALPART_EXPR, realtype,
10038 ffecom_2 (code, type,
10039 ffecom_1 (IMAGPART_EXPR, realtype,
10041 ffecom_1 (IMAGPART_EXPR, realtype,
10046 item = build (code, type, node1, node2);
10050 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2))
10051 TREE_SIDE_EFFECTS (item) = 1;
10052 return fold (item);
10056 /* ffecom_2pass_advise_entrypoint -- Advise that there's this entrypoint
10058 ffesymbol s; // the ENTRY point itself
10059 if (ffecom_2pass_advise_entrypoint(s))
10060 // the ENTRY point has been accepted
10062 Does whatever compiler needs to do when it learns about the entrypoint,
10063 like determine the return type of the master function, count the
10064 number of entrypoints, etc. Returns FALSE if the return type is
10065 not compatible with the return type(s) of other entrypoint(s).
10067 NOTE: for every call to this fn that returns TRUE, _do_entrypoint must
10068 later (after _finish_progunit) be called with the same entrypoint(s)
10069 as passed to this fn for which TRUE was returned.
10072 Return FALSE if the return type conflicts with previous entrypoints. */
10074 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10076 ffecom_2pass_advise_entrypoint (ffesymbol entry)
10078 ffebld list; /* opITEM. */
10079 ffebld mlist; /* opITEM. */
10080 ffebld plist; /* opITEM. */
10081 ffebld arg; /* ffebld_head(opITEM). */
10082 ffebld item; /* opITEM. */
10083 ffesymbol s; /* ffebld_symter(arg). */
10084 ffeinfoBasictype bt = ffesymbol_basictype (entry);
10085 ffeinfoKindtype kt = ffesymbol_kindtype (entry);
10086 ffetargetCharacterSize size = ffesymbol_size (entry);
10089 if (ffecom_num_entrypoints_ == 0)
10090 { /* First entrypoint, make list of main
10091 arglist's dummies. */
10092 assert (ffecom_primary_entry_ != NULL);
10094 ffecom_master_bt_ = ffesymbol_basictype (ffecom_primary_entry_);
10095 ffecom_master_kt_ = ffesymbol_kindtype (ffecom_primary_entry_);
10096 ffecom_master_size_ = ffesymbol_size (ffecom_primary_entry_);
10098 for (plist = NULL, list = ffesymbol_dummyargs (ffecom_primary_entry_);
10100 list = ffebld_trail (list))
10102 arg = ffebld_head (list);
10103 if (ffebld_op (arg) != FFEBLD_opSYMTER)
10104 continue; /* Alternate return or some such thing. */
10105 item = ffebld_new_item (arg, NULL);
10107 ffecom_master_arglist_ = item;
10109 ffebld_set_trail (plist, item);
10114 /* If necessary, scan entry arglist for alternate returns. Do this scan
10115 apparently redundantly (it's done below to UNIONize the arglists) so
10116 that we don't complain about RETURN 1 if an offending ENTRY is the only
10117 one with an alternate return. */
10119 if (!ffecom_is_altreturning_)
10121 for (list = ffesymbol_dummyargs (entry);
10123 list = ffebld_trail (list))
10125 arg = ffebld_head (list);
10126 if (ffebld_op (arg) == FFEBLD_opSTAR)
10128 ffecom_is_altreturning_ = TRUE;
10134 /* Now check type compatibility. */
10136 switch (ffecom_master_bt_)
10138 case FFEINFO_basictypeNONE:
10139 ok = (bt != FFEINFO_basictypeCHARACTER);
10142 case FFEINFO_basictypeCHARACTER:
10144 = (bt == FFEINFO_basictypeCHARACTER)
10145 && (kt == ffecom_master_kt_)
10146 && (size == ffecom_master_size_);
10149 case FFEINFO_basictypeANY:
10150 return FALSE; /* Just don't bother. */
10153 if (bt == FFEINFO_basictypeCHARACTER)
10159 if ((bt != ffecom_master_bt_) || (kt != ffecom_master_kt_))
10161 ffecom_master_bt_ = FFEINFO_basictypeNONE;
10162 ffecom_master_kt_ = FFEINFO_kindtypeNONE;
10169 ffebad_start (FFEBAD_ENTRY_CONFLICTS);
10170 ffest_ffebad_here_current_stmt (0);
10172 return FALSE; /* Can't handle entrypoint. */
10175 /* Entrypoint type compatible with previous types. */
10177 ++ffecom_num_entrypoints_;
10179 /* Master-arg-list = UNION(Master-arg-list,entry-arg-list). */
10181 for (list = ffesymbol_dummyargs (entry);
10183 list = ffebld_trail (list))
10185 arg = ffebld_head (list);
10186 if (ffebld_op (arg) != FFEBLD_opSYMTER)
10187 continue; /* Alternate return or some such thing. */
10188 s = ffebld_symter (arg);
10189 for (plist = NULL, mlist = ffecom_master_arglist_;
10191 plist = mlist, mlist = ffebld_trail (mlist))
10192 { /* plist points to previous item for easy
10193 appending of arg. */
10194 if (ffebld_symter (ffebld_head (mlist)) == s)
10195 break; /* Already have this arg in the master list. */
10198 continue; /* Already have this arg in the master list. */
10200 /* Append this arg to the master list. */
10202 item = ffebld_new_item (arg, NULL);
10204 ffecom_master_arglist_ = item;
10206 ffebld_set_trail (plist, item);
10213 /* ffecom_2pass_do_entrypoint -- Do compilation of entrypoint
10215 ffesymbol s; // the ENTRY point itself
10216 ffecom_2pass_do_entrypoint(s);
10218 Does whatever compiler needs to do to make the entrypoint actually
10219 happen. Must be called for each entrypoint after
10220 ffecom_finish_progunit is called. */
10222 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10224 ffecom_2pass_do_entrypoint (ffesymbol entry)
10226 static int mfn_num = 0;
10227 static int ent_num;
10229 if (mfn_num != ffecom_num_fns_)
10230 { /* First entrypoint for this program unit. */
10232 mfn_num = ffecom_num_fns_;
10233 ffecom_do_entry_ (ffecom_primary_entry_, 0);
10238 --ffecom_num_entrypoints_;
10240 ffecom_do_entry_ (entry, ent_num);
10245 /* Essentially does a "fold (build (code, type, node1, node2))" while
10246 checking for certain housekeeping things. Always sets
10247 TREE_SIDE_EFFECTS. */
10249 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10251 ffecom_2s (enum tree_code code, tree type, tree node1,
10256 if ((node1 == error_mark_node)
10257 || (node2 == error_mark_node)
10258 || (type == error_mark_node))
10259 return error_mark_node;
10261 item = build (code, type, node1, node2);
10262 TREE_SIDE_EFFECTS (item) = 1;
10263 return fold (item);
10267 /* Essentially does a "fold (build (code, type, node1, node2, node3))" while
10268 checking for certain housekeeping things. */
10270 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10272 ffecom_3 (enum tree_code code, tree type, tree node1,
10273 tree node2, tree node3)
10277 if ((node1 == error_mark_node)
10278 || (node2 == error_mark_node)
10279 || (node3 == error_mark_node)
10280 || (type == error_mark_node))
10281 return error_mark_node;
10283 item = build (code, type, node1, node2, node3);
10284 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2)
10285 || (node3 != NULL_TREE && TREE_SIDE_EFFECTS (node3)))
10286 TREE_SIDE_EFFECTS (item) = 1;
10287 return fold (item);
10291 /* Essentially does a "fold (build (code, type, node1, node2, node3))" while
10292 checking for certain housekeeping things. Always sets
10293 TREE_SIDE_EFFECTS. */
10295 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10297 ffecom_3s (enum tree_code code, tree type, tree node1,
10298 tree node2, tree node3)
10302 if ((node1 == error_mark_node)
10303 || (node2 == error_mark_node)
10304 || (node3 == error_mark_node)
10305 || (type == error_mark_node))
10306 return error_mark_node;
10308 item = build (code, type, node1, node2, node3);
10309 TREE_SIDE_EFFECTS (item) = 1;
10310 return fold (item);
10315 /* ffecom_arg_expr -- Transform argument expr into gcc tree
10317 See use by ffecom_list_expr.
10319 If expression is NULL, returns an integer zero tree. If it is not
10320 a CHARACTER expression, returns whatever ffecom_expr
10321 returns and sets the length return value to NULL_TREE. Otherwise
10322 generates code to evaluate the character expression, returns the proper
10323 pointer to the result, but does NOT set the length return value to a tree
10324 that specifies the length of the result. (In other words, the length
10325 variable is always set to NULL_TREE, because a length is never passed.)
10328 Don't set returned length, since nobody needs it (yet; someday if
10329 we allow CHARACTER*(*) dummies to statement functions, we'll need
10332 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10334 ffecom_arg_expr (ffebld expr, tree *length)
10338 *length = NULL_TREE;
10341 return integer_zero_node;
10343 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10344 return ffecom_expr (expr);
10346 return ffecom_arg_ptr_to_expr (expr, &ign);
10350 /* Transform expression into constant argument-pointer-to-expression tree.
10352 If the expression can be transformed into a argument-pointer-to-expression
10353 tree that is constant, that is done, and the tree returned. Else
10354 NULL_TREE is returned.
10356 That way, a caller can attempt to provide compile-time initialization
10357 of a variable and, if that fails, *then* choose to start a new block
10358 and resort to using temporaries, as appropriate. */
10361 ffecom_arg_ptr_to_const_expr (ffebld expr, tree *length)
10364 return integer_zero_node;
10366 if (ffebld_op (expr) == FFEBLD_opANY)
10369 *length = error_mark_node;
10370 return error_mark_node;
10373 if (ffebld_arity (expr) == 0
10374 && (ffebld_op (expr) != FFEBLD_opSYMTER
10375 || ffebld_where (expr) == FFEINFO_whereCOMMON
10376 || ffebld_where (expr) == FFEINFO_whereGLOBAL
10377 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
10381 t = ffecom_arg_ptr_to_expr (expr, length);
10382 assert (TREE_CONSTANT (t));
10383 assert (! length || TREE_CONSTANT (*length));
10388 && ffebld_size (expr) != FFETARGET_charactersizeNONE)
10389 *length = build_int_2 (ffebld_size (expr), 0);
10391 *length = NULL_TREE;
10395 /* ffecom_arg_ptr_to_expr -- Transform argument expr into gcc tree
10397 See use by ffecom_list_ptr_to_expr.
10399 If expression is NULL, returns an integer zero tree. If it is not
10400 a CHARACTER expression, returns whatever ffecom_ptr_to_expr
10401 returns and sets the length return value to NULL_TREE. Otherwise
10402 generates code to evaluate the character expression, returns the proper
10403 pointer to the result, AND sets the length return value to a tree that
10404 specifies the length of the result.
10406 If the length argument is NULL, this is a slightly special
10407 case of building a FORMAT expression, that is, an expression that
10408 will be used at run time without regard to length. For the current
10409 implementation, which uses the libf2c library, this means it is nice
10410 to append a null byte to the end of the expression, where feasible,
10411 to make sure any diagnostic about the FORMAT string terminates at
10414 For now, treat %REF(char-expr) as the same as char-expr with a NULL
10415 length argument. This might even be seen as a feature, if a null
10416 byte can always be appended. */
10418 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10420 ffecom_arg_ptr_to_expr (ffebld expr, tree *length)
10424 ffecomConcatList_ catlist;
10426 if (length != NULL)
10427 *length = NULL_TREE;
10430 return integer_zero_node;
10432 switch (ffebld_op (expr))
10434 case FFEBLD_opPERCENT_VAL:
10435 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10436 return ffecom_expr (ffebld_left (expr));
10441 temp_exp = ffecom_arg_ptr_to_expr (ffebld_left (expr), &temp_length);
10442 if (temp_exp == error_mark_node)
10443 return error_mark_node;
10445 return ffecom_1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (temp_exp)),
10449 case FFEBLD_opPERCENT_REF:
10450 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10451 return ffecom_ptr_to_expr (ffebld_left (expr));
10452 if (length != NULL)
10454 ign_length = NULL_TREE;
10455 length = &ign_length;
10457 expr = ffebld_left (expr);
10460 case FFEBLD_opPERCENT_DESCR:
10461 switch (ffeinfo_basictype (ffebld_info (expr)))
10463 #ifdef PASS_HOLLERITH_BY_DESCRIPTOR
10464 case FFEINFO_basictypeHOLLERITH:
10466 case FFEINFO_basictypeCHARACTER:
10467 break; /* Passed by descriptor anyway. */
10470 item = ffecom_ptr_to_expr (expr);
10471 if (item != error_mark_node)
10472 *length = TYPE_SIZE (TREE_TYPE (TREE_TYPE (item)));
10481 #ifdef PASS_HOLLERITH_BY_DESCRIPTOR
10482 if ((ffeinfo_basictype (ffebld_info (expr)) == FFEINFO_basictypeHOLLERITH)
10483 && (length != NULL))
10484 { /* Pass Hollerith by descriptor. */
10485 ffetargetHollerith h;
10487 assert (ffebld_op (expr) == FFEBLD_opCONTER);
10488 h = ffebld_cu_val_hollerith (ffebld_constant_union
10489 (ffebld_conter (expr)));
10491 = build_int_2 (h.length, 0);
10492 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
10496 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10497 return ffecom_ptr_to_expr (expr);
10499 assert (ffeinfo_kindtype (ffebld_info (expr))
10500 == FFEINFO_kindtypeCHARACTER1);
10502 while (ffebld_op (expr) == FFEBLD_opPAREN)
10503 expr = ffebld_left (expr);
10505 catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
10506 switch (ffecom_concat_list_count_ (catlist))
10508 case 0: /* Shouldn't happen, but in case it does... */
10509 if (length != NULL)
10511 *length = ffecom_f2c_ftnlen_zero_node;
10512 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
10514 ffecom_concat_list_kill_ (catlist);
10515 return null_pointer_node;
10517 case 1: /* The (fairly) easy case. */
10518 if (length == NULL)
10519 ffecom_char_args_with_null_ (&item, &ign_length,
10520 ffecom_concat_list_expr_ (catlist, 0));
10522 ffecom_char_args_ (&item, length,
10523 ffecom_concat_list_expr_ (catlist, 0));
10524 ffecom_concat_list_kill_ (catlist);
10525 assert (item != NULL_TREE);
10528 default: /* Must actually concatenate things. */
10533 int count = ffecom_concat_list_count_ (catlist);
10544 ffetargetCharacterSize sz;
10546 sz = ffecom_concat_list_maxlen_ (catlist);
10548 assert (sz != FFETARGET_charactersizeNONE);
10553 = ffecom_push_tempvar (ffecom_f2c_ftnlen_type_node,
10554 FFETARGET_charactersizeNONE, count, TRUE);
10557 = ffecom_push_tempvar (ffecom_f2c_address_type_node,
10558 FFETARGET_charactersizeNONE, count, TRUE);
10559 temporary = ffecom_push_tempvar (char_type_node,
10565 hook = ffebld_nonter_hook (expr);
10567 assert (TREE_CODE (hook) == TREE_VEC);
10568 assert (TREE_VEC_LENGTH (hook) == 3);
10569 length_array = lengths = TREE_VEC_ELT (hook, 0);
10570 item_array = items = TREE_VEC_ELT (hook, 1);
10571 temporary = TREE_VEC_ELT (hook, 2);
10575 known_length = ffecom_f2c_ftnlen_zero_node;
10577 for (i = 0; i < count; ++i)
10580 && (length == NULL))
10581 ffecom_char_args_with_null_ (&citem, &clength,
10582 ffecom_concat_list_expr_ (catlist, i));
10584 ffecom_char_args_ (&citem, &clength,
10585 ffecom_concat_list_expr_ (catlist, i));
10586 if ((citem == error_mark_node)
10587 || (clength == error_mark_node))
10589 ffecom_concat_list_kill_ (catlist);
10590 *length = error_mark_node;
10591 return error_mark_node;
10595 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
10596 ffecom_modify (void_type_node,
10597 ffecom_2 (ARRAY_REF,
10598 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
10600 build_int_2 (i, 0)),
10603 clength = ffecom_save_tree (clength);
10604 if (length != NULL)
10606 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
10610 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
10611 ffecom_modify (void_type_node,
10612 ffecom_2 (ARRAY_REF,
10613 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
10615 build_int_2 (i, 0)),
10620 temporary = ffecom_1 (ADDR_EXPR,
10621 build_pointer_type (TREE_TYPE (temporary)),
10624 item = build_tree_list (NULL_TREE, temporary);
10626 = build_tree_list (NULL_TREE,
10627 ffecom_1 (ADDR_EXPR,
10628 build_pointer_type (TREE_TYPE (items)),
10630 TREE_CHAIN (TREE_CHAIN (item))
10631 = build_tree_list (NULL_TREE,
10632 ffecom_1 (ADDR_EXPR,
10633 build_pointer_type (TREE_TYPE (lengths)),
10635 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
10638 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
10639 convert (ffecom_f2c_ftnlen_type_node,
10640 build_int_2 (count, 0))));
10641 num = build_int_2 (sz, 0);
10642 TREE_TYPE (num) = ffecom_f2c_ftnlen_type_node;
10643 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item))))
10644 = build_tree_list (NULL_TREE, num);
10646 item = ffecom_call_gfrt (FFECOM_gfrtCAT, item, NULL_TREE);
10647 TREE_SIDE_EFFECTS (item) = 1;
10648 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (temporary),
10652 if (length != NULL)
10653 *length = known_length;
10656 ffecom_concat_list_kill_ (catlist);
10657 assert (item != NULL_TREE);
10662 /* Generate call to run-time function.
10664 The first arg is the GNU Fortran Run-Time function index, the second
10665 arg is the list of arguments to pass to it. Returned is the expression
10666 (WITHOUT TREE_SIDE_EFFECTS set!) that makes the call and returns the
10667 result (which may be void). */
10669 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10671 ffecom_call_gfrt (ffecomGfrt ix, tree args, tree hook)
10673 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
10674 ffecom_gfrt_kindtype (ix),
10675 ffe_is_f2c_library () && ffecom_gfrt_complex_[ix],
10676 NULL_TREE, args, NULL_TREE, NULL,
10677 NULL, NULL_TREE, TRUE, hook);
10681 /* Transform constant-union to tree. */
10683 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10685 ffecom_constantunion (ffebldConstantUnion *cu, ffeinfoBasictype bt,
10686 ffeinfoKindtype kt, tree tree_type)
10692 case FFEINFO_basictypeINTEGER:
10698 #if FFETARGET_okINTEGER1
10699 case FFEINFO_kindtypeINTEGER1:
10700 val = ffebld_cu_val_integer1 (*cu);
10704 #if FFETARGET_okINTEGER2
10705 case FFEINFO_kindtypeINTEGER2:
10706 val = ffebld_cu_val_integer2 (*cu);
10710 #if FFETARGET_okINTEGER3
10711 case FFEINFO_kindtypeINTEGER3:
10712 val = ffebld_cu_val_integer3 (*cu);
10716 #if FFETARGET_okINTEGER4
10717 case FFEINFO_kindtypeINTEGER4:
10718 val = ffebld_cu_val_integer4 (*cu);
10723 assert ("bad INTEGER constant kind type" == NULL);
10724 /* Fall through. */
10725 case FFEINFO_kindtypeANY:
10726 return error_mark_node;
10728 item = build_int_2 (val, (val < 0) ? -1 : 0);
10729 TREE_TYPE (item) = tree_type;
10733 case FFEINFO_basictypeLOGICAL:
10739 #if FFETARGET_okLOGICAL1
10740 case FFEINFO_kindtypeLOGICAL1:
10741 val = ffebld_cu_val_logical1 (*cu);
10745 #if FFETARGET_okLOGICAL2
10746 case FFEINFO_kindtypeLOGICAL2:
10747 val = ffebld_cu_val_logical2 (*cu);
10751 #if FFETARGET_okLOGICAL3
10752 case FFEINFO_kindtypeLOGICAL3:
10753 val = ffebld_cu_val_logical3 (*cu);
10757 #if FFETARGET_okLOGICAL4
10758 case FFEINFO_kindtypeLOGICAL4:
10759 val = ffebld_cu_val_logical4 (*cu);
10764 assert ("bad LOGICAL constant kind type" == NULL);
10765 /* Fall through. */
10766 case FFEINFO_kindtypeANY:
10767 return error_mark_node;
10769 item = build_int_2 (val, (val < 0) ? -1 : 0);
10770 TREE_TYPE (item) = tree_type;
10774 case FFEINFO_basictypeREAL:
10776 REAL_VALUE_TYPE val;
10780 #if FFETARGET_okREAL1
10781 case FFEINFO_kindtypeREAL1:
10782 val = ffetarget_value_real1 (ffebld_cu_val_real1 (*cu));
10786 #if FFETARGET_okREAL2
10787 case FFEINFO_kindtypeREAL2:
10788 val = ffetarget_value_real2 (ffebld_cu_val_real2 (*cu));
10792 #if FFETARGET_okREAL3
10793 case FFEINFO_kindtypeREAL3:
10794 val = ffetarget_value_real3 (ffebld_cu_val_real3 (*cu));
10798 #if FFETARGET_okREAL4
10799 case FFEINFO_kindtypeREAL4:
10800 val = ffetarget_value_real4 (ffebld_cu_val_real4 (*cu));
10805 assert ("bad REAL constant kind type" == NULL);
10806 /* Fall through. */
10807 case FFEINFO_kindtypeANY:
10808 return error_mark_node;
10810 item = build_real (tree_type, val);
10814 case FFEINFO_basictypeCOMPLEX:
10816 REAL_VALUE_TYPE real;
10817 REAL_VALUE_TYPE imag;
10818 tree el_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
10822 #if FFETARGET_okCOMPLEX1
10823 case FFEINFO_kindtypeREAL1:
10824 real = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).real);
10825 imag = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).imaginary);
10829 #if FFETARGET_okCOMPLEX2
10830 case FFEINFO_kindtypeREAL2:
10831 real = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).real);
10832 imag = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).imaginary);
10836 #if FFETARGET_okCOMPLEX3
10837 case FFEINFO_kindtypeREAL3:
10838 real = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).real);
10839 imag = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).imaginary);
10843 #if FFETARGET_okCOMPLEX4
10844 case FFEINFO_kindtypeREAL4:
10845 real = ffetarget_value_real4 (ffebld_cu_val_complex4 (*cu).real);
10846 imag = ffetarget_value_real4 (ffebld_cu_val_complex4 (*cu).imaginary);
10851 assert ("bad REAL constant kind type" == NULL);
10852 /* Fall through. */
10853 case FFEINFO_kindtypeANY:
10854 return error_mark_node;
10856 item = ffecom_build_complex_constant_ (tree_type,
10857 build_real (el_type, real),
10858 build_real (el_type, imag));
10862 case FFEINFO_basictypeCHARACTER:
10863 { /* Happens only in DATA and similar contexts. */
10864 ffetargetCharacter1 val;
10868 #if FFETARGET_okCHARACTER1
10869 case FFEINFO_kindtypeLOGICAL1:
10870 val = ffebld_cu_val_character1 (*cu);
10875 assert ("bad CHARACTER constant kind type" == NULL);
10876 /* Fall through. */
10877 case FFEINFO_kindtypeANY:
10878 return error_mark_node;
10880 item = build_string (ffetarget_length_character1 (val),
10881 ffetarget_text_character1 (val));
10883 = build_type_variant (build_array_type (char_type_node,
10885 (integer_type_node,
10888 (ffetarget_length_character1
10894 case FFEINFO_basictypeHOLLERITH:
10896 ffetargetHollerith h;
10898 h = ffebld_cu_val_hollerith (*cu);
10900 /* If not at least as wide as default INTEGER, widen it. */
10901 if (h.length >= FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE)
10902 item = build_string (h.length, h.text);
10905 char str[FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE];
10907 memcpy (str, h.text, h.length);
10908 memset (&str[h.length], ' ',
10909 FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE
10911 item = build_string (FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE,
10915 = build_type_variant (build_array_type (char_type_node,
10917 (integer_type_node,
10925 case FFEINFO_basictypeTYPELESS:
10927 ffetargetInteger1 ival;
10928 ffetargetTypeless tless;
10931 tless = ffebld_cu_val_typeless (*cu);
10932 error = ffetarget_convert_integer1_typeless (&ival, tless);
10933 assert (error == FFEBAD);
10935 item = build_int_2 ((int) ival, 0);
10940 assert ("not yet on constant type" == NULL);
10941 /* Fall through. */
10942 case FFEINFO_basictypeANY:
10943 return error_mark_node;
10946 TREE_CONSTANT (item) = 1;
10953 /* Transform expression into constant tree.
10955 If the expression can be transformed into a tree that is constant,
10956 that is done, and the tree returned. Else NULL_TREE is returned.
10958 That way, a caller can attempt to provide compile-time initialization
10959 of a variable and, if that fails, *then* choose to start a new block
10960 and resort to using temporaries, as appropriate. */
10963 ffecom_const_expr (ffebld expr)
10966 return integer_zero_node;
10968 if (ffebld_op (expr) == FFEBLD_opANY)
10969 return error_mark_node;
10971 if (ffebld_arity (expr) == 0
10972 && (ffebld_op (expr) != FFEBLD_opSYMTER
10974 /* ~~Enable once common/equivalence is handled properly? */
10975 || ffebld_where (expr) == FFEINFO_whereCOMMON
10977 || ffebld_where (expr) == FFEINFO_whereGLOBAL
10978 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
10982 t = ffecom_expr (expr);
10983 assert (TREE_CONSTANT (t));
10990 /* Handy way to make a field in a struct/union. */
10992 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10994 ffecom_decl_field (tree context, tree prevfield,
10995 const char *name, tree type)
10999 field = build_decl (FIELD_DECL, get_identifier (name), type);
11000 DECL_CONTEXT (field) = context;
11001 DECL_ALIGN (field) = 0;
11002 if (prevfield != NULL_TREE)
11003 TREE_CHAIN (prevfield) = field;
11011 ffecom_close_include (FILE *f)
11013 #if FFECOM_GCC_INCLUDE
11014 ffecom_close_include_ (f);
11019 ffecom_decode_include_option (char *spec)
11021 #if FFECOM_GCC_INCLUDE
11022 return ffecom_decode_include_option_ (spec);
11028 /* End a compound statement (block). */
11030 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11032 ffecom_end_compstmt (void)
11034 return bison_rule_compstmt_ ();
11036 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
11038 /* ffecom_end_transition -- Perform end transition on all symbols
11040 ffecom_end_transition();
11042 Calls ffecom_sym_end_transition for each global and local symbol. */
11045 ffecom_end_transition ()
11047 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11051 if (ffe_is_ffedebug ())
11052 fprintf (dmpout, "; end_stmt_transition\n");
11054 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11055 ffecom_list_blockdata_ = NULL;
11056 ffecom_list_common_ = NULL;
11059 ffesymbol_drive (ffecom_sym_end_transition);
11060 if (ffe_is_ffedebug ())
11062 ffestorag_report ();
11063 #if FFECOM_targetCURRENT == FFECOM_targetFFE
11064 ffesymbol_report_all ();
11068 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11069 ffecom_start_progunit_ ();
11071 for (item = ffecom_list_blockdata_;
11073 item = ffebld_trail (item))
11081 static int number = 0;
11083 callee = ffebld_head (item);
11084 s = ffebld_symter (callee);
11085 t = ffesymbol_hook (s).decl_tree;
11086 if (t == NULL_TREE)
11088 s = ffecom_sym_transform_ (s);
11089 t = ffesymbol_hook (s).decl_tree;
11092 yes = suspend_momentary ();
11094 dt = build_pointer_type (TREE_TYPE (t));
11096 var = build_decl (VAR_DECL,
11097 ffecom_get_invented_identifier ("__g77_forceload_%d",
11100 DECL_EXTERNAL (var) = 0;
11101 TREE_STATIC (var) = 1;
11102 TREE_PUBLIC (var) = 0;
11103 DECL_INITIAL (var) = error_mark_node;
11104 TREE_USED (var) = 1;
11106 var = start_decl (var, FALSE);
11108 t = ffecom_1 (ADDR_EXPR, dt, t);
11110 finish_decl (var, t, FALSE);
11112 resume_momentary (yes);
11115 /* This handles any COMMON areas that weren't referenced but have, for
11116 example, important initial data. */
11118 for (item = ffecom_list_common_;
11120 item = ffebld_trail (item))
11121 ffecom_transform_common_ (ffebld_symter (ffebld_head (item)));
11123 ffecom_list_common_ = NULL;
11127 /* ffecom_exec_transition -- Perform exec transition on all symbols
11129 ffecom_exec_transition();
11131 Calls ffecom_sym_exec_transition for each global and local symbol.
11132 Make sure error updating not inhibited. */
11135 ffecom_exec_transition ()
11139 if (ffe_is_ffedebug ())
11140 fprintf (dmpout, "; exec_stmt_transition\n");
11142 inhibited = ffebad_inhibit ();
11143 ffebad_set_inhibit (FALSE);
11145 ffesymbol_drive (ffecom_sym_exec_transition); /* Don't retract! */
11146 ffeequiv_exec_transition (); /* Handle all pending EQUIVALENCEs. */
11147 if (ffe_is_ffedebug ())
11149 ffestorag_report ();
11150 #if FFECOM_targetCURRENT == FFECOM_targetFFE
11151 ffesymbol_report_all ();
11156 ffebad_set_inhibit (TRUE);
11159 /* Handle assignment statement.
11161 Convert dest and source using ffecom_expr, then join them
11162 with an ASSIGN op and pass the whole thing to expand_expr_stmt. */
11164 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11166 ffecom_expand_let_stmt (ffebld dest, ffebld source)
11173 if (ffeinfo_basictype (ffebld_info (dest)) != FFEINFO_basictypeCHARACTER)
11178 /* This attempts to replicate the test below, but must not be
11179 true when the test below is false. (Always err on the side
11180 of creating unused temporaries, to avoid ICEs.) */
11181 if (ffebld_op (dest) != FFEBLD_opSYMTER
11182 || ((dest_tree = ffesymbol_hook (ffebld_symter (dest)).decl_tree)
11183 && (TREE_CODE (dest_tree) != VAR_DECL
11184 || TREE_ADDRESSABLE (dest_tree))))
11186 ffecom_prepare_expr_ (source, dest);
11191 ffecom_prepare_expr_ (source, NULL);
11195 ffecom_prepare_expr_w (NULL_TREE, dest);
11197 /* For COMPLEX assignment like C1=C2, if partial overlap is possible,
11198 create a temporary through which the assignment is to take place,
11199 since MODIFY_EXPR doesn't handle partial overlap properly. */
11200 if (ffebld_basictype (dest) == FFEINFO_basictypeCOMPLEX
11201 && ffecom_possible_partial_overlap_ (dest, source))
11203 assign_temp = ffecom_make_tempvar ("complex_let",
11205 [ffebld_basictype (dest)]
11206 [ffebld_kindtype (dest)],
11207 FFETARGET_charactersizeNONE,
11211 assign_temp = NULL_TREE;
11213 ffecom_prepare_end ();
11215 dest_tree = ffecom_expr_w (NULL_TREE, dest);
11216 if (dest_tree == error_mark_node)
11219 if ((TREE_CODE (dest_tree) != VAR_DECL)
11220 || TREE_ADDRESSABLE (dest_tree))
11221 source_tree = ffecom_expr_ (source, dest_tree, dest, &dest_used,
11225 assert (! dest_used);
11227 source_tree = ffecom_expr (source);
11229 if (source_tree == error_mark_node)
11233 expr_tree = source_tree;
11234 else if (assign_temp)
11237 /* The back end understands a conceptual move (evaluate source;
11238 store into dest), so use that, in case it can determine
11239 that it is going to use, say, two registers as temporaries
11240 anyway. So don't use the temp (and someday avoid generating
11241 it, once this code starts triggering regularly). */
11242 expr_tree = ffecom_2s (MOVE_EXPR, void_type_node,
11246 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11249 expand_expr_stmt (expr_tree);
11250 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11256 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11260 expand_expr_stmt (expr_tree);
11264 ffecom_prepare_let_char_ (ffebld_size_known (dest), source);
11265 ffecom_prepare_expr_w (NULL_TREE, dest);
11267 ffecom_prepare_end ();
11269 ffecom_char_args_ (&dest_tree, &dest_length, dest);
11270 ffecom_let_char_ (dest_tree, dest_length, ffebld_size_known (dest),
11275 /* ffecom_expr -- Transform expr into gcc tree
11278 ffebld expr; // FFE expression.
11279 tree = ffecom_expr(expr);
11281 Recursive descent on expr while making corresponding tree nodes and
11282 attaching type info and such. */
11284 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11286 ffecom_expr (ffebld expr)
11288 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, FALSE, FALSE);
11292 /* Like ffecom_expr, but return tree usable for assigned GOTO or FORMAT. */
11294 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11296 ffecom_expr_assign (ffebld expr)
11298 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE);
11302 /* Like ffecom_expr_rw, but return tree usable for ASSIGN. */
11304 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11306 ffecom_expr_assign_w (ffebld expr)
11308 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE);
11312 /* Transform expr for use as into read/write tree and stabilize the
11313 reference. Not for use on CHARACTER expressions.
11315 Recursive descent on expr while making corresponding tree nodes and
11316 attaching type info and such. */
11318 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11320 ffecom_expr_rw (tree type, ffebld expr)
11322 assert (expr != NULL);
11323 /* Different target types not yet supported. */
11324 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
11326 return stabilize_reference (ffecom_expr (expr));
11330 /* Transform expr for use as into write tree and stabilize the
11331 reference. Not for use on CHARACTER expressions.
11333 Recursive descent on expr while making corresponding tree nodes and
11334 attaching type info and such. */
11336 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11338 ffecom_expr_w (tree type, ffebld expr)
11340 assert (expr != NULL);
11341 /* Different target types not yet supported. */
11342 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
11344 return stabilize_reference (ffecom_expr (expr));
11348 /* Do global stuff. */
11350 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11352 ffecom_finish_compile ()
11354 assert (ffecom_outer_function_decl_ == NULL_TREE);
11355 assert (current_function_decl == NULL_TREE);
11357 ffeglobal_drive (ffecom_finish_global_);
11361 /* Public entry point for front end to access finish_decl. */
11363 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11365 ffecom_finish_decl (tree decl, tree init, bool is_top_level)
11367 assert (!is_top_level);
11368 finish_decl (decl, init, FALSE);
11372 /* Finish a program unit. */
11374 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11376 ffecom_finish_progunit ()
11378 ffecom_end_compstmt ();
11380 ffecom_previous_function_decl_ = current_function_decl;
11381 ffecom_which_entrypoint_decl_ = NULL_TREE;
11383 finish_function (0);
11388 /* Wrapper for get_identifier. pattern is sprintf-like. */
11390 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11392 ffecom_get_invented_identifier (const char *pattern, ...)
11398 va_start (ap, pattern);
11399 if (vasprintf (&nam, pattern, ap) == 0)
11402 decl = get_identifier (nam);
11404 IDENTIFIER_INVENTED (decl) = 1;
11409 ffecom_gfrt_basictype (ffecomGfrt gfrt)
11411 assert (gfrt < FFECOM_gfrt);
11413 switch (ffecom_gfrt_type_[gfrt])
11415 case FFECOM_rttypeVOID_:
11416 case FFECOM_rttypeVOIDSTAR_:
11417 return FFEINFO_basictypeNONE;
11419 case FFECOM_rttypeFTNINT_:
11420 return FFEINFO_basictypeINTEGER;
11422 case FFECOM_rttypeINTEGER_:
11423 return FFEINFO_basictypeINTEGER;
11425 case FFECOM_rttypeLONGINT_:
11426 return FFEINFO_basictypeINTEGER;
11428 case FFECOM_rttypeLOGICAL_:
11429 return FFEINFO_basictypeLOGICAL;
11431 case FFECOM_rttypeREAL_F2C_:
11432 case FFECOM_rttypeREAL_GNU_:
11433 return FFEINFO_basictypeREAL;
11435 case FFECOM_rttypeCOMPLEX_F2C_:
11436 case FFECOM_rttypeCOMPLEX_GNU_:
11437 return FFEINFO_basictypeCOMPLEX;
11439 case FFECOM_rttypeDOUBLE_:
11440 case FFECOM_rttypeDOUBLEREAL_:
11441 return FFEINFO_basictypeREAL;
11443 case FFECOM_rttypeDBLCMPLX_F2C_:
11444 case FFECOM_rttypeDBLCMPLX_GNU_:
11445 return FFEINFO_basictypeCOMPLEX;
11447 case FFECOM_rttypeCHARACTER_:
11448 return FFEINFO_basictypeCHARACTER;
11451 return FFEINFO_basictypeANY;
11456 ffecom_gfrt_kindtype (ffecomGfrt gfrt)
11458 assert (gfrt < FFECOM_gfrt);
11460 switch (ffecom_gfrt_type_[gfrt])
11462 case FFECOM_rttypeVOID_:
11463 case FFECOM_rttypeVOIDSTAR_:
11464 return FFEINFO_kindtypeNONE;
11466 case FFECOM_rttypeFTNINT_:
11467 return FFEINFO_kindtypeINTEGER1;
11469 case FFECOM_rttypeINTEGER_:
11470 return FFEINFO_kindtypeINTEGER1;
11472 case FFECOM_rttypeLONGINT_:
11473 return FFEINFO_kindtypeINTEGER4;
11475 case FFECOM_rttypeLOGICAL_:
11476 return FFEINFO_kindtypeLOGICAL1;
11478 case FFECOM_rttypeREAL_F2C_:
11479 case FFECOM_rttypeREAL_GNU_:
11480 return FFEINFO_kindtypeREAL1;
11482 case FFECOM_rttypeCOMPLEX_F2C_:
11483 case FFECOM_rttypeCOMPLEX_GNU_:
11484 return FFEINFO_kindtypeREAL1;
11486 case FFECOM_rttypeDOUBLE_:
11487 case FFECOM_rttypeDOUBLEREAL_:
11488 return FFEINFO_kindtypeREAL2;
11490 case FFECOM_rttypeDBLCMPLX_F2C_:
11491 case FFECOM_rttypeDBLCMPLX_GNU_:
11492 return FFEINFO_kindtypeREAL2;
11494 case FFECOM_rttypeCHARACTER_:
11495 return FFEINFO_kindtypeCHARACTER1;
11498 return FFEINFO_kindtypeANY;
11512 tree double_ftype_double;
11513 tree float_ftype_float;
11514 tree ldouble_ftype_ldouble;
11515 tree ffecom_tree_ptr_to_fun_type_void;
11517 /* This block of code comes from the now-obsolete cktyps.c. It checks
11518 whether the compiler environment is buggy in known ways, some of which
11519 would, if not explicitly checked here, result in subtle bugs in g77. */
11521 if (ffe_is_do_internal_checks ())
11523 static char names[][12]
11525 {"bar", "bletch", "foo", "foobar"};
11530 name = bsearch ("foo", &names[0], ARRAY_SIZE (names), sizeof (names[0]),
11531 (int (*)(const void *, const void *)) strcmp);
11532 if (name != (char *) &names[2])
11534 assert ("bsearch doesn't work, #define FFEPROJ_BSEARCH 0 in proj.h"
11539 ul = strtoul ("123456789", NULL, 10);
11540 if (ul != 123456789L)
11542 assert ("strtoul doesn't have enough range, #define FFEPROJ_STRTOUL 0\
11543 in proj.h" == NULL);
11547 fl = atof ("56.789");
11548 if ((fl < 56.788) || (fl > 56.79))
11550 assert ("atof not type double, fix your #include <stdio.h>"
11556 #if FFECOM_GCC_INCLUDE
11557 ffecom_initialize_char_syntax_ ();
11560 ffecom_outer_function_decl_ = NULL_TREE;
11561 current_function_decl = NULL_TREE;
11562 named_labels = NULL_TREE;
11563 current_binding_level = NULL_BINDING_LEVEL;
11564 free_binding_level = NULL_BINDING_LEVEL;
11565 /* Make the binding_level structure for global names. */
11567 global_binding_level = current_binding_level;
11568 current_binding_level->prep_state = 2;
11570 build_common_tree_nodes (1);
11572 /* Define `int' and `char' first so that dbx will output them first. */
11573 pushdecl (build_decl (TYPE_DECL, get_identifier ("int"),
11574 integer_type_node));
11575 pushdecl (build_decl (TYPE_DECL, get_identifier ("char"),
11577 pushdecl (build_decl (TYPE_DECL, get_identifier ("long int"),
11578 long_integer_type_node));
11579 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned int"),
11580 unsigned_type_node));
11581 pushdecl (build_decl (TYPE_DECL, get_identifier ("long unsigned int"),
11582 long_unsigned_type_node));
11583 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long int"),
11584 long_long_integer_type_node));
11585 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long unsigned int"),
11586 long_long_unsigned_type_node));
11587 pushdecl (build_decl (TYPE_DECL, get_identifier ("short int"),
11588 short_integer_type_node));
11589 pushdecl (build_decl (TYPE_DECL, get_identifier ("short unsigned int"),
11590 short_unsigned_type_node));
11592 /* Set the sizetype before we make other types. This *should* be the
11593 first type we create. */
11596 (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE))));
11597 ffecom_typesize_pointer_
11598 = TREE_INT_CST_LOW (TYPE_SIZE (sizetype)) / BITS_PER_UNIT;
11600 build_common_tree_nodes_2 (0);
11602 /* Define both `signed char' and `unsigned char'. */
11603 pushdecl (build_decl (TYPE_DECL, get_identifier ("signed char"),
11604 signed_char_type_node));
11606 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned char"),
11607 unsigned_char_type_node));
11609 pushdecl (build_decl (TYPE_DECL, get_identifier ("float"),
11611 pushdecl (build_decl (TYPE_DECL, get_identifier ("double"),
11612 double_type_node));
11613 pushdecl (build_decl (TYPE_DECL, get_identifier ("long double"),
11614 long_double_type_node));
11616 /* For now, override what build_common_tree_nodes has done. */
11617 complex_integer_type_node = ffecom_make_complex_type_ (integer_type_node);
11618 complex_float_type_node = ffecom_make_complex_type_ (float_type_node);
11619 complex_double_type_node = ffecom_make_complex_type_ (double_type_node);
11620 complex_long_double_type_node
11621 = ffecom_make_complex_type_ (long_double_type_node);
11623 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex int"),
11624 complex_integer_type_node));
11625 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex float"),
11626 complex_float_type_node));
11627 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex double"),
11628 complex_double_type_node));
11629 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex long double"),
11630 complex_long_double_type_node));
11632 pushdecl (build_decl (TYPE_DECL, get_identifier ("void"),
11634 /* We are not going to have real types in C with less than byte alignment,
11635 so we might as well not have any types that claim to have it. */
11636 TYPE_ALIGN (void_type_node) = BITS_PER_UNIT;
11638 string_type_node = build_pointer_type (char_type_node);
11640 ffecom_tree_fun_type_void
11641 = build_function_type (void_type_node, NULL_TREE);
11643 ffecom_tree_ptr_to_fun_type_void
11644 = build_pointer_type (ffecom_tree_fun_type_void);
11646 endlink = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
11649 = build_function_type (float_type_node,
11650 tree_cons (NULL_TREE, float_type_node, endlink));
11652 double_ftype_double
11653 = build_function_type (double_type_node,
11654 tree_cons (NULL_TREE, double_type_node, endlink));
11656 ldouble_ftype_ldouble
11657 = build_function_type (long_double_type_node,
11658 tree_cons (NULL_TREE, long_double_type_node,
11661 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11662 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11664 ffecom_tree_type[i][j] = NULL_TREE;
11665 ffecom_tree_fun_type[i][j] = NULL_TREE;
11666 ffecom_tree_ptr_to_fun_type[i][j] = NULL_TREE;
11667 ffecom_f2c_typecode_[i][j] = -1;
11670 /* Set up standard g77 types. Note that INTEGER and LOGICAL are set
11671 to size FLOAT_TYPE_SIZE because they have to be the same size as
11672 REAL, which also is FLOAT_TYPE_SIZE, according to the standard.
11673 Compiler options and other such stuff that change the ways these
11674 types are set should not affect this particular setup. */
11676 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1]
11677 = t = make_signed_type (FLOAT_TYPE_SIZE);
11678 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer"),
11680 type = ffetype_new ();
11682 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER1,
11684 ffetype_set_ams (type,
11685 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11686 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11687 ffetype_set_star (base_type,
11688 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11690 ffetype_set_kind (base_type, 1, type);
11691 ffecom_typesize_integer1_ = ffetype_size (type);
11692 assert (ffetype_size (type) == sizeof (ffetargetInteger1));
11694 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER1]
11695 = t = make_unsigned_type (FLOAT_TYPE_SIZE); /* HOLLERITH means unsigned. */
11696 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned"),
11699 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER2]
11700 = t = make_signed_type (CHAR_TYPE_SIZE);
11701 pushdecl (build_decl (TYPE_DECL, get_identifier ("byte"),
11703 type = ffetype_new ();
11704 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER2,
11706 ffetype_set_ams (type,
11707 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11708 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11709 ffetype_set_star (base_type,
11710 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11712 ffetype_set_kind (base_type, 3, type);
11713 assert (ffetype_size (type) == sizeof (ffetargetInteger2));
11715 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER2]
11716 = t = make_unsigned_type (CHAR_TYPE_SIZE);
11717 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned byte"),
11720 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER3]
11721 = t = make_signed_type (CHAR_TYPE_SIZE * 2);
11722 pushdecl (build_decl (TYPE_DECL, get_identifier ("word"),
11724 type = ffetype_new ();
11725 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER3,
11727 ffetype_set_ams (type,
11728 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11729 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11730 ffetype_set_star (base_type,
11731 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11733 ffetype_set_kind (base_type, 6, type);
11734 assert (ffetype_size (type) == sizeof (ffetargetInteger3));
11736 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER3]
11737 = t = make_unsigned_type (CHAR_TYPE_SIZE * 2);
11738 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned word"),
11741 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER4]
11742 = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
11743 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer4"),
11745 type = ffetype_new ();
11746 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER4,
11748 ffetype_set_ams (type,
11749 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11750 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11751 ffetype_set_star (base_type,
11752 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11754 ffetype_set_kind (base_type, 2, type);
11755 assert (ffetype_size (type) == sizeof (ffetargetInteger4));
11757 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER4]
11758 = t = make_unsigned_type (FLOAT_TYPE_SIZE * 2);
11759 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned4"),
11763 if (ffe_is_do_internal_checks ()
11764 && LONG_TYPE_SIZE != FLOAT_TYPE_SIZE
11765 && LONG_TYPE_SIZE != CHAR_TYPE_SIZE
11766 && LONG_TYPE_SIZE != SHORT_TYPE_SIZE
11767 && LONG_TYPE_SIZE != LONG_LONG_TYPE_SIZE)
11769 fprintf (stderr, "Sorry, no g77 support for LONG_TYPE_SIZE (%d bits) yet.\n",
11774 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL1]
11775 = t = make_signed_type (FLOAT_TYPE_SIZE);
11776 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical"),
11778 type = ffetype_new ();
11780 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL1,
11782 ffetype_set_ams (type,
11783 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11784 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11785 ffetype_set_star (base_type,
11786 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11788 ffetype_set_kind (base_type, 1, type);
11789 assert (ffetype_size (type) == sizeof (ffetargetLogical1));
11791 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL2]
11792 = t = make_signed_type (CHAR_TYPE_SIZE);
11793 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical2"),
11795 type = ffetype_new ();
11796 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL2,
11798 ffetype_set_ams (type,
11799 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11800 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11801 ffetype_set_star (base_type,
11802 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11804 ffetype_set_kind (base_type, 3, type);
11805 assert (ffetype_size (type) == sizeof (ffetargetLogical2));
11807 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL3]
11808 = t = make_signed_type (CHAR_TYPE_SIZE * 2);
11809 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical3"),
11811 type = ffetype_new ();
11812 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL3,
11814 ffetype_set_ams (type,
11815 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11816 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11817 ffetype_set_star (base_type,
11818 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11820 ffetype_set_kind (base_type, 6, type);
11821 assert (ffetype_size (type) == sizeof (ffetargetLogical3));
11823 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL4]
11824 = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
11825 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical4"),
11827 type = ffetype_new ();
11828 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL4,
11830 ffetype_set_ams (type,
11831 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11832 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11833 ffetype_set_star (base_type,
11834 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11836 ffetype_set_kind (base_type, 2, type);
11837 assert (ffetype_size (type) == sizeof (ffetargetLogical4));
11839 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
11840 = t = make_node (REAL_TYPE);
11841 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE;
11842 pushdecl (build_decl (TYPE_DECL, get_identifier ("real"),
11845 type = ffetype_new ();
11847 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREAL1,
11849 ffetype_set_ams (type,
11850 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11851 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11852 ffetype_set_star (base_type,
11853 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11855 ffetype_set_kind (base_type, 1, type);
11856 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
11857 = FFETARGET_f2cTYREAL;
11858 assert (ffetype_size (type) == sizeof (ffetargetReal1));
11860 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREALDOUBLE]
11861 = t = make_node (REAL_TYPE);
11862 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE * 2; /* Always twice REAL. */
11863 pushdecl (build_decl (TYPE_DECL, get_identifier ("double precision"),
11866 type = ffetype_new ();
11867 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREALDOUBLE,
11869 ffetype_set_ams (type,
11870 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11871 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11872 ffetype_set_star (base_type,
11873 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11875 ffetype_set_kind (base_type, 2, type);
11876 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]
11877 = FFETARGET_f2cTYDREAL;
11878 assert (ffetype_size (type) == sizeof (ffetargetReal2));
11880 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
11881 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]);
11882 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex"),
11884 type = ffetype_new ();
11886 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREAL1,
11888 ffetype_set_ams (type,
11889 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11890 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11891 ffetype_set_star (base_type,
11892 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11894 ffetype_set_kind (base_type, 1, type);
11895 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
11896 = FFETARGET_f2cTYCOMPLEX;
11897 assert (ffetype_size (type) == sizeof (ffetargetComplex1));
11899 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREALDOUBLE]
11900 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]);
11901 pushdecl (build_decl (TYPE_DECL, get_identifier ("double complex"),
11903 type = ffetype_new ();
11904 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREALDOUBLE,
11906 ffetype_set_ams (type,
11907 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11908 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11909 ffetype_set_star (base_type,
11910 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11912 ffetype_set_kind (base_type, 2,
11914 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL2]
11915 = FFETARGET_f2cTYDCOMPLEX;
11916 assert (ffetype_size (type) == sizeof (ffetargetComplex2));
11918 /* Make function and ptr-to-function types for non-CHARACTER types. */
11920 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11921 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11923 if ((t = ffecom_tree_type[i][j]) != NULL_TREE)
11925 if (i == FFEINFO_basictypeINTEGER)
11927 /* Figure out the smallest INTEGER type that can hold
11928 a pointer on this machine. */
11929 if (GET_MODE_SIZE (TYPE_MODE (t))
11930 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
11932 if ((ffecom_pointer_kind_ == FFEINFO_kindtypeNONE)
11933 || (GET_MODE_SIZE (TYPE_MODE (ffecom_tree_type[i][ffecom_pointer_kind_]))
11934 > GET_MODE_SIZE (TYPE_MODE (t))))
11935 ffecom_pointer_kind_ = j;
11938 else if (i == FFEINFO_basictypeCOMPLEX)
11939 t = void_type_node;
11940 /* For f2c compatibility, REAL functions are really
11941 implemented as DOUBLE PRECISION. */
11942 else if ((i == FFEINFO_basictypeREAL)
11943 && (j == FFEINFO_kindtypeREAL1))
11944 t = ffecom_tree_type
11945 [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2];
11947 t = ffecom_tree_fun_type[i][j] = build_function_type (t,
11949 ffecom_tree_ptr_to_fun_type[i][j] = build_pointer_type (t);
11953 /* Set up pointer types. */
11955 if (ffecom_pointer_kind_ == FFEINFO_basictypeNONE)
11956 fatal ("no INTEGER type can hold a pointer on this configuration");
11957 else if (0 && ffe_is_do_internal_checks ())
11958 fprintf (stderr, "Pointer type kt=%d\n", ffecom_pointer_kind_);
11959 ffetype_set_kind (ffeinfo_type (FFEINFO_basictypeINTEGER,
11960 FFEINFO_kindtypeINTEGERDEFAULT),
11962 ffeinfo_type (FFEINFO_basictypeINTEGER,
11963 ffecom_pointer_kind_));
11965 if (ffe_is_ugly_assign ())
11966 ffecom_label_kind_ = ffecom_pointer_kind_; /* Require ASSIGN etc to this. */
11968 ffecom_label_kind_ = FFEINFO_kindtypeINTEGERDEFAULT;
11969 if (0 && ffe_is_do_internal_checks ())
11970 fprintf (stderr, "Label type kt=%d\n", ffecom_label_kind_);
11972 ffecom_integer_type_node
11973 = ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1];
11974 ffecom_integer_zero_node = convert (ffecom_integer_type_node,
11975 integer_zero_node);
11976 ffecom_integer_one_node = convert (ffecom_integer_type_node,
11979 /* Yes, the "FLOAT_TYPE_SIZE" references below are intentional.
11980 Turns out that by TYLONG, runtime/libI77/lio.h really means
11981 "whatever size an ftnint is". For consistency and sanity,
11982 com.h and runtime/f2c.h.in agree that flag, ftnint, and ftlen
11983 all are INTEGER, which we also make out of whatever back-end
11984 integer type is FLOAT_TYPE_SIZE bits wide. This change, from
11985 LONG_TYPE_SIZE, for TYLONG and TYLOGICAL, was necessary to
11986 accommodate machines like the Alpha. Note that this suggests
11987 f2c and libf2c are missing a distinction perhaps needed on
11988 some machines between "int" and "long int". -- burley 0.5.5 950215 */
11990 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, FLOAT_TYPE_SIZE,
11991 FFETARGET_f2cTYLONG);
11992 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, SHORT_TYPE_SIZE,
11993 FFETARGET_f2cTYSHORT);
11994 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, CHAR_TYPE_SIZE,
11995 FFETARGET_f2cTYINT1);
11996 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, LONG_LONG_TYPE_SIZE,
11997 FFETARGET_f2cTYQUAD);
11998 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, FLOAT_TYPE_SIZE,
11999 FFETARGET_f2cTYLOGICAL);
12000 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, SHORT_TYPE_SIZE,
12001 FFETARGET_f2cTYLOGICAL2);
12002 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, CHAR_TYPE_SIZE,
12003 FFETARGET_f2cTYLOGICAL1);
12004 /* ~~~Not really such a type in libf2c, e.g. I/O support? */
12005 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, LONG_LONG_TYPE_SIZE,
12006 FFETARGET_f2cTYQUAD);
12008 /* CHARACTER stuff is all special-cased, so it is not handled in the above
12009 loop. CHARACTER items are built as arrays of unsigned char. */
12011 ffecom_tree_type[FFEINFO_basictypeCHARACTER]
12012 [FFEINFO_kindtypeCHARACTER1] = t = char_type_node;
12013 type = ffetype_new ();
12015 ffeinfo_set_type (FFEINFO_basictypeCHARACTER,
12016 FFEINFO_kindtypeCHARACTER1,
12018 ffetype_set_ams (type,
12019 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12020 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12021 ffetype_set_kind (base_type, 1, type);
12022 assert (ffetype_size (type)
12023 == sizeof (((ffetargetCharacter1) { 0, NULL }).text[0]));
12025 ffecom_tree_fun_type[FFEINFO_basictypeCHARACTER]
12026 [FFEINFO_kindtypeCHARACTER1] = ffecom_tree_fun_type_void;
12027 ffecom_tree_ptr_to_fun_type[FFEINFO_basictypeCHARACTER]
12028 [FFEINFO_kindtypeCHARACTER1]
12029 = ffecom_tree_ptr_to_fun_type_void;
12030 ffecom_f2c_typecode_[FFEINFO_basictypeCHARACTER][FFEINFO_kindtypeCHARACTER1]
12031 = FFETARGET_f2cTYCHAR;
12033 ffecom_f2c_typecode_[FFEINFO_basictypeANY][FFEINFO_kindtypeANY]
12036 /* Make multi-return-value type and fields. */
12038 ffecom_multi_type_node_ = make_node (UNION_TYPE);
12042 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
12043 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
12047 if (ffecom_tree_type[i][j] == NULL_TREE)
12048 continue; /* Not supported. */
12049 sprintf (&name[0], "bt_%s_kt_%s",
12050 ffeinfo_basictype_string ((ffeinfoBasictype) i),
12051 ffeinfo_kindtype_string ((ffeinfoKindtype) j));
12052 ffecom_multi_fields_[i][j] = build_decl (FIELD_DECL,
12053 get_identifier (name),
12054 ffecom_tree_type[i][j]);
12055 DECL_CONTEXT (ffecom_multi_fields_[i][j])
12056 = ffecom_multi_type_node_;
12057 DECL_ALIGN (ffecom_multi_fields_[i][j]) = 0;
12058 TREE_CHAIN (ffecom_multi_fields_[i][j]) = field;
12059 field = ffecom_multi_fields_[i][j];
12062 TYPE_FIELDS (ffecom_multi_type_node_) = field;
12063 layout_type (ffecom_multi_type_node_);
12065 /* Subroutines usually return integer because they might have alternate
12068 ffecom_tree_subr_type
12069 = build_function_type (integer_type_node, NULL_TREE);
12070 ffecom_tree_ptr_to_subr_type
12071 = build_pointer_type (ffecom_tree_subr_type);
12072 ffecom_tree_blockdata_type
12073 = build_function_type (void_type_node, NULL_TREE);
12075 builtin_function ("__builtin_sqrtf", float_ftype_float,
12076 BUILT_IN_FSQRT, BUILT_IN_NORMAL, "sqrtf");
12077 builtin_function ("__builtin_fsqrt", double_ftype_double,
12078 BUILT_IN_FSQRT, BUILT_IN_NORMAL, "sqrt");
12079 builtin_function ("__builtin_sqrtl", ldouble_ftype_ldouble,
12080 BUILT_IN_FSQRT, BUILT_IN_NORMAL, "sqrtl");
12081 builtin_function ("__builtin_sinf", float_ftype_float,
12082 BUILT_IN_SIN, BUILT_IN_NORMAL, "sinf");
12083 builtin_function ("__builtin_sin", double_ftype_double,
12084 BUILT_IN_SIN, BUILT_IN_NORMAL, "sin");
12085 builtin_function ("__builtin_sinl", ldouble_ftype_ldouble,
12086 BUILT_IN_SIN, BUILT_IN_NORMAL, "sinl");
12087 builtin_function ("__builtin_cosf", float_ftype_float,
12088 BUILT_IN_COS, BUILT_IN_NORMAL, "cosf");
12089 builtin_function ("__builtin_cos", double_ftype_double,
12090 BUILT_IN_COS, BUILT_IN_NORMAL, "cos");
12091 builtin_function ("__builtin_cosl", ldouble_ftype_ldouble,
12092 BUILT_IN_COS, BUILT_IN_NORMAL, "cosl");
12095 pedantic_lvalues = FALSE;
12098 ffecom_f2c_make_type_ (&ffecom_f2c_integer_type_node,
12101 ffecom_f2c_make_type_ (&ffecom_f2c_address_type_node,
12104 ffecom_f2c_make_type_ (&ffecom_f2c_real_type_node,
12107 ffecom_f2c_make_type_ (&ffecom_f2c_doublereal_type_node,
12108 FFECOM_f2cDOUBLEREAL,
12110 ffecom_f2c_make_type_ (&ffecom_f2c_complex_type_node,
12113 ffecom_f2c_make_type_ (&ffecom_f2c_doublecomplex_type_node,
12114 FFECOM_f2cDOUBLECOMPLEX,
12116 ffecom_f2c_make_type_ (&ffecom_f2c_longint_type_node,
12119 ffecom_f2c_make_type_ (&ffecom_f2c_logical_type_node,
12122 ffecom_f2c_make_type_ (&ffecom_f2c_flag_type_node,
12125 ffecom_f2c_make_type_ (&ffecom_f2c_ftnlen_type_node,
12128 ffecom_f2c_make_type_ (&ffecom_f2c_ftnint_type_node,
12132 ffecom_f2c_ftnlen_zero_node
12133 = convert (ffecom_f2c_ftnlen_type_node, integer_zero_node);
12135 ffecom_f2c_ftnlen_one_node
12136 = convert (ffecom_f2c_ftnlen_type_node, integer_one_node);
12138 ffecom_f2c_ftnlen_two_node = build_int_2 (2, 0);
12139 TREE_TYPE (ffecom_f2c_ftnlen_two_node) = ffecom_integer_type_node;
12141 ffecom_f2c_ptr_to_ftnlen_type_node
12142 = build_pointer_type (ffecom_f2c_ftnlen_type_node);
12144 ffecom_f2c_ptr_to_ftnint_type_node
12145 = build_pointer_type (ffecom_f2c_ftnint_type_node);
12147 ffecom_f2c_ptr_to_integer_type_node
12148 = build_pointer_type (ffecom_f2c_integer_type_node);
12150 ffecom_f2c_ptr_to_real_type_node
12151 = build_pointer_type (ffecom_f2c_real_type_node);
12153 ffecom_float_zero_ = build_real (float_type_node, dconst0);
12154 ffecom_double_zero_ = build_real (double_type_node, dconst0);
12156 REAL_VALUE_TYPE point_5;
12158 #ifdef REAL_ARITHMETIC
12159 REAL_ARITHMETIC (point_5, RDIV_EXPR, dconst1, dconst2);
12163 ffecom_float_half_ = build_real (float_type_node, point_5);
12164 ffecom_double_half_ = build_real (double_type_node, point_5);
12167 /* Do "extern int xargc;". */
12169 ffecom_tree_xargc_ = build_decl (VAR_DECL,
12170 get_identifier ("f__xargc"),
12171 integer_type_node);
12172 DECL_EXTERNAL (ffecom_tree_xargc_) = 1;
12173 TREE_STATIC (ffecom_tree_xargc_) = 1;
12174 TREE_PUBLIC (ffecom_tree_xargc_) = 1;
12175 ffecom_tree_xargc_ = start_decl (ffecom_tree_xargc_, FALSE);
12176 finish_decl (ffecom_tree_xargc_, NULL_TREE, FALSE);
12178 #if 0 /* This is being fixed, and seems to be working now. */
12179 if ((FLOAT_TYPE_SIZE != 32)
12180 || (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))) != 32))
12182 warning ("configuration: REAL, INTEGER, and LOGICAL are %d bits wide,",
12183 (int) FLOAT_TYPE_SIZE);
12184 warning ("and pointers are %d bits wide, but g77 doesn't yet work",
12185 (int) TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))));
12186 warning ("properly unless they all are 32 bits wide.");
12187 warning ("Please keep this in mind before you report bugs. g77 should");
12188 warning ("support non-32-bit machines better as of version 0.6.");
12192 #if 0 /* Code in ste.c that would crash has been commented out. */
12193 if (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)
12194 < TYPE_PRECISION (string_type_node))
12195 /* I/O will probably crash. */
12196 warning ("configuration: char * holds %d bits, but ftnlen only %d",
12197 TYPE_PRECISION (string_type_node),
12198 TYPE_PRECISION (ffecom_f2c_ftnlen_type_node));
12201 #if 0 /* ASSIGN-related stuff has been changed to accommodate this. */
12202 if (TYPE_PRECISION (ffecom_integer_type_node)
12203 < TYPE_PRECISION (string_type_node))
12204 /* ASSIGN 10 TO I will crash. */
12205 warning ("configuration: char * holds %d bits, but INTEGER only %d --\n\
12206 ASSIGN statement might fail",
12207 TYPE_PRECISION (string_type_node),
12208 TYPE_PRECISION (ffecom_integer_type_node));
12213 /* ffecom_init_2 -- Initialize
12215 ffecom_init_2(); */
12217 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12221 assert (ffecom_outer_function_decl_ == NULL_TREE);
12222 assert (current_function_decl == NULL_TREE);
12223 assert (ffecom_which_entrypoint_decl_ == NULL_TREE);
12225 ffecom_master_arglist_ = NULL;
12227 ffecom_primary_entry_ = NULL;
12228 ffecom_is_altreturning_ = FALSE;
12229 ffecom_func_result_ = NULL_TREE;
12230 ffecom_multi_retval_ = NULL_TREE;
12234 /* ffecom_list_expr -- Transform list of exprs into gcc tree
12237 ffebld expr; // FFE opITEM list.
12238 tree = ffecom_list_expr(expr);
12240 List of actual args is transformed into corresponding gcc backend list. */
12242 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12244 ffecom_list_expr (ffebld expr)
12247 tree *plist = &list;
12248 tree trail = NULL_TREE; /* Append char length args here. */
12249 tree *ptrail = &trail;
12252 while (expr != NULL)
12254 tree texpr = ffecom_arg_expr (ffebld_head (expr), &length);
12256 if (texpr == error_mark_node)
12257 return error_mark_node;
12259 *plist = build_tree_list (NULL_TREE, texpr);
12260 plist = &TREE_CHAIN (*plist);
12261 expr = ffebld_trail (expr);
12262 if (length != NULL_TREE)
12264 *ptrail = build_tree_list (NULL_TREE, length);
12265 ptrail = &TREE_CHAIN (*ptrail);
12275 /* ffecom_list_ptr_to_expr -- Transform list of exprs into gcc tree
12278 ffebld expr; // FFE opITEM list.
12279 tree = ffecom_list_ptr_to_expr(expr);
12281 List of actual args is transformed into corresponding gcc backend list for
12282 use in calling an external procedure (vs. a statement function). */
12284 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12286 ffecom_list_ptr_to_expr (ffebld expr)
12289 tree *plist = &list;
12290 tree trail = NULL_TREE; /* Append char length args here. */
12291 tree *ptrail = &trail;
12294 while (expr != NULL)
12296 tree texpr = ffecom_arg_ptr_to_expr (ffebld_head (expr), &length);
12298 if (texpr == error_mark_node)
12299 return error_mark_node;
12301 *plist = build_tree_list (NULL_TREE, texpr);
12302 plist = &TREE_CHAIN (*plist);
12303 expr = ffebld_trail (expr);
12304 if (length != NULL_TREE)
12306 *ptrail = build_tree_list (NULL_TREE, length);
12307 ptrail = &TREE_CHAIN (*ptrail);
12317 /* Obtain gcc's LABEL_DECL tree for label. */
12319 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12321 ffecom_lookup_label (ffelab label)
12325 if (ffelab_hook (label) == NULL_TREE)
12327 char labelname[16];
12329 switch (ffelab_type (label))
12331 case FFELAB_typeLOOPEND:
12332 case FFELAB_typeNOTLOOP:
12333 case FFELAB_typeENDIF:
12334 sprintf (labelname, "%" ffelabValue_f "u", ffelab_value (label));
12335 glabel = build_decl (LABEL_DECL, get_identifier (labelname),
12337 DECL_CONTEXT (glabel) = current_function_decl;
12338 DECL_MODE (glabel) = VOIDmode;
12341 case FFELAB_typeFORMAT:
12342 glabel = build_decl (VAR_DECL,
12343 ffecom_get_invented_identifier
12344 ("__g77_format_%d", (int) ffelab_value (label)),
12345 build_type_variant (build_array_type
12349 TREE_CONSTANT (glabel) = 1;
12350 TREE_STATIC (glabel) = 1;
12351 DECL_CONTEXT (glabel) = 0;
12352 DECL_INITIAL (glabel) = NULL;
12353 make_decl_rtl (glabel, NULL, 0);
12354 expand_decl (glabel);
12356 ffecom_save_tree_forever (glabel);
12360 case FFELAB_typeANY:
12361 glabel = error_mark_node;
12365 assert ("bad label type" == NULL);
12369 ffelab_set_hook (label, glabel);
12373 glabel = ffelab_hook (label);
12380 /* Stabilizes the arguments. Don't use this if the lhs and rhs come from
12381 a single source specification (as in the fourth argument of MVBITS).
12382 If the type is NULL_TREE, the type of lhs is used to make the type of
12383 the MODIFY_EXPR. */
12385 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12387 ffecom_modify (tree newtype, tree lhs,
12390 if (lhs == error_mark_node || rhs == error_mark_node)
12391 return error_mark_node;
12393 if (newtype == NULL_TREE)
12394 newtype = TREE_TYPE (lhs);
12396 if (TREE_SIDE_EFFECTS (lhs))
12397 lhs = stabilize_reference (lhs);
12399 return ffecom_2s (MODIFY_EXPR, newtype, lhs, rhs);
12404 /* Register source file name. */
12407 ffecom_file (const char *name)
12409 #if FFECOM_GCC_INCLUDE
12410 ffecom_file_ (name);
12414 /* ffecom_notify_init_storage -- An aggregate storage is now fully init'ed
12417 ffecom_notify_init_storage(st);
12419 Gets called when all possible units in an aggregate storage area (a LOCAL
12420 with equivalences or a COMMON) have been initialized. The initialization
12421 info either is in ffestorag_init or, if that is NULL,
12422 ffestorag_accretion:
12424 ffestorag_init may contain an opCONTER or opARRTER. opCONTER may occur
12425 even for an array if the array is one element in length!
12427 ffestorag_accretion will contain an opACCTER. It is much like an
12428 opARRTER except it has an ffebit object in it instead of just a size.
12429 The back end can use the info in the ffebit object, if it wants, to
12430 reduce the amount of actual initialization, but in any case it should
12431 kill the ffebit object when done. Also, set accretion to NULL but
12432 init to a non-NULL value.
12434 After performing initialization, DO NOT set init to NULL, because that'll
12435 tell the front end it is ok for more initialization to happen. Instead,
12436 set init to an opANY expression or some such thing that you can use to
12437 tell that you've already initialized the object.
12440 Support two-pass FFE. */
12443 ffecom_notify_init_storage (ffestorag st)
12445 ffebld init; /* The initialization expression. */
12446 #if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12447 ffetargetOffset size; /* The size of the entity. */
12448 ffetargetAlign pad; /* Its initial padding. */
12451 if (ffestorag_init (st) == NULL)
12453 init = ffestorag_accretion (st);
12454 assert (init != NULL);
12455 ffestorag_set_accretion (st, NULL);
12456 ffestorag_set_accretes (st, 0);
12458 #if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12459 /* For GNU backend, just turn ACCTER into ARRTER and proceed. */
12460 size = ffebld_accter_size (init);
12461 pad = ffebld_accter_pad (init);
12462 ffebit_kill (ffebld_accter_bits (init));
12463 ffebld_set_op (init, FFEBLD_opARRTER);
12464 ffebld_set_arrter (init, ffebld_accter (init));
12465 ffebld_arrter_set_size (init, size);
12466 ffebld_arrter_set_pad (init, size);
12470 ffestorag_set_init (st, init);
12475 init = ffestorag_init (st);
12478 #if FFECOM_ONEPASS /* Process the inits, wipe 'em out. */
12479 ffestorag_set_init (st, ffebld_new_any ());
12481 if (ffebld_op (init) == FFEBLD_opANY)
12482 return; /* Oh, we already did this! */
12484 #if FFECOM_targetCURRENT == FFECOM_targetFFE
12488 if (ffestorag_symbol (st) != NULL)
12489 s = ffestorag_symbol (st);
12491 s = ffestorag_typesymbol (st);
12493 fprintf (dmpout, "= initialize_storage \"%s\" ",
12494 (s != NULL) ? ffesymbol_text (s) : "(unnamed)");
12495 ffebld_dump (init);
12496 fputc ('\n', dmpout);
12500 #endif /* if FFECOM_ONEPASS */
12503 /* ffecom_notify_init_symbol -- A symbol is now fully init'ed
12506 ffecom_notify_init_symbol(s);
12508 Gets called when all possible units in a symbol (not placed in COMMON
12509 or involved in EQUIVALENCE, unless it as yet has no ffestorag object)
12510 have been initialized. The initialization info either is in
12511 ffesymbol_init or, if that is NULL, ffesymbol_accretion:
12513 ffesymbol_init may contain an opCONTER or opARRTER. opCONTER may occur
12514 even for an array if the array is one element in length!
12516 ffesymbol_accretion will contain an opACCTER. It is much like an
12517 opARRTER except it has an ffebit object in it instead of just a size.
12518 The back end can use the info in the ffebit object, if it wants, to
12519 reduce the amount of actual initialization, but in any case it should
12520 kill the ffebit object when done. Also, set accretion to NULL but
12521 init to a non-NULL value.
12523 After performing initialization, DO NOT set init to NULL, because that'll
12524 tell the front end it is ok for more initialization to happen. Instead,
12525 set init to an opANY expression or some such thing that you can use to
12526 tell that you've already initialized the object.
12529 Support two-pass FFE. */
12532 ffecom_notify_init_symbol (ffesymbol s)
12534 ffebld init; /* The initialization expression. */
12535 #if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12536 ffetargetOffset size; /* The size of the entity. */
12537 ffetargetAlign pad; /* Its initial padding. */
12540 if (ffesymbol_storage (s) == NULL)
12541 return; /* Do nothing until COMMON/EQUIVALENCE
12542 possibilities checked. */
12544 if ((ffesymbol_init (s) == NULL)
12545 && ((init = ffesymbol_accretion (s)) != NULL))
12547 ffesymbol_set_accretion (s, NULL);
12548 ffesymbol_set_accretes (s, 0);
12550 #if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12551 /* For GNU backend, just turn ACCTER into ARRTER and proceed. */
12552 size = ffebld_accter_size (init);
12553 pad = ffebld_accter_pad (init);
12554 ffebit_kill (ffebld_accter_bits (init));
12555 ffebld_set_op (init, FFEBLD_opARRTER);
12556 ffebld_set_arrter (init, ffebld_accter (init));
12557 ffebld_arrter_set_size (init, size);
12558 ffebld_arrter_set_pad (init, size);
12562 ffesymbol_set_init (s, init);
12567 init = ffesymbol_init (s);
12571 ffesymbol_set_init (s, ffebld_new_any ());
12573 if (ffebld_op (init) == FFEBLD_opANY)
12574 return; /* Oh, we already did this! */
12576 #if FFECOM_targetCURRENT == FFECOM_targetFFE
12577 fprintf (dmpout, "= initialize_symbol \"%s\" ", ffesymbol_text (s));
12578 ffebld_dump (init);
12579 fputc ('\n', dmpout);
12582 #endif /* if FFECOM_ONEPASS */
12585 /* ffecom_notify_primary_entry -- Learn which is the primary entry point
12588 ffecom_notify_primary_entry(s);
12590 Gets called when implicit or explicit PROGRAM statement seen or when
12591 FUNCTION, SUBROUTINE, or BLOCK DATA statement seen, with the primary
12592 global symbol that serves as the entry point. */
12595 ffecom_notify_primary_entry (ffesymbol s)
12597 ffecom_primary_entry_ = s;
12598 ffecom_primary_entry_kind_ = ffesymbol_kind (s);
12600 if ((ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
12601 || (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE))
12602 ffecom_primary_entry_is_proc_ = TRUE;
12604 ffecom_primary_entry_is_proc_ = FALSE;
12606 if (!ffe_is_silent ())
12608 if (ffecom_primary_entry_kind_ == FFEINFO_kindPROGRAM)
12609 fprintf (stderr, "%s:\n", ffesymbol_text (s));
12611 fprintf (stderr, " %s:\n", ffesymbol_text (s));
12614 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12615 if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
12620 for (list = ffesymbol_dummyargs (s);
12622 list = ffebld_trail (list))
12624 arg = ffebld_head (list);
12625 if (ffebld_op (arg) == FFEBLD_opSTAR)
12627 ffecom_is_altreturning_ = TRUE;
12636 ffecom_open_include (char *name, ffewhereLine l, ffewhereColumn c)
12638 #if FFECOM_GCC_INCLUDE
12639 return ffecom_open_include_ (name, l, c);
12641 return fopen (name, "r");
12645 /* ffecom_ptr_to_expr -- Transform expr into gcc tree with & in front
12648 ffebld expr; // FFE expression.
12649 tree = ffecom_ptr_to_expr(expr);
12651 Like ffecom_expr, but sticks address-of in front of most things. */
12653 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12655 ffecom_ptr_to_expr (ffebld expr)
12658 ffeinfoBasictype bt;
12659 ffeinfoKindtype kt;
12662 assert (expr != NULL);
12664 switch (ffebld_op (expr))
12666 case FFEBLD_opSYMTER:
12667 s = ffebld_symter (expr);
12668 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
12672 ix = ffeintrin_gfrt_indirect (ffebld_symter_implementation (expr));
12673 assert (ix != FFECOM_gfrt);
12674 if ((item = ffecom_gfrt_[ix]) == NULL_TREE)
12676 ffecom_make_gfrt_ (ix);
12677 item = ffecom_gfrt_[ix];
12682 item = ffesymbol_hook (s).decl_tree;
12683 if (item == NULL_TREE)
12685 s = ffecom_sym_transform_ (s);
12686 item = ffesymbol_hook (s).decl_tree;
12689 assert (item != NULL);
12690 if (item == error_mark_node)
12692 if (!ffesymbol_hook (s).addr)
12693 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12697 case FFEBLD_opARRAYREF:
12698 return ffecom_arrayref_ (NULL_TREE, expr, 1);
12700 case FFEBLD_opCONTER:
12702 bt = ffeinfo_basictype (ffebld_info (expr));
12703 kt = ffeinfo_kindtype (ffebld_info (expr));
12705 item = ffecom_constantunion (&ffebld_constant_union
12706 (ffebld_conter (expr)), bt, kt,
12707 ffecom_tree_type[bt][kt]);
12708 if (item == error_mark_node)
12709 return error_mark_node;
12710 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12715 return error_mark_node;
12718 bt = ffeinfo_basictype (ffebld_info (expr));
12719 kt = ffeinfo_kindtype (ffebld_info (expr));
12721 item = ffecom_expr (expr);
12722 if (item == error_mark_node)
12723 return error_mark_node;
12725 /* The back end currently optimizes a bit too zealously for us, in that
12726 we fail JCB001 if the following block of code is omitted. It checks
12727 to see if the transformed expression is a symbol or array reference,
12728 and encloses it in a SAVE_EXPR if that is the case. */
12731 if ((TREE_CODE (item) == VAR_DECL)
12732 || (TREE_CODE (item) == PARM_DECL)
12733 || (TREE_CODE (item) == RESULT_DECL)
12734 || (TREE_CODE (item) == INDIRECT_REF)
12735 || (TREE_CODE (item) == ARRAY_REF)
12736 || (TREE_CODE (item) == COMPONENT_REF)
12738 || (TREE_CODE (item) == OFFSET_REF)
12740 || (TREE_CODE (item) == BUFFER_REF)
12741 || (TREE_CODE (item) == REALPART_EXPR)
12742 || (TREE_CODE (item) == IMAGPART_EXPR))
12744 item = ffecom_save_tree (item);
12747 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12752 assert ("fall-through error" == NULL);
12753 return error_mark_node;
12757 /* Obtain a temp var with given data type.
12759 size is FFETARGET_charactersizeNONE for a non-CHARACTER type
12760 or >= 0 for a CHARACTER type.
12762 elements is -1 for a scalar or > 0 for an array of type. */
12764 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12766 ffecom_make_tempvar (const char *commentary, tree type,
12767 ffetargetCharacterSize size, int elements)
12771 static int mynumber;
12773 assert (current_binding_level->prep_state < 2);
12775 if (type == error_mark_node)
12776 return error_mark_node;
12778 yes = suspend_momentary ();
12780 if (size != FFETARGET_charactersizeNONE)
12781 type = build_array_type (type,
12782 build_range_type (ffecom_f2c_ftnlen_type_node,
12783 ffecom_f2c_ftnlen_one_node,
12784 build_int_2 (size, 0)));
12785 if (elements != -1)
12786 type = build_array_type (type,
12787 build_range_type (integer_type_node,
12789 build_int_2 (elements - 1,
12791 t = build_decl (VAR_DECL,
12792 ffecom_get_invented_identifier ("__g77_%s_%d",
12797 t = start_decl (t, FALSE);
12798 finish_decl (t, NULL_TREE, FALSE);
12800 resume_momentary (yes);
12806 /* Prepare argument pointer to expression.
12808 Like ffecom_prepare_expr, except for expressions to be evaluated
12809 via ffecom_arg_ptr_to_expr. */
12812 ffecom_prepare_arg_ptr_to_expr (ffebld expr)
12814 /* ~~For now, it seems to be the same thing. */
12815 ffecom_prepare_expr (expr);
12819 /* End of preparations. */
12822 ffecom_prepare_end (void)
12824 int prep_state = current_binding_level->prep_state;
12826 assert (prep_state < 2);
12827 current_binding_level->prep_state = 2;
12829 return (prep_state == 1) ? TRUE : FALSE;
12832 /* Prepare expression.
12834 This is called before any code is generated for the current block.
12835 It scans the expression, declares any temporaries that might be needed
12836 during evaluation of the expression, and stores those temporaries in
12837 the appropriate "hook" fields of the expression. `dest', if not NULL,
12838 specifies the destination that ffecom_expr_ will see, in case that
12839 helps avoid generating unused temporaries.
12841 ~~Improve to avoid allocating unused temporaries by taking `dest'
12842 into account vis-a-vis aliasing requirements of complex/character
12846 ffecom_prepare_expr_ (ffebld expr, ffebld dest UNUSED)
12848 ffeinfoBasictype bt;
12849 ffeinfoKindtype kt;
12850 ffetargetCharacterSize sz;
12851 tree tempvar = NULL_TREE;
12853 assert (current_binding_level->prep_state < 2);
12858 bt = ffeinfo_basictype (ffebld_info (expr));
12859 kt = ffeinfo_kindtype (ffebld_info (expr));
12860 sz = ffeinfo_size (ffebld_info (expr));
12862 /* Generate whatever temporaries are needed to represent the result
12863 of the expression. */
12865 if (bt == FFEINFO_basictypeCHARACTER)
12867 while (ffebld_op (expr) == FFEBLD_opPAREN)
12868 expr = ffebld_left (expr);
12871 switch (ffebld_op (expr))
12874 /* Don't make temps for SYMTER, CONTER, etc. */
12875 if (ffebld_arity (expr) == 0)
12880 case FFEINFO_basictypeCOMPLEX:
12881 if (ffebld_op (expr) == FFEBLD_opFUNCREF)
12885 if (ffebld_op (ffebld_left (expr)) != FFEBLD_opSYMTER)
12888 s = ffebld_symter (ffebld_left (expr));
12889 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT
12890 || (ffesymbol_where (s) != FFEINFO_whereINTRINSIC
12891 && ! ffesymbol_is_f2c (s))
12892 || (ffesymbol_where (s) == FFEINFO_whereINTRINSIC
12893 && ! ffe_is_f2c_library ()))
12896 else if (ffebld_op (expr) == FFEBLD_opPOWER)
12898 /* Requires special treatment. There's no POW_CC function
12899 in libg2c, so POW_ZZ is used, which means we always
12900 need a double-complex temp, not a single-complex. */
12901 kt = FFEINFO_kindtypeREAL2;
12903 else if (ffebld_op (expr) != FFEBLD_opDIVIDE)
12904 /* The other ops don't need temps for complex operands. */
12907 /* ~~~Avoid making temps for some intrinsics, such as AIMAG(C),
12908 REAL(C). See 19990325-0.f, routine `check', for cases. */
12909 tempvar = ffecom_make_tempvar ("complex",
12911 [FFEINFO_basictypeCOMPLEX][kt],
12912 FFETARGET_charactersizeNONE,
12916 case FFEINFO_basictypeCHARACTER:
12917 if (ffebld_op (expr) != FFEBLD_opFUNCREF)
12920 if (sz == FFETARGET_charactersizeNONE)
12921 /* ~~Kludge alert! This should someday be fixed. */
12924 tempvar = ffecom_make_tempvar ("char", char_type_node, sz, -1);
12933 case FFEBLD_opPOWER:
12936 tree rtmp, ltmp, result;
12938 ltype = ffecom_type_expr (ffebld_left (expr));
12939 rtype = ffecom_type_expr (ffebld_right (expr));
12941 rtmp = ffecom_make_tempvar (rtype, FFETARGET_charactersizeNONE, -1);
12942 ltmp = ffecom_make_tempvar (ltype, FFETARGET_charactersizeNONE, -1);
12943 result = ffecom_make_tempvar (ltype, FFETARGET_charactersizeNONE, -1);
12945 tempvar = make_tree_vec (3);
12946 TREE_VEC_ELT (tempvar, 0) = rtmp;
12947 TREE_VEC_ELT (tempvar, 1) = ltmp;
12948 TREE_VEC_ELT (tempvar, 2) = result;
12953 case FFEBLD_opCONCATENATE:
12955 /* This gets special handling, because only one set of temps
12956 is needed for a tree of these -- the tree is treated as
12957 a flattened list of concatenations when generating code. */
12959 ffecomConcatList_ catlist;
12960 tree ltmp, itmp, result;
12964 catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
12965 count = ffecom_concat_list_count_ (catlist);
12970 = ffecom_make_tempvar ("concat_len",
12971 ffecom_f2c_ftnlen_type_node,
12972 FFETARGET_charactersizeNONE, count);
12974 = ffecom_make_tempvar ("concat_item",
12975 ffecom_f2c_address_type_node,
12976 FFETARGET_charactersizeNONE, count);
12978 = ffecom_make_tempvar ("concat_res",
12980 ffecom_concat_list_maxlen_ (catlist),
12983 tempvar = make_tree_vec (3);
12984 TREE_VEC_ELT (tempvar, 0) = ltmp;
12985 TREE_VEC_ELT (tempvar, 1) = itmp;
12986 TREE_VEC_ELT (tempvar, 2) = result;
12989 for (i = 0; i < count; ++i)
12990 ffecom_prepare_arg_ptr_to_expr (ffecom_concat_list_expr_ (catlist,
12993 ffecom_concat_list_kill_ (catlist);
12997 ffebld_nonter_set_hook (expr, tempvar);
12998 current_binding_level->prep_state = 1;
13003 case FFEBLD_opCONVERT:
13004 if (bt == FFEINFO_basictypeCHARACTER
13005 && ((ffebld_size_known (ffebld_left (expr))
13006 == FFETARGET_charactersizeNONE)
13007 || (ffebld_size_known (ffebld_left (expr)) >= sz)))
13008 tempvar = ffecom_make_tempvar ("convert", char_type_node, sz, -1);
13014 ffebld_nonter_set_hook (expr, tempvar);
13015 current_binding_level->prep_state = 1;
13018 /* Prepare subexpressions for this expr. */
13020 switch (ffebld_op (expr))
13022 case FFEBLD_opPERCENT_LOC:
13023 ffecom_prepare_ptr_to_expr (ffebld_left (expr));
13026 case FFEBLD_opPERCENT_VAL:
13027 case FFEBLD_opPERCENT_REF:
13028 ffecom_prepare_expr (ffebld_left (expr));
13031 case FFEBLD_opPERCENT_DESCR:
13032 ffecom_prepare_arg_ptr_to_expr (ffebld_left (expr));
13035 case FFEBLD_opITEM:
13041 item = ffebld_trail (item))
13042 if (ffebld_head (item) != NULL)
13043 ffecom_prepare_expr (ffebld_head (item));
13048 /* Need to handle character conversion specially. */
13049 switch (ffebld_arity (expr))
13052 ffecom_prepare_expr (ffebld_left (expr));
13053 ffecom_prepare_expr (ffebld_right (expr));
13057 ffecom_prepare_expr (ffebld_left (expr));
13068 /* Prepare expression for reading and writing.
13070 Like ffecom_prepare_expr, except for expressions to be evaluated
13071 via ffecom_expr_rw. */
13074 ffecom_prepare_expr_rw (tree type, ffebld expr)
13076 /* This is all we support for now. */
13077 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
13079 /* ~~For now, it seems to be the same thing. */
13080 ffecom_prepare_expr (expr);
13084 /* Prepare expression for writing.
13086 Like ffecom_prepare_expr, except for expressions to be evaluated
13087 via ffecom_expr_w. */
13090 ffecom_prepare_expr_w (tree type, ffebld expr)
13092 /* This is all we support for now. */
13093 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
13095 /* ~~For now, it seems to be the same thing. */
13096 ffecom_prepare_expr (expr);
13100 /* Prepare expression for returning.
13102 Like ffecom_prepare_expr, except for expressions to be evaluated
13103 via ffecom_return_expr. */
13106 ffecom_prepare_return_expr (ffebld expr)
13108 assert (current_binding_level->prep_state < 2);
13110 if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE
13111 && ffecom_is_altreturning_
13113 ffecom_prepare_expr (expr);
13116 /* Prepare pointer to expression.
13118 Like ffecom_prepare_expr, except for expressions to be evaluated
13119 via ffecom_ptr_to_expr. */
13122 ffecom_prepare_ptr_to_expr (ffebld expr)
13124 /* ~~For now, it seems to be the same thing. */
13125 ffecom_prepare_expr (expr);
13129 /* Transform expression into constant pointer-to-expression tree.
13131 If the expression can be transformed into a pointer-to-expression tree
13132 that is constant, that is done, and the tree returned. Else NULL_TREE
13135 That way, a caller can attempt to provide compile-time initialization
13136 of a variable and, if that fails, *then* choose to start a new block
13137 and resort to using temporaries, as appropriate. */
13140 ffecom_ptr_to_const_expr (ffebld expr)
13143 return integer_zero_node;
13145 if (ffebld_op (expr) == FFEBLD_opANY)
13146 return error_mark_node;
13148 if (ffebld_arity (expr) == 0
13149 && (ffebld_op (expr) != FFEBLD_opSYMTER
13150 || ffebld_where (expr) == FFEINFO_whereCOMMON
13151 || ffebld_where (expr) == FFEINFO_whereGLOBAL
13152 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
13156 t = ffecom_ptr_to_expr (expr);
13157 assert (TREE_CONSTANT (t));
13164 /* ffecom_return_expr -- Returns return-value expr given alt return expr
13166 tree rtn; // NULL_TREE means use expand_null_return()
13167 ffebld expr; // NULL if no alt return expr to RETURN stmt
13168 rtn = ffecom_return_expr(expr);
13170 Based on the program unit type and other info (like return function
13171 type, return master function type when alternate ENTRY points,
13172 whether subroutine has any alternate RETURN points, etc), returns the
13173 appropriate expression to be returned to the caller, or NULL_TREE
13174 meaning no return value or the caller expects it to be returned somewhere
13175 else (which is handled by other parts of this module). */
13177 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13179 ffecom_return_expr (ffebld expr)
13183 switch (ffecom_primary_entry_kind_)
13185 case FFEINFO_kindPROGRAM:
13186 case FFEINFO_kindBLOCKDATA:
13190 case FFEINFO_kindSUBROUTINE:
13191 if (!ffecom_is_altreturning_)
13192 rtn = NULL_TREE; /* No alt returns, never an expr. */
13193 else if (expr == NULL)
13194 rtn = integer_zero_node;
13196 rtn = ffecom_expr (expr);
13199 case FFEINFO_kindFUNCTION:
13200 if ((ffecom_multi_retval_ != NULL_TREE)
13201 || (ffesymbol_basictype (ffecom_primary_entry_)
13202 == FFEINFO_basictypeCHARACTER)
13203 || ((ffesymbol_basictype (ffecom_primary_entry_)
13204 == FFEINFO_basictypeCOMPLEX)
13205 && (ffecom_num_entrypoints_ == 0)
13206 && ffesymbol_is_f2c (ffecom_primary_entry_)))
13207 { /* Value is returned by direct assignment
13208 into (implicit) dummy. */
13212 rtn = ffecom_func_result_;
13214 /* Spurious error if RETURN happens before first reference! So elide
13215 this code. In particular, for debugging registry, rtn should always
13216 be non-null after all, but TREE_USED won't be set until we encounter
13217 a reference in the code. Perfectly okay (but weird) code that,
13218 e.g., has "GOTO 20;10 RETURN;20 RTN=0;GOTO 10", would result in
13219 this diagnostic for no reason. Have people use -O -Wuninitialized
13220 and leave it to the back end to find obviously weird cases. */
13222 /* Used to "assert(rtn != NULL_TREE);" here, but it's kind of a valid
13223 situation; if the return value has never been referenced, it won't
13224 have a tree under 2pass mode. */
13225 if ((rtn == NULL_TREE)
13226 || !TREE_USED (rtn))
13228 ffebad_start (FFEBAD_RETURN_VALUE_UNSET);
13229 ffebad_here (0, ffesymbol_where_line (ffecom_primary_entry_),
13230 ffesymbol_where_column (ffecom_primary_entry_));
13231 ffebad_string (ffesymbol_text (ffesymbol_funcresult
13232 (ffecom_primary_entry_)));
13239 assert ("bad unit kind" == NULL);
13240 case FFEINFO_kindANY:
13241 rtn = error_mark_node;
13249 /* Do save_expr only if tree is not error_mark_node. */
13251 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13253 ffecom_save_tree (tree t)
13255 return save_expr (t);
13259 /* Start a compound statement (block). */
13261 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13263 ffecom_start_compstmt (void)
13265 bison_rule_pushlevel_ ();
13267 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
13269 /* Public entry point for front end to access start_decl. */
13271 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13273 ffecom_start_decl (tree decl, bool is_initialized)
13275 DECL_INITIAL (decl) = is_initialized ? error_mark_node : NULL_TREE;
13276 return start_decl (decl, FALSE);
13280 /* ffecom_sym_commit -- Symbol's state being committed to reality
13283 ffecom_sym_commit(s);
13285 Does whatever the backend needs when a symbol is committed after having
13286 been backtrackable for a period of time. */
13288 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13290 ffecom_sym_commit (ffesymbol s UNUSED)
13292 assert (!ffesymbol_retractable ());
13296 /* ffecom_sym_end_transition -- Perform end transition on all symbols
13298 ffecom_sym_end_transition();
13300 Does backend-specific stuff and also calls ffest_sym_end_transition
13301 to do the necessary FFE stuff.
13303 Backtracking is never enabled when this fn is called, so don't worry
13307 ffecom_sym_end_transition (ffesymbol s)
13311 assert (!ffesymbol_retractable ());
13313 s = ffest_sym_end_transition (s);
13315 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13316 if ((ffesymbol_kind (s) == FFEINFO_kindBLOCKDATA)
13317 && (ffesymbol_where (s) == FFEINFO_whereGLOBAL))
13319 ffecom_list_blockdata_
13320 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
13321 FFEINTRIN_specNONE,
13322 FFEINTRIN_impNONE),
13323 ffecom_list_blockdata_);
13327 /* This is where we finally notice that a symbol has partial initialization
13328 and finalize it. */
13330 if (ffesymbol_accretion (s) != NULL)
13332 assert (ffesymbol_init (s) == NULL);
13333 ffecom_notify_init_symbol (s);
13335 else if (((st = ffesymbol_storage (s)) != NULL)
13336 && ((st = ffestorag_parent (st)) != NULL)
13337 && (ffestorag_accretion (st) != NULL))
13339 assert (ffestorag_init (st) == NULL);
13340 ffecom_notify_init_storage (st);
13343 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13344 if ((ffesymbol_kind (s) == FFEINFO_kindCOMMON)
13345 && (ffesymbol_where (s) == FFEINFO_whereLOCAL)
13346 && (ffesymbol_storage (s) != NULL))
13348 ffecom_list_common_
13349 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
13350 FFEINTRIN_specNONE,
13351 FFEINTRIN_impNONE),
13352 ffecom_list_common_);
13359 /* ffecom_sym_exec_transition -- Perform exec transition on all symbols
13361 ffecom_sym_exec_transition();
13363 Does backend-specific stuff and also calls ffest_sym_exec_transition
13364 to do the necessary FFE stuff.
13366 See the long-winded description in ffecom_sym_learned for info
13367 on handling the situation where backtracking is inhibited. */
13370 ffecom_sym_exec_transition (ffesymbol s)
13372 s = ffest_sym_exec_transition (s);
13377 /* ffecom_sym_learned -- Initial or more info gained on symbol after exec
13380 s = ffecom_sym_learned(s);
13382 Called when a new symbol is seen after the exec transition or when more
13383 info (perhaps) is gained for an UNCERTAIN symbol. The symbol state when
13384 it arrives here is that all its latest info is updated already, so its
13385 state may be UNCERTAIN or UNDERSTOOD, it might already have the hook
13386 field filled in if its gone through here or exec_transition first, and
13389 The backend probably wants to check ffesymbol_retractable() to see if
13390 backtracking is in effect. If so, the FFE's changes to the symbol may
13391 be retracted (undone) or committed (ratified), at which time the
13392 appropriate ffecom_sym_retract or _commit function will be called
13395 If the backend has its own backtracking mechanism, great, use it so that
13396 committal is a simple operation. Though it doesn't make much difference,
13397 I suppose: the reason for tentative symbol evolution in the FFE is to
13398 enable error detection in weird incorrect statements early and to disable
13399 incorrect error detection on a correct statement. The backend is not
13400 likely to introduce any information that'll get involved in these
13401 considerations, so it is probably just fine that the implementation
13402 model for this fn and for _exec_transition is to not do anything
13403 (besides the required FFE stuff) if ffesymbol_retractable() returns TRUE
13404 and instead wait until ffecom_sym_commit is called (which it never
13405 will be as long as we're using ambiguity-detecting statement analysis in
13406 the FFE, which we are initially to shake out the code, but don't depend
13407 on this), otherwise go ahead and do whatever is needed.
13409 In essence, then, when this fn and _exec_transition get called while
13410 backtracking is enabled, a general mechanism would be to flag which (or
13411 both) of these were called (and in what order? neat question as to what
13412 might happen that I'm too lame to think through right now) and then when
13413 _commit is called reproduce the original calling sequence, if any, for
13414 the two fns (at which point backtracking will, of course, be disabled). */
13417 ffecom_sym_learned (ffesymbol s)
13419 ffestorag_exec_layout (s);
13424 /* ffecom_sym_retract -- Symbol's state being retracted from reality
13427 ffecom_sym_retract(s);
13429 Does whatever the backend needs when a symbol is retracted after having
13430 been backtrackable for a period of time. */
13432 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13434 ffecom_sym_retract (ffesymbol s UNUSED)
13436 assert (!ffesymbol_retractable ());
13438 #if 0 /* GCC doesn't commit any backtrackable sins,
13439 so nothing needed here. */
13440 switch (ffesymbol_hook (s).state)
13442 case 0: /* nothing happened yet. */
13445 case 1: /* exec transition happened. */
13448 case 2: /* learned happened. */
13451 case 3: /* learned then exec. */
13454 case 4: /* exec then learned. */
13458 assert ("bad hook state" == NULL);
13465 /* Create temporary gcc label. */
13467 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13469 ffecom_temp_label ()
13472 static int mynumber = 0;
13474 glabel = build_decl (LABEL_DECL,
13475 ffecom_get_invented_identifier ("__g77_label_%d",
13478 DECL_CONTEXT (glabel) = current_function_decl;
13479 DECL_MODE (glabel) = VOIDmode;
13485 /* Return an expression that is usable as an arg in a conditional context
13486 (IF, DO WHILE, .NOT., and so on).
13488 Use the one provided for the back end as of >2.6.0. */
13490 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13492 ffecom_truth_value (tree expr)
13494 return truthvalue_conversion (expr);
13498 /* Return the inversion of a truth value (the inversion of what
13499 ffecom_truth_value builds).
13501 Apparently invert_truthvalue, which is properly in the back end, is
13502 enough for now, so just use it. */
13504 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13506 ffecom_truth_value_invert (tree expr)
13508 return invert_truthvalue (ffecom_truth_value (expr));
13513 /* Return the tree that is the type of the expression, as would be
13514 returned in TREE_TYPE(ffecom_expr(expr)), without otherwise
13515 transforming the expression, generating temporaries, etc. */
13518 ffecom_type_expr (ffebld expr)
13520 ffeinfoBasictype bt;
13521 ffeinfoKindtype kt;
13524 assert (expr != NULL);
13526 bt = ffeinfo_basictype (ffebld_info (expr));
13527 kt = ffeinfo_kindtype (ffebld_info (expr));
13528 tree_type = ffecom_tree_type[bt][kt];
13530 switch (ffebld_op (expr))
13532 case FFEBLD_opCONTER:
13533 case FFEBLD_opSYMTER:
13534 case FFEBLD_opARRAYREF:
13535 case FFEBLD_opUPLUS:
13536 case FFEBLD_opPAREN:
13537 case FFEBLD_opUMINUS:
13539 case FFEBLD_opSUBTRACT:
13540 case FFEBLD_opMULTIPLY:
13541 case FFEBLD_opDIVIDE:
13542 case FFEBLD_opPOWER:
13544 case FFEBLD_opFUNCREF:
13545 case FFEBLD_opSUBRREF:
13549 case FFEBLD_opNEQV:
13551 case FFEBLD_opCONVERT:
13558 case FFEBLD_opPERCENT_LOC:
13561 case FFEBLD_opACCTER:
13562 case FFEBLD_opARRTER:
13563 case FFEBLD_opITEM:
13564 case FFEBLD_opSTAR:
13565 case FFEBLD_opBOUNDS:
13566 case FFEBLD_opREPEAT:
13567 case FFEBLD_opLABTER:
13568 case FFEBLD_opLABTOK:
13569 case FFEBLD_opIMPDO:
13570 case FFEBLD_opCONCATENATE:
13571 case FFEBLD_opSUBSTR:
13573 assert ("bad op for ffecom_type_expr" == NULL);
13574 /* Fall through. */
13576 return error_mark_node;
13580 /* Return PARM_DECL for arg#1 of master fn containing alternate ENTRY points
13582 If the PARM_DECL already exists, return it, else create it. It's an
13583 integer_type_node argument for the master function that implements a
13584 subroutine or function with more than one entrypoint and is bound at
13585 run time with the entrypoint number (0 for SUBROUTINE/FUNCTION, 1 for
13586 first ENTRY statement, and so on). */
13588 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13590 ffecom_which_entrypoint_decl ()
13592 assert (ffecom_which_entrypoint_decl_ != NULL_TREE);
13594 return ffecom_which_entrypoint_decl_;
13599 /* The following sections consists of private and public functions
13600 that have the same names and perform roughly the same functions
13601 as counterparts in the C front end. Changes in the C front end
13602 might affect how things should be done here. Only functions
13603 needed by the back end should be public here; the rest should
13604 be private (static in the C sense). Functions needed by other
13605 g77 front-end modules should be accessed by them via public
13606 ffecom_* names, which should themselves call private versions
13607 in this section so the private versions are easy to recognize
13608 when upgrading to a new gcc and finding interesting changes
13611 Functions named after rule "foo:" in c-parse.y are named
13612 "bison_rule_foo_" so they are easy to find. */
13614 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13617 bison_rule_pushlevel_ ()
13619 emit_line_note (input_filename, lineno);
13621 clear_last_expr ();
13623 expand_start_bindings (0);
13627 bison_rule_compstmt_ ()
13630 int keep = kept_level_p ();
13632 /* Make the temps go away. */
13634 current_binding_level->names = NULL_TREE;
13636 emit_line_note (input_filename, lineno);
13637 expand_end_bindings (getdecls (), keep, 0);
13638 t = poplevel (keep, 1, 0);
13644 /* Return a definition for a builtin function named NAME and whose data type
13645 is TYPE. TYPE should be a function type with argument types.
13646 FUNCTION_CODE tells later passes how to compile calls to this function.
13647 See tree.h for its possible values.
13649 If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME,
13650 the name to be called if we can't opencode the function. */
13653 builtin_function (const char *name, tree type, int function_code,
13654 enum built_in_class class,
13655 const char *library_name)
13657 tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
13658 DECL_EXTERNAL (decl) = 1;
13659 TREE_PUBLIC (decl) = 1;
13661 DECL_ASSEMBLER_NAME (decl) = get_identifier (library_name);
13662 make_decl_rtl (decl, NULL_PTR, 1);
13664 DECL_BUILT_IN_CLASS (decl) = class;
13665 DECL_FUNCTION_CODE (decl) = function_code;
13670 /* Handle when a new declaration NEWDECL
13671 has the same name as an old one OLDDECL
13672 in the same binding contour.
13673 Prints an error message if appropriate.
13675 If safely possible, alter OLDDECL to look like NEWDECL, and return 1.
13676 Otherwise, return 0. */
13679 duplicate_decls (tree newdecl, tree olddecl)
13681 int types_match = 1;
13682 int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
13683 && DECL_INITIAL (newdecl) != 0);
13684 tree oldtype = TREE_TYPE (olddecl);
13685 tree newtype = TREE_TYPE (newdecl);
13687 if (olddecl == newdecl)
13690 if (TREE_CODE (newtype) == ERROR_MARK
13691 || TREE_CODE (oldtype) == ERROR_MARK)
13694 /* New decl is completely inconsistent with the old one =>
13695 tell caller to replace the old one.
13696 This is always an error except in the case of shadowing a builtin. */
13697 if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
13700 /* For real parm decl following a forward decl,
13701 return 1 so old decl will be reused. */
13702 if (types_match && TREE_CODE (newdecl) == PARM_DECL
13703 && TREE_ASM_WRITTEN (olddecl) && ! TREE_ASM_WRITTEN (newdecl))
13706 /* The new declaration is the same kind of object as the old one.
13707 The declarations may partially match. Print warnings if they don't
13708 match enough. Ultimately, copy most of the information from the new
13709 decl to the old one, and keep using the old one. */
13711 if (TREE_CODE (olddecl) == FUNCTION_DECL
13712 && DECL_BUILT_IN (olddecl))
13714 /* A function declaration for a built-in function. */
13715 if (!TREE_PUBLIC (newdecl))
13717 else if (!types_match)
13719 /* Accept the return type of the new declaration if same modes. */
13720 tree oldreturntype = TREE_TYPE (TREE_TYPE (olddecl));
13721 tree newreturntype = TREE_TYPE (TREE_TYPE (newdecl));
13723 if (TYPE_MODE (oldreturntype) == TYPE_MODE (newreturntype))
13725 /* Function types may be shared, so we can't just modify
13726 the return type of olddecl's function type. */
13728 = build_function_type (newreturntype,
13729 TYPE_ARG_TYPES (TREE_TYPE (olddecl)));
13733 TREE_TYPE (olddecl) = newtype;
13739 else if (TREE_CODE (olddecl) == FUNCTION_DECL
13740 && DECL_SOURCE_LINE (olddecl) == 0)
13742 /* A function declaration for a predeclared function
13743 that isn't actually built in. */
13744 if (!TREE_PUBLIC (newdecl))
13746 else if (!types_match)
13748 /* If the types don't match, preserve volatility indication.
13749 Later on, we will discard everything else about the
13750 default declaration. */
13751 TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
13755 /* Copy all the DECL_... slots specified in the new decl
13756 except for any that we copy here from the old type.
13758 Past this point, we don't change OLDTYPE and NEWTYPE
13759 even if we change the types of NEWDECL and OLDDECL. */
13763 /* Merge the data types specified in the two decls. */
13764 if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl))
13765 TREE_TYPE (newdecl)
13766 = TREE_TYPE (olddecl)
13767 = TREE_TYPE (newdecl);
13769 /* Lay the type out, unless already done. */
13770 if (oldtype != TREE_TYPE (newdecl))
13772 if (TREE_TYPE (newdecl) != error_mark_node)
13773 layout_type (TREE_TYPE (newdecl));
13774 if (TREE_CODE (newdecl) != FUNCTION_DECL
13775 && TREE_CODE (newdecl) != TYPE_DECL
13776 && TREE_CODE (newdecl) != CONST_DECL)
13777 layout_decl (newdecl, 0);
13781 /* Since the type is OLDDECL's, make OLDDECL's size go with. */
13782 DECL_SIZE (newdecl) = DECL_SIZE (olddecl);
13783 DECL_SIZE_UNIT (newdecl) = DECL_SIZE_UNIT (olddecl);
13784 if (TREE_CODE (olddecl) != FUNCTION_DECL)
13785 if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
13786 DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
13789 /* Keep the old rtl since we can safely use it. */
13790 DECL_RTL (newdecl) = DECL_RTL (olddecl);
13792 /* Merge the type qualifiers. */
13793 if (DECL_BUILT_IN_NONANSI (olddecl) && TREE_THIS_VOLATILE (olddecl)
13794 && !TREE_THIS_VOLATILE (newdecl))
13795 TREE_THIS_VOLATILE (olddecl) = 0;
13796 if (TREE_READONLY (newdecl))
13797 TREE_READONLY (olddecl) = 1;
13798 if (TREE_THIS_VOLATILE (newdecl))
13800 TREE_THIS_VOLATILE (olddecl) = 1;
13801 if (TREE_CODE (newdecl) == VAR_DECL)
13802 make_var_volatile (newdecl);
13805 /* Keep source location of definition rather than declaration.
13806 Likewise, keep decl at outer scope. */
13807 if ((DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0)
13808 || (DECL_CONTEXT (newdecl) != 0 && DECL_CONTEXT (olddecl) == 0))
13810 DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl);
13811 DECL_SOURCE_FILE (newdecl) = DECL_SOURCE_FILE (olddecl);
13813 if (DECL_CONTEXT (olddecl) == 0
13814 && TREE_CODE (newdecl) != FUNCTION_DECL)
13815 DECL_CONTEXT (newdecl) = 0;
13818 /* Merge the unused-warning information. */
13819 if (DECL_IN_SYSTEM_HEADER (olddecl))
13820 DECL_IN_SYSTEM_HEADER (newdecl) = 1;
13821 else if (DECL_IN_SYSTEM_HEADER (newdecl))
13822 DECL_IN_SYSTEM_HEADER (olddecl) = 1;
13824 /* Merge the initialization information. */
13825 if (DECL_INITIAL (newdecl) == 0)
13826 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
13828 /* Merge the section attribute.
13829 We want to issue an error if the sections conflict but that must be
13830 done later in decl_attributes since we are called before attributes
13832 if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
13833 DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
13836 if (TREE_CODE (newdecl) == FUNCTION_DECL)
13838 DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
13839 DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
13843 /* If cannot merge, then use the new type and qualifiers,
13844 and don't preserve the old rtl. */
13847 TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
13848 TREE_READONLY (olddecl) = TREE_READONLY (newdecl);
13849 TREE_THIS_VOLATILE (olddecl) = TREE_THIS_VOLATILE (newdecl);
13850 TREE_SIDE_EFFECTS (olddecl) = TREE_SIDE_EFFECTS (newdecl);
13853 /* Merge the storage class information. */
13854 /* For functions, static overrides non-static. */
13855 if (TREE_CODE (newdecl) == FUNCTION_DECL)
13857 TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl);
13858 /* This is since we don't automatically
13859 copy the attributes of NEWDECL into OLDDECL. */
13860 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
13861 /* If this clears `static', clear it in the identifier too. */
13862 if (! TREE_PUBLIC (olddecl))
13863 TREE_PUBLIC (DECL_NAME (olddecl)) = 0;
13865 if (DECL_EXTERNAL (newdecl))
13867 TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
13868 DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
13869 /* An extern decl does not override previous storage class. */
13870 TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
13874 TREE_STATIC (olddecl) = TREE_STATIC (newdecl);
13875 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
13878 /* If either decl says `inline', this fn is inline,
13879 unless its definition was passed already. */
13880 if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == 0)
13881 DECL_INLINE (olddecl) = 1;
13882 DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
13884 /* Get rid of any built-in function if new arg types don't match it
13885 or if we have a function definition. */
13886 if (TREE_CODE (newdecl) == FUNCTION_DECL
13887 && DECL_BUILT_IN (olddecl)
13888 && (!types_match || new_is_definition))
13890 TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
13891 DECL_BUILT_IN_CLASS (olddecl) = NOT_BUILT_IN;
13894 /* If redeclaring a builtin function, and not a definition,
13896 Also preserve various other info from the definition. */
13897 if (TREE_CODE (newdecl) == FUNCTION_DECL && !new_is_definition)
13899 if (DECL_BUILT_IN (olddecl))
13901 DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
13902 DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
13905 DECL_FRAME_SIZE (newdecl) = DECL_FRAME_SIZE (olddecl);
13907 DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
13908 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
13909 DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
13910 DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
13913 /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
13914 But preserve olddecl's DECL_UID. */
13916 register unsigned olddecl_uid = DECL_UID (olddecl);
13918 memcpy ((char *) olddecl + sizeof (struct tree_common),
13919 (char *) newdecl + sizeof (struct tree_common),
13920 sizeof (struct tree_decl) - sizeof (struct tree_common));
13921 DECL_UID (olddecl) = olddecl_uid;
13927 /* Finish processing of a declaration;
13928 install its initial value.
13929 If the length of an array type is not known before,
13930 it must be determined now, from the initial value, or it is an error. */
13933 finish_decl (tree decl, tree init, bool is_top_level)
13935 register tree type = TREE_TYPE (decl);
13936 int was_incomplete = (DECL_SIZE (decl) == 0);
13937 int temporary = allocation_temporary_p ();
13938 bool at_top_level = (current_binding_level == global_binding_level);
13939 bool top_level = is_top_level || at_top_level;
13941 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
13943 assert (!is_top_level || !at_top_level);
13945 if (TREE_CODE (decl) == PARM_DECL)
13946 assert (init == NULL_TREE);
13947 /* Remember that PARM_DECL doesn't have a DECL_INITIAL field per se -- it
13948 overlaps DECL_ARG_TYPE. */
13949 else if (init == NULL_TREE)
13950 assert (DECL_INITIAL (decl) == NULL_TREE);
13952 assert (DECL_INITIAL (decl) == error_mark_node);
13954 if (init != NULL_TREE)
13956 if (TREE_CODE (decl) != TYPE_DECL)
13957 DECL_INITIAL (decl) = init;
13960 /* typedef foo = bar; store the type of bar as the type of foo. */
13961 TREE_TYPE (decl) = TREE_TYPE (init);
13962 DECL_INITIAL (decl) = init = 0;
13966 /* Pop back to the obstack that is current for this binding level. This is
13967 because MAXINDEX, rtl, etc. to be made below must go in the permanent
13968 obstack. But don't discard the temporary data yet. */
13971 /* Deduce size of array from initialization, if not already known */
13973 if (TREE_CODE (type) == ARRAY_TYPE
13974 && TYPE_DOMAIN (type) == 0
13975 && TREE_CODE (decl) != TYPE_DECL)
13977 assert (top_level);
13978 assert (was_incomplete);
13980 layout_decl (decl, 0);
13983 if (TREE_CODE (decl) == VAR_DECL)
13985 if (DECL_SIZE (decl) == NULL_TREE
13986 && TYPE_SIZE (TREE_TYPE (decl)) != NULL_TREE)
13987 layout_decl (decl, 0);
13989 if (DECL_SIZE (decl) == NULL_TREE
13990 && (TREE_STATIC (decl)
13992 /* A static variable with an incomplete type is an error if it is
13993 initialized. Also if it is not file scope. Otherwise, let it
13994 through, but if it is not `extern' then it may cause an error
13996 (DECL_INITIAL (decl) != 0 || DECL_CONTEXT (decl) != 0)
13998 /* An automatic variable with an incomplete type is an error. */
13999 !DECL_EXTERNAL (decl)))
14001 assert ("storage size not known" == NULL);
14005 if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
14006 && (DECL_SIZE (decl) != 0)
14007 && (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST))
14009 assert ("storage size not constant" == NULL);
14014 /* Output the assembler code and/or RTL code for variables and functions,
14015 unless the type is an undefined structure or union. If not, it will get
14016 done when the type is completed. */
14018 if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
14020 rest_of_decl_compilation (decl, NULL,
14021 DECL_CONTEXT (decl) == 0,
14024 if (DECL_CONTEXT (decl) != 0)
14026 /* Recompute the RTL of a local array now if it used to be an
14027 incomplete type. */
14029 && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
14031 /* If we used it already as memory, it must stay in memory. */
14032 TREE_ADDRESSABLE (decl) = TREE_USED (decl);
14033 /* If it's still incomplete now, no init will save it. */
14034 if (DECL_SIZE (decl) == 0)
14035 DECL_INITIAL (decl) = 0;
14036 expand_decl (decl);
14038 /* Compute and store the initial value. */
14039 if (TREE_CODE (decl) != FUNCTION_DECL)
14040 expand_decl_init (decl);
14043 else if (TREE_CODE (decl) == TYPE_DECL)
14045 rest_of_decl_compilation (decl, NULL_PTR,
14046 DECL_CONTEXT (decl) == 0,
14050 if (!(TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl))
14052 /* DECL_INITIAL is not defined in PARM_DECLs, since it shares space with
14054 && TREE_CODE (decl) != PARM_DECL)
14056 /* We need to remember that this array HAD an initialization, but
14057 discard the actual temporary nodes, since we can't have a permanent
14058 node keep pointing to them. */
14059 /* We make an exception for inline functions, since it's normal for a
14060 local extern redeclaration of an inline function to have a copy of
14061 the top-level decl's DECL_INLINE. */
14062 if ((DECL_INITIAL (decl) != 0)
14063 && (DECL_INITIAL (decl) != error_mark_node))
14065 /* If this is a const variable, then preserve the
14066 initializer instead of discarding it so that we can optimize
14067 references to it. */
14068 /* This test used to include TREE_STATIC, but this won't be set
14069 for function level initializers. */
14070 if (TREE_READONLY (decl))
14072 preserve_initializer ();
14074 /* The initializer and DECL must have the same (or equivalent
14075 types), but if the initializer is a STRING_CST, its type
14076 might not be on the right obstack, so copy the type
14078 TREE_TYPE (DECL_INITIAL (decl)) = type;
14081 DECL_INITIAL (decl) = error_mark_node;
14085 /* If we have gone back from temporary to permanent allocation, actually
14086 free the temporary space that we no longer need. */
14087 if (temporary && !allocation_temporary_p ())
14088 permanent_allocation (0);
14090 /* At the end of a declaration, throw away any variable type sizes of types
14091 defined inside that declaration. There is no use computing them in the
14092 following function definition. */
14093 if (current_binding_level == global_binding_level)
14094 get_pending_sizes ();
14097 /* Finish up a function declaration and compile that function
14098 all the way to assembler language output. The free the storage
14099 for the function definition.
14101 This is called after parsing the body of the function definition.
14103 NESTED is nonzero if the function being finished is nested in another. */
14106 finish_function (int nested)
14108 register tree fndecl = current_function_decl;
14110 assert (fndecl != NULL_TREE);
14111 if (TREE_CODE (fndecl) != ERROR_MARK)
14114 assert (DECL_CONTEXT (fndecl) != NULL_TREE);
14116 assert (DECL_CONTEXT (fndecl) == NULL_TREE);
14119 /* TREE_READONLY (fndecl) = 1;
14120 This caused &foo to be of type ptr-to-const-function
14121 which then got a warning when stored in a ptr-to-function variable. */
14123 poplevel (1, 0, 1);
14125 if (TREE_CODE (fndecl) != ERROR_MARK)
14127 BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
14129 /* Must mark the RESULT_DECL as being in this function. */
14131 DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
14133 /* Obey `register' declarations if `setjmp' is called in this fn. */
14134 /* Generate rtl for function exit. */
14135 expand_function_end (input_filename, lineno, 0);
14137 /* So we can tell if jump_optimize sets it to 1. */
14140 /* If this is a nested function, protect the local variables in the stack
14141 above us from being collected while we're compiling this function. */
14142 if (ggc_p && nested)
14143 ggc_push_context ();
14145 /* Run the optimizers and output the assembler code for this function. */
14146 rest_of_compilation (fndecl);
14148 /* Undo the GC context switch. */
14149 if (ggc_p && nested)
14150 ggc_pop_context ();
14153 /* Free all the tree nodes making up this function. */
14154 /* Switch back to allocating nodes permanently until we start another
14157 permanent_allocation (1);
14159 if (TREE_CODE (fndecl) != ERROR_MARK
14161 && DECL_SAVED_INSNS (fndecl) == 0)
14163 /* Stop pointing to the local nodes about to be freed. */
14164 /* But DECL_INITIAL must remain nonzero so we know this was an actual
14165 function definition. */
14166 /* For a nested function, this is done in pop_f_function_context. */
14167 /* If rest_of_compilation set this to 0, leave it 0. */
14168 if (DECL_INITIAL (fndecl) != 0)
14169 DECL_INITIAL (fndecl) = error_mark_node;
14170 DECL_ARGUMENTS (fndecl) = 0;
14175 /* Let the error reporting routines know that we're outside a function.
14176 For a nested function, this value is used in pop_c_function_context
14177 and then reset via pop_function_context. */
14178 ffecom_outer_function_decl_ = current_function_decl = NULL;
14182 /* Plug-in replacement for identifying the name of a decl and, for a
14183 function, what we call it in diagnostics. For now, "program unit"
14184 should suffice, since it's a bit of a hassle to figure out which
14185 of several kinds of things it is. Note that it could conceivably
14186 be a statement function, which probably isn't really a program unit
14187 per se, but if that comes up, it should be easy to check (being a
14188 nested function and all). */
14190 static const char *
14191 lang_printable_name (tree decl, int v)
14193 /* Just to keep GCC quiet about the unused variable.
14194 In theory, differing values of V should produce different
14199 if (TREE_CODE (decl) == ERROR_MARK)
14200 return "erroneous code";
14201 return IDENTIFIER_POINTER (DECL_NAME (decl));
14205 /* g77's function to print out name of current function that caused
14210 lang_print_error_function (const char *file)
14212 static ffeglobal last_g = NULL;
14213 static ffesymbol last_s = NULL;
14218 if ((ffecom_primary_entry_ == NULL)
14219 || (ffesymbol_global (ffecom_primary_entry_) == NULL))
14227 g = ffesymbol_global (ffecom_primary_entry_);
14228 if (ffecom_nested_entry_ == NULL)
14230 s = ffecom_primary_entry_;
14231 switch (ffesymbol_kind (s))
14233 case FFEINFO_kindFUNCTION:
14237 case FFEINFO_kindSUBROUTINE:
14238 kind = "subroutine";
14241 case FFEINFO_kindPROGRAM:
14245 case FFEINFO_kindBLOCKDATA:
14246 kind = "block-data";
14250 kind = ffeinfo_kind_message (ffesymbol_kind (s));
14256 s = ffecom_nested_entry_;
14257 kind = "statement function";
14261 if ((last_g != g) || (last_s != s))
14264 fprintf (stderr, "%s: ", file);
14267 fprintf (stderr, "Outside of any program unit:\n");
14270 const char *name = ffesymbol_text (s);
14272 fprintf (stderr, "In %s `%s':\n", kind, name);
14281 /* Similar to `lookup_name' but look only at current binding level. */
14284 lookup_name_current_level (tree name)
14288 if (current_binding_level == global_binding_level)
14289 return IDENTIFIER_GLOBAL_VALUE (name);
14291 if (IDENTIFIER_LOCAL_VALUE (name) == 0)
14294 for (t = current_binding_level->names; t; t = TREE_CHAIN (t))
14295 if (DECL_NAME (t) == name)
14301 /* Create a new `struct binding_level'. */
14303 static struct binding_level *
14304 make_binding_level ()
14307 return (struct binding_level *) xmalloc (sizeof (struct binding_level));
14310 /* Save and restore the variables in this file and elsewhere
14311 that keep track of the progress of compilation of the current function.
14312 Used for nested functions. */
14316 struct f_function *next;
14318 tree shadowed_labels;
14319 struct binding_level *binding_level;
14322 struct f_function *f_function_chain;
14324 /* Restore the variables used during compilation of a C function. */
14327 pop_f_function_context ()
14329 struct f_function *p = f_function_chain;
14332 /* Bring back all the labels that were shadowed. */
14333 for (link = shadowed_labels; link; link = TREE_CHAIN (link))
14334 if (DECL_NAME (TREE_VALUE (link)) != 0)
14335 IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)))
14336 = TREE_VALUE (link);
14338 if (current_function_decl != error_mark_node
14339 && DECL_SAVED_INSNS (current_function_decl) == 0)
14341 /* Stop pointing to the local nodes about to be freed. */
14342 /* But DECL_INITIAL must remain nonzero so we know this was an actual
14343 function definition. */
14344 DECL_INITIAL (current_function_decl) = error_mark_node;
14345 DECL_ARGUMENTS (current_function_decl) = 0;
14348 pop_function_context ();
14350 f_function_chain = p->next;
14352 named_labels = p->named_labels;
14353 shadowed_labels = p->shadowed_labels;
14354 current_binding_level = p->binding_level;
14359 /* Save and reinitialize the variables
14360 used during compilation of a C function. */
14363 push_f_function_context ()
14365 struct f_function *p
14366 = (struct f_function *) xmalloc (sizeof (struct f_function));
14368 push_function_context ();
14370 p->next = f_function_chain;
14371 f_function_chain = p;
14373 p->named_labels = named_labels;
14374 p->shadowed_labels = shadowed_labels;
14375 p->binding_level = current_binding_level;
14379 push_parm_decl (tree parm)
14381 int old_immediate_size_expand = immediate_size_expand;
14383 /* Don't try computing parm sizes now -- wait till fn is called. */
14385 immediate_size_expand = 0;
14387 push_obstacks_nochange ();
14389 /* Fill in arg stuff. */
14391 DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
14392 DECL_ARG_TYPE_AS_WRITTEN (parm) = TREE_TYPE (parm);
14393 TREE_READONLY (parm) = 1; /* All implementation args are read-only. */
14395 parm = pushdecl (parm);
14397 immediate_size_expand = old_immediate_size_expand;
14399 finish_decl (parm, NULL_TREE, FALSE);
14402 /* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL, if appropriate. */
14405 pushdecl_top_level (x)
14409 register struct binding_level *b = current_binding_level;
14410 register tree f = current_function_decl;
14412 current_binding_level = global_binding_level;
14413 current_function_decl = NULL_TREE;
14415 current_binding_level = b;
14416 current_function_decl = f;
14420 /* Store the list of declarations of the current level.
14421 This is done for the parameter declarations of a function being defined,
14422 after they are modified in the light of any missing parameters. */
14428 return current_binding_level->names = decls;
14431 /* Store the parameter declarations into the current function declaration.
14432 This is called after parsing the parameter declarations, before
14433 digesting the body of the function.
14435 For an old-style definition, modify the function's type
14436 to specify at least the number of arguments. */
14439 store_parm_decls (int is_main_program UNUSED)
14441 register tree fndecl = current_function_decl;
14443 if (fndecl == error_mark_node)
14446 /* This is a chain of PARM_DECLs from old-style parm declarations. */
14447 DECL_ARGUMENTS (fndecl) = storedecls (nreverse (getdecls ()));
14449 /* Initialize the RTL code for the function. */
14451 init_function_start (fndecl, input_filename, lineno);
14453 /* Set up parameters and prepare for return, for the function. */
14455 expand_function_start (fndecl, 0);
14459 start_decl (tree decl, bool is_top_level)
14462 bool at_top_level = (current_binding_level == global_binding_level);
14463 bool top_level = is_top_level || at_top_level;
14465 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
14467 assert (!is_top_level || !at_top_level);
14469 /* The corresponding pop_obstacks is in finish_decl. */
14470 push_obstacks_nochange ();
14472 if (DECL_INITIAL (decl) != NULL_TREE)
14474 assert (DECL_INITIAL (decl) == error_mark_node);
14475 assert (!DECL_EXTERNAL (decl));
14477 else if (top_level)
14478 assert ((TREE_STATIC (decl) == 1) || DECL_EXTERNAL (decl) == 1);
14480 /* For Fortran, we by default put things in .common when possible. */
14481 DECL_COMMON (decl) = 1;
14483 /* Add this decl to the current binding level. TEM may equal DECL or it may
14484 be a previous decl of the same name. */
14486 tem = pushdecl_top_level (decl);
14488 tem = pushdecl (decl);
14490 /* For a local variable, define the RTL now. */
14492 /* But not if this is a duplicate decl and we preserved the rtl from the
14493 previous one (which may or may not happen). */
14494 && DECL_RTL (tem) == 0)
14496 if (TYPE_SIZE (TREE_TYPE (tem)) != 0)
14498 else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
14499 && DECL_INITIAL (tem) != 0)
14503 if (DECL_INITIAL (tem) != NULL_TREE)
14505 /* When parsing and digesting the initializer, use temporary storage.
14506 Do this even if we will ignore the value. */
14508 temporary_allocation ();
14514 /* Create the FUNCTION_DECL for a function definition.
14515 DECLSPECS and DECLARATOR are the parts of the declaration;
14516 they describe the function's name and the type it returns,
14517 but twisted together in a fashion that parallels the syntax of C.
14519 This function creates a binding context for the function body
14520 as well as setting up the FUNCTION_DECL in current_function_decl.
14522 Returns 1 on success. If the DECLARATOR is not suitable for a function
14523 (it defines a datum instead), we return 0, which tells
14524 yyparse to report a parse error.
14526 NESTED is nonzero for a function nested within another function. */
14529 start_function (tree name, tree type, int nested, int public)
14533 int old_immediate_size_expand = immediate_size_expand;
14536 shadowed_labels = 0;
14538 /* Don't expand any sizes in the return type of the function. */
14539 immediate_size_expand = 0;
14544 assert (current_function_decl != NULL_TREE);
14545 assert (DECL_CONTEXT (current_function_decl) == NULL_TREE);
14549 assert (current_function_decl == NULL_TREE);
14552 if (TREE_CODE (type) == ERROR_MARK)
14553 decl1 = current_function_decl = error_mark_node;
14556 decl1 = build_decl (FUNCTION_DECL,
14559 TREE_PUBLIC (decl1) = public ? 1 : 0;
14561 DECL_INLINE (decl1) = 1;
14562 TREE_STATIC (decl1) = 1;
14563 DECL_EXTERNAL (decl1) = 0;
14565 announce_function (decl1);
14567 /* Make the init_value nonzero so pushdecl knows this is not tentative.
14568 error_mark_node is replaced below (in poplevel) with the BLOCK. */
14569 DECL_INITIAL (decl1) = error_mark_node;
14571 /* Record the decl so that the function name is defined. If we already have
14572 a decl for this name, and it is a FUNCTION_DECL, use the old decl. */
14574 current_function_decl = pushdecl (decl1);
14578 ffecom_outer_function_decl_ = current_function_decl;
14581 current_binding_level->prep_state = 2;
14583 if (TREE_CODE (current_function_decl) != ERROR_MARK)
14585 make_function_rtl (current_function_decl);
14587 restype = TREE_TYPE (TREE_TYPE (current_function_decl));
14588 DECL_RESULT (current_function_decl)
14589 = build_decl (RESULT_DECL, NULL_TREE, restype);
14593 /* Allocate further tree nodes temporarily during compilation of this
14595 temporary_allocation ();
14597 if (!nested && (TREE_CODE (current_function_decl) != ERROR_MARK))
14598 TREE_ADDRESSABLE (current_function_decl) = 1;
14600 immediate_size_expand = old_immediate_size_expand;
14603 /* Here are the public functions the GNU back end needs. */
14606 convert (type, expr)
14609 register tree e = expr;
14610 register enum tree_code code = TREE_CODE (type);
14612 if (type == TREE_TYPE (e)
14613 || TREE_CODE (e) == ERROR_MARK)
14615 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
14616 return fold (build1 (NOP_EXPR, type, e));
14617 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
14618 || code == ERROR_MARK)
14619 return error_mark_node;
14620 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
14622 assert ("void value not ignored as it ought to be" == NULL);
14623 return error_mark_node;
14625 if (code == VOID_TYPE)
14626 return build1 (CONVERT_EXPR, type, e);
14627 if ((code != RECORD_TYPE)
14628 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
14629 e = ffecom_1 (REALPART_EXPR, TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e))),
14631 if (code == INTEGER_TYPE || code == ENUMERAL_TYPE)
14632 return fold (convert_to_integer (type, e));
14633 if (code == POINTER_TYPE)
14634 return fold (convert_to_pointer (type, e));
14635 if (code == REAL_TYPE)
14636 return fold (convert_to_real (type, e));
14637 if (code == COMPLEX_TYPE)
14638 return fold (convert_to_complex (type, e));
14639 if (code == RECORD_TYPE)
14640 return fold (ffecom_convert_to_complex_ (type, e));
14642 assert ("conversion to non-scalar type requested" == NULL);
14643 return error_mark_node;
14646 /* integrate_decl_tree calls this function, but since we don't use the
14647 DECL_LANG_SPECIFIC field, this is a no-op. */
14650 copy_lang_decl (node)
14655 /* Return the list of declarations of the current level.
14656 Note that this list is in reverse order unless/until
14657 you nreverse it; and when you do nreverse it, you must
14658 store the result back using `storedecls' or you will lose. */
14663 return current_binding_level->names;
14666 /* Nonzero if we are currently in the global binding level. */
14669 global_bindings_p ()
14671 return current_binding_level == global_binding_level;
14674 /* Print an error message for invalid use of an incomplete type.
14675 VALUE is the expression that was used (or 0 if that isn't known)
14676 and TYPE is the type that was invalid. */
14679 incomplete_type_error (value, type)
14683 if (TREE_CODE (type) == ERROR_MARK)
14686 assert ("incomplete type?!?" == NULL);
14689 /* Mark ARG for GC. */
14691 mark_binding_level (void *arg)
14693 struct binding_level *level = *(struct binding_level **) arg;
14697 ggc_mark_tree (level->names);
14698 ggc_mark_tree (level->blocks);
14699 ggc_mark_tree (level->this_block);
14700 level = level->level_chain;
14705 init_decl_processing ()
14707 static tree *const tree_roots[] = {
14708 ¤t_function_decl,
14710 &ffecom_tree_fun_type_void,
14711 &ffecom_integer_zero_node,
14712 &ffecom_integer_one_node,
14713 &ffecom_tree_subr_type,
14714 &ffecom_tree_ptr_to_subr_type,
14715 &ffecom_tree_blockdata_type,
14716 &ffecom_tree_xargc_,
14717 &ffecom_f2c_integer_type_node,
14718 &ffecom_f2c_ptr_to_integer_type_node,
14719 &ffecom_f2c_address_type_node,
14720 &ffecom_f2c_real_type_node,
14721 &ffecom_f2c_ptr_to_real_type_node,
14722 &ffecom_f2c_doublereal_type_node,
14723 &ffecom_f2c_complex_type_node,
14724 &ffecom_f2c_doublecomplex_type_node,
14725 &ffecom_f2c_longint_type_node,
14726 &ffecom_f2c_logical_type_node,
14727 &ffecom_f2c_flag_type_node,
14728 &ffecom_f2c_ftnlen_type_node,
14729 &ffecom_f2c_ftnlen_zero_node,
14730 &ffecom_f2c_ftnlen_one_node,
14731 &ffecom_f2c_ftnlen_two_node,
14732 &ffecom_f2c_ptr_to_ftnlen_type_node,
14733 &ffecom_f2c_ftnint_type_node,
14734 &ffecom_f2c_ptr_to_ftnint_type_node,
14735 &ffecom_outer_function_decl_,
14736 &ffecom_previous_function_decl_,
14737 &ffecom_which_entrypoint_decl_,
14738 &ffecom_float_zero_,
14739 &ffecom_float_half_,
14740 &ffecom_double_zero_,
14741 &ffecom_double_half_,
14742 &ffecom_func_result_,
14743 &ffecom_func_length_,
14744 &ffecom_multi_type_node_,
14745 &ffecom_multi_retval_,
14753 /* Record our roots. */
14754 for (i = 0; i < sizeof(tree_roots)/sizeof(tree_roots[0]); i++)
14755 ggc_add_tree_root (tree_roots[i], 1);
14756 ggc_add_tree_root (&ffecom_tree_type[0][0],
14757 FFEINFO_basictype*FFEINFO_kindtype);
14758 ggc_add_tree_root (&ffecom_tree_fun_type[0][0],
14759 FFEINFO_basictype*FFEINFO_kindtype);
14760 ggc_add_tree_root (&ffecom_tree_ptr_to_fun_type[0][0],
14761 FFEINFO_basictype*FFEINFO_kindtype);
14762 ggc_add_tree_root (ffecom_gfrt_, FFECOM_gfrt);
14763 ggc_add_root (¤t_binding_level, 1, sizeof current_binding_level,
14764 mark_binding_level);
14765 ggc_add_root (&free_binding_level, 1, sizeof current_binding_level,
14766 mark_binding_level);
14767 ggc_add_root (&tracker_head, 1, sizeof tracker_head, mark_tracker_head);
14773 init_parse (filename)
14774 const char *filename;
14776 /* Open input file. */
14777 if (filename == 0 || !strcmp (filename, "-"))
14780 filename = "stdin";
14783 finput = fopen (filename, "r");
14785 pfatal_with_name (filename);
14787 #ifdef IO_BUFFER_SIZE
14788 setvbuf (finput, (char *) xmalloc (IO_BUFFER_SIZE), _IOFBF, IO_BUFFER_SIZE);
14791 /* Make identifier nodes long enough for the language-specific slots. */
14792 set_identifier_size (sizeof (struct lang_identifier));
14793 decl_printable_name = lang_printable_name;
14795 print_error_function = lang_print_error_function;
14807 /* Delete the node BLOCK from the current binding level.
14808 This is used for the block inside a stmt expr ({...})
14809 so that the block can be reinserted where appropriate. */
14812 delete_block (block)
14816 if (current_binding_level->blocks == block)
14817 current_binding_level->blocks = TREE_CHAIN (block);
14818 for (t = current_binding_level->blocks; t;)
14820 if (TREE_CHAIN (t) == block)
14821 TREE_CHAIN (t) = TREE_CHAIN (block);
14823 t = TREE_CHAIN (t);
14825 TREE_CHAIN (block) = NULL;
14826 /* Clear TREE_USED which is always set by poplevel.
14827 The flag is set again if insert_block is called. */
14828 TREE_USED (block) = 0;
14832 insert_block (block)
14835 TREE_USED (block) = 1;
14836 current_binding_level->blocks
14837 = chainon (current_binding_level->blocks, block);
14841 lang_decode_option (argc, argv)
14845 return ffe_decode_option (argc, argv);
14848 /* used by print-tree.c */
14851 lang_print_xnode (file, node, indent)
14861 ffe_terminate_0 ();
14863 if (ffe_is_ffedebug ())
14864 malloc_pool_display (malloc_pool_image ());
14873 /* Return the typed-based alias set for T, which may be an expression
14874 or a type. Return -1 if we don't do anything special. */
14877 lang_get_alias_set (t)
14878 tree t ATTRIBUTE_UNUSED;
14880 /* We do not wish to use alias-set based aliasing at all. Used in the
14881 extreme (every object with its own set, with equivalences recorded)
14882 it might be helpful, but there are problems when it comes to inlining.
14883 We get on ok with flag_argument_noalias, and alias-set aliasing does
14884 currently limit how stack slots can be reused, which is a lose. */
14889 lang_init_options ()
14891 /* Set default options for Fortran. */
14892 flag_move_all_movables = 1;
14893 flag_reduce_all_givs = 1;
14894 flag_argument_noalias = 2;
14895 flag_errno_math = 0;
14896 flag_complex_divide_method = 1;
14902 /* If the file is output from cpp, it should contain a first line
14903 `# 1 "real-filename"', and the current design of gcc (toplev.c
14904 in particular and the way it sets up information relied on by
14905 INCLUDE) requires that we read this now, and store the
14906 "real-filename" info in master_input_filename. Ask the lexer
14907 to try doing this. */
14908 ffelex_hash_kludge (finput);
14912 mark_addressable (exp)
14915 register tree x = exp;
14917 switch (TREE_CODE (x))
14920 case COMPONENT_REF:
14922 x = TREE_OPERAND (x, 0);
14926 TREE_ADDRESSABLE (x) = 1;
14933 if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x)
14934 && DECL_NONLOCAL (x))
14936 if (TREE_PUBLIC (x))
14938 assert ("address of global register var requested" == NULL);
14941 assert ("address of register variable requested" == NULL);
14943 else if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x))
14945 if (TREE_PUBLIC (x))
14947 assert ("address of global register var requested" == NULL);
14950 assert ("address of register var requested" == NULL);
14952 put_var_into_stack (x);
14955 case FUNCTION_DECL:
14956 TREE_ADDRESSABLE (x) = 1;
14957 #if 0 /* poplevel deals with this now. */
14958 if (DECL_CONTEXT (x) == 0)
14959 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;
14967 /* If DECL has a cleanup, build and return that cleanup here.
14968 This is a callback called by expand_expr. */
14971 maybe_build_cleanup (decl)
14974 /* There are no cleanups in Fortran. */
14978 /* Exit a binding level.
14979 Pop the level off, and restore the state of the identifier-decl mappings
14980 that were in effect when this level was entered.
14982 If KEEP is nonzero, this level had explicit declarations, so
14983 and create a "block" (a BLOCK node) for the level
14984 to record its declarations and subblocks for symbol table output.
14986 If FUNCTIONBODY is nonzero, this level is the body of a function,
14987 so create a block as if KEEP were set and also clear out all
14990 If REVERSE is nonzero, reverse the order of decls before putting
14991 them into the BLOCK. */
14994 poplevel (keep, reverse, functionbody)
14999 register tree link;
15000 /* The chain of decls was accumulated in reverse order.
15001 Put it into forward order, just for cleanliness. */
15003 tree subblocks = current_binding_level->blocks;
15006 int block_previously_created;
15008 /* Get the decls in the order they were written.
15009 Usually current_binding_level->names is in reverse order.
15010 But parameter decls were previously put in forward order. */
15013 current_binding_level->names
15014 = decls = nreverse (current_binding_level->names);
15016 decls = current_binding_level->names;
15018 /* Output any nested inline functions within this block
15019 if they weren't already output. */
15021 for (decl = decls; decl; decl = TREE_CHAIN (decl))
15022 if (TREE_CODE (decl) == FUNCTION_DECL
15023 && ! TREE_ASM_WRITTEN (decl)
15024 && DECL_INITIAL (decl) != 0
15025 && TREE_ADDRESSABLE (decl))
15027 /* If this decl was copied from a file-scope decl
15028 on account of a block-scope extern decl,
15029 propagate TREE_ADDRESSABLE to the file-scope decl.
15031 DECL_ABSTRACT_ORIGIN can be set to itself if warn_return_type is
15032 true, since then the decl goes through save_for_inline_copying. */
15033 if (DECL_ABSTRACT_ORIGIN (decl) != 0
15034 && DECL_ABSTRACT_ORIGIN (decl) != decl)
15035 TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
15036 else if (DECL_SAVED_INSNS (decl) != 0)
15038 push_function_context ();
15039 output_inline_function (decl);
15040 pop_function_context ();
15044 /* If there were any declarations or structure tags in that level,
15045 or if this level is a function body,
15046 create a BLOCK to record them for the life of this function. */
15049 block_previously_created = (current_binding_level->this_block != 0);
15050 if (block_previously_created)
15051 block = current_binding_level->this_block;
15052 else if (keep || functionbody)
15053 block = make_node (BLOCK);
15056 BLOCK_VARS (block) = decls;
15057 BLOCK_SUBBLOCKS (block) = subblocks;
15060 /* In each subblock, record that this is its superior. */
15062 for (link = subblocks; link; link = TREE_CHAIN (link))
15063 BLOCK_SUPERCONTEXT (link) = block;
15065 /* Clear out the meanings of the local variables of this level. */
15067 for (link = decls; link; link = TREE_CHAIN (link))
15069 if (DECL_NAME (link) != 0)
15071 /* If the ident. was used or addressed via a local extern decl,
15072 don't forget that fact. */
15073 if (DECL_EXTERNAL (link))
15075 if (TREE_USED (link))
15076 TREE_USED (DECL_NAME (link)) = 1;
15077 if (TREE_ADDRESSABLE (link))
15078 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1;
15080 IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = 0;
15084 /* If the level being exited is the top level of a function,
15085 check over all the labels, and clear out the current
15086 (function local) meanings of their names. */
15090 /* If this is the top level block of a function,
15091 the vars are the function's parameters.
15092 Don't leave them in the BLOCK because they are
15093 found in the FUNCTION_DECL instead. */
15095 BLOCK_VARS (block) = 0;
15098 /* Pop the current level, and free the structure for reuse. */
15101 register struct binding_level *level = current_binding_level;
15102 current_binding_level = current_binding_level->level_chain;
15104 level->level_chain = free_binding_level;
15105 free_binding_level = level;
15108 /* Dispose of the block that we just made inside some higher level. */
15110 && current_function_decl != error_mark_node)
15111 DECL_INITIAL (current_function_decl) = block;
15114 if (!block_previously_created)
15115 current_binding_level->blocks
15116 = chainon (current_binding_level->blocks, block);
15118 /* If we did not make a block for the level just exited,
15119 any blocks made for inner levels
15120 (since they cannot be recorded as subblocks in that level)
15121 must be carried forward so they will later become subblocks
15122 of something else. */
15123 else if (subblocks)
15124 current_binding_level->blocks
15125 = chainon (current_binding_level->blocks, subblocks);
15128 TREE_USED (block) = 1;
15133 print_lang_decl (file, node, indent)
15141 print_lang_identifier (file, node, indent)
15146 print_node (file, "global", IDENTIFIER_GLOBAL_VALUE (node), indent + 4);
15147 print_node (file, "local", IDENTIFIER_LOCAL_VALUE (node), indent + 4);
15151 print_lang_statistics ()
15156 print_lang_type (file, node, indent)
15163 /* Record a decl-node X as belonging to the current lexical scope.
15164 Check for errors (such as an incompatible declaration for the same
15165 name already seen in the same scope).
15167 Returns either X or an old decl for the same name.
15168 If an old decl is returned, it may have been smashed
15169 to agree with what X says. */
15176 register tree name = DECL_NAME (x);
15177 register struct binding_level *b = current_binding_level;
15179 if ((TREE_CODE (x) == FUNCTION_DECL)
15180 && (DECL_INITIAL (x) == 0)
15181 && DECL_EXTERNAL (x))
15182 DECL_CONTEXT (x) = NULL_TREE;
15184 DECL_CONTEXT (x) = current_function_decl;
15188 if (IDENTIFIER_INVENTED (name))
15191 DECL_ARTIFICIAL (x) = 1;
15193 DECL_IN_SYSTEM_HEADER (x) = 1;
15196 t = lookup_name_current_level (name);
15198 assert ((t == NULL_TREE) || (DECL_CONTEXT (x) == NULL_TREE));
15200 /* Don't push non-parms onto list for parms until we understand
15201 why we're doing this and whether it works. */
15203 assert ((b == global_binding_level)
15204 || !ffecom_transform_only_dummies_
15205 || TREE_CODE (x) == PARM_DECL);
15207 if ((t != NULL_TREE) && duplicate_decls (x, t))
15210 /* If we are processing a typedef statement, generate a whole new
15211 ..._TYPE node (which will be just an variant of the existing
15212 ..._TYPE node with identical properties) and then install the
15213 TYPE_DECL node generated to represent the typedef name as the
15214 TYPE_NAME of this brand new (duplicate) ..._TYPE node.
15216 The whole point here is to end up with a situation where each and every
15217 ..._TYPE node the compiler creates will be uniquely associated with
15218 AT MOST one node representing a typedef name. This way, even though
15219 the compiler substitutes corresponding ..._TYPE nodes for TYPE_DECL
15220 (i.e. "typedef name") nodes very early on, later parts of the
15221 compiler can always do the reverse translation and get back the
15222 corresponding typedef name. For example, given:
15224 typedef struct S MY_TYPE; MY_TYPE object;
15226 Later parts of the compiler might only know that `object' was of type
15227 `struct S' if it were not for code just below. With this code
15228 however, later parts of the compiler see something like:
15230 struct S' == struct S typedef struct S' MY_TYPE; struct S' object;
15232 And they can then deduce (from the node for type struct S') that the
15233 original object declaration was:
15237 Being able to do this is important for proper support of protoize, and
15238 also for generating precise symbolic debugging information which
15239 takes full account of the programmer's (typedef) vocabulary.
15241 Obviously, we don't want to generate a duplicate ..._TYPE node if the
15242 TYPE_DECL node that we are now processing really represents a
15243 standard built-in type.
15245 Since all standard types are effectively declared at line zero in the
15246 source file, we can easily check to see if we are working on a
15247 standard type by checking the current value of lineno. */
15249 if (TREE_CODE (x) == TYPE_DECL)
15251 if (DECL_SOURCE_LINE (x) == 0)
15253 if (TYPE_NAME (TREE_TYPE (x)) == 0)
15254 TYPE_NAME (TREE_TYPE (x)) = x;
15256 else if (TREE_TYPE (x) != error_mark_node)
15258 tree tt = TREE_TYPE (x);
15260 tt = build_type_copy (tt);
15261 TYPE_NAME (tt) = x;
15262 TREE_TYPE (x) = tt;
15266 /* This name is new in its binding level. Install the new declaration
15268 if (b == global_binding_level)
15269 IDENTIFIER_GLOBAL_VALUE (name) = x;
15271 IDENTIFIER_LOCAL_VALUE (name) = x;
15274 /* Put decls on list in reverse order. We will reverse them later if
15276 TREE_CHAIN (x) = b->names;
15282 /* Nonzero if the current level needs to have a BLOCK made. */
15289 for (decl = current_binding_level->names;
15291 decl = TREE_CHAIN (decl))
15293 if (TREE_USED (decl) || TREE_CODE (decl) != VAR_DECL
15294 || (DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl)))
15295 /* Currently, there aren't supposed to be non-artificial names
15296 at other than the top block for a function -- they're
15297 believed to always be temps. But it's wise to check anyway. */
15303 /* Enter a new binding level.
15304 If TAG_TRANSPARENT is nonzero, do so only for the name space of variables,
15305 not for that of tags. */
15308 pushlevel (tag_transparent)
15309 int tag_transparent;
15311 register struct binding_level *newlevel = NULL_BINDING_LEVEL;
15313 assert (! tag_transparent);
15315 if (current_binding_level == global_binding_level)
15320 /* Reuse or create a struct for this binding level. */
15322 if (free_binding_level)
15324 newlevel = free_binding_level;
15325 free_binding_level = free_binding_level->level_chain;
15329 newlevel = make_binding_level ();
15332 /* Add this level to the front of the chain (stack) of levels that
15335 *newlevel = clear_binding_level;
15336 newlevel->level_chain = current_binding_level;
15337 current_binding_level = newlevel;
15340 /* Set the BLOCK node for the innermost scope
15341 (the one we are currently in). */
15345 register tree block;
15347 current_binding_level->this_block = block;
15350 /* ~~gcc/tree.h *should* declare this, because toplev.c references it. */
15352 /* Can't 'yydebug' a front end not generated by yacc/bison! */
15355 set_yydebug (value)
15359 fprintf (stderr, "warning: no yacc/bison-generated output to debug!\n");
15363 signed_or_unsigned_type (unsignedp, type)
15369 if (! INTEGRAL_TYPE_P (type))
15371 if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node))
15372 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15373 if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
15374 return unsignedp ? unsigned_type_node : integer_type_node;
15375 if (TYPE_PRECISION (type) == TYPE_PRECISION (short_integer_type_node))
15376 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15377 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_integer_type_node))
15378 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15379 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_long_integer_type_node))
15380 return (unsignedp ? long_long_unsigned_type_node
15381 : long_long_integer_type_node);
15383 type2 = type_for_size (TYPE_PRECISION (type), unsignedp);
15384 if (type2 == NULL_TREE)
15394 tree type1 = TYPE_MAIN_VARIANT (type);
15395 ffeinfoKindtype kt;
15398 if (type1 == unsigned_char_type_node || type1 == char_type_node)
15399 return signed_char_type_node;
15400 if (type1 == unsigned_type_node)
15401 return integer_type_node;
15402 if (type1 == short_unsigned_type_node)
15403 return short_integer_type_node;
15404 if (type1 == long_unsigned_type_node)
15405 return long_integer_type_node;
15406 if (type1 == long_long_unsigned_type_node)
15407 return long_long_integer_type_node;
15408 #if 0 /* gcc/c-* files only */
15409 if (type1 == unsigned_intDI_type_node)
15410 return intDI_type_node;
15411 if (type1 == unsigned_intSI_type_node)
15412 return intSI_type_node;
15413 if (type1 == unsigned_intHI_type_node)
15414 return intHI_type_node;
15415 if (type1 == unsigned_intQI_type_node)
15416 return intQI_type_node;
15419 type2 = type_for_size (TYPE_PRECISION (type1), 0);
15420 if (type2 != NULL_TREE)
15423 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15425 type2 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
15427 if (type1 == type2)
15428 return ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15434 /* Prepare expr to be an argument of a TRUTH_NOT_EXPR,
15435 or validate its data type for an `if' or `while' statement or ?..: exp.
15437 This preparation consists of taking the ordinary
15438 representation of an expression expr and producing a valid tree
15439 boolean expression describing whether expr is nonzero. We could
15440 simply always do build_binary_op (NE_EXPR, expr, integer_zero_node, 1),
15441 but we optimize comparisons, &&, ||, and !.
15443 The resulting type should always be `integer_type_node'. */
15446 truthvalue_conversion (expr)
15449 if (TREE_CODE (expr) == ERROR_MARK)
15452 #if 0 /* This appears to be wrong for C++. */
15453 /* These really should return error_mark_node after 2.4 is stable.
15454 But not all callers handle ERROR_MARK properly. */
15455 switch (TREE_CODE (TREE_TYPE (expr)))
15458 error ("struct type value used where scalar is required");
15459 return integer_zero_node;
15462 error ("union type value used where scalar is required");
15463 return integer_zero_node;
15466 error ("array type value used where scalar is required");
15467 return integer_zero_node;
15474 switch (TREE_CODE (expr))
15476 /* It is simpler and generates better code to have only TRUTH_*_EXPR
15477 or comparison expressions as truth values at this level. */
15479 case COMPONENT_REF:
15480 /* A one-bit unsigned bit-field is already acceptable. */
15481 if (1 == TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (expr, 1)))
15482 && TREE_UNSIGNED (TREE_OPERAND (expr, 1)))
15488 /* It is simpler and generates better code to have only TRUTH_*_EXPR
15489 or comparison expressions as truth values at this level. */
15491 if (integer_zerop (TREE_OPERAND (expr, 1)))
15492 return build_unary_op (TRUTH_NOT_EXPR, TREE_OPERAND (expr, 0), 0);
15494 case NE_EXPR: case LE_EXPR: case GE_EXPR: case LT_EXPR: case GT_EXPR:
15495 case TRUTH_ANDIF_EXPR:
15496 case TRUTH_ORIF_EXPR:
15497 case TRUTH_AND_EXPR:
15498 case TRUTH_OR_EXPR:
15499 case TRUTH_XOR_EXPR:
15500 TREE_TYPE (expr) = integer_type_node;
15507 return integer_zerop (expr) ? integer_zero_node : integer_one_node;
15510 return real_zerop (expr) ? integer_zero_node : integer_one_node;
15513 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 0)))
15514 return build (COMPOUND_EXPR, integer_type_node,
15515 TREE_OPERAND (expr, 0), integer_one_node);
15517 return integer_one_node;
15520 return ffecom_2 ((TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
15521 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
15523 truthvalue_conversion (TREE_OPERAND (expr, 0)),
15524 truthvalue_conversion (TREE_OPERAND (expr, 1)));
15530 /* These don't change whether an object is non-zero or zero. */
15531 return truthvalue_conversion (TREE_OPERAND (expr, 0));
15535 /* These don't change whether an object is zero or non-zero, but
15536 we can't ignore them if their second arg has side-effects. */
15537 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
15538 return build (COMPOUND_EXPR, integer_type_node, TREE_OPERAND (expr, 1),
15539 truthvalue_conversion (TREE_OPERAND (expr, 0)));
15541 return truthvalue_conversion (TREE_OPERAND (expr, 0));
15544 /* Distribute the conversion into the arms of a COND_EXPR. */
15545 return fold (build (COND_EXPR, integer_type_node, TREE_OPERAND (expr, 0),
15546 truthvalue_conversion (TREE_OPERAND (expr, 1)),
15547 truthvalue_conversion (TREE_OPERAND (expr, 2))));
15550 /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
15551 since that affects how `default_conversion' will behave. */
15552 if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE
15553 || TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE)
15555 /* fall through... */
15557 /* If this is widening the argument, we can ignore it. */
15558 if (TYPE_PRECISION (TREE_TYPE (expr))
15559 >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))
15560 return truthvalue_conversion (TREE_OPERAND (expr, 0));
15564 /* With IEEE arithmetic, x - x may not equal 0, so we can't optimize
15566 if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
15567 && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE)
15569 /* fall through... */
15571 /* This and MINUS_EXPR can be changed into a comparison of the
15573 if (TREE_TYPE (TREE_OPERAND (expr, 0))
15574 == TREE_TYPE (TREE_OPERAND (expr, 1)))
15575 return ffecom_2 (NE_EXPR, integer_type_node,
15576 TREE_OPERAND (expr, 0),
15577 TREE_OPERAND (expr, 1));
15578 return ffecom_2 (NE_EXPR, integer_type_node,
15579 TREE_OPERAND (expr, 0),
15580 fold (build1 (NOP_EXPR,
15581 TREE_TYPE (TREE_OPERAND (expr, 0)),
15582 TREE_OPERAND (expr, 1))));
15585 if (integer_onep (TREE_OPERAND (expr, 1)))
15590 #if 0 /* No such thing in Fortran. */
15591 if (warn_parentheses && C_EXP_ORIGINAL_CODE (expr) == MODIFY_EXPR)
15592 warning ("suggest parentheses around assignment used as truth value");
15600 if (TREE_CODE (TREE_TYPE (expr)) == COMPLEX_TYPE)
15602 ((TREE_SIDE_EFFECTS (expr)
15603 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
15605 truthvalue_conversion (ffecom_1 (REALPART_EXPR,
15606 TREE_TYPE (TREE_TYPE (expr)),
15608 truthvalue_conversion (ffecom_1 (IMAGPART_EXPR,
15609 TREE_TYPE (TREE_TYPE (expr)),
15612 return ffecom_2 (NE_EXPR, integer_type_node,
15614 convert (TREE_TYPE (expr), integer_zero_node));
15618 type_for_mode (mode, unsignedp)
15619 enum machine_mode mode;
15626 if (mode == TYPE_MODE (integer_type_node))
15627 return unsignedp ? unsigned_type_node : integer_type_node;
15629 if (mode == TYPE_MODE (signed_char_type_node))
15630 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15632 if (mode == TYPE_MODE (short_integer_type_node))
15633 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15635 if (mode == TYPE_MODE (long_integer_type_node))
15636 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15638 if (mode == TYPE_MODE (long_long_integer_type_node))
15639 return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
15641 #if HOST_BITS_PER_WIDE_INT >= 64
15642 if (mode == TYPE_MODE (intTI_type_node))
15643 return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
15646 if (mode == TYPE_MODE (float_type_node))
15647 return float_type_node;
15649 if (mode == TYPE_MODE (double_type_node))
15650 return double_type_node;
15652 if (mode == TYPE_MODE (build_pointer_type (char_type_node)))
15653 return build_pointer_type (char_type_node);
15655 if (mode == TYPE_MODE (build_pointer_type (integer_type_node)))
15656 return build_pointer_type (integer_type_node);
15658 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
15659 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
15661 if (((t = ffecom_tree_type[i][j]) != NULL_TREE)
15662 && (mode == TYPE_MODE (t)))
15664 if ((i == FFEINFO_basictypeINTEGER) && unsignedp)
15665 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][j];
15675 type_for_size (bits, unsignedp)
15679 ffeinfoKindtype kt;
15682 if (bits == TYPE_PRECISION (integer_type_node))
15683 return unsignedp ? unsigned_type_node : integer_type_node;
15685 if (bits == TYPE_PRECISION (signed_char_type_node))
15686 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15688 if (bits == TYPE_PRECISION (short_integer_type_node))
15689 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15691 if (bits == TYPE_PRECISION (long_integer_type_node))
15692 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15694 if (bits == TYPE_PRECISION (long_long_integer_type_node))
15695 return (unsignedp ? long_long_unsigned_type_node
15696 : long_long_integer_type_node);
15698 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15700 type_node = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15702 if ((type_node != NULL_TREE) && (bits == TYPE_PRECISION (type_node)))
15703 return unsignedp ? ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt]
15711 unsigned_type (type)
15714 tree type1 = TYPE_MAIN_VARIANT (type);
15715 ffeinfoKindtype kt;
15718 if (type1 == signed_char_type_node || type1 == char_type_node)
15719 return unsigned_char_type_node;
15720 if (type1 == integer_type_node)
15721 return unsigned_type_node;
15722 if (type1 == short_integer_type_node)
15723 return short_unsigned_type_node;
15724 if (type1 == long_integer_type_node)
15725 return long_unsigned_type_node;
15726 if (type1 == long_long_integer_type_node)
15727 return long_long_unsigned_type_node;
15728 #if 0 /* gcc/c-* files only */
15729 if (type1 == intDI_type_node)
15730 return unsigned_intDI_type_node;
15731 if (type1 == intSI_type_node)
15732 return unsigned_intSI_type_node;
15733 if (type1 == intHI_type_node)
15734 return unsigned_intHI_type_node;
15735 if (type1 == intQI_type_node)
15736 return unsigned_intQI_type_node;
15739 type2 = type_for_size (TYPE_PRECISION (type1), 1);
15740 if (type2 != NULL_TREE)
15743 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15745 type2 = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15747 if (type1 == type2)
15748 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
15754 /* Callback routines for garbage collection. */
15760 union tree_node *t ATTRIBUTE_UNUSED;
15762 if (TREE_CODE (t) == IDENTIFIER_NODE)
15764 struct lang_identifier *i = (struct lang_identifier *) t;
15765 ggc_mark_tree (IDENTIFIER_GLOBAL_VALUE (i));
15766 ggc_mark_tree (IDENTIFIER_LOCAL_VALUE (i));
15767 ggc_mark_tree (IDENTIFIER_LABEL_VALUE (i));
15769 else if (TYPE_P (t) && TYPE_LANG_SPECIFIC (t))
15770 ggc_mark (TYPE_LANG_SPECIFIC (t));
15774 lang_mark_false_label_stack (l)
15775 struct label_node *l;
15777 /* Fortran doesn't use false_label_stack. It better be NULL. */
15782 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
15784 #if FFECOM_GCC_INCLUDE
15786 /* From gcc/cccp.c, the code to handle -I. */
15788 /* Skip leading "./" from a directory name.
15789 This may yield the empty string, which represents the current directory. */
15791 static const char *
15792 skip_redundant_dir_prefix (const char *dir)
15794 while (dir[0] == '.' && dir[1] == '/')
15795 for (dir += 2; *dir == '/'; dir++)
15797 if (dir[0] == '.' && !dir[1])
15802 /* The file_name_map structure holds a mapping of file names for a
15803 particular directory. This mapping is read from the file named
15804 FILE_NAME_MAP_FILE in that directory. Such a file can be used to
15805 map filenames on a file system with severe filename restrictions,
15806 such as DOS. The format of the file name map file is just a series
15807 of lines with two tokens on each line. The first token is the name
15808 to map, and the second token is the actual name to use. */
15810 struct file_name_map
15812 struct file_name_map *map_next;
15817 #define FILE_NAME_MAP_FILE "header.gcc"
15819 /* Current maximum length of directory names in the search path
15820 for include files. (Altered as we get more of them.) */
15822 static int max_include_len = 0;
15824 struct file_name_list
15826 struct file_name_list *next;
15828 /* Mapping of file names for this directory. */
15829 struct file_name_map *name_map;
15830 /* Non-zero if name_map is valid. */
15834 static struct file_name_list *include = NULL; /* First dir to search */
15835 static struct file_name_list *last_include = NULL; /* Last in chain */
15837 /* I/O buffer structure.
15838 The `fname' field is nonzero for source files and #include files
15839 and for the dummy text used for -D and -U.
15840 It is zero for rescanning results of macro expansion
15841 and for expanding macro arguments. */
15842 #define INPUT_STACK_MAX 400
15843 static struct file_buf {
15845 /* Filename specified with #line command. */
15846 const char *nominal_fname;
15847 /* Record where in the search path this file was found.
15848 For #include_next. */
15849 struct file_name_list *dir;
15851 ffewhereColumn column;
15852 } instack[INPUT_STACK_MAX];
15854 static int last_error_tick = 0; /* Incremented each time we print it. */
15855 static int input_file_stack_tick = 0; /* Incremented when status changes. */
15857 /* Current nesting level of input sources.
15858 `instack[indepth]' is the level currently being read. */
15859 static int indepth = -1;
15861 typedef struct file_buf FILE_BUF;
15863 typedef unsigned char U_CHAR;
15865 /* table to tell if char can be part of a C identifier. */
15866 U_CHAR is_idchar[256];
15867 /* table to tell if char can be first char of a c identifier. */
15868 U_CHAR is_idstart[256];
15869 /* table to tell if c is horizontal space. */
15870 U_CHAR is_hor_space[256];
15871 /* table to tell if c is horizontal or vertical space. */
15872 static U_CHAR is_space[256];
15874 #define SKIP_WHITE_SPACE(p) do { while (is_hor_space[*p]) p++; } while (0)
15875 #define SKIP_ALL_WHITE_SPACE(p) do { while (is_space[*p]) p++; } while (0)
15877 /* Nonzero means -I- has been seen,
15878 so don't look for #include "foo" the source-file directory. */
15879 static int ignore_srcdir;
15881 #ifndef INCLUDE_LEN_FUDGE
15882 #define INCLUDE_LEN_FUDGE 0
15885 static void append_include_chain (struct file_name_list *first,
15886 struct file_name_list *last);
15887 static FILE *open_include_file (char *filename,
15888 struct file_name_list *searchptr);
15889 static void print_containing_files (ffebadSeverity sev);
15890 static const char *skip_redundant_dir_prefix (const char *);
15891 static char *read_filename_string (int ch, FILE *f);
15892 static struct file_name_map *read_name_map (const char *dirname);
15894 /* Append a chain of `struct file_name_list's
15895 to the end of the main include chain.
15896 FIRST is the beginning of the chain to append, and LAST is the end. */
15899 append_include_chain (first, last)
15900 struct file_name_list *first, *last;
15902 struct file_name_list *dir;
15904 if (!first || !last)
15910 last_include->next = first;
15912 for (dir = first; ; dir = dir->next) {
15913 int len = strlen (dir->fname) + INCLUDE_LEN_FUDGE;
15914 if (len > max_include_len)
15915 max_include_len = len;
15921 last_include = last;
15924 /* Try to open include file FILENAME. SEARCHPTR is the directory
15925 being tried from the include file search path. This function maps
15926 filenames on file systems based on information read by
15930 open_include_file (filename, searchptr)
15932 struct file_name_list *searchptr;
15934 register struct file_name_map *map;
15935 register char *from;
15938 if (searchptr && ! searchptr->got_name_map)
15940 searchptr->name_map = read_name_map (searchptr->fname
15941 ? searchptr->fname : ".");
15942 searchptr->got_name_map = 1;
15945 /* First check the mapping for the directory we are using. */
15946 if (searchptr && searchptr->name_map)
15949 if (searchptr->fname)
15950 from += strlen (searchptr->fname) + 1;
15951 for (map = searchptr->name_map; map; map = map->map_next)
15953 if (! strcmp (map->map_from, from))
15955 /* Found a match. */
15956 return fopen (map->map_to, "r");
15961 /* Try to find a mapping file for the particular directory we are
15962 looking in. Thus #include <sys/types.h> will look up sys/types.h
15963 in /usr/include/header.gcc and look up types.h in
15964 /usr/include/sys/header.gcc. */
15965 p = rindex (filename, '/');
15966 #ifdef DIR_SEPARATOR
15967 if (! p) p = rindex (filename, DIR_SEPARATOR);
15969 char *tmp = rindex (filename, DIR_SEPARATOR);
15970 if (tmp != NULL && tmp > p) p = tmp;
15976 && searchptr->fname
15977 && strlen (searchptr->fname) == (size_t) (p - filename)
15978 && ! strncmp (searchptr->fname, filename, (int) (p - filename)))
15980 /* FILENAME is in SEARCHPTR, which we've already checked. */
15981 return fopen (filename, "r");
15987 map = read_name_map (".");
15991 dir = (char *) xmalloc (p - filename + 1);
15992 memcpy (dir, filename, p - filename);
15993 dir[p - filename] = '\0';
15995 map = read_name_map (dir);
15998 for (; map; map = map->map_next)
15999 if (! strcmp (map->map_from, from))
16000 return fopen (map->map_to, "r");
16002 return fopen (filename, "r");
16005 /* Print the file names and line numbers of the #include
16006 commands which led to the current file. */
16009 print_containing_files (ffebadSeverity sev)
16011 FILE_BUF *ip = NULL;
16017 /* If stack of files hasn't changed since we last printed
16018 this info, don't repeat it. */
16019 if (last_error_tick == input_file_stack_tick)
16022 for (i = indepth; i >= 0; i--)
16023 if (instack[i].fname != NULL) {
16028 /* Give up if we don't find a source file. */
16032 /* Find the other, outer source files. */
16033 for (i--; i >= 0; i--)
16034 if (instack[i].fname != NULL)
16040 str1 = "In file included";
16052 ffebad_start_msg ("%A from %B at %0%C", sev);
16053 ffebad_here (0, ip->line, ip->column);
16054 ffebad_string (str1);
16055 ffebad_string (ip->nominal_fname);
16056 ffebad_string (str2);
16060 /* Record we have printed the status as of this time. */
16061 last_error_tick = input_file_stack_tick;
16064 /* Read a space delimited string of unlimited length from a stdio
16068 read_filename_string (ch, f)
16076 set = alloc = xmalloc (len + 1);
16077 if (! is_space[ch])
16080 while ((ch = getc (f)) != EOF && ! is_space[ch])
16082 if (set - alloc == len)
16085 alloc = xrealloc (alloc, len + 1);
16086 set = alloc + len / 2;
16096 /* Read the file name map file for DIRNAME. */
16098 static struct file_name_map *
16099 read_name_map (dirname)
16100 const char *dirname;
16102 /* This structure holds a linked list of file name maps, one per
16104 struct file_name_map_list
16106 struct file_name_map_list *map_list_next;
16107 char *map_list_name;
16108 struct file_name_map *map_list_map;
16110 static struct file_name_map_list *map_list;
16111 register struct file_name_map_list *map_list_ptr;
16115 int separator_needed;
16117 dirname = skip_redundant_dir_prefix (dirname);
16119 for (map_list_ptr = map_list; map_list_ptr;
16120 map_list_ptr = map_list_ptr->map_list_next)
16121 if (! strcmp (map_list_ptr->map_list_name, dirname))
16122 return map_list_ptr->map_list_map;
16124 map_list_ptr = ((struct file_name_map_list *)
16125 xmalloc (sizeof (struct file_name_map_list)));
16126 map_list_ptr->map_list_name = xstrdup (dirname);
16127 map_list_ptr->map_list_map = NULL;
16129 dirlen = strlen (dirname);
16130 separator_needed = dirlen != 0 && dirname[dirlen - 1] != '/';
16131 name = (char *) xmalloc (dirlen + strlen (FILE_NAME_MAP_FILE) + 2);
16132 strcpy (name, dirname);
16133 name[dirlen] = '/';
16134 strcpy (name + dirlen + separator_needed, FILE_NAME_MAP_FILE);
16135 f = fopen (name, "r");
16138 map_list_ptr->map_list_map = NULL;
16143 while ((ch = getc (f)) != EOF)
16146 struct file_name_map *ptr;
16150 from = read_filename_string (ch, f);
16151 while ((ch = getc (f)) != EOF && is_hor_space[ch])
16153 to = read_filename_string (ch, f);
16155 ptr = ((struct file_name_map *)
16156 xmalloc (sizeof (struct file_name_map)));
16157 ptr->map_from = from;
16159 /* Make the real filename absolute. */
16164 ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
16165 strcpy (ptr->map_to, dirname);
16166 ptr->map_to[dirlen] = '/';
16167 strcpy (ptr->map_to + dirlen + separator_needed, to);
16171 ptr->map_next = map_list_ptr->map_list_map;
16172 map_list_ptr->map_list_map = ptr;
16174 while ((ch = getc (f)) != '\n')
16181 map_list_ptr->map_list_next = map_list;
16182 map_list = map_list_ptr;
16184 return map_list_ptr->map_list_map;
16188 ffecom_file_ (const char *name)
16192 /* Do partial setup of input buffer for the sake of generating
16193 early #line directives (when -g is in effect). */
16195 fp = &instack[++indepth];
16196 memset ((char *) fp, 0, sizeof (FILE_BUF));
16199 fp->nominal_fname = fp->fname = name;
16202 /* Initialize syntactic classifications of characters. */
16205 ffecom_initialize_char_syntax_ ()
16210 * Set up is_idchar and is_idstart tables. These should be
16211 * faster than saying (is_alpha (c) || c == '_'), etc.
16212 * Set up these things before calling any routines tthat
16215 for (i = 'a'; i <= 'z'; i++) {
16216 is_idchar[i - 'a' + 'A'] = 1;
16218 is_idstart[i - 'a' + 'A'] = 1;
16221 for (i = '0'; i <= '9'; i++)
16223 is_idchar['_'] = 1;
16224 is_idstart['_'] = 1;
16226 /* horizontal space table */
16227 is_hor_space[' '] = 1;
16228 is_hor_space['\t'] = 1;
16229 is_hor_space['\v'] = 1;
16230 is_hor_space['\f'] = 1;
16231 is_hor_space['\r'] = 1;
16234 is_space['\t'] = 1;
16235 is_space['\v'] = 1;
16236 is_space['\f'] = 1;
16237 is_space['\n'] = 1;
16238 is_space['\r'] = 1;
16242 ffecom_close_include_ (FILE *f)
16247 input_file_stack_tick++;
16249 ffewhere_line_kill (instack[indepth].line);
16250 ffewhere_column_kill (instack[indepth].column);
16254 ffecom_decode_include_option_ (char *spec)
16256 struct file_name_list *dirtmp;
16258 if (! ignore_srcdir && !strcmp (spec, "-"))
16262 dirtmp = (struct file_name_list *)
16263 xmalloc (sizeof (struct file_name_list));
16264 dirtmp->next = 0; /* New one goes on the end */
16266 dirtmp->fname = spec;
16268 fatal ("Directory name must immediately follow -I option with no intervening spaces, as in `-Idir', not `-I dir'");
16269 dirtmp->got_name_map = 0;
16270 append_include_chain (dirtmp, dirtmp);
16275 /* Open INCLUDEd file. */
16278 ffecom_open_include_ (char *name, ffewhereLine l, ffewhereColumn c)
16281 size_t flen = strlen (fbeg);
16282 struct file_name_list *search_start = include; /* Chain of dirs to search */
16283 struct file_name_list dsp[1]; /* First in chain, if #include "..." */
16284 struct file_name_list *searchptr = 0;
16285 char *fname; /* Dynamically allocated fname buffer */
16292 dsp[0].fname = NULL;
16294 /* If -I- was specified, don't search current dir, only spec'd ones. */
16295 if (!ignore_srcdir)
16297 for (fp = &instack[indepth]; fp >= instack; fp--)
16303 if ((nam = fp->nominal_fname) != NULL)
16305 /* Found a named file. Figure out dir of the file,
16306 and put it in front of the search list. */
16307 dsp[0].next = search_start;
16308 search_start = dsp;
16310 ep = rindex (nam, '/');
16311 #ifdef DIR_SEPARATOR
16312 if (ep == NULL) ep = rindex (nam, DIR_SEPARATOR);
16314 char *tmp = rindex (nam, DIR_SEPARATOR);
16315 if (tmp != NULL && tmp > ep) ep = tmp;
16319 ep = rindex (nam, ']');
16320 if (ep == NULL) ep = rindex (nam, '>');
16321 if (ep == NULL) ep = rindex (nam, ':');
16322 if (ep != NULL) ep++;
16327 dsp[0].fname = (char *) xmalloc (n + 1);
16328 strncpy (dsp[0].fname, nam, n);
16329 dsp[0].fname[n] = '\0';
16330 if (n + INCLUDE_LEN_FUDGE > max_include_len)
16331 max_include_len = n + INCLUDE_LEN_FUDGE;
16334 dsp[0].fname = NULL; /* Current directory */
16335 dsp[0].got_name_map = 0;
16341 /* Allocate this permanently, because it gets stored in the definitions
16343 fname = xmalloc (max_include_len + flen + 4);
16344 /* + 2 above for slash and terminating null. */
16345 /* + 2 added for '.h' on VMS (to support '#include filename') (NOT USED
16348 /* If specified file name is absolute, just open it. */
16351 #ifdef DIR_SEPARATOR
16352 || *fbeg == DIR_SEPARATOR
16356 strncpy (fname, (char *) fbeg, flen);
16358 f = open_include_file (fname, NULL_PTR);
16364 /* Search directory path, trying to open the file.
16365 Copy each filename tried into FNAME. */
16367 for (searchptr = search_start; searchptr; searchptr = searchptr->next)
16369 if (searchptr->fname)
16371 /* The empty string in a search path is ignored.
16372 This makes it possible to turn off entirely
16373 a standard piece of the list. */
16374 if (searchptr->fname[0] == 0)
16376 strcpy (fname, skip_redundant_dir_prefix (searchptr->fname));
16377 if (fname[0] && fname[strlen (fname) - 1] != '/')
16378 strcat (fname, "/");
16379 fname[strlen (fname) + flen] = 0;
16384 strncat (fname, fbeg, flen);
16386 /* Change this 1/2 Unix 1/2 VMS file specification into a
16387 full VMS file specification */
16388 if (searchptr->fname && (searchptr->fname[0] != 0))
16390 /* Fix up the filename */
16391 hack_vms_include_specification (fname);
16395 /* This is a normal VMS filespec, so use it unchanged. */
16396 strncpy (fname, (char *) fbeg, flen);
16398 #if 0 /* Not for g77. */
16399 /* if it's '#include filename', add the missing .h */
16400 if (index (fname, '.') == NULL)
16401 strcat (fname, ".h");
16405 f = open_include_file (fname, searchptr);
16407 if (f == NULL && errno == EACCES)
16409 print_containing_files (FFEBAD_severityWARNING);
16410 ffebad_start_msg ("At %0, INCLUDE file %A exists, but is not readable",
16411 FFEBAD_severityWARNING);
16412 ffebad_string (fname);
16413 ffebad_here (0, l, c);
16424 /* A file that was not found. */
16426 strncpy (fname, (char *) fbeg, flen);
16428 print_containing_files (ffebad_severity (FFEBAD_OPEN_INCLUDE));
16429 ffebad_start (FFEBAD_OPEN_INCLUDE);
16430 ffebad_here (0, l, c);
16431 ffebad_string (fname);
16435 if (dsp[0].fname != NULL)
16436 free (dsp[0].fname);
16441 if (indepth >= (INPUT_STACK_MAX - 1))
16443 print_containing_files (FFEBAD_severityFATAL);
16444 ffebad_start_msg ("At %0, INCLUDE nesting too deep",
16445 FFEBAD_severityFATAL);
16446 ffebad_string (fname);
16447 ffebad_here (0, l, c);
16452 instack[indepth].line = ffewhere_line_use (l);
16453 instack[indepth].column = ffewhere_column_use (c);
16455 fp = &instack[indepth + 1];
16456 memset ((char *) fp, 0, sizeof (FILE_BUF));
16457 fp->nominal_fname = fp->fname = fname;
16458 fp->dir = searchptr;
16461 input_file_stack_tick++;
16465 #endif /* FFECOM_GCC_INCLUDE */
16467 /**INDENT* (Do not reformat this comment even with -fca option.)
16468 Data-gathering files: Given the source file listed below, compiled with
16469 f2c I obtained the output file listed after that, and from the output
16470 file I derived the above code.
16472 -------- (begin input file to f2c)
16478 double precision D1,D2
16480 call getem(A1,A2,C1,C2,I1,I2,R1,R2,D1,D2)
16507 c FFEINTRIN_impACOS
16508 call fooR(ACOS(R1))
16509 c FFEINTRIN_impAIMAG
16510 call fooR(AIMAG(C1))
16511 c FFEINTRIN_impAINT
16512 call fooR(AINT(R1))
16513 c FFEINTRIN_impALOG
16514 call fooR(ALOG(R1))
16515 c FFEINTRIN_impALOG10
16516 call fooR(ALOG10(R1))
16517 c FFEINTRIN_impAMAX0
16518 call fooR(AMAX0(I1,I2))
16519 c FFEINTRIN_impAMAX1
16520 call fooR(AMAX1(R1,R2))
16521 c FFEINTRIN_impAMIN0
16522 call fooR(AMIN0(I1,I2))
16523 c FFEINTRIN_impAMIN1
16524 call fooR(AMIN1(R1,R2))
16525 c FFEINTRIN_impAMOD
16526 call fooR(AMOD(R1,R2))
16527 c FFEINTRIN_impANINT
16528 call fooR(ANINT(R1))
16529 c FFEINTRIN_impASIN
16530 call fooR(ASIN(R1))
16531 c FFEINTRIN_impATAN
16532 call fooR(ATAN(R1))
16533 c FFEINTRIN_impATAN2
16534 call fooR(ATAN2(R1,R2))
16535 c FFEINTRIN_impCABS
16536 call fooR(CABS(C1))
16537 c FFEINTRIN_impCCOS
16538 call fooC(CCOS(C1))
16539 c FFEINTRIN_impCEXP
16540 call fooC(CEXP(C1))
16541 c FFEINTRIN_impCHAR
16542 call fooA(CHAR(I1))
16543 c FFEINTRIN_impCLOG
16544 call fooC(CLOG(C1))
16545 c FFEINTRIN_impCONJG
16546 call fooC(CONJG(C1))
16549 c FFEINTRIN_impCOSH
16550 call fooR(COSH(R1))
16551 c FFEINTRIN_impCSIN
16552 call fooC(CSIN(C1))
16553 c FFEINTRIN_impCSQRT
16554 call fooC(CSQRT(C1))
16555 c FFEINTRIN_impDABS
16556 call fooD(DABS(D1))
16557 c FFEINTRIN_impDACOS
16558 call fooD(DACOS(D1))
16559 c FFEINTRIN_impDASIN
16560 call fooD(DASIN(D1))
16561 c FFEINTRIN_impDATAN
16562 call fooD(DATAN(D1))
16563 c FFEINTRIN_impDATAN2
16564 call fooD(DATAN2(D1,D2))
16565 c FFEINTRIN_impDCOS
16566 call fooD(DCOS(D1))
16567 c FFEINTRIN_impDCOSH
16568 call fooD(DCOSH(D1))
16569 c FFEINTRIN_impDDIM
16570 call fooD(DDIM(D1,D2))
16571 c FFEINTRIN_impDEXP
16572 call fooD(DEXP(D1))
16574 call fooR(DIM(R1,R2))
16575 c FFEINTRIN_impDINT
16576 call fooD(DINT(D1))
16577 c FFEINTRIN_impDLOG
16578 call fooD(DLOG(D1))
16579 c FFEINTRIN_impDLOG10
16580 call fooD(DLOG10(D1))
16581 c FFEINTRIN_impDMAX1
16582 call fooD(DMAX1(D1,D2))
16583 c FFEINTRIN_impDMIN1
16584 call fooD(DMIN1(D1,D2))
16585 c FFEINTRIN_impDMOD
16586 call fooD(DMOD(D1,D2))
16587 c FFEINTRIN_impDNINT
16588 call fooD(DNINT(D1))
16589 c FFEINTRIN_impDPROD
16590 call fooD(DPROD(R1,R2))
16591 c FFEINTRIN_impDSIGN
16592 call fooD(DSIGN(D1,D2))
16593 c FFEINTRIN_impDSIN
16594 call fooD(DSIN(D1))
16595 c FFEINTRIN_impDSINH
16596 call fooD(DSINH(D1))
16597 c FFEINTRIN_impDSQRT
16598 call fooD(DSQRT(D1))
16599 c FFEINTRIN_impDTAN
16600 call fooD(DTAN(D1))
16601 c FFEINTRIN_impDTANH
16602 call fooD(DTANH(D1))
16605 c FFEINTRIN_impIABS
16606 call fooI(IABS(I1))
16607 c FFEINTRIN_impICHAR
16608 call fooI(ICHAR(A1))
16609 c FFEINTRIN_impIDIM
16610 call fooI(IDIM(I1,I2))
16611 c FFEINTRIN_impIDNINT
16612 call fooI(IDNINT(D1))
16613 c FFEINTRIN_impINDEX
16614 call fooI(INDEX(A1,A2))
16615 c FFEINTRIN_impISIGN
16616 call fooI(ISIGN(I1,I2))
16620 call fooL(LGE(A1,A2))
16622 call fooL(LGT(A1,A2))
16624 call fooL(LLE(A1,A2))
16626 call fooL(LLT(A1,A2))
16627 c FFEINTRIN_impMAX0
16628 call fooI(MAX0(I1,I2))
16629 c FFEINTRIN_impMAX1
16630 call fooI(MAX1(R1,R2))
16631 c FFEINTRIN_impMIN0
16632 call fooI(MIN0(I1,I2))
16633 c FFEINTRIN_impMIN1
16634 call fooI(MIN1(R1,R2))
16636 call fooI(MOD(I1,I2))
16637 c FFEINTRIN_impNINT
16638 call fooI(NINT(R1))
16639 c FFEINTRIN_impSIGN
16640 call fooR(SIGN(R1,R2))
16643 c FFEINTRIN_impSINH
16644 call fooR(SINH(R1))
16645 c FFEINTRIN_impSQRT
16646 call fooR(SQRT(R1))
16649 c FFEINTRIN_impTANH
16650 call fooR(TANH(R1))
16651 c FFEINTRIN_imp_CMPLX_C
16652 call fooC(cmplx(C1,C2))
16653 c FFEINTRIN_imp_CMPLX_D
16654 call fooZ(cmplx(D1,D2))
16655 c FFEINTRIN_imp_CMPLX_I
16656 call fooC(cmplx(I1,I2))
16657 c FFEINTRIN_imp_CMPLX_R
16658 call fooC(cmplx(R1,R2))
16659 c FFEINTRIN_imp_DBLE_C
16660 call fooD(dble(C1))
16661 c FFEINTRIN_imp_DBLE_D
16662 call fooD(dble(D1))
16663 c FFEINTRIN_imp_DBLE_I
16664 call fooD(dble(I1))
16665 c FFEINTRIN_imp_DBLE_R
16666 call fooD(dble(R1))
16667 c FFEINTRIN_imp_INT_C
16669 c FFEINTRIN_imp_INT_D
16671 c FFEINTRIN_imp_INT_I
16673 c FFEINTRIN_imp_INT_R
16675 c FFEINTRIN_imp_REAL_C
16676 call fooR(real(C1))
16677 c FFEINTRIN_imp_REAL_D
16678 call fooR(real(D1))
16679 c FFEINTRIN_imp_REAL_I
16680 call fooR(real(I1))
16681 c FFEINTRIN_imp_REAL_R
16682 call fooR(real(R1))
16684 c FFEINTRIN_imp_INT_D:
16686 c FFEINTRIN_specIDINT
16687 call fooI(IDINT(D1))
16689 c FFEINTRIN_imp_INT_R:
16691 c FFEINTRIN_specIFIX
16692 call fooI(IFIX(R1))
16693 c FFEINTRIN_specINT
16696 c FFEINTRIN_imp_REAL_D:
16698 c FFEINTRIN_specSNGL
16699 call fooR(SNGL(D1))
16701 c FFEINTRIN_imp_REAL_I:
16703 c FFEINTRIN_specFLOAT
16704 call fooR(FLOAT(I1))
16705 c FFEINTRIN_specREAL
16706 call fooR(REAL(I1))
16709 -------- (end input file to f2c)
16711 -------- (begin output from providing above input file as input to:
16712 -------- `f2c | gcc -E -C - | sed -e "s:/[*]*://:g" -e "s:[*]*[/]://:g" \
16713 -------- -e "s:^#.*$::g"')
16715 // -- translated by f2c (version 19950223).
16716 You must link the resulting object file with the libraries:
16717 -lf2c -lm (in that order)
16721 // f2c.h -- Standard Fortran to C header file //
16723 /// barf [ba:rf] 2. "He suggested using FORTRAN, and everybody barfed."
16725 - From The Shogakukan DICTIONARY OF NEW ENGLISH (Second edition) //
16730 // F2C_INTEGER will normally be `int' but would be `long' on 16-bit systems //
16731 // we assume short, float are OK //
16732 typedef long int // long int // integer;
16733 typedef char *address;
16734 typedef short int shortint;
16735 typedef float real;
16736 typedef double doublereal;
16737 typedef struct { real r, i; } complex;
16738 typedef struct { doublereal r, i; } doublecomplex;
16739 typedef long int // long int // logical;
16740 typedef short int shortlogical;
16741 typedef char logical1;
16742 typedef char integer1;
16743 // typedef long long longint; // // system-dependent //
16748 // Extern is for use with -E //
16762 typedef long int // int or long int // flag;
16763 typedef long int // int or long int // ftnlen;
16764 typedef long int // int or long int // ftnint;
16767 //external read, write//
16776 //internal read, write//
16806 //rewind, backspace, endfile//
16818 ftnint *inex; //parameters in standard's order//
16844 union Multitype { // for multiple entry points //
16855 typedef union Multitype Multitype;
16857 typedef long Long; // No longer used; formerly in Namelist //
16859 struct Vardesc { // for Namelist //
16865 typedef struct Vardesc Vardesc;
16872 typedef struct Namelist Namelist;
16881 // procedure parameter types for -A and -C++ //
16886 typedef int // Unknown procedure type // (*U_fp)();
16887 typedef shortint (*J_fp)();
16888 typedef integer (*I_fp)();
16889 typedef real (*R_fp)();
16890 typedef doublereal (*D_fp)(), (*E_fp)();
16891 typedef // Complex // void (*C_fp)();
16892 typedef // Double Complex // void (*Z_fp)();
16893 typedef logical (*L_fp)();
16894 typedef shortlogical (*K_fp)();
16895 typedef // Character // void (*H_fp)();
16896 typedef // Subroutine // int (*S_fp)();
16898 // E_fp is for real functions when -R is not specified //
16899 typedef void C_f; // complex function //
16900 typedef void H_f; // character function //
16901 typedef void Z_f; // double complex function //
16902 typedef doublereal E_f; // real function with -R not specified //
16904 // undef any lower-case symbols that your C compiler predefines, e.g.: //
16907 // (No such symbols should be defined in a strict ANSI C compiler.
16908 We can avoid trouble with f2c-translated code by using
16909 gcc -ansi [-traditional].) //
16933 // Main program // MAIN__()
16935 // System generated locals //
16938 doublereal d__1, d__2;
16940 doublecomplex z__1, z__2, z__3;
16944 // Builtin functions //
16947 double pow_ri(), pow_di();
16951 double acos(), r_imag(), r_int(), log(), r_lg10(), r_mod(), r_nint(),
16952 asin(), atan(), atan2(), c_abs();
16953 void c_cos(), c_exp(), c_log(), r_cnjg();
16954 double cos(), cosh();
16955 void c_sin(), c_sqrt();
16956 double d_dim(), exp(), r_dim(), d_int(), d_lg10(), d_mod(), d_nint(),
16957 d_sign(), sin(), sinh(), sqrt(), tan(), tanh();
16958 integer i_dim(), i_dnnt(), i_indx(), i_sign(), i_len();
16959 logical l_ge(), l_gt(), l_le(), l_lt();
16963 // Local variables //
16964 extern // Subroutine // int fooa_(), fooc_(), food_(), fooi_(), foor_(),
16965 fool_(), fooz_(), getem_();
16966 static char a1[10], a2[10];
16967 static complex c1, c2;
16968 static doublereal d1, d2;
16969 static integer i1, i2;
16970 static real r1, r2;
16973 getem_(a1, a2, &c1, &c2, &i1, &i2, &r1, &r2, &d1, &d2, 10L, 10L);
16981 d__1 = (doublereal) i1;
16982 q__1.r = c1.r / d__1, q__1.i = c1.i / d__1;
16992 c_div(&q__1, &c1, &c2);
16994 q__1.r = c1.r / r1, q__1.i = c1.i / r1;
16996 z__1.r = c1.r / d1, z__1.i = c1.i / d1;
16999 i__1 = pow_ii(&i1, &i2);
17001 r__1 = pow_ri(&r1, &i1);
17003 d__1 = pow_di(&d1, &i1);
17005 pow_ci(&q__1, &c1, &i1);
17007 d__1 = (doublereal) r1;
17008 d__2 = (doublereal) r2;
17009 r__1 = pow_dd(&d__1, &d__2);
17011 d__2 = (doublereal) r1;
17012 d__1 = pow_dd(&d__2, &d1);
17014 d__1 = pow_dd(&d1, &d2);
17016 d__2 = (doublereal) r1;
17017 d__1 = pow_dd(&d1, &d__2);
17019 z__2.r = c1.r, z__2.i = c1.i;
17020 z__3.r = c2.r, z__3.i = c2.i;
17021 pow_zz(&z__1, &z__2, &z__3);
17022 q__1.r = z__1.r, q__1.i = z__1.i;
17024 z__2.r = c1.r, z__2.i = c1.i;
17025 z__3.r = r1, z__3.i = 0.;
17026 pow_zz(&z__1, &z__2, &z__3);
17027 q__1.r = z__1.r, q__1.i = z__1.i;
17029 z__2.r = c1.r, z__2.i = c1.i;
17030 z__3.r = d1, z__3.i = 0.;
17031 pow_zz(&z__1, &z__2, &z__3);
17033 // FFEINTRIN_impABS //
17034 r__1 = (doublereal)(( r1 ) >= 0 ? ( r1 ) : -( r1 )) ;
17036 // FFEINTRIN_impACOS //
17039 // FFEINTRIN_impAIMAG //
17040 r__1 = r_imag(&c1);
17042 // FFEINTRIN_impAINT //
17045 // FFEINTRIN_impALOG //
17048 // FFEINTRIN_impALOG10 //
17049 r__1 = r_lg10(&r1);
17051 // FFEINTRIN_impAMAX0 //
17052 r__1 = (real) (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
17054 // FFEINTRIN_impAMAX1 //
17055 r__1 = (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
17057 // FFEINTRIN_impAMIN0 //
17058 r__1 = (real) (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
17060 // FFEINTRIN_impAMIN1 //
17061 r__1 = (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
17063 // FFEINTRIN_impAMOD //
17064 r__1 = r_mod(&r1, &r2);
17066 // FFEINTRIN_impANINT //
17067 r__1 = r_nint(&r1);
17069 // FFEINTRIN_impASIN //
17072 // FFEINTRIN_impATAN //
17075 // FFEINTRIN_impATAN2 //
17076 r__1 = atan2(r1, r2);
17078 // FFEINTRIN_impCABS //
17081 // FFEINTRIN_impCCOS //
17084 // FFEINTRIN_impCEXP //
17087 // FFEINTRIN_impCHAR //
17088 *(unsigned char *)&ch__1[0] = i1;
17090 // FFEINTRIN_impCLOG //
17093 // FFEINTRIN_impCONJG //
17094 r_cnjg(&q__1, &c1);
17096 // FFEINTRIN_impCOS //
17099 // FFEINTRIN_impCOSH //
17102 // FFEINTRIN_impCSIN //
17105 // FFEINTRIN_impCSQRT //
17106 c_sqrt(&q__1, &c1);
17108 // FFEINTRIN_impDABS //
17109 d__1 = (( d1 ) >= 0 ? ( d1 ) : -( d1 )) ;
17111 // FFEINTRIN_impDACOS //
17114 // FFEINTRIN_impDASIN //
17117 // FFEINTRIN_impDATAN //
17120 // FFEINTRIN_impDATAN2 //
17121 d__1 = atan2(d1, d2);
17123 // FFEINTRIN_impDCOS //
17126 // FFEINTRIN_impDCOSH //
17129 // FFEINTRIN_impDDIM //
17130 d__1 = d_dim(&d1, &d2);
17132 // FFEINTRIN_impDEXP //
17135 // FFEINTRIN_impDIM //
17136 r__1 = r_dim(&r1, &r2);
17138 // FFEINTRIN_impDINT //
17141 // FFEINTRIN_impDLOG //
17144 // FFEINTRIN_impDLOG10 //
17145 d__1 = d_lg10(&d1);
17147 // FFEINTRIN_impDMAX1 //
17148 d__1 = (( d1 ) >= ( d2 ) ? ( d1 ) : ( d2 )) ;
17150 // FFEINTRIN_impDMIN1 //
17151 d__1 = (( d1 ) <= ( d2 ) ? ( d1 ) : ( d2 )) ;
17153 // FFEINTRIN_impDMOD //
17154 d__1 = d_mod(&d1, &d2);
17156 // FFEINTRIN_impDNINT //
17157 d__1 = d_nint(&d1);
17159 // FFEINTRIN_impDPROD //
17160 d__1 = (doublereal) r1 * r2;
17162 // FFEINTRIN_impDSIGN //
17163 d__1 = d_sign(&d1, &d2);
17165 // FFEINTRIN_impDSIN //
17168 // FFEINTRIN_impDSINH //
17171 // FFEINTRIN_impDSQRT //
17174 // FFEINTRIN_impDTAN //
17177 // FFEINTRIN_impDTANH //
17180 // FFEINTRIN_impEXP //
17183 // FFEINTRIN_impIABS //
17184 i__1 = (( i1 ) >= 0 ? ( i1 ) : -( i1 )) ;
17186 // FFEINTRIN_impICHAR //
17187 i__1 = *(unsigned char *)a1;
17189 // FFEINTRIN_impIDIM //
17190 i__1 = i_dim(&i1, &i2);
17192 // FFEINTRIN_impIDNINT //
17193 i__1 = i_dnnt(&d1);
17195 // FFEINTRIN_impINDEX //
17196 i__1 = i_indx(a1, a2, 10L, 10L);
17198 // FFEINTRIN_impISIGN //
17199 i__1 = i_sign(&i1, &i2);
17201 // FFEINTRIN_impLEN //
17202 i__1 = i_len(a1, 10L);
17204 // FFEINTRIN_impLGE //
17205 L__1 = l_ge(a1, a2, 10L, 10L);
17207 // FFEINTRIN_impLGT //
17208 L__1 = l_gt(a1, a2, 10L, 10L);
17210 // FFEINTRIN_impLLE //
17211 L__1 = l_le(a1, a2, 10L, 10L);
17213 // FFEINTRIN_impLLT //
17214 L__1 = l_lt(a1, a2, 10L, 10L);
17216 // FFEINTRIN_impMAX0 //
17217 i__1 = (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
17219 // FFEINTRIN_impMAX1 //
17220 i__1 = (integer) (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
17222 // FFEINTRIN_impMIN0 //
17223 i__1 = (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
17225 // FFEINTRIN_impMIN1 //
17226 i__1 = (integer) (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
17228 // FFEINTRIN_impMOD //
17231 // FFEINTRIN_impNINT //
17232 i__1 = i_nint(&r1);
17234 // FFEINTRIN_impSIGN //
17235 r__1 = r_sign(&r1, &r2);
17237 // FFEINTRIN_impSIN //
17240 // FFEINTRIN_impSINH //
17243 // FFEINTRIN_impSQRT //
17246 // FFEINTRIN_impTAN //
17249 // FFEINTRIN_impTANH //
17252 // FFEINTRIN_imp_CMPLX_C //
17255 q__1.r = r__1, q__1.i = r__2;
17257 // FFEINTRIN_imp_CMPLX_D //
17258 z__1.r = d1, z__1.i = d2;
17260 // FFEINTRIN_imp_CMPLX_I //
17263 q__1.r = r__1, q__1.i = r__2;
17265 // FFEINTRIN_imp_CMPLX_R //
17266 q__1.r = r1, q__1.i = r2;
17268 // FFEINTRIN_imp_DBLE_C //
17269 d__1 = (doublereal) c1.r;
17271 // FFEINTRIN_imp_DBLE_D //
17274 // FFEINTRIN_imp_DBLE_I //
17275 d__1 = (doublereal) i1;
17277 // FFEINTRIN_imp_DBLE_R //
17278 d__1 = (doublereal) r1;
17280 // FFEINTRIN_imp_INT_C //
17281 i__1 = (integer) c1.r;
17283 // FFEINTRIN_imp_INT_D //
17284 i__1 = (integer) d1;
17286 // FFEINTRIN_imp_INT_I //
17289 // FFEINTRIN_imp_INT_R //
17290 i__1 = (integer) r1;
17292 // FFEINTRIN_imp_REAL_C //
17295 // FFEINTRIN_imp_REAL_D //
17298 // FFEINTRIN_imp_REAL_I //
17301 // FFEINTRIN_imp_REAL_R //
17305 // FFEINTRIN_imp_INT_D: //
17307 // FFEINTRIN_specIDINT //
17308 i__1 = (integer) d1;
17311 // FFEINTRIN_imp_INT_R: //
17313 // FFEINTRIN_specIFIX //
17314 i__1 = (integer) r1;
17316 // FFEINTRIN_specINT //
17317 i__1 = (integer) r1;
17320 // FFEINTRIN_imp_REAL_D: //
17322 // FFEINTRIN_specSNGL //
17326 // FFEINTRIN_imp_REAL_I: //
17328 // FFEINTRIN_specFLOAT //
17331 // FFEINTRIN_specREAL //
17337 -------- (end output file from f2c)