1 /* com.c -- Implementation File (module.c template V1.0)
2 Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001
3 Free Software Foundation, Inc.
4 Contributed by James Craig Burley.
6 This file is part of GNU Fortran.
8 GNU Fortran is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 GNU Fortran is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Fortran; see the file COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
27 Contains compiler-specific functions.
32 /* Understanding this module means understanding the interface between
33 the g77 front end and the gcc back end (or, perhaps, some other
34 back end). In here are the functions called by the front end proper
35 to notify whatever back end is in place about certain things, and
36 also the back-end-specific functions. It's a bear to deal with, so
37 lately I've been trying to simplify things, especially with regard
38 to the gcc-back-end-specific stuff.
40 Building expressions generally seems quite easy, but building decls
41 has been challenging and is undergoing revision. gcc has several
44 TYPE_DECL -- a type (int, float, struct, function, etc.)
45 CONST_DECL -- a constant of some type other than function
46 LABEL_DECL -- a variable or a constant?
47 PARM_DECL -- an argument to a function (a variable that is a dummy)
48 RESULT_DECL -- the return value of a function (a variable)
49 VAR_DECL -- other variable (can hold a ptr-to-function, struct, int, etc.)
50 FUNCTION_DECL -- a function (either the actual function or an extern ref)
51 FIELD_DECL -- a field in a struct or union (goes into types)
53 g77 has a set of functions that somewhat parallels the gcc front end
54 when it comes to building decls:
56 Internal Function (one we define, not just declare as extern):
57 if (is_nested) push_f_function_context ();
58 start_function (get_identifier ("function_name"), function_type,
59 is_nested, is_public);
60 // for each arg, build PARM_DECL and call push_parm_decl (decl) with it;
61 store_parm_decls (is_main_program);
62 ffecom_start_compstmt ();
63 // for stmts and decls inside function, do appropriate things;
64 ffecom_end_compstmt ();
65 finish_function (is_nested);
66 if (is_nested) pop_f_function_context ();
71 // fill in external, public, static, &c for decl, and
72 // set DECL_INITIAL to error_mark_node if going to initialize
73 // set is_top_level TRUE only if not at top level and decl
74 // must go in top level (i.e. not within current function decl context)
75 d = start_decl (decl, is_top_level);
76 init = ...; // if have initializer
77 finish_decl (d, init, is_top_level);
84 #if FFECOM_targetCURRENT == FFECOM_targetGCC
89 #include "output.h" /* Must follow tree.h so TREE_CODE is defined! */
92 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
94 #define FFECOM_GCC_INCLUDE 1 /* Enable -I. */
96 /* BEGIN stuff from gcc/cccp.c. */
98 /* The following symbols should be autoconfigured:
104 In the mean time, we'll get by with approximations based
105 on existing GCC configuration symbols. */
108 # ifndef HAVE_STDLIB_H
109 # define HAVE_STDLIB_H 1
111 # ifndef HAVE_UNISTD_H
112 # define HAVE_UNISTD_H 1
114 #endif /* defined (POSIX) */
116 #if defined (POSIX) || (defined (USG) && !defined (VMS))
117 # ifndef HAVE_FCNTL_H
118 # define HAVE_FCNTL_H 1
123 # include <sys/resource.h>
130 /* This defines "errno" properly for VMS, and gives us EACCES. */
143 /* VMS-specific definitions */
146 #define O_RDONLY 0 /* Open arg for Read/Only */
147 #define O_WRONLY 1 /* Open arg for Write/Only */
148 #define read(fd,buf,size) VMS_read (fd,buf,size)
149 #define write(fd,buf,size) VMS_write (fd,buf,size)
150 #define open(fname,mode,prot) VMS_open (fname,mode,prot)
151 #define fopen(fname,mode) VMS_fopen (fname,mode)
152 #define freopen(fname,mode,ofile) VMS_freopen (fname,mode,ofile)
153 #define strncat(dst,src,cnt) VMS_strncat (dst,src,cnt)
154 #define fstat(fd,stbuf) VMS_fstat (fd,stbuf)
155 static int VMS_fstat (), VMS_stat ();
156 static char * VMS_strncat ();
157 static int VMS_read ();
158 static int VMS_write ();
159 static int VMS_open ();
160 static FILE * VMS_fopen ();
161 static FILE * VMS_freopen ();
162 static void hack_vms_include_specification ();
163 typedef struct { unsigned :16, :16, :16; } vms_ino_t;
164 #define ino_t vms_ino_t
165 #define INCLUDE_LEN_FUDGE 10 /* leave room for VMS syntax conversion */
172 /* END stuff from gcc/cccp.c. */
174 #define FFECOM_DETERMINE_TYPES 1 /* for com.h */
191 /* Externals defined here. */
193 #if FFECOM_targetCURRENT == FFECOM_targetGCC
195 /* ~~gcc/tree.h *should* declare this, because toplev.c and dwarfout.c
198 const char * const language_string = "GNU F77";
200 /* Stream for reading from the input file. */
203 /* These definitions parallel those in c-decl.c so that code from that
204 module can be used pretty much as is. Much of these defs aren't
205 otherwise used, i.e. by g77 code per se, except some of them are used
206 to build some of them that are. The ones that are global (i.e. not
207 "static") are those that ste.c and such might use (directly
208 or by using com macros that reference them in their definitions). */
210 tree string_type_node;
212 /* The rest of these are inventions for g77, though there might be
213 similar things in the C front end. As they are found, these
214 inventions should be renamed to be canonical. Note that only
215 the ones currently required to be global are so. */
217 static tree ffecom_tree_fun_type_void;
219 tree ffecom_integer_type_node; /* Abbrev for _tree_type[blah][blah]. */
220 tree ffecom_integer_zero_node; /* Like *_*_* with g77's integer type. */
221 tree ffecom_integer_one_node; /* " */
222 tree ffecom_tree_type[FFEINFO_basictype][FFEINFO_kindtype];
224 /* _fun_type things are the f2c-specific versions. For -fno-f2c,
225 just use build_function_type and build_pointer_type on the
226 appropriate _tree_type array element. */
228 static tree ffecom_tree_fun_type[FFEINFO_basictype][FFEINFO_kindtype];
229 static tree ffecom_tree_ptr_to_fun_type[FFEINFO_basictype][FFEINFO_kindtype];
230 static tree ffecom_tree_subr_type;
231 static tree ffecom_tree_ptr_to_subr_type;
232 static tree ffecom_tree_blockdata_type;
234 static tree ffecom_tree_xargc_;
236 ffecomSymbol ffecom_symbol_null_
245 ffeinfoKindtype ffecom_pointer_kind_ = FFEINFO_basictypeNONE;
246 ffeinfoKindtype ffecom_label_kind_ = FFEINFO_basictypeNONE;
248 int ffecom_f2c_typecode_[FFEINFO_basictype][FFEINFO_kindtype];
249 tree ffecom_f2c_integer_type_node;
250 tree ffecom_f2c_ptr_to_integer_type_node;
251 tree ffecom_f2c_address_type_node;
252 tree ffecom_f2c_real_type_node;
253 tree ffecom_f2c_ptr_to_real_type_node;
254 tree ffecom_f2c_doublereal_type_node;
255 tree ffecom_f2c_complex_type_node;
256 tree ffecom_f2c_doublecomplex_type_node;
257 tree ffecom_f2c_longint_type_node;
258 tree ffecom_f2c_logical_type_node;
259 tree ffecom_f2c_flag_type_node;
260 tree ffecom_f2c_ftnlen_type_node;
261 tree ffecom_f2c_ftnlen_zero_node;
262 tree ffecom_f2c_ftnlen_one_node;
263 tree ffecom_f2c_ftnlen_two_node;
264 tree ffecom_f2c_ptr_to_ftnlen_type_node;
265 tree ffecom_f2c_ftnint_type_node;
266 tree ffecom_f2c_ptr_to_ftnint_type_node;
267 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
269 /* Simple definitions and enumerations. */
271 #ifndef FFECOM_sizeMAXSTACKITEM
272 #define FFECOM_sizeMAXSTACKITEM 32*1024 /* Keep user-declared things
273 larger than this # bytes
274 off stack if possible. */
277 /* For systems that have large enough stacks, they should define
278 this to 0, and here, for ease of use later on, we just undefine
281 #if FFECOM_sizeMAXSTACKITEM == 0
282 #undef FFECOM_sizeMAXSTACKITEM
288 FFECOM_rttypeVOIDSTAR_, /* C's `void *' type. */
289 FFECOM_rttypeFTNINT_, /* f2c's `ftnint' type. */
290 FFECOM_rttypeINTEGER_, /* f2c's `integer' type. */
291 FFECOM_rttypeLONGINT_, /* f2c's `longint' type. */
292 FFECOM_rttypeLOGICAL_, /* f2c's `logical' type. */
293 FFECOM_rttypeREAL_F2C_, /* f2c's `real' returned as `double'. */
294 FFECOM_rttypeREAL_GNU_, /* `real' returned as such. */
295 FFECOM_rttypeCOMPLEX_F2C_, /* f2c's `complex' returned via 1st arg. */
296 FFECOM_rttypeCOMPLEX_GNU_, /* f2c's `complex' returned directly. */
297 FFECOM_rttypeDOUBLE_, /* C's `double' type. */
298 FFECOM_rttypeDOUBLEREAL_, /* f2c's `doublereal' type. */
299 FFECOM_rttypeDBLCMPLX_F2C_, /* f2c's `doublecomplex' returned via 1st arg. */
300 FFECOM_rttypeDBLCMPLX_GNU_, /* f2c's `doublecomplex' returned directly. */
301 FFECOM_rttypeCHARACTER_, /* f2c `char *'/`ftnlen' pair. */
305 /* Internal typedefs. */
307 #if FFECOM_targetCURRENT == FFECOM_targetGCC
308 typedef struct _ffecom_concat_list_ ffecomConcatList_;
309 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
311 /* Private include files. */
314 /* Internal structure definitions. */
316 #if FFECOM_targetCURRENT == FFECOM_targetGCC
317 struct _ffecom_concat_list_
322 ffetargetCharacterSize minlen;
323 ffetargetCharacterSize maxlen;
325 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
327 /* Static functions (internal). */
329 #if FFECOM_targetCURRENT == FFECOM_targetGCC
330 static tree ffecom_arglist_expr_ (const char *argstring, ffebld args);
331 static tree ffecom_widest_expr_type_ (ffebld list);
332 static bool ffecom_overlap_ (tree dest_decl, tree dest_offset,
333 tree dest_size, tree source_tree,
334 ffebld source, bool scalar_arg);
335 static bool ffecom_args_overlapping_ (tree dest_tree, ffebld dest,
336 tree args, tree callee_commons,
338 static tree ffecom_build_f2c_string_ (int i, const char *s);
339 static tree ffecom_call_ (tree fn, ffeinfoKindtype kt,
340 bool is_f2c_complex, tree type,
341 tree args, tree dest_tree,
342 ffebld dest, bool *dest_used,
343 tree callee_commons, bool scalar_args, tree hook);
344 static tree ffecom_call_binop_ (tree fn, ffeinfoKindtype kt,
345 bool is_f2c_complex, tree type,
346 ffebld left, ffebld right,
347 tree dest_tree, ffebld dest,
348 bool *dest_used, tree callee_commons,
349 bool scalar_args, bool ref, tree hook);
350 static void ffecom_char_args_x_ (tree *xitem, tree *length,
351 ffebld expr, bool with_null);
352 static tree ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy);
353 static tree ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s);
354 static ffecomConcatList_
355 ffecom_concat_list_gather_ (ffecomConcatList_ catlist,
357 ffetargetCharacterSize max);
358 static void ffecom_concat_list_kill_ (ffecomConcatList_ catlist);
359 static ffecomConcatList_ ffecom_concat_list_new_ (ffebld expr,
360 ffetargetCharacterSize max);
361 static void ffecom_debug_kludge_ (tree aggr, const char *aggr_type,
362 ffesymbol member, tree member_type,
363 ffetargetOffset offset);
364 static void ffecom_do_entry_ (ffesymbol fn, int entrynum);
365 static tree ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
366 bool *dest_used, bool assignp, bool widenp);
367 static tree ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
368 ffebld dest, bool *dest_used);
369 static tree ffecom_expr_power_integer_ (ffebld expr);
370 static void ffecom_expr_transform_ (ffebld expr);
371 static void ffecom_f2c_make_type_ (tree *type, int tcode, const char *name);
372 static void ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size,
374 static ffeglobal ffecom_finish_global_ (ffeglobal global);
375 static ffesymbol ffecom_finish_symbol_transform_ (ffesymbol s);
376 static tree ffecom_get_appended_identifier_ (char us, const char *text);
377 static tree ffecom_get_external_identifier_ (ffesymbol s);
378 static tree ffecom_get_identifier_ (const char *text);
379 static tree ffecom_gen_sfuncdef_ (ffesymbol s,
382 static const char *ffecom_gfrt_args_ (ffecomGfrt ix);
383 static tree ffecom_gfrt_tree_ (ffecomGfrt ix);
384 static tree ffecom_init_zero_ (tree decl);
385 static tree ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg,
387 static tree ffecom_intrinsic_len_ (ffebld expr);
388 static void ffecom_let_char_ (tree dest_tree,
390 ffetargetCharacterSize dest_size,
392 static void ffecom_make_gfrt_ (ffecomGfrt ix);
393 static void ffecom_member_phase1_ (ffestorag mst, ffestorag st);
394 static void ffecom_member_phase2_ (ffestorag mst, ffestorag st);
395 static void ffecom_prepare_let_char_ (ffetargetCharacterSize dest_size,
397 static void ffecom_push_dummy_decls_ (ffebld dumlist,
399 static void ffecom_start_progunit_ (void);
400 static ffesymbol ffecom_sym_transform_ (ffesymbol s);
401 static ffesymbol ffecom_sym_transform_assign_ (ffesymbol s);
402 static void ffecom_transform_common_ (ffesymbol s);
403 static void ffecom_transform_equiv_ (ffestorag st);
404 static tree ffecom_transform_namelist_ (ffesymbol s);
405 static void ffecom_tree_canonize_ptr_ (tree *decl, tree *offset,
407 static void ffecom_tree_canonize_ref_ (tree *decl, tree *offset,
408 tree *size, tree tree);
409 static tree ffecom_tree_divide_ (tree tree_type, tree left, tree right,
410 tree dest_tree, ffebld dest,
411 bool *dest_used, tree hook);
412 static tree ffecom_type_localvar_ (ffesymbol s,
415 static tree ffecom_type_namelist_ (void);
416 static tree ffecom_type_vardesc_ (void);
417 static tree ffecom_vardesc_ (ffebld expr);
418 static tree ffecom_vardesc_array_ (ffesymbol s);
419 static tree ffecom_vardesc_dims_ (ffesymbol s);
420 static tree ffecom_convert_narrow_ (tree type, tree expr);
421 static tree ffecom_convert_widen_ (tree type, tree expr);
422 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
424 /* These are static functions that parallel those found in the C front
425 end and thus have the same names. */
427 #if FFECOM_targetCURRENT == FFECOM_targetGCC
428 static tree bison_rule_compstmt_ (void);
429 static void bison_rule_pushlevel_ (void);
430 static void delete_block (tree block);
431 static int duplicate_decls (tree newdecl, tree olddecl);
432 static void finish_decl (tree decl, tree init, bool is_top_level);
433 static void finish_function (int nested);
434 static const char *lang_printable_name (tree decl, int v);
435 static tree lookup_name_current_level (tree name);
436 static struct binding_level *make_binding_level (void);
437 static void pop_f_function_context (void);
438 static void push_f_function_context (void);
439 static void push_parm_decl (tree parm);
440 static tree pushdecl_top_level (tree decl);
441 static int kept_level_p (void);
442 static tree storedecls (tree decls);
443 static void store_parm_decls (int is_main_program);
444 static tree start_decl (tree decl, bool is_top_level);
445 static void start_function (tree name, tree type, int nested, int public);
446 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
447 #if FFECOM_GCC_INCLUDE
448 static void ffecom_file_ (const char *name);
449 static void ffecom_initialize_char_syntax_ (void);
450 static void ffecom_close_include_ (FILE *f);
451 static int ffecom_decode_include_option_ (char *spec);
452 static FILE *ffecom_open_include_ (char *name, ffewhereLine l,
454 #endif /* FFECOM_GCC_INCLUDE */
456 /* Static objects accessed by functions in this module. */
458 static ffesymbol ffecom_primary_entry_ = NULL;
459 static ffesymbol ffecom_nested_entry_ = NULL;
460 static ffeinfoKind ffecom_primary_entry_kind_;
461 static bool ffecom_primary_entry_is_proc_;
462 #if FFECOM_targetCURRENT == FFECOM_targetGCC
463 static tree ffecom_outer_function_decl_;
464 static tree ffecom_previous_function_decl_;
465 static tree ffecom_which_entrypoint_decl_;
466 static tree ffecom_float_zero_ = NULL_TREE;
467 static tree ffecom_float_half_ = NULL_TREE;
468 static tree ffecom_double_zero_ = NULL_TREE;
469 static tree ffecom_double_half_ = NULL_TREE;
470 static tree ffecom_func_result_;/* For functions. */
471 static tree ffecom_func_length_;/* For CHARACTER fns. */
472 static ffebld ffecom_list_blockdata_;
473 static ffebld ffecom_list_common_;
474 static ffebld ffecom_master_arglist_;
475 static ffeinfoBasictype ffecom_master_bt_;
476 static ffeinfoKindtype ffecom_master_kt_;
477 static ffetargetCharacterSize ffecom_master_size_;
478 static int ffecom_num_fns_ = 0;
479 static int ffecom_num_entrypoints_ = 0;
480 static bool ffecom_is_altreturning_ = FALSE;
481 static tree ffecom_multi_type_node_;
482 static tree ffecom_multi_retval_;
484 ffecom_multi_fields_[FFEINFO_basictype][FFEINFO_kindtype];
485 static bool ffecom_member_namelisted_; /* _member_phase1_ namelisted? */
486 static bool ffecom_doing_entry_ = FALSE;
487 static bool ffecom_transform_only_dummies_ = FALSE;
488 static int ffecom_typesize_pointer_;
489 static int ffecom_typesize_integer1_;
491 /* Holds pointer-to-function expressions. */
493 static tree ffecom_gfrt_[FFECOM_gfrt]
496 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) NULL_TREE,
497 #include "com-rt.def"
501 /* Holds the external names of the functions. */
503 static const char *ffecom_gfrt_name_[FFECOM_gfrt]
506 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) NAME,
507 #include "com-rt.def"
511 /* Whether the function returns. */
513 static bool ffecom_gfrt_volatile_[FFECOM_gfrt]
516 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) VOLATILE,
517 #include "com-rt.def"
521 /* Whether the function returns type complex. */
523 static bool ffecom_gfrt_complex_[FFECOM_gfrt]
526 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) COMPLEX,
527 #include "com-rt.def"
531 /* Whether the function is const
532 (i.e., has no side effects and only depends on its arguments). */
534 static bool ffecom_gfrt_const_[FFECOM_gfrt]
537 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) CONST,
538 #include "com-rt.def"
542 /* Type code for the function return value. */
544 static ffecomRttype_ ffecom_gfrt_type_[FFECOM_gfrt]
547 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) TYPE,
548 #include "com-rt.def"
552 /* String of codes for the function's arguments. */
554 static const char *ffecom_gfrt_argstring_[FFECOM_gfrt]
557 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) ARGS,
558 #include "com-rt.def"
561 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
563 /* Internal macros. */
565 #if FFECOM_targetCURRENT == FFECOM_targetGCC
567 /* We let tm.h override the types used here, to handle trivial differences
568 such as the choice of unsigned int or long unsigned int for size_t.
569 When machines start needing nontrivial differences in the size type,
570 it would be best to do something here to figure out automatically
571 from other information what type to use. */
574 #define SIZE_TYPE "long unsigned int"
577 #define ffecom_concat_list_count_(catlist) ((catlist).count)
578 #define ffecom_concat_list_expr_(catlist,i) ((catlist).exprs[(i)])
579 #define ffecom_concat_list_maxlen_(catlist) ((catlist).maxlen)
580 #define ffecom_concat_list_minlen_(catlist) ((catlist).minlen)
582 #define ffecom_char_args_(i,l,e) ffecom_char_args_x_((i),(l),(e),FALSE)
583 #define ffecom_char_args_with_null_(i,l,e) ffecom_char_args_x_((i),(l),(e),TRUE)
585 /* For each binding contour we allocate a binding_level structure
586 * which records the names defined in that contour.
589 * 1) one for each function definition,
590 * where internal declarations of the parameters appear.
592 * The current meaning of a name can be found by searching the levels from
593 * the current one out to the global one.
596 /* Note that the information in the `names' component of the global contour
597 is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers. */
601 /* A chain of _DECL nodes for all variables, constants, functions,
602 and typedef types. These are in the reverse of the order supplied.
606 /* For each level (except not the global one),
607 a chain of BLOCK nodes for all the levels
608 that were entered and exited one level down. */
611 /* The BLOCK node for this level, if one has been preallocated.
612 If 0, the BLOCK is allocated (if needed) when the level is popped. */
615 /* The binding level which this one is contained in (inherits from). */
616 struct binding_level *level_chain;
618 /* 0: no ffecom_prepare_* functions called at this level yet;
619 1: ffecom_prepare* functions called, except not ffecom_prepare_end;
620 2: ffecom_prepare_end called. */
624 #define NULL_BINDING_LEVEL (struct binding_level *) NULL
626 /* The binding level currently in effect. */
628 static struct binding_level *current_binding_level;
630 /* A chain of binding_level structures awaiting reuse. */
632 static struct binding_level *free_binding_level;
634 /* The outermost binding level, for names of file scope.
635 This is created when the compiler is started and exists
636 through the entire run. */
638 static struct binding_level *global_binding_level;
640 /* Binding level structures are initialized by copying this one. */
642 static struct binding_level clear_binding_level
644 {NULL, NULL, NULL, NULL_BINDING_LEVEL, 0};
646 /* Language-dependent contents of an identifier. */
648 struct lang_identifier
650 struct tree_identifier ignore;
651 tree global_value, local_value, label_value;
655 /* Macros for access to language-specific slots in an identifier. */
656 /* Each of these slots contains a DECL node or null. */
658 /* This represents the value which the identifier has in the
659 file-scope namespace. */
660 #define IDENTIFIER_GLOBAL_VALUE(NODE) \
661 (((struct lang_identifier *)(NODE))->global_value)
662 /* This represents the value which the identifier has in the current
664 #define IDENTIFIER_LOCAL_VALUE(NODE) \
665 (((struct lang_identifier *)(NODE))->local_value)
666 /* This represents the value which the identifier has as a label in
667 the current label scope. */
668 #define IDENTIFIER_LABEL_VALUE(NODE) \
669 (((struct lang_identifier *)(NODE))->label_value)
670 /* This is nonzero if the identifier was "made up" by g77 code. */
671 #define IDENTIFIER_INVENTED(NODE) \
672 (((struct lang_identifier *)(NODE))->invented)
674 /* In identifiers, C uses the following fields in a special way:
675 TREE_PUBLIC to record that there was a previous local extern decl.
676 TREE_USED to record that such a decl was used.
677 TREE_ADDRESSABLE to record that the address of such a decl was used. */
679 /* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
680 that have names. Here so we can clear out their names' definitions
681 at the end of the function. */
683 static tree named_labels;
685 /* A list of LABEL_DECLs from outer contexts that are currently shadowed. */
687 static tree shadowed_labels;
689 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
691 /* Return the subscript expression, modified to do range-checking.
693 `array' is the array to be checked against.
694 `element' is the subscript expression to check.
695 `dim' is the dimension number (starting at 0).
696 `total_dims' is the total number of dimensions (0 for CHARACTER substring).
700 ffecom_subscript_check_ (tree array, tree element, int dim, int total_dims,
701 const char *array_name)
703 tree low = TYPE_MIN_VALUE (TYPE_DOMAIN (array));
704 tree high = TYPE_MAX_VALUE (TYPE_DOMAIN (array));
709 if (element == error_mark_node)
712 if (TREE_TYPE (low) != TREE_TYPE (element))
714 if (TYPE_PRECISION (TREE_TYPE (low))
715 > TYPE_PRECISION (TREE_TYPE (element)))
716 element = convert (TREE_TYPE (low), element);
719 low = convert (TREE_TYPE (element), low);
721 high = convert (TREE_TYPE (element), high);
725 element = ffecom_save_tree (element);
726 cond = ffecom_2 (LE_EXPR, integer_type_node,
731 cond = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
733 ffecom_2 (LE_EXPR, integer_type_node,
750 var = xmalloc (strlen (array_name) + 20);
751 sprintf (var, "%s[%s-substring]",
753 dim ? "end" : "start");
754 len = strlen (var) + 1;
755 arg1 = build_string (len, var);
760 len = strlen (array_name) + 1;
761 arg1 = build_string (len, array_name);
765 var = xmalloc (strlen (array_name) + 40);
766 sprintf (var, "%s[subscript-%d-of-%d]",
768 dim + 1, total_dims);
769 len = strlen (var) + 1;
770 arg1 = build_string (len, var);
776 = build_type_variant (build_array_type (char_type_node,
780 build_int_2 (len, 0))),
782 TREE_CONSTANT (arg1) = 1;
783 TREE_STATIC (arg1) = 1;
784 arg1 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg1)),
787 /* s_rnge adds one to the element to print it, so bias against
788 that -- want to print a faithful *subscript* value. */
789 arg2 = convert (ffecom_f2c_ftnint_type_node,
790 ffecom_2 (MINUS_EXPR,
793 convert (TREE_TYPE (element),
796 proc = xmalloc ((len = strlen (input_filename)
797 + IDENTIFIER_LENGTH (DECL_NAME (current_function_decl))
800 sprintf (&proc[0], "%s/%s",
802 IDENTIFIER_POINTER (DECL_NAME (current_function_decl)));
803 arg3 = build_string (len, proc);
808 = build_type_variant (build_array_type (char_type_node,
812 build_int_2 (len, 0))),
814 TREE_CONSTANT (arg3) = 1;
815 TREE_STATIC (arg3) = 1;
816 arg3 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg3)),
819 arg4 = convert (ffecom_f2c_ftnint_type_node,
820 build_int_2 (lineno, 0));
822 arg1 = build_tree_list (NULL_TREE, arg1);
823 arg2 = build_tree_list (NULL_TREE, arg2);
824 arg3 = build_tree_list (NULL_TREE, arg3);
825 arg4 = build_tree_list (NULL_TREE, arg4);
826 TREE_CHAIN (arg3) = arg4;
827 TREE_CHAIN (arg2) = arg3;
828 TREE_CHAIN (arg1) = arg2;
832 die = ffecom_call_gfrt (FFECOM_gfrtRANGE,
834 TREE_SIDE_EFFECTS (die) = 1;
836 element = ffecom_3 (COND_EXPR,
845 /* Return the computed element of an array reference.
847 `item' is NULL_TREE, or the transformed pointer to the array.
848 `expr' is the original opARRAYREF expression, which is transformed
849 if `item' is NULL_TREE.
850 `want_ptr' is non-zero if a pointer to the element, instead of
851 the element itself, is to be returned. */
854 ffecom_arrayref_ (tree item, ffebld expr, int want_ptr)
856 ffebld dims[FFECOM_dimensionsMAX];
859 int flatten = ffe_is_flatten_arrays ();
865 const char *array_name;
869 if (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER)
870 array_name = ffesymbol_text (ffebld_symter (ffebld_left (expr)));
872 array_name = "[expr?]";
874 /* Build up ARRAY_REFs in reverse order (since we're column major
875 here in Fortran land). */
877 for (i = 0, list = ffebld_right (expr);
879 ++i, list = ffebld_trail (list))
881 dims[i] = ffebld_head (list);
882 type = ffeinfo_type (ffebld_basictype (dims[i]),
883 ffebld_kindtype (dims[i]));
885 && ffecom_typesize_pointer_ > ffecom_typesize_integer1_
886 && ffetype_size (type) > ffecom_typesize_integer1_)
887 /* E.g. ARRAY(INDEX), given INTEGER*8 INDEX, on a system with 64-bit
888 pointers and 32-bit integers. Do the full 64-bit pointer
889 arithmetic, for codes using arrays for nonstandard heap-like
896 need_ptr = want_ptr || flatten;
901 item = ffecom_ptr_to_expr (ffebld_left (expr));
903 item = ffecom_expr (ffebld_left (expr));
905 if (item == error_mark_node)
908 if (ffeinfo_where (ffebld_info (expr)) == FFEINFO_whereFLEETING
909 && ! mark_addressable (item))
910 return error_mark_node;
913 if (item == error_mark_node)
920 for (--i, array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
922 --i, array = TYPE_MAIN_VARIANT (TREE_TYPE (array)))
924 min = TYPE_MIN_VALUE (TYPE_DOMAIN (array));
925 element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
926 if (flag_bounds_check)
927 element = ffecom_subscript_check_ (array, element, i, total_dims,
929 if (element == error_mark_node)
932 /* Widen integral arithmetic as desired while preserving
934 tree_type = TREE_TYPE (element);
935 tree_type_x = tree_type;
937 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
938 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
939 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
941 if (TREE_TYPE (min) != tree_type_x)
942 min = convert (tree_type_x, min);
943 if (TREE_TYPE (element) != tree_type_x)
944 element = convert (tree_type_x, element);
946 item = ffecom_2 (PLUS_EXPR,
947 build_pointer_type (TREE_TYPE (array)),
949 size_binop (MULT_EXPR,
950 size_in_bytes (TREE_TYPE (array)),
952 fold (build (MINUS_EXPR,
958 item = ffecom_1 (INDIRECT_REF,
959 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))),
969 array = TYPE_MAIN_VARIANT (TREE_TYPE (item));
971 element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
972 if (flag_bounds_check)
973 element = ffecom_subscript_check_ (array, element, i, total_dims,
975 if (element == error_mark_node)
978 /* Widen integral arithmetic as desired while preserving
980 tree_type = TREE_TYPE (element);
981 tree_type_x = tree_type;
983 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
984 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
985 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
987 element = convert (tree_type_x, element);
989 item = ffecom_2 (ARRAY_REF,
990 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))),
999 /* This is like gcc's stabilize_reference -- in fact, most of the code
1000 comes from that -- but it handles the situation where the reference
1001 is going to have its subparts picked at, and it shouldn't change
1002 (or trigger extra invocations of functions in the subtrees) due to
1003 this. save_expr is a bit overzealous, because we don't need the
1004 entire thing calculated and saved like a temp. So, for DECLs, no
1005 change is needed, because these are stable aggregates, and ARRAY_REF
1006 and such might well be stable too, but for things like calculations,
1007 we do need to calculate a snapshot of a value before picking at it. */
1009 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1011 ffecom_stabilize_aggregate_ (tree ref)
1014 enum tree_code code = TREE_CODE (ref);
1021 /* No action is needed in this case. */
1027 case FIX_TRUNC_EXPR:
1028 case FIX_FLOOR_EXPR:
1029 case FIX_ROUND_EXPR:
1031 result = build_nt (code, stabilize_reference (TREE_OPERAND (ref, 0)));
1035 result = build_nt (INDIRECT_REF,
1036 stabilize_reference_1 (TREE_OPERAND (ref, 0)));
1040 result = build_nt (COMPONENT_REF,
1041 stabilize_reference (TREE_OPERAND (ref, 0)),
1042 TREE_OPERAND (ref, 1));
1046 result = build_nt (BIT_FIELD_REF,
1047 stabilize_reference (TREE_OPERAND (ref, 0)),
1048 stabilize_reference_1 (TREE_OPERAND (ref, 1)),
1049 stabilize_reference_1 (TREE_OPERAND (ref, 2)));
1053 result = build_nt (ARRAY_REF,
1054 stabilize_reference (TREE_OPERAND (ref, 0)),
1055 stabilize_reference_1 (TREE_OPERAND (ref, 1)));
1059 result = build_nt (COMPOUND_EXPR,
1060 stabilize_reference_1 (TREE_OPERAND (ref, 0)),
1061 stabilize_reference (TREE_OPERAND (ref, 1)));
1069 return save_expr (ref);
1072 return error_mark_node;
1075 TREE_TYPE (result) = TREE_TYPE (ref);
1076 TREE_READONLY (result) = TREE_READONLY (ref);
1077 TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (ref);
1078 TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (ref);
1084 /* A rip-off of gcc's convert.c convert_to_complex function,
1085 reworked to handle complex implemented as C structures
1086 (RECORD_TYPE with two fields, real and imaginary `r' and `i'). */
1088 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1090 ffecom_convert_to_complex_ (tree type, tree expr)
1092 register enum tree_code form = TREE_CODE (TREE_TYPE (expr));
1095 assert (TREE_CODE (type) == RECORD_TYPE);
1097 subtype = TREE_TYPE (TYPE_FIELDS (type));
1099 if (form == REAL_TYPE || form == INTEGER_TYPE || form == ENUMERAL_TYPE)
1101 expr = convert (subtype, expr);
1102 return ffecom_2 (COMPLEX_EXPR, type, expr,
1103 convert (subtype, integer_zero_node));
1106 if (form == RECORD_TYPE)
1108 tree elt_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr)));
1109 if (TYPE_MAIN_VARIANT (elt_type) == TYPE_MAIN_VARIANT (subtype))
1113 expr = save_expr (expr);
1114 return ffecom_2 (COMPLEX_EXPR,
1117 ffecom_1 (REALPART_EXPR,
1118 TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))),
1121 ffecom_1 (IMAGPART_EXPR,
1122 TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))),
1127 if (form == POINTER_TYPE || form == REFERENCE_TYPE)
1128 error ("pointer value used where a complex was expected");
1130 error ("aggregate value used where a complex was expected");
1132 return ffecom_2 (COMPLEX_EXPR, type,
1133 convert (subtype, integer_zero_node),
1134 convert (subtype, integer_zero_node));
1138 /* Like gcc's convert(), but crashes if widening might happen. */
1140 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1142 ffecom_convert_narrow_ (type, expr)
1145 register tree e = expr;
1146 register enum tree_code code = TREE_CODE (type);
1148 if (type == TREE_TYPE (e)
1149 || TREE_CODE (e) == ERROR_MARK)
1151 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
1152 return fold (build1 (NOP_EXPR, type, e));
1153 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
1154 || code == ERROR_MARK)
1155 return error_mark_node;
1156 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
1158 assert ("void value not ignored as it ought to be" == NULL);
1159 return error_mark_node;
1161 assert (code != VOID_TYPE);
1162 if ((code != RECORD_TYPE)
1163 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
1164 assert ("converting COMPLEX to REAL" == NULL);
1165 assert (code != ENUMERAL_TYPE);
1166 if (code == INTEGER_TYPE)
1168 assert ((TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE
1169 && TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)))
1170 || (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
1171 && (TYPE_PRECISION (type)
1172 == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (e))))));
1173 return fold (convert_to_integer (type, e));
1175 if (code == POINTER_TYPE)
1177 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
1178 return fold (convert_to_pointer (type, e));
1180 if (code == REAL_TYPE)
1182 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
1183 assert (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)));
1184 return fold (convert_to_real (type, e));
1186 if (code == COMPLEX_TYPE)
1188 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
1189 assert (TYPE_PRECISION (TREE_TYPE (type)) <= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
1190 return fold (convert_to_complex (type, e));
1192 if (code == RECORD_TYPE)
1194 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
1195 /* Check that at least the first field name agrees. */
1196 assert (DECL_NAME (TYPE_FIELDS (type))
1197 == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e))));
1198 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1199 <= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
1200 if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1201 == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))))
1203 return fold (ffecom_convert_to_complex_ (type, e));
1206 assert ("conversion to non-scalar type requested" == NULL);
1207 return error_mark_node;
1211 /* Like gcc's convert(), but crashes if narrowing might happen. */
1213 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1215 ffecom_convert_widen_ (type, expr)
1218 register tree e = expr;
1219 register enum tree_code code = TREE_CODE (type);
1221 if (type == TREE_TYPE (e)
1222 || TREE_CODE (e) == ERROR_MARK)
1224 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
1225 return fold (build1 (NOP_EXPR, type, e));
1226 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
1227 || code == ERROR_MARK)
1228 return error_mark_node;
1229 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
1231 assert ("void value not ignored as it ought to be" == NULL);
1232 return error_mark_node;
1234 assert (code != VOID_TYPE);
1235 if ((code != RECORD_TYPE)
1236 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
1237 assert ("narrowing COMPLEX to REAL" == NULL);
1238 assert (code != ENUMERAL_TYPE);
1239 if (code == INTEGER_TYPE)
1241 assert ((TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE
1242 && TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)))
1243 || (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
1244 && (TYPE_PRECISION (type)
1245 == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (e))))));
1246 return fold (convert_to_integer (type, e));
1248 if (code == POINTER_TYPE)
1250 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
1251 return fold (convert_to_pointer (type, e));
1253 if (code == REAL_TYPE)
1255 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
1256 assert (TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)));
1257 return fold (convert_to_real (type, e));
1259 if (code == COMPLEX_TYPE)
1261 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
1262 assert (TYPE_PRECISION (TREE_TYPE (type)) >= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
1263 return fold (convert_to_complex (type, e));
1265 if (code == RECORD_TYPE)
1267 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
1268 /* Check that at least the first field name agrees. */
1269 assert (DECL_NAME (TYPE_FIELDS (type))
1270 == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e))));
1271 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1272 >= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
1273 if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1274 == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))))
1276 return fold (ffecom_convert_to_complex_ (type, e));
1279 assert ("conversion to non-scalar type requested" == NULL);
1280 return error_mark_node;
1284 /* Handles making a COMPLEX type, either the standard
1285 (but buggy?) gbe way, or the safer (but less elegant?)
1288 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1290 ffecom_make_complex_type_ (tree subtype)
1296 if (ffe_is_emulate_complex ())
1298 type = make_node (RECORD_TYPE);
1299 realfield = ffecom_decl_field (type, NULL_TREE, "r", subtype);
1300 imagfield = ffecom_decl_field (type, realfield, "i", subtype);
1301 TYPE_FIELDS (type) = realfield;
1306 type = make_node (COMPLEX_TYPE);
1307 TREE_TYPE (type) = subtype;
1315 /* Chooses either the gbe or the f2c way to build a
1316 complex constant. */
1318 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1320 ffecom_build_complex_constant_ (tree type, tree realpart, tree imagpart)
1324 if (ffe_is_emulate_complex ())
1326 bothparts = build_tree_list (TYPE_FIELDS (type), realpart);
1327 TREE_CHAIN (bothparts) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), imagpart);
1328 bothparts = build (CONSTRUCTOR, type, NULL_TREE, bothparts);
1332 bothparts = build_complex (type, realpart, imagpart);
1339 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1341 ffecom_arglist_expr_ (const char *c, ffebld expr)
1344 tree *plist = &list;
1345 tree trail = NULL_TREE; /* Append char length args here. */
1346 tree *ptrail = &trail;
1351 tree wanted = NULL_TREE;
1352 static char zed[] = "0";
1357 while (expr != NULL)
1380 wanted = ffecom_f2c_complex_type_node;
1384 wanted = ffecom_f2c_doublereal_type_node;
1388 wanted = ffecom_f2c_doublecomplex_type_node;
1392 wanted = ffecom_f2c_real_type_node;
1396 wanted = ffecom_f2c_integer_type_node;
1400 wanted = ffecom_f2c_longint_type_node;
1404 assert ("bad argstring code" == NULL);
1410 exprh = ffebld_head (expr);
1414 if ((wanted == NULL_TREE)
1417 (ffecom_tree_type[ffeinfo_basictype (ffebld_info (exprh))]
1418 [ffeinfo_kindtype (ffebld_info (exprh))])
1419 == TYPE_MODE (wanted))))
1421 = build_tree_list (NULL_TREE,
1422 ffecom_arg_ptr_to_expr (exprh,
1426 item = ffecom_arg_expr (exprh, &length);
1427 item = ffecom_convert_widen_ (wanted, item);
1430 item = ffecom_1 (ADDR_EXPR,
1431 build_pointer_type (TREE_TYPE (item)),
1435 = build_tree_list (NULL_TREE,
1439 plist = &TREE_CHAIN (*plist);
1440 expr = ffebld_trail (expr);
1441 if (length != NULL_TREE)
1443 *ptrail = build_tree_list (NULL_TREE, length);
1444 ptrail = &TREE_CHAIN (*ptrail);
1448 /* We've run out of args in the call; if the implementation expects
1449 more, supply null pointers for them, which the implementation can
1450 check to see if an arg was omitted. */
1452 while (*c != '\0' && *c != '0')
1457 assert ("missing arg to run-time routine!" == NULL);
1472 assert ("bad arg string code" == NULL);
1476 = build_tree_list (NULL_TREE,
1478 plist = &TREE_CHAIN (*plist);
1487 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1489 ffecom_widest_expr_type_ (ffebld list)
1492 ffebld widest = NULL;
1494 ffetype widest_type = NULL;
1497 for (; list != NULL; list = ffebld_trail (list))
1499 item = ffebld_head (list);
1502 if ((widest != NULL)
1503 && (ffeinfo_basictype (ffebld_info (item))
1504 != ffeinfo_basictype (ffebld_info (widest))))
1506 type = ffeinfo_type (ffeinfo_basictype (ffebld_info (item)),
1507 ffeinfo_kindtype (ffebld_info (item)));
1508 if ((widest == FFEINFO_kindtypeNONE)
1509 || (ffetype_size (type)
1510 > ffetype_size (widest_type)))
1517 assert (widest != NULL);
1518 t = ffecom_tree_type[ffeinfo_basictype (ffebld_info (widest))]
1519 [ffeinfo_kindtype (ffebld_info (widest))];
1520 assert (t != NULL_TREE);
1525 /* Check whether a partial overlap between two expressions is possible.
1527 Can *starting* to write a portion of expr1 change the value
1528 computed (perhaps already, *partially*) by expr2?
1530 Currently, this is a concern only for a COMPLEX expr1. But if it
1531 isn't in COMMON or local EQUIVALENCE, since we don't support
1532 aliasing of arguments, it isn't a concern. */
1535 ffecom_possible_partial_overlap_ (ffebld expr1, ffebld expr2 ATTRIBUTE_UNUSED)
1540 switch (ffebld_op (expr1))
1542 case FFEBLD_opSYMTER:
1543 sym = ffebld_symter (expr1);
1546 case FFEBLD_opARRAYREF:
1547 if (ffebld_op (ffebld_left (expr1)) != FFEBLD_opSYMTER)
1549 sym = ffebld_symter (ffebld_left (expr1));
1556 if (ffesymbol_where (sym) != FFEINFO_whereCOMMON
1557 && (ffesymbol_where (sym) != FFEINFO_whereLOCAL
1558 || ! (st = ffesymbol_storage (sym))
1559 || ! ffestorag_parent (st)))
1562 /* It's in COMMON or local EQUIVALENCE. */
1567 /* Check whether dest and source might overlap. ffebld versions of these
1568 might or might not be passed, will be NULL if not.
1570 The test is really whether source_tree is modifiable and, if modified,
1571 might overlap destination such that the value(s) in the destination might
1572 change before it is finally modified. dest_* are the canonized
1573 destination itself. */
1575 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1577 ffecom_overlap_ (tree dest_decl, tree dest_offset, tree dest_size,
1578 tree source_tree, ffebld source UNUSED,
1586 if (source_tree == NULL_TREE)
1589 switch (TREE_CODE (source_tree))
1592 case IDENTIFIER_NODE:
1603 case TRUNC_DIV_EXPR:
1605 case FLOOR_DIV_EXPR:
1606 case ROUND_DIV_EXPR:
1607 case TRUNC_MOD_EXPR:
1609 case FLOOR_MOD_EXPR:
1610 case ROUND_MOD_EXPR:
1612 case EXACT_DIV_EXPR:
1613 case FIX_TRUNC_EXPR:
1615 case FIX_FLOOR_EXPR:
1616 case FIX_ROUND_EXPR:
1631 case BIT_ANDTC_EXPR:
1633 case TRUTH_ANDIF_EXPR:
1634 case TRUTH_ORIF_EXPR:
1635 case TRUTH_AND_EXPR:
1637 case TRUTH_XOR_EXPR:
1638 case TRUTH_NOT_EXPR:
1654 return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1655 TREE_OPERAND (source_tree, 1), NULL,
1659 return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1660 TREE_OPERAND (source_tree, 0), NULL,
1665 case NON_LVALUE_EXPR:
1667 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1670 ffecom_tree_canonize_ptr_ (&source_decl, &source_offset,
1672 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1677 ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1678 TREE_OPERAND (source_tree, 1), NULL,
1680 || ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1681 TREE_OPERAND (source_tree, 2), NULL,
1686 ffecom_tree_canonize_ref_ (&source_decl, &source_offset,
1688 TREE_OPERAND (source_tree, 0));
1692 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1695 source_decl = source_tree;
1696 source_offset = bitsize_zero_node;
1697 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1701 case REFERENCE_EXPR:
1702 case PREDECREMENT_EXPR:
1703 case PREINCREMENT_EXPR:
1704 case POSTDECREMENT_EXPR:
1705 case POSTINCREMENT_EXPR:
1713 /* Come here when source_decl, source_offset, and source_size filled
1714 in appropriately. */
1716 if (source_decl == NULL_TREE)
1717 return FALSE; /* No decl involved, so no overlap. */
1719 if (source_decl != dest_decl)
1720 return FALSE; /* Different decl, no overlap. */
1722 if (TREE_CODE (dest_size) == ERROR_MARK)
1723 return TRUE; /* Assignment into entire assumed-size
1724 array? Shouldn't happen.... */
1726 t = ffecom_2 (LE_EXPR, integer_type_node,
1727 ffecom_2 (PLUS_EXPR, TREE_TYPE (dest_offset),
1729 convert (TREE_TYPE (dest_offset),
1731 convert (TREE_TYPE (dest_offset),
1734 if (integer_onep (t))
1735 return FALSE; /* Destination precedes source. */
1738 || (source_size == NULL_TREE)
1739 || (TREE_CODE (source_size) == ERROR_MARK)
1740 || integer_zerop (source_size))
1741 return TRUE; /* No way to tell if dest follows source. */
1743 t = ffecom_2 (LE_EXPR, integer_type_node,
1744 ffecom_2 (PLUS_EXPR, TREE_TYPE (source_offset),
1746 convert (TREE_TYPE (source_offset),
1748 convert (TREE_TYPE (source_offset),
1751 if (integer_onep (t))
1752 return FALSE; /* Destination follows source. */
1754 return TRUE; /* Destination and source overlap. */
1758 /* Check whether dest might overlap any of a list of arguments or is
1759 in a COMMON area the callee might know about (and thus modify). */
1761 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1763 ffecom_args_overlapping_ (tree dest_tree, ffebld dest UNUSED,
1764 tree args, tree callee_commons,
1772 ffecom_tree_canonize_ref_ (&dest_decl, &dest_offset, &dest_size,
1775 if (dest_decl == NULL_TREE)
1776 return FALSE; /* Seems unlikely! */
1778 /* If the decl cannot be determined reliably, or if its in COMMON
1779 and the callee isn't known to not futz with COMMON via other
1780 means, overlap might happen. */
1782 if ((TREE_CODE (dest_decl) == ERROR_MARK)
1783 || ((callee_commons != NULL_TREE)
1784 && TREE_PUBLIC (dest_decl)))
1787 for (; args != NULL_TREE; args = TREE_CHAIN (args))
1789 if (((arg = TREE_VALUE (args)) != NULL_TREE)
1790 && ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1791 arg, NULL, scalar_args))
1799 /* Build a string for a variable name as used by NAMELIST. This means that
1800 if we're using the f2c library, we build an uppercase string, since
1803 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1805 ffecom_build_f2c_string_ (int i, const char *s)
1807 if (!ffe_is_f2c_library ())
1808 return build_string (i, s);
1817 if (((size_t) i) > ARRAY_SIZE (space))
1818 tmp = malloc_new_ks (malloc_pool_image (), "f2c_string", i);
1822 for (p = s, q = tmp; *p != '\0'; ++p, ++q)
1826 t = build_string (i, tmp);
1828 if (((size_t) i) > ARRAY_SIZE (space))
1829 malloc_kill_ks (malloc_pool_image (), tmp, i);
1836 /* Returns CALL_EXPR or equivalent with given type (pass NULL_TREE for
1837 type to just get whatever the function returns), handling the
1838 f2c value-returning convention, if required, by prepending
1839 to the arglist a pointer to a temporary to receive the return value. */
1841 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1843 ffecom_call_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1844 tree type, tree args, tree dest_tree,
1845 ffebld dest, bool *dest_used, tree callee_commons,
1846 bool scalar_args, tree hook)
1851 if (dest_used != NULL)
1856 if ((dest_used == NULL)
1858 || (ffeinfo_basictype (ffebld_info (dest))
1859 != FFEINFO_basictypeCOMPLEX)
1860 || (ffeinfo_kindtype (ffebld_info (dest)) != kt)
1861 || ((type != NULL_TREE) && (TREE_TYPE (dest_tree) != type))
1862 || ffecom_args_overlapping_ (dest_tree, dest, args,
1867 tempvar = ffecom_make_tempvar (ffecom_tree_type
1868 [FFEINFO_basictypeCOMPLEX][kt],
1869 FFETARGET_charactersizeNONE,
1879 tempvar = dest_tree;
1884 = build_tree_list (NULL_TREE,
1885 ffecom_1 (ADDR_EXPR,
1886 build_pointer_type (TREE_TYPE (tempvar)),
1888 TREE_CHAIN (item) = args;
1890 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1893 if (tempvar != dest_tree)
1894 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item, tempvar);
1897 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1900 if ((type != NULL_TREE) && (TREE_TYPE (item) != type))
1901 item = ffecom_convert_narrow_ (type, item);
1907 /* Given two arguments, transform them and make a call to the given
1908 function via ffecom_call_. */
1910 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1912 ffecom_call_binop_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1913 tree type, ffebld left, ffebld right,
1914 tree dest_tree, ffebld dest, bool *dest_used,
1915 tree callee_commons, bool scalar_args, bool ref, tree hook)
1924 /* Pass arguments by reference. */
1925 left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
1926 right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
1930 /* Pass arguments by value. */
1931 left_tree = ffecom_arg_expr (left, &left_length);
1932 right_tree = ffecom_arg_expr (right, &right_length);
1936 left_tree = build_tree_list (NULL_TREE, left_tree);
1937 right_tree = build_tree_list (NULL_TREE, right_tree);
1938 TREE_CHAIN (left_tree) = right_tree;
1940 if (left_length != NULL_TREE)
1942 left_length = build_tree_list (NULL_TREE, left_length);
1943 TREE_CHAIN (right_tree) = left_length;
1946 if (right_length != NULL_TREE)
1948 right_length = build_tree_list (NULL_TREE, right_length);
1949 if (left_length != NULL_TREE)
1950 TREE_CHAIN (left_length) = right_length;
1952 TREE_CHAIN (right_tree) = right_length;
1955 return ffecom_call_ (fn, kt, is_f2c_complex, type, left_tree,
1956 dest_tree, dest, dest_used, callee_commons,
1961 /* Return ptr/length args for char subexpression
1963 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
1964 subexpressions by constructing the appropriate trees for the ptr-to-
1965 character-text and length-of-character-text arguments in a calling
1968 Note that if with_null is TRUE, and the expression is an opCONTER,
1969 a null byte is appended to the string. */
1971 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1973 ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
1977 ffetargetCharacter1 val;
1978 ffetargetCharacterSize newlen;
1980 switch (ffebld_op (expr))
1982 case FFEBLD_opCONTER:
1983 val = ffebld_constant_character1 (ffebld_conter (expr));
1984 newlen = ffetarget_length_character1 (val);
1987 /* Begin FFETARGET-NULL-KLUDGE. */
1991 *length = build_int_2 (newlen, 0);
1992 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
1993 high = build_int_2 (newlen, 0);
1994 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
1995 item = build_string (newlen,
1996 ffetarget_text_character1 (val));
1997 /* End FFETARGET-NULL-KLUDGE. */
1999 = build_type_variant
2003 (ffecom_f2c_ftnlen_type_node,
2004 ffecom_f2c_ftnlen_one_node,
2007 TREE_CONSTANT (item) = 1;
2008 TREE_STATIC (item) = 1;
2009 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
2013 case FFEBLD_opSYMTER:
2015 ffesymbol s = ffebld_symter (expr);
2017 item = ffesymbol_hook (s).decl_tree;
2018 if (item == NULL_TREE)
2020 s = ffecom_sym_transform_ (s);
2021 item = ffesymbol_hook (s).decl_tree;
2023 if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
2025 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
2026 *length = ffesymbol_hook (s).length_tree;
2029 *length = build_int_2 (ffesymbol_size (s), 0);
2030 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2033 else if (item == error_mark_node)
2034 *length = error_mark_node;
2036 /* FFEINFO_kindFUNCTION. */
2037 *length = NULL_TREE;
2038 if (!ffesymbol_hook (s).addr
2039 && (item != error_mark_node))
2040 item = ffecom_1 (ADDR_EXPR,
2041 build_pointer_type (TREE_TYPE (item)),
2046 case FFEBLD_opARRAYREF:
2048 ffecom_char_args_ (&item, length, ffebld_left (expr));
2050 if (item == error_mark_node || *length == error_mark_node)
2052 item = *length = error_mark_node;
2056 item = ffecom_arrayref_ (item, expr, 1);
2060 case FFEBLD_opSUBSTR:
2064 ffebld thing = ffebld_right (expr);
2067 const char *char_name;
2071 assert (ffebld_op (thing) == FFEBLD_opITEM);
2072 start = ffebld_head (thing);
2073 thing = ffebld_trail (thing);
2074 assert (ffebld_trail (thing) == NULL);
2075 end = ffebld_head (thing);
2077 /* Determine name for pretty-printing range-check errors. */
2078 for (left_symter = ffebld_left (expr);
2079 left_symter && ffebld_op (left_symter) == FFEBLD_opARRAYREF;
2080 left_symter = ffebld_left (left_symter))
2082 if (ffebld_op (left_symter) == FFEBLD_opSYMTER)
2083 char_name = ffesymbol_text (ffebld_symter (left_symter));
2085 char_name = "[expr?]";
2087 ffecom_char_args_ (&item, length, ffebld_left (expr));
2089 if (item == error_mark_node || *length == error_mark_node)
2091 item = *length = error_mark_node;
2095 array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
2097 /* ~~~~Handle INTEGER*8 start/end, a la FFEBLD_opARRAYREF. */
2105 end_tree = ffecom_expr (end);
2106 if (flag_bounds_check)
2107 end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
2109 end_tree = convert (ffecom_f2c_ftnlen_type_node,
2112 if (end_tree == error_mark_node)
2114 item = *length = error_mark_node;
2123 start_tree = ffecom_expr (start);
2124 if (flag_bounds_check)
2125 start_tree = ffecom_subscript_check_ (array, start_tree, 0, 0,
2127 start_tree = convert (ffecom_f2c_ftnlen_type_node,
2130 if (start_tree == error_mark_node)
2132 item = *length = error_mark_node;
2136 start_tree = ffecom_save_tree (start_tree);
2138 item = ffecom_2 (PLUS_EXPR, TREE_TYPE (item),
2140 ffecom_2 (MINUS_EXPR,
2141 TREE_TYPE (start_tree),
2143 ffecom_f2c_ftnlen_one_node));
2147 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
2148 ffecom_f2c_ftnlen_one_node,
2149 ffecom_2 (MINUS_EXPR,
2150 ffecom_f2c_ftnlen_type_node,
2156 end_tree = ffecom_expr (end);
2157 if (flag_bounds_check)
2158 end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
2160 end_tree = convert (ffecom_f2c_ftnlen_type_node,
2163 if (end_tree == error_mark_node)
2165 item = *length = error_mark_node;
2169 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
2170 ffecom_f2c_ftnlen_one_node,
2171 ffecom_2 (MINUS_EXPR,
2172 ffecom_f2c_ftnlen_type_node,
2173 end_tree, start_tree));
2179 case FFEBLD_opFUNCREF:
2181 ffesymbol s = ffebld_symter (ffebld_left (expr));
2184 ffetargetCharacterSize size = ffeinfo_size (ffebld_info (expr));
2187 if (size == FFETARGET_charactersizeNONE)
2188 /* ~~Kludge alert! This should someday be fixed. */
2191 *length = build_int_2 (size, 0);
2192 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2194 if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
2195 == FFEINFO_whereINTRINSIC)
2199 /* Invocation of an intrinsic returning CHARACTER*1. */
2200 item = ffecom_expr_intrinsic_ (expr, NULL_TREE,
2204 ix = ffeintrin_gfrt_direct (ffebld_symter_implementation (ffebld_left (expr)));
2205 assert (ix != FFECOM_gfrt);
2206 item = ffecom_gfrt_tree_ (ix);
2211 item = ffesymbol_hook (s).decl_tree;
2212 if (item == NULL_TREE)
2214 s = ffecom_sym_transform_ (s);
2215 item = ffesymbol_hook (s).decl_tree;
2217 if (item == error_mark_node)
2219 item = *length = error_mark_node;
2223 if (!ffesymbol_hook (s).addr)
2224 item = ffecom_1_fn (item);
2228 tempvar = ffecom_push_tempvar (char_type_node, size, -1, TRUE);
2230 tempvar = ffebld_nonter_hook (expr);
2233 tempvar = ffecom_1 (ADDR_EXPR,
2234 build_pointer_type (TREE_TYPE (tempvar)),
2237 args = build_tree_list (NULL_TREE, tempvar);
2239 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT) /* Sfunc args by value. */
2240 TREE_CHAIN (args) = ffecom_list_expr (ffebld_right (expr));
2243 TREE_CHAIN (args) = build_tree_list (NULL_TREE, *length);
2244 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
2246 TREE_CHAIN (TREE_CHAIN (args))
2247 = ffecom_arglist_expr_ (ffecom_gfrt_args_ (ix),
2248 ffebld_right (expr));
2252 TREE_CHAIN (TREE_CHAIN (args))
2253 = ffecom_list_ptr_to_expr (ffebld_right (expr));
2257 item = ffecom_3s (CALL_EXPR,
2258 TREE_TYPE (TREE_TYPE (TREE_TYPE (item))),
2259 item, args, NULL_TREE);
2260 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item,
2265 case FFEBLD_opCONVERT:
2267 ffecom_char_args_ (&item, length, ffebld_left (expr));
2269 if (item == error_mark_node || *length == error_mark_node)
2271 item = *length = error_mark_node;
2275 if ((ffebld_size_known (ffebld_left (expr))
2276 == FFETARGET_charactersizeNONE)
2277 || (ffebld_size_known (ffebld_left (expr)) < (ffebld_size (expr))))
2278 { /* Possible blank-padding needed, copy into
2285 tempvar = ffecom_make_tempvar (char_type_node,
2286 ffebld_size (expr), -1);
2288 tempvar = ffebld_nonter_hook (expr);
2291 tempvar = ffecom_1 (ADDR_EXPR,
2292 build_pointer_type (TREE_TYPE (tempvar)),
2295 newlen = build_int_2 (ffebld_size (expr), 0);
2296 TREE_TYPE (newlen) = ffecom_f2c_ftnlen_type_node;
2298 args = build_tree_list (NULL_TREE, tempvar);
2299 TREE_CHAIN (args) = build_tree_list (NULL_TREE, item);
2300 TREE_CHAIN (TREE_CHAIN (args)) = build_tree_list (NULL_TREE, newlen);
2301 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (args)))
2302 = build_tree_list (NULL_TREE, *length);
2304 item = ffecom_call_gfrt (FFECOM_gfrtCOPY, args, NULL_TREE);
2305 TREE_SIDE_EFFECTS (item) = 1;
2306 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), fold (item),
2311 { /* Just truncate the length. */
2312 *length = build_int_2 (ffebld_size (expr), 0);
2313 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2318 assert ("bad op for single char arg expr" == NULL);
2327 /* Check the size of the type to be sure it doesn't overflow the
2328 "portable" capacities of the compiler back end. `dummy' types
2329 can generally overflow the normal sizes as long as the computations
2330 themselves don't overflow. A particular target of the back end
2331 must still enforce its size requirements, though, and the back
2332 end takes care of this in stor-layout.c. */
2334 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2336 ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy)
2338 if (TREE_CODE (type) == ERROR_MARK)
2341 if (TYPE_SIZE (type) == NULL_TREE)
2344 if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
2347 if ((tree_int_cst_sgn (TYPE_SIZE (type)) < 0)
2348 || (!dummy && (((TREE_INT_CST_HIGH (TYPE_SIZE (type)) != 0))
2349 || TREE_OVERFLOW (TYPE_SIZE (type)))))
2351 ffebad_start (FFEBAD_ARRAY_LARGE);
2352 ffebad_string (ffesymbol_text (s));
2353 ffebad_here (0, ffesymbol_where_line (s), ffesymbol_where_column (s));
2356 return error_mark_node;
2363 /* Builds a length argument (PARM_DECL). Also wraps type in an array type
2364 where the dimension info is (1:size) where <size> is ffesymbol_size(s) if
2365 known, length_arg if not known (FFETARGET_charactersizeNONE). */
2367 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2369 ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s)
2371 ffetargetCharacterSize sz = ffesymbol_size (s);
2376 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
2377 tlen = NULL_TREE; /* A statement function, no length passed. */
2380 if (ffesymbol_where (s) == FFEINFO_whereDUMMY)
2381 tlen = ffecom_get_invented_identifier ("__g77_length_%s",
2382 ffesymbol_text (s));
2384 tlen = ffecom_get_invented_identifier ("__g77_%s", "length");
2385 tlen = build_decl (PARM_DECL, tlen, ffecom_f2c_ftnlen_type_node);
2387 DECL_ARTIFICIAL (tlen) = 1;
2391 if (sz == FFETARGET_charactersizeNONE)
2393 assert (tlen != NULL_TREE);
2394 highval = variable_size (tlen);
2398 highval = build_int_2 (sz, 0);
2399 TREE_TYPE (highval) = ffecom_f2c_ftnlen_type_node;
2402 type = build_array_type (type,
2403 build_range_type (ffecom_f2c_ftnlen_type_node,
2404 ffecom_f2c_ftnlen_one_node,
2412 /* ffecom_concat_list_gather_ -- Gather list of concatenated string exprs
2414 ffecomConcatList_ catlist;
2415 ffebld expr; // expr of CHARACTER basictype.
2416 ffetargetCharacterSize max; // max chars to gather or _...NONE if no max
2417 catlist = ffecom_concat_list_gather_(catlist,expr,max);
2419 Scans expr for character subexpressions, updates and returns catlist
2422 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2423 static ffecomConcatList_
2424 ffecom_concat_list_gather_ (ffecomConcatList_ catlist, ffebld expr,
2425 ffetargetCharacterSize max)
2427 ffetargetCharacterSize sz;
2429 recurse: /* :::::::::::::::::::: */
2434 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen >= max))
2435 return catlist; /* Don't append any more items. */
2437 switch (ffebld_op (expr))
2439 case FFEBLD_opCONTER:
2440 case FFEBLD_opSYMTER:
2441 case FFEBLD_opARRAYREF:
2442 case FFEBLD_opFUNCREF:
2443 case FFEBLD_opSUBSTR:
2444 case FFEBLD_opCONVERT: /* Callers should strip this off beforehand
2445 if they don't need to preserve it. */
2446 if (catlist.count == catlist.max)
2447 { /* Make a (larger) list. */
2451 newmax = (catlist.max == 0) ? 8 : catlist.max * 2;
2452 newx = malloc_new_ks (malloc_pool_image (), "catlist",
2453 newmax * sizeof (newx[0]));
2454 if (catlist.max != 0)
2456 memcpy (newx, catlist.exprs, catlist.max * sizeof (newx[0]));
2457 malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2458 catlist.max * sizeof (newx[0]));
2460 catlist.max = newmax;
2461 catlist.exprs = newx;
2463 if ((sz = ffebld_size_known (expr)) != FFETARGET_charactersizeNONE)
2464 catlist.minlen += sz;
2466 ++catlist.minlen; /* Not true for F90; can be 0 length. */
2467 if ((sz = ffebld_size_max (expr)) == FFETARGET_charactersizeNONE)
2468 catlist.maxlen = sz;
2470 catlist.maxlen += sz;
2471 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen > max))
2472 { /* This item overlaps (or is beyond) the end
2473 of the destination. */
2474 switch (ffebld_op (expr))
2476 case FFEBLD_opCONTER:
2477 case FFEBLD_opSYMTER:
2478 case FFEBLD_opARRAYREF:
2479 case FFEBLD_opFUNCREF:
2480 case FFEBLD_opSUBSTR:
2481 /* ~~Do useful truncations here. */
2485 assert ("op changed or inconsistent switches!" == NULL);
2489 catlist.exprs[catlist.count++] = expr;
2492 case FFEBLD_opPAREN:
2493 expr = ffebld_left (expr);
2494 goto recurse; /* :::::::::::::::::::: */
2496 case FFEBLD_opCONCATENATE:
2497 catlist = ffecom_concat_list_gather_ (catlist, ffebld_left (expr), max);
2498 expr = ffebld_right (expr);
2499 goto recurse; /* :::::::::::::::::::: */
2501 #if 0 /* Breaks passing small actual arg to larger
2502 dummy arg of sfunc */
2503 case FFEBLD_opCONVERT:
2504 expr = ffebld_left (expr);
2506 ffetargetCharacterSize cmax;
2508 cmax = catlist.len + ffebld_size_known (expr);
2510 if ((max == FFETARGET_charactersizeNONE) || (max > cmax))
2513 goto recurse; /* :::::::::::::::::::: */
2520 assert ("bad op in _gather_" == NULL);
2526 /* ffecom_concat_list_kill_ -- Kill list of concatenated string exprs
2528 ffecomConcatList_ catlist;
2529 ffecom_concat_list_kill_(catlist);
2531 Anything allocated within the list info is deallocated. */
2533 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2535 ffecom_concat_list_kill_ (ffecomConcatList_ catlist)
2537 if (catlist.max != 0)
2538 malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2539 catlist.max * sizeof (catlist.exprs[0]));
2543 /* Make list of concatenated string exprs.
2545 Returns a flattened list of concatenated subexpressions given a
2546 tree of such expressions. */
2548 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2549 static ffecomConcatList_
2550 ffecom_concat_list_new_ (ffebld expr, ffetargetCharacterSize max)
2552 ffecomConcatList_ catlist;
2554 catlist.maxlen = catlist.minlen = catlist.max = catlist.count = 0;
2555 return ffecom_concat_list_gather_ (catlist, expr, max);
2560 /* Provide some kind of useful info on member of aggregate area,
2561 since current g77/gcc technology does not provide debug info
2562 on these members. */
2564 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2566 ffecom_debug_kludge_ (tree aggr, const char *aggr_type, ffesymbol member,
2567 tree member_type UNUSED, ffetargetOffset offset)
2577 for (type_id = member_type;
2578 TREE_CODE (type_id) != IDENTIFIER_NODE;
2581 switch (TREE_CODE (type_id))
2585 type_id = TYPE_NAME (type_id);
2590 type_id = TREE_TYPE (type_id);
2594 assert ("no IDENTIFIER_NODE for type!" == NULL);
2595 type_id = error_mark_node;
2601 if (ffecom_transform_only_dummies_
2602 || !ffe_is_debug_kludge ())
2603 return; /* Can't do this yet, maybe later. */
2606 + strlen (aggr_type)
2607 + IDENTIFIER_LENGTH (DECL_NAME (aggr));
2609 + IDENTIFIER_LENGTH (type_id);
2612 if (((size_t) len) >= ARRAY_SIZE (space))
2613 buff = malloc_new_ks (malloc_pool_image (), "debug_kludge", len + 1);
2617 sprintf (&buff[0], "At (%s) `%s' plus %ld bytes",
2619 IDENTIFIER_POINTER (DECL_NAME (aggr)),
2622 value = build_string (len, buff);
2624 = build_type_variant (build_array_type (char_type_node,
2628 build_int_2 (strlen (buff), 0))),
2630 decl = build_decl (VAR_DECL,
2631 ffecom_get_identifier_ (ffesymbol_text (member)),
2633 TREE_CONSTANT (decl) = 1;
2634 TREE_STATIC (decl) = 1;
2635 DECL_INITIAL (decl) = error_mark_node;
2636 DECL_IN_SYSTEM_HEADER (decl) = 1; /* Don't let -Wunused complain. */
2637 decl = start_decl (decl, FALSE);
2638 finish_decl (decl, value, FALSE);
2640 if (buff != &space[0])
2641 malloc_kill_ks (malloc_pool_image (), buff, len + 1);
2645 /* ffecom_do_entry_ -- Do compilation of a particular entrypoint
2647 ffesymbol fn; // the SUBROUTINE, FUNCTION, or ENTRY symbol itself
2648 int i; // entry# for this entrypoint (used by master fn)
2649 ffecom_do_entrypoint_(s,i);
2651 Makes a public entry point that calls our private master fn (already
2654 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2656 ffecom_do_entry_ (ffesymbol fn, int entrynum)
2659 tree type; /* Type of function. */
2660 tree multi_retval; /* Var holding return value (union). */
2661 tree result; /* Var holding result. */
2662 ffeinfoBasictype bt;
2666 bool charfunc; /* All entry points return same type
2668 bool cmplxfunc; /* Use f2c way of returning COMPLEX. */
2669 bool multi; /* Master fn has multiple return types. */
2670 bool altreturning = FALSE; /* This entry point has alternate returns. */
2671 int old_lineno = lineno;
2672 const char *old_input_filename = input_filename;
2674 input_filename = ffesymbol_where_filename (fn);
2675 lineno = ffesymbol_where_filelinenum (fn);
2677 ffecom_doing_entry_ = TRUE; /* Don't bother with array dimensions. */
2679 switch (ffecom_primary_entry_kind_)
2681 case FFEINFO_kindFUNCTION:
2683 /* Determine actual return type for function. */
2685 gt = FFEGLOBAL_typeFUNC;
2686 bt = ffesymbol_basictype (fn);
2687 kt = ffesymbol_kindtype (fn);
2688 if (bt == FFEINFO_basictypeNONE)
2690 ffeimplic_establish_symbol (fn);
2691 if (ffesymbol_funcresult (fn) != NULL)
2692 ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
2693 bt = ffesymbol_basictype (fn);
2694 kt = ffesymbol_kindtype (fn);
2697 if (bt == FFEINFO_basictypeCHARACTER)
2698 charfunc = TRUE, cmplxfunc = FALSE;
2699 else if ((bt == FFEINFO_basictypeCOMPLEX)
2700 && ffesymbol_is_f2c (fn))
2701 charfunc = FALSE, cmplxfunc = TRUE;
2703 charfunc = cmplxfunc = FALSE;
2706 type = ffecom_tree_fun_type_void;
2707 else if (ffesymbol_is_f2c (fn))
2708 type = ffecom_tree_fun_type[bt][kt];
2710 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
2712 if ((type == NULL_TREE)
2713 || (TREE_TYPE (type) == NULL_TREE))
2714 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */
2716 multi = (ffecom_master_bt_ == FFEINFO_basictypeNONE);
2719 case FFEINFO_kindSUBROUTINE:
2720 gt = FFEGLOBAL_typeSUBR;
2721 bt = FFEINFO_basictypeNONE;
2722 kt = FFEINFO_kindtypeNONE;
2723 if (ffecom_is_altreturning_)
2724 { /* Am _I_ altreturning? */
2725 for (item = ffesymbol_dummyargs (fn);
2727 item = ffebld_trail (item))
2729 if (ffebld_op (ffebld_head (item)) == FFEBLD_opSTAR)
2731 altreturning = TRUE;
2736 type = ffecom_tree_subr_type;
2738 type = ffecom_tree_fun_type_void;
2741 type = ffecom_tree_fun_type_void;
2748 assert ("say what??" == NULL);
2750 case FFEINFO_kindANY:
2751 gt = FFEGLOBAL_typeANY;
2752 bt = FFEINFO_basictypeNONE;
2753 kt = FFEINFO_kindtypeNONE;
2754 type = error_mark_node;
2761 /* build_decl uses the current lineno and input_filename to set the decl
2762 source info. So, I've putzed with ffestd and ffeste code to update that
2763 source info to point to the appropriate statement just before calling
2764 ffecom_do_entrypoint (which calls this fn). */
2766 start_function (ffecom_get_external_identifier_ (fn),
2768 0, /* nested/inline */
2769 1); /* TREE_PUBLIC */
2771 if (((g = ffesymbol_global (fn)) != NULL)
2772 && ((ffeglobal_type (g) == gt)
2773 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
2775 ffeglobal_set_hook (g, current_function_decl);
2778 /* Reset args in master arg list so they get retransitioned. */
2780 for (item = ffecom_master_arglist_;
2782 item = ffebld_trail (item))
2787 arg = ffebld_head (item);
2788 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2789 continue; /* Alternate return or some such thing. */
2790 s = ffebld_symter (arg);
2791 ffesymbol_hook (s).decl_tree = NULL_TREE;
2792 ffesymbol_hook (s).length_tree = NULL_TREE;
2795 /* Build dummy arg list for this entry point. */
2797 if (charfunc || cmplxfunc)
2798 { /* Prepend arg for where result goes. */
2803 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
2805 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
2807 result = ffecom_get_invented_identifier ("__g77_%s", "result");
2809 /* Make length arg _and_ enhance type info for CHAR arg itself. */
2812 length = ffecom_char_enhance_arg_ (&type, fn);
2814 length = NULL_TREE; /* Not ref'd if !charfunc. */
2816 type = build_pointer_type (type);
2817 result = build_decl (PARM_DECL, result, type);
2819 push_parm_decl (result);
2820 ffecom_func_result_ = result;
2824 push_parm_decl (length);
2825 ffecom_func_length_ = length;
2829 result = DECL_RESULT (current_function_decl);
2831 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (fn), FALSE);
2833 store_parm_decls (0);
2835 ffecom_start_compstmt ();
2836 /* Disallow temp vars at this level. */
2837 current_binding_level->prep_state = 2;
2839 /* Make local var to hold return type for multi-type master fn. */
2843 multi_retval = ffecom_get_invented_identifier ("__g77_%s",
2845 multi_retval = build_decl (VAR_DECL, multi_retval,
2846 ffecom_multi_type_node_);
2847 multi_retval = start_decl (multi_retval, FALSE);
2848 finish_decl (multi_retval, NULL_TREE, FALSE);
2851 multi_retval = NULL_TREE; /* Not actually ref'd if !multi. */
2853 /* Here we emit the actual code for the entry point. */
2859 tree arglist = NULL_TREE;
2860 tree *plist = &arglist;
2866 /* Prepare actual arg list based on master arg list. */
2868 for (list = ffecom_master_arglist_;
2870 list = ffebld_trail (list))
2872 arg = ffebld_head (list);
2873 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2875 s = ffebld_symter (arg);
2876 if (ffesymbol_hook (s).decl_tree == NULL_TREE
2877 || ffesymbol_hook (s).decl_tree == error_mark_node)
2878 actarg = null_pointer_node; /* We don't have this arg. */
2880 actarg = ffesymbol_hook (s).decl_tree;
2881 *plist = build_tree_list (NULL_TREE, actarg);
2882 plist = &TREE_CHAIN (*plist);
2885 /* This code appends the length arguments for character
2886 variables/arrays. */
2888 for (list = ffecom_master_arglist_;
2890 list = ffebld_trail (list))
2892 arg = ffebld_head (list);
2893 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2895 s = ffebld_symter (arg);
2896 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
2897 continue; /* Only looking for CHARACTER arguments. */
2898 if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
2899 continue; /* Only looking for variables and arrays. */
2900 if (ffesymbol_hook (s).length_tree == NULL_TREE
2901 || ffesymbol_hook (s).length_tree == error_mark_node)
2902 actarg = ffecom_f2c_ftnlen_zero_node; /* We don't have this arg. */
2904 actarg = ffesymbol_hook (s).length_tree;
2905 *plist = build_tree_list (NULL_TREE, actarg);
2906 plist = &TREE_CHAIN (*plist);
2909 /* Prepend character-value return info to actual arg list. */
2913 prepend = build_tree_list (NULL_TREE, ffecom_func_result_);
2914 TREE_CHAIN (prepend)
2915 = build_tree_list (NULL_TREE, ffecom_func_length_);
2916 TREE_CHAIN (TREE_CHAIN (prepend)) = arglist;
2920 /* Prepend multi-type return value to actual arg list. */
2925 = build_tree_list (NULL_TREE,
2926 ffecom_1 (ADDR_EXPR,
2927 build_pointer_type (TREE_TYPE (multi_retval)),
2929 TREE_CHAIN (prepend) = arglist;
2933 /* Prepend my entry-point number to the actual arg list. */
2935 prepend = build_tree_list (NULL_TREE, build_int_2 (entrynum, 0));
2936 TREE_CHAIN (prepend) = arglist;
2939 /* Build the call to the master function. */
2941 master_fn = ffecom_1_fn (ffecom_previous_function_decl_);
2942 call = ffecom_3s (CALL_EXPR,
2943 TREE_TYPE (TREE_TYPE (TREE_TYPE (master_fn))),
2944 master_fn, arglist, NULL_TREE);
2946 /* Decide whether the master function is a function or subroutine, and
2947 handle the return value for my entry point. */
2949 if (charfunc || ((ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
2952 expand_expr_stmt (call);
2953 expand_null_return ();
2955 else if (multi && cmplxfunc)
2957 expand_expr_stmt (call);
2959 = ffecom_1 (INDIRECT_REF,
2960 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
2962 result = ffecom_modify (NULL_TREE, result,
2963 ffecom_2 (COMPONENT_REF, TREE_TYPE (result),
2965 ffecom_multi_fields_[bt][kt]));
2966 expand_expr_stmt (result);
2967 expand_null_return ();
2971 expand_expr_stmt (call);
2973 = ffecom_modify (NULL_TREE, result,
2974 convert (TREE_TYPE (result),
2975 ffecom_2 (COMPONENT_REF,
2976 ffecom_tree_type[bt][kt],
2978 ffecom_multi_fields_[bt][kt])));
2979 expand_return (result);
2984 = ffecom_1 (INDIRECT_REF,
2985 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
2987 result = ffecom_modify (NULL_TREE, result, call);
2988 expand_expr_stmt (result);
2989 expand_null_return ();
2993 result = ffecom_modify (NULL_TREE,
2995 convert (TREE_TYPE (result),
2997 expand_return (result);
3001 ffecom_end_compstmt ();
3003 finish_function (0);
3005 lineno = old_lineno;
3006 input_filename = old_input_filename;
3008 ffecom_doing_entry_ = FALSE;
3012 /* Transform expr into gcc tree with possible destination
3014 Recursive descent on expr while making corresponding tree nodes and
3015 attaching type info and such. If destination supplied and compatible
3016 with temporary that would be made in certain cases, temporary isn't
3017 made, destination used instead, and dest_used flag set TRUE. */
3019 #if FFECOM_targetCURRENT == FFECOM_targetGCC
3021 ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
3022 bool *dest_used, bool assignp, bool widenp)
3027 ffeinfoBasictype bt;
3030 tree dt; /* decl_tree for an ffesymbol. */
3031 tree tree_type, tree_type_x;
3034 enum tree_code code;
3036 assert (expr != NULL);
3038 if (dest_used != NULL)
3041 bt = ffeinfo_basictype (ffebld_info (expr));
3042 kt = ffeinfo_kindtype (ffebld_info (expr));
3043 tree_type = ffecom_tree_type[bt][kt];
3045 /* Widen integral arithmetic as desired while preserving signedness. */
3046 tree_type_x = NULL_TREE;
3047 if (widenp && tree_type
3048 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
3049 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
3050 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
3052 switch (ffebld_op (expr))
3054 case FFEBLD_opACCTER:
3057 ffebit bits = ffebld_accter_bits (expr);
3058 ffetargetOffset source_offset = 0;
3059 ffetargetOffset dest_offset = ffebld_accter_pad (expr);
3062 assert (dest_offset == 0
3063 || (bt == FFEINFO_basictypeCHARACTER
3064 && kt == FFEINFO_kindtypeCHARACTER1));
3069 ffebldConstantUnion cu;
3072 ffebldConstantArray ca = ffebld_accter (expr);
3074 ffebit_test (bits, source_offset, &value, &length);
3080 for (i = 0; i < length; ++i)
3082 cu = ffebld_constantarray_get (ca, bt, kt,
3085 t = ffecom_constantunion (&cu, bt, kt, tree_type);
3088 && dest_offset != 0)
3089 purpose = build_int_2 (dest_offset, 0);
3091 purpose = NULL_TREE;
3093 if (list == NULL_TREE)
3094 list = item = build_tree_list (purpose, t);
3097 TREE_CHAIN (item) = build_tree_list (purpose, t);
3098 item = TREE_CHAIN (item);
3102 source_offset += length;
3103 dest_offset += length;
3107 item = build_int_2 ((ffebld_accter_size (expr)
3108 + ffebld_accter_pad (expr)) - 1, 0);
3109 ffebit_kill (ffebld_accter_bits (expr));
3110 TREE_TYPE (item) = ffecom_integer_type_node;
3114 build_range_type (ffecom_integer_type_node,
3115 ffecom_integer_zero_node,
3117 list = build (CONSTRUCTOR, item, NULL_TREE, list);
3118 TREE_CONSTANT (list) = 1;
3119 TREE_STATIC (list) = 1;
3122 case FFEBLD_opARRTER:
3127 if (ffebld_arrter_pad (expr) == 0)
3131 assert (bt == FFEINFO_basictypeCHARACTER
3132 && kt == FFEINFO_kindtypeCHARACTER1);
3134 /* Becomes PURPOSE first time through loop. */
3135 item = build_int_2 (ffebld_arrter_pad (expr), 0);
3138 for (i = 0; i < ffebld_arrter_size (expr); ++i)
3140 ffebldConstantUnion cu
3141 = ffebld_constantarray_get (ffebld_arrter (expr), bt, kt, i);
3143 t = ffecom_constantunion (&cu, bt, kt, tree_type);
3145 if (list == NULL_TREE)
3146 /* Assume item is PURPOSE first time through loop. */
3147 list = item = build_tree_list (item, t);
3150 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
3151 item = TREE_CHAIN (item);
3156 item = build_int_2 ((ffebld_arrter_size (expr)
3157 + ffebld_arrter_pad (expr)) - 1, 0);
3158 TREE_TYPE (item) = ffecom_integer_type_node;
3162 build_range_type (ffecom_integer_type_node,
3163 ffecom_integer_zero_node,
3165 list = build (CONSTRUCTOR, item, NULL_TREE, list);
3166 TREE_CONSTANT (list) = 1;
3167 TREE_STATIC (list) = 1;
3170 case FFEBLD_opCONTER:
3171 assert (ffebld_conter_pad (expr) == 0);
3173 = ffecom_constantunion (&ffebld_constant_union (ffebld_conter (expr)),
3177 case FFEBLD_opSYMTER:
3178 if ((ffebld_symter_generic (expr) != FFEINTRIN_genNONE)
3179 || (ffebld_symter_specific (expr) != FFEINTRIN_specNONE))
3180 return ffecom_ptr_to_expr (expr); /* Same as %REF(intrinsic). */
3181 s = ffebld_symter (expr);
3182 t = ffesymbol_hook (s).decl_tree;
3185 { /* ASSIGN'ed-label expr. */
3186 if (ffe_is_ugly_assign ())
3188 /* User explicitly wants ASSIGN'ed variables to be at the same
3189 memory address as the variables when used in non-ASSIGN
3190 contexts. That can make old, arcane, non-standard code
3191 work, but don't try to do it when a pointer wouldn't fit
3192 in the normal variable (take other approach, and warn,
3197 s = ffecom_sym_transform_ (s);
3198 t = ffesymbol_hook (s).decl_tree;
3199 assert (t != NULL_TREE);
3202 if (t == error_mark_node)
3205 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (t)))
3206 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
3208 if (ffesymbol_hook (s).addr)
3209 t = ffecom_1 (INDIRECT_REF,
3210 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
3214 if (ffesymbol_hook (s).assign_tree == NULL_TREE)
3216 ffebad_start_msg ("ASSIGN'ed label cannot fit into `%A' at %0 -- using wider sibling",
3217 FFEBAD_severityWARNING);
3218 ffebad_string (ffesymbol_text (s));
3219 ffebad_here (0, ffesymbol_where_line (s),
3220 ffesymbol_where_column (s));
3225 /* Don't use the normal variable's tree for ASSIGN, though mark
3226 it as in the system header (housekeeping). Use an explicit,
3227 specially created sibling that is known to be wide enough
3228 to hold pointers to labels. */
3231 && TREE_CODE (t) == VAR_DECL)
3232 DECL_IN_SYSTEM_HEADER (t) = 1; /* Don't let -Wunused complain. */
3234 t = ffesymbol_hook (s).assign_tree;
3237 s = ffecom_sym_transform_assign_ (s);
3238 t = ffesymbol_hook (s).assign_tree;
3239 assert (t != NULL_TREE);
3246 s = ffecom_sym_transform_ (s);
3247 t = ffesymbol_hook (s).decl_tree;
3248 assert (t != NULL_TREE);
3250 if (ffesymbol_hook (s).addr)
3251 t = ffecom_1 (INDIRECT_REF,
3252 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
3256 case FFEBLD_opARRAYREF:
3257 return ffecom_arrayref_ (NULL_TREE, expr, 0);
3259 case FFEBLD_opUPLUS:
3260 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3261 return ffecom_1 (NOP_EXPR, tree_type, left);
3263 case FFEBLD_opPAREN:
3264 /* ~~~Make sure Fortran rules respected here */
3265 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3266 return ffecom_1 (NOP_EXPR, tree_type, left);
3268 case FFEBLD_opUMINUS:
3269 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3272 tree_type = tree_type_x;
3273 left = convert (tree_type, left);
3275 return ffecom_1 (NEGATE_EXPR, tree_type, left);
3278 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3279 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3282 tree_type = tree_type_x;
3283 left = convert (tree_type, left);
3284 right = convert (tree_type, right);
3286 return ffecom_2 (PLUS_EXPR, tree_type, left, right);
3288 case FFEBLD_opSUBTRACT:
3289 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3290 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3293 tree_type = tree_type_x;
3294 left = convert (tree_type, left);
3295 right = convert (tree_type, right);
3297 return ffecom_2 (MINUS_EXPR, tree_type, left, right);
3299 case FFEBLD_opMULTIPLY:
3300 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3301 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3304 tree_type = tree_type_x;
3305 left = convert (tree_type, left);
3306 right = convert (tree_type, right);
3308 return ffecom_2 (MULT_EXPR, tree_type, left, right);
3310 case FFEBLD_opDIVIDE:
3311 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3312 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3315 tree_type = tree_type_x;
3316 left = convert (tree_type, left);
3317 right = convert (tree_type, right);
3319 return ffecom_tree_divide_ (tree_type, left, right,
3320 dest_tree, dest, dest_used,
3321 ffebld_nonter_hook (expr));
3323 case FFEBLD_opPOWER:
3325 ffebld left = ffebld_left (expr);
3326 ffebld right = ffebld_right (expr);
3328 ffeinfoKindtype rtkt;
3329 ffeinfoKindtype ltkt;
3332 switch (ffeinfo_basictype (ffebld_info (right)))
3335 case FFEINFO_basictypeINTEGER:
3338 item = ffecom_expr_power_integer_ (expr);
3339 if (item != NULL_TREE)
3343 rtkt = FFEINFO_kindtypeINTEGER1;
3344 switch (ffeinfo_basictype (ffebld_info (left)))
3346 case FFEINFO_basictypeINTEGER:
3347 if ((ffeinfo_kindtype (ffebld_info (left))
3348 == FFEINFO_kindtypeINTEGER4)
3349 || (ffeinfo_kindtype (ffebld_info (right))
3350 == FFEINFO_kindtypeINTEGER4))
3352 code = FFECOM_gfrtPOW_QQ;
3353 ltkt = FFEINFO_kindtypeINTEGER4;
3354 rtkt = FFEINFO_kindtypeINTEGER4;
3358 code = FFECOM_gfrtPOW_II;
3359 ltkt = FFEINFO_kindtypeINTEGER1;
3363 case FFEINFO_basictypeREAL:
3364 if (ffeinfo_kindtype (ffebld_info (left))
3365 == FFEINFO_kindtypeREAL1)
3367 code = FFECOM_gfrtPOW_RI;
3368 ltkt = FFEINFO_kindtypeREAL1;
3372 code = FFECOM_gfrtPOW_DI;
3373 ltkt = FFEINFO_kindtypeREAL2;
3377 case FFEINFO_basictypeCOMPLEX:
3378 if (ffeinfo_kindtype (ffebld_info (left))
3379 == FFEINFO_kindtypeREAL1)
3381 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */
3382 ltkt = FFEINFO_kindtypeREAL1;
3386 code = FFECOM_gfrtPOW_ZI; /* Overlapping result okay. */
3387 ltkt = FFEINFO_kindtypeREAL2;
3392 assert ("bad pow_*i" == NULL);
3393 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */
3394 ltkt = FFEINFO_kindtypeREAL1;
3397 if (ffeinfo_kindtype (ffebld_info (left)) != ltkt)
3398 left = ffeexpr_convert (left, NULL, NULL,
3399 ffeinfo_basictype (ffebld_info (left)),
3401 FFETARGET_charactersizeNONE,
3402 FFEEXPR_contextLET);
3403 if (ffeinfo_kindtype (ffebld_info (right)) != rtkt)
3404 right = ffeexpr_convert (right, NULL, NULL,
3405 FFEINFO_basictypeINTEGER,
3407 FFETARGET_charactersizeNONE,
3408 FFEEXPR_contextLET);
3411 case FFEINFO_basictypeREAL:
3412 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3413 left = ffeexpr_convert (left, NULL, NULL, FFEINFO_basictypeREAL,
3414 FFEINFO_kindtypeREALDOUBLE, 0,
3415 FFETARGET_charactersizeNONE,
3416 FFEEXPR_contextLET);
3417 if (ffeinfo_kindtype (ffebld_info (right))
3418 == FFEINFO_kindtypeREAL1)
3419 right = ffeexpr_convert (right, NULL, NULL,
3420 FFEINFO_basictypeREAL,
3421 FFEINFO_kindtypeREALDOUBLE, 0,
3422 FFETARGET_charactersizeNONE,
3423 FFEEXPR_contextLET);
3424 /* We used to call FFECOM_gfrtPOW_DD here,
3425 which passes arguments by reference. */
3426 code = FFECOM_gfrtL_POW;
3427 /* Pass arguments by value. */
3431 case FFEINFO_basictypeCOMPLEX:
3432 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3433 left = ffeexpr_convert (left, NULL, NULL,
3434 FFEINFO_basictypeCOMPLEX,
3435 FFEINFO_kindtypeREALDOUBLE, 0,
3436 FFETARGET_charactersizeNONE,
3437 FFEEXPR_contextLET);
3438 if (ffeinfo_kindtype (ffebld_info (right))
3439 == FFEINFO_kindtypeREAL1)
3440 right = ffeexpr_convert (right, NULL, NULL,
3441 FFEINFO_basictypeCOMPLEX,
3442 FFEINFO_kindtypeREALDOUBLE, 0,
3443 FFETARGET_charactersizeNONE,
3444 FFEEXPR_contextLET);
3445 code = FFECOM_gfrtPOW_ZZ; /* Overlapping result okay. */
3446 ref = TRUE; /* Pass arguments by reference. */
3450 assert ("bad pow_x*" == NULL);
3451 code = FFECOM_gfrtPOW_II;
3454 return ffecom_call_binop_ (ffecom_gfrt_tree_ (code),
3455 ffecom_gfrt_kindtype (code),
3456 (ffe_is_f2c_library ()
3457 && ffecom_gfrt_complex_[code]),
3458 tree_type, left, right,
3459 dest_tree, dest, dest_used,
3460 NULL_TREE, FALSE, ref,
3461 ffebld_nonter_hook (expr));
3467 case FFEINFO_basictypeLOGICAL:
3468 item = ffecom_truth_value_invert (ffecom_expr (ffebld_left (expr)));
3469 return convert (tree_type, item);
3471 case FFEINFO_basictypeINTEGER:
3472 return ffecom_1 (BIT_NOT_EXPR, tree_type,
3473 ffecom_expr (ffebld_left (expr)));
3476 assert ("NOT bad basictype" == NULL);
3478 case FFEINFO_basictypeANY:
3479 return error_mark_node;
3483 case FFEBLD_opFUNCREF:
3484 assert (ffeinfo_basictype (ffebld_info (expr))
3485 != FFEINFO_basictypeCHARACTER);
3487 case FFEBLD_opSUBRREF:
3488 if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
3489 == FFEINFO_whereINTRINSIC)
3490 { /* Invocation of an intrinsic. */
3491 item = ffecom_expr_intrinsic_ (expr, dest_tree, dest,
3495 s = ffebld_symter (ffebld_left (expr));
3496 dt = ffesymbol_hook (s).decl_tree;
3497 if (dt == NULL_TREE)
3499 s = ffecom_sym_transform_ (s);
3500 dt = ffesymbol_hook (s).decl_tree;
3502 if (dt == error_mark_node)
3505 if (ffesymbol_hook (s).addr)
3508 item = ffecom_1_fn (dt);
3510 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
3511 args = ffecom_list_expr (ffebld_right (expr));
3513 args = ffecom_list_ptr_to_expr (ffebld_right (expr));
3515 if (args == error_mark_node)
3516 return error_mark_node;
3518 item = ffecom_call_ (item, kt,
3519 ffesymbol_is_f2c (s)
3520 && (bt == FFEINFO_basictypeCOMPLEX)
3521 && (ffesymbol_where (s)
3522 != FFEINFO_whereCONSTANT),
3525 dest_tree, dest, dest_used,
3526 error_mark_node, FALSE,
3527 ffebld_nonter_hook (expr));
3528 TREE_SIDE_EFFECTS (item) = 1;
3534 case FFEINFO_basictypeLOGICAL:
3536 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3537 ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3538 ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3539 return convert (tree_type, item);
3541 case FFEINFO_basictypeINTEGER:
3542 return ffecom_2 (BIT_AND_EXPR, tree_type,
3543 ffecom_expr (ffebld_left (expr)),
3544 ffecom_expr (ffebld_right (expr)));
3547 assert ("AND bad basictype" == NULL);
3549 case FFEINFO_basictypeANY:
3550 return error_mark_node;
3557 case FFEINFO_basictypeLOGICAL:
3559 = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
3560 ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3561 ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3562 return convert (tree_type, item);
3564 case FFEINFO_basictypeINTEGER:
3565 return ffecom_2 (BIT_IOR_EXPR, tree_type,
3566 ffecom_expr (ffebld_left (expr)),
3567 ffecom_expr (ffebld_right (expr)));
3570 assert ("OR bad basictype" == NULL);
3572 case FFEINFO_basictypeANY:
3573 return error_mark_node;
3581 case FFEINFO_basictypeLOGICAL:
3583 = ffecom_2 (NE_EXPR, integer_type_node,
3584 ffecom_expr (ffebld_left (expr)),
3585 ffecom_expr (ffebld_right (expr)));
3586 return convert (tree_type, ffecom_truth_value (item));
3588 case FFEINFO_basictypeINTEGER:
3589 return ffecom_2 (BIT_XOR_EXPR, tree_type,
3590 ffecom_expr (ffebld_left (expr)),
3591 ffecom_expr (ffebld_right (expr)));
3594 assert ("XOR/NEQV bad basictype" == NULL);
3596 case FFEINFO_basictypeANY:
3597 return error_mark_node;
3604 case FFEINFO_basictypeLOGICAL:
3606 = ffecom_2 (EQ_EXPR, integer_type_node,
3607 ffecom_expr (ffebld_left (expr)),
3608 ffecom_expr (ffebld_right (expr)));
3609 return convert (tree_type, ffecom_truth_value (item));
3611 case FFEINFO_basictypeINTEGER:
3613 ffecom_1 (BIT_NOT_EXPR, tree_type,
3614 ffecom_2 (BIT_XOR_EXPR, tree_type,
3615 ffecom_expr (ffebld_left (expr)),
3616 ffecom_expr (ffebld_right (expr))));
3619 assert ("EQV bad basictype" == NULL);
3621 case FFEINFO_basictypeANY:
3622 return error_mark_node;
3626 case FFEBLD_opCONVERT:
3627 if (ffebld_op (ffebld_left (expr)) == FFEBLD_opANY)
3628 return error_mark_node;
3632 case FFEINFO_basictypeLOGICAL:
3633 case FFEINFO_basictypeINTEGER:
3634 case FFEINFO_basictypeREAL:
3635 return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3637 case FFEINFO_basictypeCOMPLEX:
3638 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3640 case FFEINFO_basictypeINTEGER:
3641 case FFEINFO_basictypeLOGICAL:
3642 case FFEINFO_basictypeREAL:
3643 item = ffecom_expr (ffebld_left (expr));
3644 if (item == error_mark_node)
3645 return error_mark_node;
3646 /* convert() takes care of converting to the subtype first,
3647 at least in gcc-2.7.2. */
3648 item = convert (tree_type, item);
3651 case FFEINFO_basictypeCOMPLEX:
3652 return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3655 assert ("CONVERT COMPLEX bad basictype" == NULL);
3657 case FFEINFO_basictypeANY:
3658 return error_mark_node;
3663 assert ("CONVERT bad basictype" == NULL);
3665 case FFEINFO_basictypeANY:
3666 return error_mark_node;
3672 goto relational; /* :::::::::::::::::::: */
3676 goto relational; /* :::::::::::::::::::: */
3680 goto relational; /* :::::::::::::::::::: */
3684 goto relational; /* :::::::::::::::::::: */
3688 goto relational; /* :::::::::::::::::::: */
3693 relational: /* :::::::::::::::::::: */
3694 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3696 case FFEINFO_basictypeLOGICAL:
3697 case FFEINFO_basictypeINTEGER:
3698 case FFEINFO_basictypeREAL:
3699 item = ffecom_2 (code, integer_type_node,
3700 ffecom_expr (ffebld_left (expr)),
3701 ffecom_expr (ffebld_right (expr)));
3702 return convert (tree_type, item);
3704 case FFEINFO_basictypeCOMPLEX:
3705 assert (code == EQ_EXPR || code == NE_EXPR);
3708 tree arg1 = ffecom_expr (ffebld_left (expr));
3709 tree arg2 = ffecom_expr (ffebld_right (expr));
3711 if (arg1 == error_mark_node || arg2 == error_mark_node)
3712 return error_mark_node;
3714 arg1 = ffecom_save_tree (arg1);
3715 arg2 = ffecom_save_tree (arg2);
3717 if (TREE_CODE (TREE_TYPE (arg1)) == COMPLEX_TYPE)
3719 real_type = TREE_TYPE (TREE_TYPE (arg1));
3720 assert (real_type == TREE_TYPE (TREE_TYPE (arg2)));
3724 real_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg1)));
3725 assert (real_type == TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg2))));
3729 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3730 ffecom_2 (EQ_EXPR, integer_type_node,
3731 ffecom_1 (REALPART_EXPR, real_type, arg1),
3732 ffecom_1 (REALPART_EXPR, real_type, arg2)),
3733 ffecom_2 (EQ_EXPR, integer_type_node,
3734 ffecom_1 (IMAGPART_EXPR, real_type, arg1),
3735 ffecom_1 (IMAGPART_EXPR, real_type,
3737 if (code == EQ_EXPR)
3738 item = ffecom_truth_value (item);
3740 item = ffecom_truth_value_invert (item);
3741 return convert (tree_type, item);
3744 case FFEINFO_basictypeCHARACTER:
3746 ffebld left = ffebld_left (expr);
3747 ffebld right = ffebld_right (expr);
3753 /* f2c run-time functions do the implicit blank-padding for us,
3754 so we don't usually have to implement blank-padding ourselves.
3755 (The exception is when we pass an argument to a separately
3756 compiled statement function -- if we know the arg is not the
3757 same length as the dummy, we must truncate or extend it. If
3758 we "inline" statement functions, that necessity goes away as
3761 Strip off the CONVERT operators that blank-pad. (Truncation by
3762 CONVERT shouldn't happen here, but it can happen in
3765 while (ffebld_op (left) == FFEBLD_opCONVERT)
3766 left = ffebld_left (left);
3767 while (ffebld_op (right) == FFEBLD_opCONVERT)
3768 right = ffebld_left (right);
3770 left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
3771 right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
3773 if (left_tree == error_mark_node || left_length == error_mark_node
3774 || right_tree == error_mark_node
3775 || right_length == error_mark_node)
3776 return error_mark_node;
3778 if ((ffebld_size_known (left) == 1)
3779 && (ffebld_size_known (right) == 1))
3782 = ffecom_1 (INDIRECT_REF,
3783 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3786 = ffecom_1 (INDIRECT_REF,
3787 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3791 = ffecom_2 (code, integer_type_node,
3792 ffecom_2 (ARRAY_REF,
3793 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3796 ffecom_2 (ARRAY_REF,
3797 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3803 item = build_tree_list (NULL_TREE, left_tree);
3804 TREE_CHAIN (item) = build_tree_list (NULL_TREE, right_tree);
3805 TREE_CHAIN (TREE_CHAIN (item)) = build_tree_list (NULL_TREE,
3807 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
3808 = build_tree_list (NULL_TREE, right_length);
3809 item = ffecom_call_gfrt (FFECOM_gfrtCMP, item, NULL_TREE);
3810 item = ffecom_2 (code, integer_type_node,
3812 convert (TREE_TYPE (item),
3813 integer_zero_node));
3815 item = convert (tree_type, item);
3821 assert ("relational bad basictype" == NULL);
3823 case FFEINFO_basictypeANY:
3824 return error_mark_node;
3828 case FFEBLD_opPERCENT_LOC:
3829 item = ffecom_arg_ptr_to_expr (ffebld_left (expr), &list);
3830 return convert (tree_type, item);
3834 case FFEBLD_opBOUNDS:
3835 case FFEBLD_opREPEAT:
3836 case FFEBLD_opLABTER:
3837 case FFEBLD_opLABTOK:
3838 case FFEBLD_opIMPDO:
3839 case FFEBLD_opCONCATENATE:
3840 case FFEBLD_opSUBSTR:
3842 assert ("bad op" == NULL);
3845 return error_mark_node;
3849 assert ("didn't think anything got here anymore!!" == NULL);
3851 switch (ffebld_arity (expr))
3854 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3855 TREE_OPERAND (item, 1) = ffecom_expr (ffebld_right (expr));
3856 if (TREE_OPERAND (item, 0) == error_mark_node
3857 || TREE_OPERAND (item, 1) == error_mark_node)
3858 return error_mark_node;
3862 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3863 if (TREE_OPERAND (item, 0) == error_mark_node)
3864 return error_mark_node;
3876 /* Returns the tree that does the intrinsic invocation.
3878 Note: this function applies only to intrinsics returning
3879 CHARACTER*1 or non-CHARACTER results, and to intrinsic
3882 #if FFECOM_targetCURRENT == FFECOM_targetGCC
3884 ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
3885 ffebld dest, bool *dest_used)
3888 tree saved_expr1; /* For those who need it. */
3889 tree saved_expr2; /* For those who need it. */
3890 ffeinfoBasictype bt;
3894 tree real_type; /* REAL type corresponding to COMPLEX. */
3896 ffebld list = ffebld_right (expr); /* List of (some) args. */
3897 ffebld arg1; /* For handy reference. */
3900 ffeintrinImp codegen_imp;
3903 assert (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER);
3905 if (dest_used != NULL)
3908 bt = ffeinfo_basictype (ffebld_info (expr));
3909 kt = ffeinfo_kindtype (ffebld_info (expr));
3910 tree_type = ffecom_tree_type[bt][kt];
3914 arg1 = ffebld_head (list);
3915 if (arg1 != NULL && ffebld_op (arg1) == FFEBLD_opANY)
3916 return error_mark_node;
3917 if ((list = ffebld_trail (list)) != NULL)
3919 arg2 = ffebld_head (list);
3920 if (arg2 != NULL && ffebld_op (arg2) == FFEBLD_opANY)
3921 return error_mark_node;
3922 if ((list = ffebld_trail (list)) != NULL)
3924 arg3 = ffebld_head (list);
3925 if (arg3 != NULL && ffebld_op (arg3) == FFEBLD_opANY)
3926 return error_mark_node;
3935 arg1 = arg2 = arg3 = NULL;
3937 /* <list> ends up at the opITEM of the 3rd arg, or NULL if there are < 3
3938 args. This is used by the MAX/MIN expansions. */
3941 arg1_type = ffecom_tree_type
3942 [ffeinfo_basictype (ffebld_info (arg1))]
3943 [ffeinfo_kindtype (ffebld_info (arg1))];
3945 arg1_type = NULL_TREE; /* Really not needed, but might catch bugs
3948 /* There are several ways for each of the cases in the following switch
3949 statements to exit (from simplest to use to most complicated):
3951 break; (when expr_tree == NULL)
3953 A standard call is made to the specific intrinsic just as if it had been
3954 passed in as a dummy procedure and called as any old procedure. This
3955 method can produce slower code but in some cases it's the easiest way for
3956 now. However, if a (presumably faster) direct call is available,
3957 that is used, so this is the easiest way in many more cases now.
3959 gfrt = FFECOM_gfrtWHATEVER;
3962 gfrt contains the gfrt index of a library function to call, passing the
3963 argument(s) by value rather than by reference. Used when a more
3964 careful choice of library function is needed than that provided
3965 by the vanilla `break;'.
3969 The expr_tree has been completely set up and is ready to be returned
3970 as is. No further actions are taken. Use this when the tree is not
3971 in the simple form for one of the arity_n labels. */
3973 /* For info on how the switch statement cases were written, see the files
3974 enclosed in comments below the switch statement. */
3976 codegen_imp = ffebld_symter_implementation (ffebld_left (expr));
3977 gfrt = ffeintrin_gfrt_direct (codegen_imp);
3978 if (gfrt == FFECOM_gfrt)
3979 gfrt = ffeintrin_gfrt_indirect (codegen_imp);
3981 switch (codegen_imp)
3983 case FFEINTRIN_impABS:
3984 case FFEINTRIN_impCABS:
3985 case FFEINTRIN_impCDABS:
3986 case FFEINTRIN_impDABS:
3987 case FFEINTRIN_impIABS:
3988 if (ffeinfo_basictype (ffebld_info (arg1))
3989 == FFEINFO_basictypeCOMPLEX)
3991 if (kt == FFEINFO_kindtypeREAL1)
3992 gfrt = FFECOM_gfrtCABS;
3993 else if (kt == FFEINFO_kindtypeREAL2)
3994 gfrt = FFECOM_gfrtCDABS;
3997 return ffecom_1 (ABS_EXPR, tree_type,
3998 convert (tree_type, ffecom_expr (arg1)));
4000 case FFEINTRIN_impACOS:
4001 case FFEINTRIN_impDACOS:
4004 case FFEINTRIN_impAIMAG:
4005 case FFEINTRIN_impDIMAG:
4006 case FFEINTRIN_impIMAGPART:
4007 if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
4008 arg1_type = TREE_TYPE (arg1_type);
4010 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
4014 ffecom_1 (IMAGPART_EXPR, arg1_type,
4015 ffecom_expr (arg1)));
4017 case FFEINTRIN_impAINT:
4018 case FFEINTRIN_impDINT:
4020 /* ~~Someday implement FIX_TRUNC_EXPR yielding same type as arg. */
4021 return ffecom_1 (FIX_TRUNC_EXPR, tree_type, ffecom_expr (arg1));
4022 #else /* in the meantime, must use floor to avoid range problems with ints */
4023 /* r__1 = r1 >= 0 ? floor(r1) : -floor(-r1); */
4024 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4027 ffecom_3 (COND_EXPR, double_type_node,
4029 (ffecom_2 (GE_EXPR, integer_type_node,
4032 ffecom_float_zero_))),
4033 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4034 build_tree_list (NULL_TREE,
4035 convert (double_type_node,
4038 ffecom_1 (NEGATE_EXPR, double_type_node,
4039 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4040 build_tree_list (NULL_TREE,
4041 convert (double_type_node,
4042 ffecom_1 (NEGATE_EXPR,
4050 case FFEINTRIN_impANINT:
4051 case FFEINTRIN_impDNINT:
4052 #if 0 /* This way of doing it won't handle real
4053 numbers of large magnitudes. */
4054 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4055 expr_tree = convert (tree_type,
4056 convert (integer_type_node,
4057 ffecom_3 (COND_EXPR, tree_type,
4062 ffecom_float_zero_)),
4063 ffecom_2 (PLUS_EXPR,
4066 ffecom_float_half_),
4067 ffecom_2 (MINUS_EXPR,
4070 ffecom_float_half_))));
4072 #else /* So we instead call floor. */
4073 /* r__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1) */
4074 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4077 ffecom_3 (COND_EXPR, double_type_node,
4079 (ffecom_2 (GE_EXPR, integer_type_node,
4082 ffecom_float_zero_))),
4083 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4084 build_tree_list (NULL_TREE,
4085 convert (double_type_node,
4086 ffecom_2 (PLUS_EXPR,
4090 ffecom_float_half_)))),
4092 ffecom_1 (NEGATE_EXPR, double_type_node,
4093 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4094 build_tree_list (NULL_TREE,
4095 convert (double_type_node,
4096 ffecom_2 (MINUS_EXPR,
4099 ffecom_float_half_),
4106 case FFEINTRIN_impASIN:
4107 case FFEINTRIN_impDASIN:
4108 case FFEINTRIN_impATAN:
4109 case FFEINTRIN_impDATAN:
4110 case FFEINTRIN_impATAN2:
4111 case FFEINTRIN_impDATAN2:
4114 case FFEINTRIN_impCHAR:
4115 case FFEINTRIN_impACHAR:
4117 tempvar = ffecom_make_tempvar (char_type_node, 1, -1);
4119 tempvar = ffebld_nonter_hook (expr);
4123 tree tmv = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (tempvar)));
4125 expr_tree = ffecom_modify (tmv,
4126 ffecom_2 (ARRAY_REF, tmv, tempvar,
4128 convert (tmv, ffecom_expr (arg1)));
4130 expr_tree = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar),
4133 expr_tree = ffecom_1 (ADDR_EXPR,
4134 build_pointer_type (TREE_TYPE (expr_tree)),
4138 case FFEINTRIN_impCMPLX:
4139 case FFEINTRIN_impDCMPLX:
4142 convert (tree_type, ffecom_expr (arg1));
4144 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
4146 ffecom_2 (COMPLEX_EXPR, tree_type,
4147 convert (real_type, ffecom_expr (arg1)),
4149 ffecom_expr (arg2)));
4151 case FFEINTRIN_impCOMPLEX:
4153 ffecom_2 (COMPLEX_EXPR, tree_type,
4155 ffecom_expr (arg2));
4157 case FFEINTRIN_impCONJG:
4158 case FFEINTRIN_impDCONJG:
4162 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
4163 arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4165 ffecom_2 (COMPLEX_EXPR, tree_type,
4166 ffecom_1 (REALPART_EXPR, real_type, arg1_tree),
4167 ffecom_1 (NEGATE_EXPR, real_type,
4168 ffecom_1 (IMAGPART_EXPR, real_type, arg1_tree)));
4171 case FFEINTRIN_impCOS:
4172 case FFEINTRIN_impCCOS:
4173 case FFEINTRIN_impCDCOS:
4174 case FFEINTRIN_impDCOS:
4175 if (bt == FFEINFO_basictypeCOMPLEX)
4177 if (kt == FFEINFO_kindtypeREAL1)
4178 gfrt = FFECOM_gfrtCCOS; /* Overlapping result okay. */
4179 else if (kt == FFEINFO_kindtypeREAL2)
4180 gfrt = FFECOM_gfrtCDCOS; /* Overlapping result okay. */
4184 case FFEINTRIN_impCOSH:
4185 case FFEINTRIN_impDCOSH:
4188 case FFEINTRIN_impDBLE:
4189 case FFEINTRIN_impDFLOAT:
4190 case FFEINTRIN_impDREAL:
4191 case FFEINTRIN_impFLOAT:
4192 case FFEINTRIN_impIDINT:
4193 case FFEINTRIN_impIFIX:
4194 case FFEINTRIN_impINT2:
4195 case FFEINTRIN_impINT8:
4196 case FFEINTRIN_impINT:
4197 case FFEINTRIN_impLONG:
4198 case FFEINTRIN_impREAL:
4199 case FFEINTRIN_impSHORT:
4200 case FFEINTRIN_impSNGL:
4201 return convert (tree_type, ffecom_expr (arg1));
4203 case FFEINTRIN_impDIM:
4204 case FFEINTRIN_impDDIM:
4205 case FFEINTRIN_impIDIM:
4206 saved_expr1 = ffecom_save_tree (convert (tree_type,
4207 ffecom_expr (arg1)));
4208 saved_expr2 = ffecom_save_tree (convert (tree_type,
4209 ffecom_expr (arg2)));
4211 ffecom_3 (COND_EXPR, tree_type,
4213 (ffecom_2 (GT_EXPR, integer_type_node,
4216 ffecom_2 (MINUS_EXPR, tree_type,
4219 convert (tree_type, ffecom_float_zero_));
4221 case FFEINTRIN_impDPROD:
4223 ffecom_2 (MULT_EXPR, tree_type,
4224 convert (tree_type, ffecom_expr (arg1)),
4225 convert (tree_type, ffecom_expr (arg2)));
4227 case FFEINTRIN_impEXP:
4228 case FFEINTRIN_impCDEXP:
4229 case FFEINTRIN_impCEXP:
4230 case FFEINTRIN_impDEXP:
4231 if (bt == FFEINFO_basictypeCOMPLEX)
4233 if (kt == FFEINFO_kindtypeREAL1)
4234 gfrt = FFECOM_gfrtCEXP; /* Overlapping result okay. */
4235 else if (kt == FFEINFO_kindtypeREAL2)
4236 gfrt = FFECOM_gfrtCDEXP; /* Overlapping result okay. */
4240 case FFEINTRIN_impICHAR:
4241 case FFEINTRIN_impIACHAR:
4242 #if 0 /* The simple approach. */
4243 ffecom_char_args_ (&expr_tree, &saved_expr1 /* Ignored */ , arg1);
4245 = ffecom_1 (INDIRECT_REF,
4246 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
4249 = ffecom_2 (ARRAY_REF,
4250 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
4253 return convert (tree_type, expr_tree);
4254 #else /* The more interesting (and more optimal) approach. */
4255 expr_tree = ffecom_intrinsic_ichar_ (tree_type, arg1, &saved_expr1);
4256 expr_tree = ffecom_3 (COND_EXPR, tree_type,
4259 convert (tree_type, integer_zero_node));
4263 case FFEINTRIN_impINDEX:
4266 case FFEINTRIN_impLEN:
4268 break; /* The simple approach. */
4270 return ffecom_intrinsic_len_ (arg1); /* The more optimal approach. */
4273 case FFEINTRIN_impLGE:
4274 case FFEINTRIN_impLGT:
4275 case FFEINTRIN_impLLE:
4276 case FFEINTRIN_impLLT:
4279 case FFEINTRIN_impLOG:
4280 case FFEINTRIN_impALOG:
4281 case FFEINTRIN_impCDLOG:
4282 case FFEINTRIN_impCLOG:
4283 case FFEINTRIN_impDLOG:
4284 if (bt == FFEINFO_basictypeCOMPLEX)
4286 if (kt == FFEINFO_kindtypeREAL1)
4287 gfrt = FFECOM_gfrtCLOG; /* Overlapping result okay. */
4288 else if (kt == FFEINFO_kindtypeREAL2)
4289 gfrt = FFECOM_gfrtCDLOG; /* Overlapping result okay. */
4293 case FFEINTRIN_impLOG10:
4294 case FFEINTRIN_impALOG10:
4295 case FFEINTRIN_impDLOG10:
4296 if (gfrt != FFECOM_gfrt)
4297 break; /* Already picked one, stick with it. */
4299 if (kt == FFEINFO_kindtypeREAL1)
4300 /* We used to call FFECOM_gfrtALOG10 here. */
4301 gfrt = FFECOM_gfrtL_LOG10;
4302 else if (kt == FFEINFO_kindtypeREAL2)
4303 /* We used to call FFECOM_gfrtDLOG10 here. */
4304 gfrt = FFECOM_gfrtL_LOG10;
4307 case FFEINTRIN_impMAX:
4308 case FFEINTRIN_impAMAX0:
4309 case FFEINTRIN_impAMAX1:
4310 case FFEINTRIN_impDMAX1:
4311 case FFEINTRIN_impMAX0:
4312 case FFEINTRIN_impMAX1:
4313 if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4314 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4316 arg1_type = tree_type;
4317 expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4318 convert (arg1_type, ffecom_expr (arg1)),
4319 convert (arg1_type, ffecom_expr (arg2)));
4320 for (; list != NULL; list = ffebld_trail (list))
4322 if ((ffebld_head (list) == NULL)
4323 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4325 expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4328 ffecom_expr (ffebld_head (list))));
4330 return convert (tree_type, expr_tree);
4332 case FFEINTRIN_impMIN:
4333 case FFEINTRIN_impAMIN0:
4334 case FFEINTRIN_impAMIN1:
4335 case FFEINTRIN_impDMIN1:
4336 case FFEINTRIN_impMIN0:
4337 case FFEINTRIN_impMIN1:
4338 if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4339 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4341 arg1_type = tree_type;
4342 expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4343 convert (arg1_type, ffecom_expr (arg1)),
4344 convert (arg1_type, ffecom_expr (arg2)));
4345 for (; list != NULL; list = ffebld_trail (list))
4347 if ((ffebld_head (list) == NULL)
4348 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4350 expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4353 ffecom_expr (ffebld_head (list))));
4355 return convert (tree_type, expr_tree);
4357 case FFEINTRIN_impMOD:
4358 case FFEINTRIN_impAMOD:
4359 case FFEINTRIN_impDMOD:
4360 if (bt != FFEINFO_basictypeREAL)
4361 return ffecom_2 (TRUNC_MOD_EXPR, tree_type,
4362 convert (tree_type, ffecom_expr (arg1)),
4363 convert (tree_type, ffecom_expr (arg2)));
4365 if (kt == FFEINFO_kindtypeREAL1)
4366 /* We used to call FFECOM_gfrtAMOD here. */
4367 gfrt = FFECOM_gfrtL_FMOD;
4368 else if (kt == FFEINFO_kindtypeREAL2)
4369 /* We used to call FFECOM_gfrtDMOD here. */
4370 gfrt = FFECOM_gfrtL_FMOD;
4373 case FFEINTRIN_impNINT:
4374 case FFEINTRIN_impIDNINT:
4376 /* ~~Ideally FIX_ROUND_EXPR would be implemented, but it ain't yet. */
4377 return ffecom_1 (FIX_ROUND_EXPR, tree_type, ffecom_expr (arg1));
4379 /* i__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1); */
4380 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4382 convert (ffecom_integer_type_node,
4383 ffecom_3 (COND_EXPR, arg1_type,
4385 (ffecom_2 (GE_EXPR, integer_type_node,
4388 ffecom_float_zero_))),
4389 ffecom_2 (PLUS_EXPR, arg1_type,
4392 ffecom_float_half_)),
4393 ffecom_2 (MINUS_EXPR, arg1_type,
4396 ffecom_float_half_))));
4399 case FFEINTRIN_impSIGN:
4400 case FFEINTRIN_impDSIGN:
4401 case FFEINTRIN_impISIGN:
4403 tree arg2_tree = ffecom_expr (arg2);
4407 (ffecom_1 (ABS_EXPR, tree_type,
4409 ffecom_expr (arg1))));
4411 = ffecom_3 (COND_EXPR, tree_type,
4413 (ffecom_2 (GE_EXPR, integer_type_node,
4415 convert (TREE_TYPE (arg2_tree),
4416 integer_zero_node))),
4418 ffecom_1 (NEGATE_EXPR, tree_type, saved_expr1));
4419 /* Make sure SAVE_EXPRs get referenced early enough. */
4421 = ffecom_2 (COMPOUND_EXPR, tree_type,
4422 convert (void_type_node, saved_expr1),
4427 case FFEINTRIN_impSIN:
4428 case FFEINTRIN_impCDSIN:
4429 case FFEINTRIN_impCSIN:
4430 case FFEINTRIN_impDSIN:
4431 if (bt == FFEINFO_basictypeCOMPLEX)
4433 if (kt == FFEINFO_kindtypeREAL1)
4434 gfrt = FFECOM_gfrtCSIN; /* Overlapping result okay. */
4435 else if (kt == FFEINFO_kindtypeREAL2)
4436 gfrt = FFECOM_gfrtCDSIN; /* Overlapping result okay. */
4440 case FFEINTRIN_impSINH:
4441 case FFEINTRIN_impDSINH:
4444 case FFEINTRIN_impSQRT:
4445 case FFEINTRIN_impCDSQRT:
4446 case FFEINTRIN_impCSQRT:
4447 case FFEINTRIN_impDSQRT:
4448 if (bt == FFEINFO_basictypeCOMPLEX)
4450 if (kt == FFEINFO_kindtypeREAL1)
4451 gfrt = FFECOM_gfrtCSQRT; /* Overlapping result okay. */
4452 else if (kt == FFEINFO_kindtypeREAL2)
4453 gfrt = FFECOM_gfrtCDSQRT; /* Overlapping result okay. */
4457 case FFEINTRIN_impTAN:
4458 case FFEINTRIN_impDTAN:
4459 case FFEINTRIN_impTANH:
4460 case FFEINTRIN_impDTANH:
4463 case FFEINTRIN_impREALPART:
4464 if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
4465 arg1_type = TREE_TYPE (arg1_type);
4467 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
4471 ffecom_1 (REALPART_EXPR, arg1_type,
4472 ffecom_expr (arg1)));
4474 case FFEINTRIN_impIAND:
4475 case FFEINTRIN_impAND:
4476 return ffecom_2 (BIT_AND_EXPR, tree_type,
4478 ffecom_expr (arg1)),
4480 ffecom_expr (arg2)));
4482 case FFEINTRIN_impIOR:
4483 case FFEINTRIN_impOR:
4484 return ffecom_2 (BIT_IOR_EXPR, tree_type,
4486 ffecom_expr (arg1)),
4488 ffecom_expr (arg2)));
4490 case FFEINTRIN_impIEOR:
4491 case FFEINTRIN_impXOR:
4492 return ffecom_2 (BIT_XOR_EXPR, tree_type,
4494 ffecom_expr (arg1)),
4496 ffecom_expr (arg2)));
4498 case FFEINTRIN_impLSHIFT:
4499 return ffecom_2 (LSHIFT_EXPR, tree_type,
4501 convert (integer_type_node,
4502 ffecom_expr (arg2)));
4504 case FFEINTRIN_impRSHIFT:
4505 return ffecom_2 (RSHIFT_EXPR, tree_type,
4507 convert (integer_type_node,
4508 ffecom_expr (arg2)));
4510 case FFEINTRIN_impNOT:
4511 return ffecom_1 (BIT_NOT_EXPR, tree_type, ffecom_expr (arg1));
4513 case FFEINTRIN_impBIT_SIZE:
4514 return convert (tree_type, TYPE_SIZE (arg1_type));
4516 case FFEINTRIN_impBTEST:
4518 ffetargetLogical1 true;
4519 ffetargetLogical1 false;
4523 ffetarget_logical1 (&true, TRUE);
4524 ffetarget_logical1 (&false, FALSE);
4526 true_tree = convert (tree_type, integer_one_node);
4528 true_tree = convert (tree_type, build_int_2 (true, 0));
4530 false_tree = convert (tree_type, integer_zero_node);
4532 false_tree = convert (tree_type, build_int_2 (false, 0));
4535 ffecom_3 (COND_EXPR, tree_type,
4537 (ffecom_2 (EQ_EXPR, integer_type_node,
4538 ffecom_2 (BIT_AND_EXPR, arg1_type,
4540 ffecom_2 (LSHIFT_EXPR, arg1_type,
4543 convert (integer_type_node,
4544 ffecom_expr (arg2)))),
4546 integer_zero_node))),
4551 case FFEINTRIN_impIBCLR:
4553 ffecom_2 (BIT_AND_EXPR, tree_type,
4555 ffecom_1 (BIT_NOT_EXPR, tree_type,
4556 ffecom_2 (LSHIFT_EXPR, tree_type,
4559 convert (integer_type_node,
4560 ffecom_expr (arg2)))));
4562 case FFEINTRIN_impIBITS:
4564 tree arg3_tree = ffecom_save_tree (convert (integer_type_node,
4565 ffecom_expr (arg3)));
4567 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4570 = ffecom_2 (BIT_AND_EXPR, tree_type,
4571 ffecom_2 (RSHIFT_EXPR, tree_type,
4573 convert (integer_type_node,
4574 ffecom_expr (arg2))),
4576 ffecom_2 (RSHIFT_EXPR, uns_type,
4577 ffecom_1 (BIT_NOT_EXPR,
4580 integer_zero_node)),
4581 ffecom_2 (MINUS_EXPR,
4583 TYPE_SIZE (uns_type),
4585 #if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4587 = ffecom_3 (COND_EXPR, tree_type,
4589 (ffecom_2 (NE_EXPR, integer_type_node,
4591 integer_zero_node)),
4593 convert (tree_type, integer_zero_node));
4598 case FFEINTRIN_impIBSET:
4600 ffecom_2 (BIT_IOR_EXPR, tree_type,
4602 ffecom_2 (LSHIFT_EXPR, tree_type,
4603 convert (tree_type, integer_one_node),
4604 convert (integer_type_node,
4605 ffecom_expr (arg2))));
4607 case FFEINTRIN_impISHFT:
4609 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4610 tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4611 ffecom_expr (arg2)));
4613 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4616 = ffecom_3 (COND_EXPR, tree_type,
4618 (ffecom_2 (GE_EXPR, integer_type_node,
4620 integer_zero_node)),
4621 ffecom_2 (LSHIFT_EXPR, tree_type,
4625 ffecom_2 (RSHIFT_EXPR, uns_type,
4626 convert (uns_type, arg1_tree),
4627 ffecom_1 (NEGATE_EXPR,
4630 #if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4632 = ffecom_3 (COND_EXPR, tree_type,
4634 (ffecom_2 (NE_EXPR, integer_type_node,
4636 TYPE_SIZE (uns_type))),
4638 convert (tree_type, integer_zero_node));
4640 /* Make sure SAVE_EXPRs get referenced early enough. */
4642 = ffecom_2 (COMPOUND_EXPR, tree_type,
4643 convert (void_type_node, arg1_tree),
4644 ffecom_2 (COMPOUND_EXPR, tree_type,
4645 convert (void_type_node, arg2_tree),
4650 case FFEINTRIN_impISHFTC:
4652 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4653 tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4654 ffecom_expr (arg2)));
4655 tree arg3_tree = (arg3 == NULL) ? TYPE_SIZE (tree_type)
4656 : ffecom_save_tree (convert (integer_type_node, ffecom_expr (arg3)));
4662 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4665 = ffecom_2 (LSHIFT_EXPR, tree_type,
4666 ffecom_1 (BIT_NOT_EXPR, tree_type,
4667 convert (tree_type, integer_zero_node)),
4669 #if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4671 = ffecom_3 (COND_EXPR, tree_type,
4673 (ffecom_2 (NE_EXPR, integer_type_node,
4675 TYPE_SIZE (uns_type))),
4677 convert (tree_type, integer_zero_node));
4679 mask_arg1 = ffecom_save_tree (mask_arg1);
4681 = ffecom_2 (BIT_AND_EXPR, tree_type,
4683 ffecom_1 (BIT_NOT_EXPR, tree_type,
4685 masked_arg1 = ffecom_save_tree (masked_arg1);
4687 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4689 ffecom_2 (RSHIFT_EXPR, uns_type,
4690 convert (uns_type, masked_arg1),
4691 ffecom_1 (NEGATE_EXPR,
4694 ffecom_2 (LSHIFT_EXPR, tree_type,
4696 ffecom_2 (PLUS_EXPR, integer_type_node,
4700 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4701 ffecom_2 (LSHIFT_EXPR, tree_type,
4705 ffecom_2 (RSHIFT_EXPR, uns_type,
4706 convert (uns_type, masked_arg1),
4707 ffecom_2 (MINUS_EXPR,
4712 = ffecom_3 (COND_EXPR, tree_type,
4714 (ffecom_2 (LT_EXPR, integer_type_node,
4716 integer_zero_node)),
4720 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4721 ffecom_2 (BIT_AND_EXPR, tree_type,
4724 ffecom_2 (BIT_AND_EXPR, tree_type,
4725 ffecom_1 (BIT_NOT_EXPR, tree_type,
4729 = ffecom_3 (COND_EXPR, tree_type,
4731 (ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
4732 ffecom_2 (EQ_EXPR, integer_type_node,
4737 ffecom_2 (EQ_EXPR, integer_type_node,
4739 integer_zero_node))),
4742 /* Make sure SAVE_EXPRs get referenced early enough. */
4744 = ffecom_2 (COMPOUND_EXPR, tree_type,
4745 convert (void_type_node, arg1_tree),
4746 ffecom_2 (COMPOUND_EXPR, tree_type,
4747 convert (void_type_node, arg2_tree),
4748 ffecom_2 (COMPOUND_EXPR, tree_type,
4749 convert (void_type_node,
4751 ffecom_2 (COMPOUND_EXPR, tree_type,
4752 convert (void_type_node,
4756 = ffecom_2 (COMPOUND_EXPR, tree_type,
4757 convert (void_type_node,
4763 case FFEINTRIN_impLOC:
4765 tree arg1_tree = ffecom_expr (arg1);
4768 = convert (tree_type,
4769 ffecom_1 (ADDR_EXPR,
4770 build_pointer_type (TREE_TYPE (arg1_tree)),
4775 case FFEINTRIN_impMVBITS:
4780 ffebld arg4 = ffebld_head (ffebld_trail (list));
4783 ffebld arg5 = ffebld_head (ffebld_trail (ffebld_trail (list)));
4787 tree arg5_plus_arg3;
4789 arg2_tree = convert (integer_type_node,
4790 ffecom_expr (arg2));
4791 arg3_tree = ffecom_save_tree (convert (integer_type_node,
4792 ffecom_expr (arg3)));
4793 arg4_tree = ffecom_expr_rw (NULL_TREE, arg4);
4794 arg4_type = TREE_TYPE (arg4_tree);
4796 arg1_tree = ffecom_save_tree (convert (arg4_type,
4797 ffecom_expr (arg1)));
4799 arg5_tree = ffecom_save_tree (convert (integer_type_node,
4800 ffecom_expr (arg5)));
4803 = ffecom_2 (LSHIFT_EXPR, arg4_type,
4804 ffecom_2 (BIT_AND_EXPR, arg4_type,
4805 ffecom_2 (RSHIFT_EXPR, arg4_type,
4808 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4809 ffecom_2 (LSHIFT_EXPR, arg4_type,
4810 ffecom_1 (BIT_NOT_EXPR,
4814 integer_zero_node)),
4818 = ffecom_save_tree (ffecom_2 (PLUS_EXPR, arg4_type,
4822 = ffecom_2 (LSHIFT_EXPR, arg4_type,
4823 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4825 integer_zero_node)),
4827 #if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4829 = ffecom_3 (COND_EXPR, arg4_type,
4831 (ffecom_2 (NE_EXPR, integer_type_node,
4833 convert (TREE_TYPE (arg5_plus_arg3),
4834 TYPE_SIZE (arg4_type)))),
4836 convert (arg4_type, integer_zero_node));
4839 = ffecom_2 (BIT_AND_EXPR, arg4_type,
4841 ffecom_2 (BIT_IOR_EXPR, arg4_type,
4843 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4844 ffecom_2 (LSHIFT_EXPR, arg4_type,
4845 ffecom_1 (BIT_NOT_EXPR,
4849 integer_zero_node)),
4852 = ffecom_2 (BIT_IOR_EXPR, arg4_type,
4855 #if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4857 = ffecom_3 (COND_EXPR, arg4_type,
4859 (ffecom_2 (NE_EXPR, integer_type_node,
4861 convert (TREE_TYPE (arg3_tree),
4862 integer_zero_node))),
4866 = ffecom_3 (COND_EXPR, arg4_type,
4868 (ffecom_2 (NE_EXPR, integer_type_node,
4870 convert (TREE_TYPE (arg3_tree),
4871 TYPE_SIZE (arg4_type)))),
4876 = ffecom_2s (MODIFY_EXPR, void_type_node,
4879 /* Make sure SAVE_EXPRs get referenced early enough. */
4881 = ffecom_2 (COMPOUND_EXPR, void_type_node,
4883 ffecom_2 (COMPOUND_EXPR, void_type_node,
4885 ffecom_2 (COMPOUND_EXPR, void_type_node,
4887 ffecom_2 (COMPOUND_EXPR, void_type_node,
4891 = ffecom_2 (COMPOUND_EXPR, void_type_node,
4898 case FFEINTRIN_impDERF:
4899 case FFEINTRIN_impERF:
4900 case FFEINTRIN_impDERFC:
4901 case FFEINTRIN_impERFC:
4904 case FFEINTRIN_impIARGC:
4905 /* extern int xargc; i__1 = xargc - 1; */
4906 expr_tree = ffecom_2 (MINUS_EXPR, TREE_TYPE (ffecom_tree_xargc_),
4908 convert (TREE_TYPE (ffecom_tree_xargc_),
4912 case FFEINTRIN_impSIGNAL_func:
4913 case FFEINTRIN_impSIGNAL_subr:
4919 arg1_tree = convert (ffecom_f2c_integer_type_node,
4920 ffecom_expr (arg1));
4921 arg1_tree = ffecom_1 (ADDR_EXPR,
4922 build_pointer_type (TREE_TYPE (arg1_tree)),
4925 /* Pass procedure as a pointer to it, anything else by value. */
4926 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
4927 arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
4929 arg2_tree = ffecom_ptr_to_expr (arg2);
4930 arg2_tree = convert (TREE_TYPE (null_pointer_node),
4934 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
4936 arg3_tree = NULL_TREE;
4938 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4939 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4940 TREE_CHAIN (arg1_tree) = arg2_tree;
4943 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4944 ffecom_gfrt_kindtype (gfrt),
4946 ((codegen_imp == FFEINTRIN_impSIGNAL_subr) ?
4950 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
4951 ffebld_nonter_hook (expr));
4953 if (arg3_tree != NULL_TREE)
4955 = ffecom_modify (NULL_TREE, arg3_tree,
4956 convert (TREE_TYPE (arg3_tree),
4961 case FFEINTRIN_impALARM:
4967 arg1_tree = convert (ffecom_f2c_integer_type_node,
4968 ffecom_expr (arg1));
4969 arg1_tree = ffecom_1 (ADDR_EXPR,
4970 build_pointer_type (TREE_TYPE (arg1_tree)),
4973 /* Pass procedure as a pointer to it, anything else by value. */
4974 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
4975 arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
4977 arg2_tree = ffecom_ptr_to_expr (arg2);
4978 arg2_tree = convert (TREE_TYPE (null_pointer_node),
4982 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
4984 arg3_tree = NULL_TREE;
4986 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4987 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4988 TREE_CHAIN (arg1_tree) = arg2_tree;
4991 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4992 ffecom_gfrt_kindtype (gfrt),
4996 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
4997 ffebld_nonter_hook (expr));
4999 if (arg3_tree != NULL_TREE)
5001 = ffecom_modify (NULL_TREE, arg3_tree,
5002 convert (TREE_TYPE (arg3_tree),
5007 case FFEINTRIN_impCHDIR_subr:
5008 case FFEINTRIN_impFDATE_subr:
5009 case FFEINTRIN_impFGET_subr:
5010 case FFEINTRIN_impFPUT_subr:
5011 case FFEINTRIN_impGETCWD_subr:
5012 case FFEINTRIN_impHOSTNM_subr:
5013 case FFEINTRIN_impSYSTEM_subr:
5014 case FFEINTRIN_impUNLINK_subr:
5016 tree arg1_len = integer_zero_node;
5020 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5023 arg2_tree = ffecom_expr_w (NULL_TREE, arg2);
5025 arg2_tree = NULL_TREE;
5027 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5028 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5029 TREE_CHAIN (arg1_tree) = arg1_len;
5032 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5033 ffecom_gfrt_kindtype (gfrt),
5037 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5038 ffebld_nonter_hook (expr));
5040 if (arg2_tree != NULL_TREE)
5042 = ffecom_modify (NULL_TREE, arg2_tree,
5043 convert (TREE_TYPE (arg2_tree),
5048 case FFEINTRIN_impEXIT:
5052 expr_tree = build_tree_list (NULL_TREE,
5053 ffecom_1 (ADDR_EXPR,
5055 (ffecom_integer_type_node),
5056 integer_zero_node));
5059 ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5060 ffecom_gfrt_kindtype (gfrt),
5064 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5065 ffebld_nonter_hook (expr));
5067 case FFEINTRIN_impFLUSH:
5069 gfrt = FFECOM_gfrtFLUSH;
5071 gfrt = FFECOM_gfrtFLUSH1;
5074 case FFEINTRIN_impCHMOD_subr:
5075 case FFEINTRIN_impLINK_subr:
5076 case FFEINTRIN_impRENAME_subr:
5077 case FFEINTRIN_impSYMLNK_subr:
5079 tree arg1_len = integer_zero_node;
5081 tree arg2_len = integer_zero_node;
5085 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5086 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
5088 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5090 arg3_tree = NULL_TREE;
5092 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5093 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5094 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5095 arg2_len = build_tree_list (NULL_TREE, arg2_len);
5096 TREE_CHAIN (arg1_tree) = arg2_tree;
5097 TREE_CHAIN (arg2_tree) = arg1_len;
5098 TREE_CHAIN (arg1_len) = arg2_len;
5099 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5100 ffecom_gfrt_kindtype (gfrt),
5104 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5105 ffebld_nonter_hook (expr));
5106 if (arg3_tree != NULL_TREE)
5107 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5108 convert (TREE_TYPE (arg3_tree),
5113 case FFEINTRIN_impLSTAT_subr:
5114 case FFEINTRIN_impSTAT_subr:
5116 tree arg1_len = integer_zero_node;
5121 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5123 arg2_tree = ffecom_ptr_to_expr (arg2);
5126 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5128 arg3_tree = NULL_TREE;
5130 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5131 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5132 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5133 TREE_CHAIN (arg1_tree) = arg2_tree;
5134 TREE_CHAIN (arg2_tree) = arg1_len;
5135 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5136 ffecom_gfrt_kindtype (gfrt),
5140 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5141 ffebld_nonter_hook (expr));
5142 if (arg3_tree != NULL_TREE)
5143 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5144 convert (TREE_TYPE (arg3_tree),
5149 case FFEINTRIN_impFGETC_subr:
5150 case FFEINTRIN_impFPUTC_subr:
5154 tree arg2_len = integer_zero_node;
5157 arg1_tree = convert (ffecom_f2c_integer_type_node,
5158 ffecom_expr (arg1));
5159 arg1_tree = ffecom_1 (ADDR_EXPR,
5160 build_pointer_type (TREE_TYPE (arg1_tree)),
5163 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
5165 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5167 arg3_tree = NULL_TREE;
5169 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5170 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5171 arg2_len = build_tree_list (NULL_TREE, arg2_len);
5172 TREE_CHAIN (arg1_tree) = arg2_tree;
5173 TREE_CHAIN (arg2_tree) = arg2_len;
5175 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5176 ffecom_gfrt_kindtype (gfrt),
5180 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5181 ffebld_nonter_hook (expr));
5182 if (arg3_tree != NULL_TREE)
5183 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5184 convert (TREE_TYPE (arg3_tree),
5189 case FFEINTRIN_impFSTAT_subr:
5195 arg1_tree = convert (ffecom_f2c_integer_type_node,
5196 ffecom_expr (arg1));
5197 arg1_tree = ffecom_1 (ADDR_EXPR,
5198 build_pointer_type (TREE_TYPE (arg1_tree)),
5201 arg2_tree = convert (ffecom_f2c_ptr_to_integer_type_node,
5202 ffecom_ptr_to_expr (arg2));
5205 arg3_tree = NULL_TREE;
5207 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5209 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5210 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5211 TREE_CHAIN (arg1_tree) = arg2_tree;
5212 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5213 ffecom_gfrt_kindtype (gfrt),
5217 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5218 ffebld_nonter_hook (expr));
5219 if (arg3_tree != NULL_TREE) {
5220 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5221 convert (TREE_TYPE (arg3_tree),
5227 case FFEINTRIN_impKILL_subr:
5233 arg1_tree = convert (ffecom_f2c_integer_type_node,
5234 ffecom_expr (arg1));
5235 arg1_tree = ffecom_1 (ADDR_EXPR,
5236 build_pointer_type (TREE_TYPE (arg1_tree)),
5239 arg2_tree = convert (ffecom_f2c_integer_type_node,
5240 ffecom_expr (arg2));
5241 arg2_tree = ffecom_1 (ADDR_EXPR,
5242 build_pointer_type (TREE_TYPE (arg2_tree)),
5246 arg3_tree = NULL_TREE;
5248 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5250 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5251 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5252 TREE_CHAIN (arg1_tree) = arg2_tree;
5253 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5254 ffecom_gfrt_kindtype (gfrt),
5258 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5259 ffebld_nonter_hook (expr));
5260 if (arg3_tree != NULL_TREE) {
5261 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5262 convert (TREE_TYPE (arg3_tree),
5268 case FFEINTRIN_impCTIME_subr:
5269 case FFEINTRIN_impTTYNAM_subr:
5271 tree arg1_len = integer_zero_node;
5275 arg1_tree = ffecom_arg_ptr_to_expr (arg2, &arg1_len);
5277 arg2_tree = convert (((codegen_imp == FFEINTRIN_impCTIME_subr) ?
5278 ffecom_f2c_longint_type_node :
5279 ffecom_f2c_integer_type_node),
5280 ffecom_expr (arg1));
5281 arg2_tree = ffecom_1 (ADDR_EXPR,
5282 build_pointer_type (TREE_TYPE (arg2_tree)),
5285 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5286 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5287 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5288 TREE_CHAIN (arg1_len) = arg2_tree;
5289 TREE_CHAIN (arg1_tree) = arg1_len;
5292 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5293 ffecom_gfrt_kindtype (gfrt),
5297 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5298 ffebld_nonter_hook (expr));
5299 TREE_SIDE_EFFECTS (expr_tree) = 1;
5303 case FFEINTRIN_impIRAND:
5304 case FFEINTRIN_impRAND:
5305 /* Arg defaults to 0 (normal random case) */
5310 arg1_tree = ffecom_integer_zero_node;
5312 arg1_tree = ffecom_expr (arg1);
5313 arg1_tree = convert (ffecom_f2c_integer_type_node,
5315 arg1_tree = ffecom_1 (ADDR_EXPR,
5316 build_pointer_type (TREE_TYPE (arg1_tree)),
5318 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5320 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5321 ffecom_gfrt_kindtype (gfrt),
5323 ((codegen_imp == FFEINTRIN_impIRAND) ?
5324 ffecom_f2c_integer_type_node :
5325 ffecom_f2c_real_type_node),
5327 dest_tree, dest, dest_used,
5329 ffebld_nonter_hook (expr));
5333 case FFEINTRIN_impFTELL_subr:
5334 case FFEINTRIN_impUMASK_subr:
5339 arg1_tree = convert (ffecom_f2c_integer_type_node,
5340 ffecom_expr (arg1));
5341 arg1_tree = ffecom_1 (ADDR_EXPR,
5342 build_pointer_type (TREE_TYPE (arg1_tree)),
5346 arg2_tree = NULL_TREE;
5348 arg2_tree = ffecom_expr_w (NULL_TREE, arg2);
5350 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5351 ffecom_gfrt_kindtype (gfrt),
5354 build_tree_list (NULL_TREE, arg1_tree),
5355 NULL_TREE, NULL, NULL, NULL_TREE,
5357 ffebld_nonter_hook (expr));
5358 if (arg2_tree != NULL_TREE) {
5359 expr_tree = ffecom_modify (NULL_TREE, arg2_tree,
5360 convert (TREE_TYPE (arg2_tree),
5366 case FFEINTRIN_impCPU_TIME:
5367 case FFEINTRIN_impSECOND_subr:
5371 arg1_tree = ffecom_expr_w (NULL_TREE, arg1);
5374 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5375 ffecom_gfrt_kindtype (gfrt),
5379 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5380 ffebld_nonter_hook (expr));
5383 = ffecom_modify (NULL_TREE, arg1_tree,
5384 convert (TREE_TYPE (arg1_tree),
5389 case FFEINTRIN_impDTIME_subr:
5390 case FFEINTRIN_impETIME_subr:
5395 result_tree = ffecom_expr_w (NULL_TREE, arg2);
5397 arg1_tree = ffecom_ptr_to_expr (arg1);
5399 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5400 ffecom_gfrt_kindtype (gfrt),
5403 build_tree_list (NULL_TREE, arg1_tree),
5404 NULL_TREE, NULL, NULL, NULL_TREE,
5406 ffebld_nonter_hook (expr));
5407 expr_tree = ffecom_modify (NULL_TREE, result_tree,
5408 convert (TREE_TYPE (result_tree),
5413 /* Straightforward calls of libf2c routines: */
5414 case FFEINTRIN_impABORT:
5415 case FFEINTRIN_impACCESS:
5416 case FFEINTRIN_impBESJ0:
5417 case FFEINTRIN_impBESJ1:
5418 case FFEINTRIN_impBESJN:
5419 case FFEINTRIN_impBESY0:
5420 case FFEINTRIN_impBESY1:
5421 case FFEINTRIN_impBESYN:
5422 case FFEINTRIN_impCHDIR_func:
5423 case FFEINTRIN_impCHMOD_func:
5424 case FFEINTRIN_impDATE:
5425 case FFEINTRIN_impDATE_AND_TIME:
5426 case FFEINTRIN_impDBESJ0:
5427 case FFEINTRIN_impDBESJ1:
5428 case FFEINTRIN_impDBESJN:
5429 case FFEINTRIN_impDBESY0:
5430 case FFEINTRIN_impDBESY1:
5431 case FFEINTRIN_impDBESYN:
5432 case FFEINTRIN_impDTIME_func:
5433 case FFEINTRIN_impETIME_func:
5434 case FFEINTRIN_impFGETC_func:
5435 case FFEINTRIN_impFGET_func:
5436 case FFEINTRIN_impFNUM:
5437 case FFEINTRIN_impFPUTC_func:
5438 case FFEINTRIN_impFPUT_func:
5439 case FFEINTRIN_impFSEEK:
5440 case FFEINTRIN_impFSTAT_func:
5441 case FFEINTRIN_impFTELL_func:
5442 case FFEINTRIN_impGERROR:
5443 case FFEINTRIN_impGETARG:
5444 case FFEINTRIN_impGETCWD_func:
5445 case FFEINTRIN_impGETENV:
5446 case FFEINTRIN_impGETGID:
5447 case FFEINTRIN_impGETLOG:
5448 case FFEINTRIN_impGETPID:
5449 case FFEINTRIN_impGETUID:
5450 case FFEINTRIN_impGMTIME:
5451 case FFEINTRIN_impHOSTNM_func:
5452 case FFEINTRIN_impIDATE_unix:
5453 case FFEINTRIN_impIDATE_vxt:
5454 case FFEINTRIN_impIERRNO:
5455 case FFEINTRIN_impISATTY:
5456 case FFEINTRIN_impITIME:
5457 case FFEINTRIN_impKILL_func:
5458 case FFEINTRIN_impLINK_func:
5459 case FFEINTRIN_impLNBLNK:
5460 case FFEINTRIN_impLSTAT_func:
5461 case FFEINTRIN_impLTIME:
5462 case FFEINTRIN_impMCLOCK8:
5463 case FFEINTRIN_impMCLOCK:
5464 case FFEINTRIN_impPERROR:
5465 case FFEINTRIN_impRENAME_func:
5466 case FFEINTRIN_impSECNDS:
5467 case FFEINTRIN_impSECOND_func:
5468 case FFEINTRIN_impSLEEP:
5469 case FFEINTRIN_impSRAND:
5470 case FFEINTRIN_impSTAT_func:
5471 case FFEINTRIN_impSYMLNK_func:
5472 case FFEINTRIN_impSYSTEM_CLOCK:
5473 case FFEINTRIN_impSYSTEM_func:
5474 case FFEINTRIN_impTIME8:
5475 case FFEINTRIN_impTIME_unix:
5476 case FFEINTRIN_impTIME_vxt:
5477 case FFEINTRIN_impUMASK_func:
5478 case FFEINTRIN_impUNLINK_func:
5481 case FFEINTRIN_impCTIME_func: /* CHARACTER functions not handled here. */
5482 case FFEINTRIN_impFDATE_func: /* CHARACTER functions not handled here. */
5483 case FFEINTRIN_impTTYNAM_func: /* CHARACTER functions not handled here. */
5484 case FFEINTRIN_impNONE:
5485 case FFEINTRIN_imp: /* Hush up gcc warning. */
5486 fprintf (stderr, "No %s implementation.\n",
5487 ffeintrin_name_implementation (ffebld_symter_implementation (ffebld_left (expr))));
5488 assert ("unimplemented intrinsic" == NULL);
5489 return error_mark_node;
5492 assert (gfrt != FFECOM_gfrt); /* Must have an implementation! */
5494 expr_tree = ffecom_arglist_expr_ (ffecom_gfrt_args_ (gfrt),
5495 ffebld_right (expr));
5497 return ffecom_call_ (ffecom_gfrt_tree_ (gfrt), ffecom_gfrt_kindtype (gfrt),
5498 (ffe_is_f2c_library () && ffecom_gfrt_complex_[gfrt]),
5500 expr_tree, dest_tree, dest, dest_used,
5502 ffebld_nonter_hook (expr));
5504 /* See bottom of this file for f2c transforms used to determine
5505 many of the above implementations. The info seems to confuse
5506 Emacs's C mode indentation, which is why it's been moved to
5507 the bottom of this source file. */
5511 /* For power (exponentiation) where right-hand operand is type INTEGER,
5512 generate in-line code to do it the fast way (which, if the operand
5513 is a constant, might just mean a series of multiplies). */
5515 #if FFECOM_targetCURRENT == FFECOM_targetGCC
5517 ffecom_expr_power_integer_ (ffebld expr)
5519 tree l = ffecom_expr (ffebld_left (expr));
5520 tree r = ffecom_expr (ffebld_right (expr));
5521 tree ltype = TREE_TYPE (l);
5522 tree rtype = TREE_TYPE (r);
5523 tree result = NULL_TREE;
5525 if (l == error_mark_node
5526 || r == error_mark_node)
5527 return error_mark_node;
5529 if (TREE_CODE (r) == INTEGER_CST)
5531 int sgn = tree_int_cst_sgn (r);
5534 return convert (ltype, integer_one_node);
5536 if ((TREE_CODE (ltype) == INTEGER_TYPE)
5539 /* Reciprocal of integer is either 0, -1, or 1, so after
5540 calculating that (which we leave to the back end to do
5541 or not do optimally), don't bother with any multiplying. */
5543 result = ffecom_tree_divide_ (ltype,
5544 convert (ltype, integer_one_node),
5546 NULL_TREE, NULL, NULL, NULL_TREE);
5547 r = ffecom_1 (NEGATE_EXPR,
5550 if ((TREE_INT_CST_LOW (r) & 1) == 0)
5551 result = ffecom_1 (ABS_EXPR, rtype,
5555 /* Generate appropriate series of multiplies, preceded
5556 by divide if the exponent is negative. */
5562 l = ffecom_tree_divide_ (ltype,
5563 convert (ltype, integer_one_node),
5565 NULL_TREE, NULL, NULL,
5566 ffebld_nonter_hook (expr));
5567 r = ffecom_1 (NEGATE_EXPR, rtype, r);
5568 assert (TREE_CODE (r) == INTEGER_CST);
5570 if (tree_int_cst_sgn (r) < 0)
5571 { /* The "most negative" number. */
5572 r = ffecom_1 (NEGATE_EXPR, rtype,
5573 ffecom_2 (RSHIFT_EXPR, rtype,
5577 l = ffecom_2 (MULT_EXPR, ltype,
5585 if (TREE_INT_CST_LOW (r) & 1)
5587 if (result == NULL_TREE)
5590 result = ffecom_2 (MULT_EXPR, ltype,
5595 r = ffecom_2 (RSHIFT_EXPR, rtype,
5598 if (integer_zerop (r))
5600 assert (TREE_CODE (r) == INTEGER_CST);
5603 l = ffecom_2 (MULT_EXPR, ltype,
5610 /* Though rhs isn't a constant, in-line code cannot be expanded
5611 while transforming dummies
5612 because the back end cannot be easily convinced to generate
5613 stores (MODIFY_EXPR), handle temporaries, and so on before
5614 all the appropriate rtx's have been generated for things like
5615 dummy args referenced in rhs -- which doesn't happen until
5616 store_parm_decls() is called (expand_function_start, I believe,
5617 does the actual rtx-stuffing of PARM_DECLs).
5619 So, in this case, let the caller generate the call to the
5620 run-time-library function to evaluate the power for us. */
5622 if (ffecom_transform_only_dummies_)
5625 /* Right-hand operand not a constant, expand in-line code to figure
5626 out how to do the multiplies, &c.
5628 The returned expression is expressed this way in GNU C, where l and
5631 ({ typeof (r) rtmp = r;
5632 typeof (l) ltmp = l;
5639 if ((basetypeof (l) == basetypeof (int))
5642 result = ((typeof (l)) 1) / ltmp;
5643 if ((ltmp < 0) && (((-rtmp) & 1) == 0))
5649 if ((basetypeof (l) != basetypeof (int))
5652 ltmp = ((typeof (l)) 1) / ltmp;
5656 rtmp = -(rtmp >> 1);
5664 if ((rtmp >>= 1) == 0)
5673 Note that some of the above is compile-time collapsable, such as
5674 the first part of the if statements that checks the base type of
5675 l against int. The if statements are phrased that way to suggest
5676 an easy way to generate the if/else constructs here, knowing that
5677 the back end should (and probably does) eliminate the resulting
5678 dead code (either the int case or the non-int case), something
5679 it couldn't do without the redundant phrasing, requiring explicit
5680 dead-code elimination here, which would be kind of difficult to
5687 tree basetypeof_l_is_int;
5692 = build_int_2 ((TREE_CODE (ltype) == INTEGER_TYPE), 0);
5694 se = expand_start_stmt_expr ();
5696 ffecom_start_compstmt ();
5699 rtmp = ffecom_make_tempvar ("power_r", rtype,
5700 FFETARGET_charactersizeNONE, -1);
5701 ltmp = ffecom_make_tempvar ("power_l", ltype,
5702 FFETARGET_charactersizeNONE, -1);
5703 result = ffecom_make_tempvar ("power_res", ltype,
5704 FFETARGET_charactersizeNONE, -1);
5705 if (TREE_CODE (ltype) == COMPLEX_TYPE
5706 || TREE_CODE (ltype) == RECORD_TYPE)
5707 divide = ffecom_make_tempvar ("power_div", ltype,
5708 FFETARGET_charactersizeNONE, -1);
5715 hook = ffebld_nonter_hook (expr);
5717 assert (TREE_CODE (hook) == TREE_VEC);
5718 assert (TREE_VEC_LENGTH (hook) == 4);
5719 rtmp = TREE_VEC_ELT (hook, 0);
5720 ltmp = TREE_VEC_ELT (hook, 1);
5721 result = TREE_VEC_ELT (hook, 2);
5722 divide = TREE_VEC_ELT (hook, 3);
5723 if (TREE_CODE (ltype) == COMPLEX_TYPE
5724 || TREE_CODE (ltype) == RECORD_TYPE)
5731 expand_expr_stmt (ffecom_modify (void_type_node,
5734 expand_expr_stmt (ffecom_modify (void_type_node,
5737 expand_start_cond (ffecom_truth_value
5738 (ffecom_2 (EQ_EXPR, integer_type_node,
5740 convert (rtype, integer_zero_node))),
5742 expand_expr_stmt (ffecom_modify (void_type_node,
5744 convert (ltype, integer_one_node)));
5745 expand_start_else ();
5746 if (! integer_zerop (basetypeof_l_is_int))
5748 expand_start_cond (ffecom_2 (LT_EXPR, integer_type_node,
5751 integer_zero_node)),
5753 expand_expr_stmt (ffecom_modify (void_type_node,
5757 convert (ltype, integer_one_node),
5759 NULL_TREE, NULL, NULL,
5761 expand_start_cond (ffecom_truth_value
5762 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
5763 ffecom_2 (LT_EXPR, integer_type_node,
5766 integer_zero_node)),
5767 ffecom_2 (EQ_EXPR, integer_type_node,
5768 ffecom_2 (BIT_AND_EXPR,
5770 ffecom_1 (NEGATE_EXPR,
5776 integer_zero_node)))),
5778 expand_expr_stmt (ffecom_modify (void_type_node,
5780 ffecom_1 (NEGATE_EXPR,
5784 expand_start_else ();
5786 expand_expr_stmt (ffecom_modify (void_type_node,
5788 convert (ltype, integer_one_node)));
5789 expand_start_cond (ffecom_truth_value
5790 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
5791 ffecom_truth_value_invert
5792 (basetypeof_l_is_int),
5793 ffecom_2 (LT_EXPR, integer_type_node,
5796 integer_zero_node)))),
5798 expand_expr_stmt (ffecom_modify (void_type_node,
5802 convert (ltype, integer_one_node),
5804 NULL_TREE, NULL, NULL,
5806 expand_expr_stmt (ffecom_modify (void_type_node,
5808 ffecom_1 (NEGATE_EXPR, rtype,
5810 expand_start_cond (ffecom_truth_value
5811 (ffecom_2 (LT_EXPR, integer_type_node,
5813 convert (rtype, integer_zero_node))),
5815 expand_expr_stmt (ffecom_modify (void_type_node,
5817 ffecom_1 (NEGATE_EXPR, rtype,
5818 ffecom_2 (RSHIFT_EXPR,
5821 integer_one_node))));
5822 expand_expr_stmt (ffecom_modify (void_type_node,
5824 ffecom_2 (MULT_EXPR, ltype,
5829 expand_start_loop (1);
5830 expand_start_cond (ffecom_truth_value
5831 (ffecom_2 (BIT_AND_EXPR, rtype,
5833 convert (rtype, integer_one_node))),
5835 expand_expr_stmt (ffecom_modify (void_type_node,
5837 ffecom_2 (MULT_EXPR, ltype,
5841 expand_exit_loop_if_false (NULL,
5843 (ffecom_modify (rtype,
5845 ffecom_2 (RSHIFT_EXPR,
5848 integer_one_node))));
5849 expand_expr_stmt (ffecom_modify (void_type_node,
5851 ffecom_2 (MULT_EXPR, ltype,
5856 if (!integer_zerop (basetypeof_l_is_int))
5858 expand_expr_stmt (result);
5860 t = ffecom_end_compstmt ();
5862 result = expand_end_stmt_expr (se);
5864 /* This code comes from c-parse.in, after its expand_end_stmt_expr. */
5866 if (TREE_CODE (t) == BLOCK)
5868 /* Make a BIND_EXPR for the BLOCK already made. */
5869 result = build (BIND_EXPR, TREE_TYPE (result),
5870 NULL_TREE, result, t);
5871 /* Remove the block from the tree at this point.
5872 It gets put back at the proper place
5873 when the BIND_EXPR is expanded. */
5884 /* ffecom_expr_transform_ -- Transform symbols in expr
5886 ffebld expr; // FFE expression.
5887 ffecom_expr_transform_ (expr);
5889 Recursive descent on expr while transforming any untransformed SYMTERs. */
5891 #if FFECOM_targetCURRENT == FFECOM_targetGCC
5893 ffecom_expr_transform_ (ffebld expr)
5898 tail_recurse: /* :::::::::::::::::::: */
5903 switch (ffebld_op (expr))
5905 case FFEBLD_opSYMTER:
5906 s = ffebld_symter (expr);
5907 t = ffesymbol_hook (s).decl_tree;
5908 if ((t == NULL_TREE)
5909 && ((ffesymbol_kind (s) != FFEINFO_kindNONE)
5910 || ((ffesymbol_where (s) != FFEINFO_whereNONE)
5911 && (ffesymbol_where (s) != FFEINFO_whereINTRINSIC))))
5913 s = ffecom_sym_transform_ (s);
5914 t = ffesymbol_hook (s).decl_tree; /* Sfunc expr non-dummy,
5917 break; /* Ok if (t == NULL) here. */
5920 ffecom_expr_transform_ (ffebld_head (expr));
5921 expr = ffebld_trail (expr);
5922 goto tail_recurse; /* :::::::::::::::::::: */
5928 switch (ffebld_arity (expr))
5931 ffecom_expr_transform_ (ffebld_left (expr));
5932 expr = ffebld_right (expr);
5933 goto tail_recurse; /* :::::::::::::::::::: */
5936 expr = ffebld_left (expr);
5937 goto tail_recurse; /* :::::::::::::::::::: */
5947 /* Make a type based on info in live f2c.h file. */
5949 #if FFECOM_targetCURRENT == FFECOM_targetGCC
5951 ffecom_f2c_make_type_ (tree *type, int tcode, const char *name)
5955 case FFECOM_f2ccodeCHAR:
5956 *type = make_signed_type (CHAR_TYPE_SIZE);
5959 case FFECOM_f2ccodeSHORT:
5960 *type = make_signed_type (SHORT_TYPE_SIZE);
5963 case FFECOM_f2ccodeINT:
5964 *type = make_signed_type (INT_TYPE_SIZE);
5967 case FFECOM_f2ccodeLONG:
5968 *type = make_signed_type (LONG_TYPE_SIZE);
5971 case FFECOM_f2ccodeLONGLONG:
5972 *type = make_signed_type (LONG_LONG_TYPE_SIZE);
5975 case FFECOM_f2ccodeCHARPTR:
5976 *type = build_pointer_type (DEFAULT_SIGNED_CHAR
5977 ? signed_char_type_node
5978 : unsigned_char_type_node);
5981 case FFECOM_f2ccodeFLOAT:
5982 *type = make_node (REAL_TYPE);
5983 TYPE_PRECISION (*type) = FLOAT_TYPE_SIZE;
5984 layout_type (*type);
5987 case FFECOM_f2ccodeDOUBLE:
5988 *type = make_node (REAL_TYPE);
5989 TYPE_PRECISION (*type) = DOUBLE_TYPE_SIZE;
5990 layout_type (*type);
5993 case FFECOM_f2ccodeLONGDOUBLE:
5994 *type = make_node (REAL_TYPE);
5995 TYPE_PRECISION (*type) = LONG_DOUBLE_TYPE_SIZE;
5996 layout_type (*type);
5999 case FFECOM_f2ccodeTWOREALS:
6000 *type = ffecom_make_complex_type_ (ffecom_f2c_real_type_node);
6003 case FFECOM_f2ccodeTWODOUBLEREALS:
6004 *type = ffecom_make_complex_type_ (ffecom_f2c_doublereal_type_node);
6008 assert ("unexpected FFECOM_f2ccodeXYZZY!" == NULL);
6009 *type = error_mark_node;
6013 pushdecl (build_decl (TYPE_DECL,
6014 ffecom_get_invented_identifier ("__g77_f2c_%s", name),
6019 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6020 /* Set the f2c list-directed-I/O code for whatever (integral) type has the
6024 ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size,
6030 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
6031 if ((t = ffecom_tree_type[bt][j]) != NULL_TREE
6032 && compare_tree_int (TYPE_SIZE (t), size) == 0)
6034 assert (code != -1);
6035 ffecom_f2c_typecode_[bt][j] = code;
6041 /* Finish up globals after doing all program units in file
6043 Need to handle only uninitialized COMMON areas. */
6045 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6047 ffecom_finish_global_ (ffeglobal global)
6053 if (ffeglobal_type (global) != FFEGLOBAL_typeCOMMON)
6056 if (ffeglobal_common_init (global))
6059 cbt = ffeglobal_hook (global);
6060 if ((cbt == NULL_TREE)
6061 || !ffeglobal_common_have_size (global))
6062 return global; /* No need to make common, never ref'd. */
6064 DECL_EXTERNAL (cbt) = 0;
6066 /* Give the array a size now. */
6068 size = build_int_2 ((ffeglobal_common_size (global)
6069 + ffeglobal_common_pad (global)) - 1,
6072 cbtype = TREE_TYPE (cbt);
6073 TYPE_DOMAIN (cbtype) = build_range_type (integer_type_node,
6076 if (!TREE_TYPE (size))
6077 TREE_TYPE (size) = TYPE_DOMAIN (cbtype);
6078 layout_type (cbtype);
6080 cbt = start_decl (cbt, FALSE);
6081 assert (cbt == ffeglobal_hook (global));
6083 finish_decl (cbt, NULL_TREE, FALSE);
6089 /* Finish up any untransformed symbols. */
6091 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6093 ffecom_finish_symbol_transform_ (ffesymbol s)
6095 if ((s == NULL) || (TREE_CODE (current_function_decl) == ERROR_MARK))
6098 /* It's easy to know to transform an untransformed symbol, to make sure
6099 we put out debugging info for it. But COMMON variables, unlike
6100 EQUIVALENCE ones, aren't given declarations in addition to the
6101 tree expressions that specify offsets, because COMMON variables
6102 can be referenced in the outer scope where only dummy arguments
6103 (PARM_DECLs) should really be seen. To be safe, just don't do any
6104 VAR_DECLs for COMMON variables when we transform them for real
6105 use, and therefore we do all the VAR_DECL creating here. */
6107 if (ffesymbol_hook (s).decl_tree == NULL_TREE)
6109 if (ffesymbol_kind (s) != FFEINFO_kindNONE
6110 || (ffesymbol_where (s) != FFEINFO_whereNONE
6111 && ffesymbol_where (s) != FFEINFO_whereINTRINSIC
6112 && ffesymbol_where (s) != FFEINFO_whereDUMMY))
6113 /* Not transformed, and not CHARACTER*(*), and not a dummy
6114 argument, which can happen only if the entry point names
6115 it "rides in on" are all invalidated for other reasons. */
6116 s = ffecom_sym_transform_ (s);
6119 if ((ffesymbol_where (s) == FFEINFO_whereCOMMON)
6120 && (ffesymbol_hook (s).decl_tree != error_mark_node))
6122 /* This isn't working, at least for dbxout. The .s file looks
6123 okay to me (burley), but in gdb 4.9 at least, the variables
6124 appear to reside somewhere outside of the common area, so
6125 it doesn't make sense to mislead anyone by generating the info
6126 on those variables until this is fixed. NOTE: Same problem
6127 with EQUIVALENCE, sadly...see similar #if later. */
6128 ffecom_member_phase2_ (ffesymbol_storage (ffesymbol_common (s)),
6129 ffesymbol_storage (s));
6136 /* Append underscore(s) to name before calling get_identifier. "us"
6137 is nonzero if the name already contains an underscore and thus
6138 needs two underscores appended. */
6140 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6142 ffecom_get_appended_identifier_ (char us, const char *name)
6148 newname = xmalloc ((i = strlen (name)) + 1
6149 + ffe_is_underscoring ()
6151 memcpy (newname, name, i);
6153 newname[i + us] = '_';
6154 newname[i + 1 + us] = '\0';
6155 id = get_identifier (newname);
6163 /* Decide whether to append underscore to name before calling
6166 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6168 ffecom_get_external_identifier_ (ffesymbol s)
6171 const char *name = ffesymbol_text (s);
6173 /* If name is a built-in name, just return it as is. */
6175 if (!ffe_is_underscoring ()
6176 || (strcmp (name, FFETARGET_nameBLANK_COMMON) == 0)
6177 #if FFETARGET_isENFORCED_MAIN_NAME
6178 || (strcmp (name, FFETARGET_nameENFORCED_NAME) == 0)
6180 || (strcmp (name, FFETARGET_nameUNNAMED_MAIN) == 0)
6182 || (strcmp (name, FFETARGET_nameUNNAMED_BLOCK_DATA) == 0))
6183 return get_identifier (name);
6185 us = ffe_is_second_underscore ()
6186 ? (strchr (name, '_') != NULL)
6189 return ffecom_get_appended_identifier_ (us, name);
6193 /* Decide whether to append underscore to internal name before calling
6196 This is for non-external, top-function-context names only. Transform
6197 identifier so it doesn't conflict with the transformed result
6198 of using a _different_ external name. E.g. if "CALL FOO" is
6199 transformed into "FOO_();", then the variable in "FOO_ = 3"
6200 must be transformed into something that does not conflict, since
6201 these two things should be independent.
6203 The transformation is as follows. If the name does not contain
6204 an underscore, there is no possible conflict, so just return.
6205 If the name does contain an underscore, then transform it just
6206 like we transform an external identifier. */
6208 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6210 ffecom_get_identifier_ (const char *name)
6212 /* If name does not contain an underscore, just return it as is. */
6214 if (!ffe_is_underscoring ()
6215 || (strchr (name, '_') == NULL))
6216 return get_identifier (name);
6218 return ffecom_get_appended_identifier_ (ffe_is_second_underscore (),
6223 /* ffecom_gen_sfuncdef_ -- Generate definition of statement function
6226 ffesymbol s; // kindFUNCTION, whereIMMEDIATE.
6227 t = ffecom_gen_sfuncdef_(s,ffesymbol_basictype(s),
6228 ffesymbol_kindtype(s));
6230 Call after setting up containing function and getting trees for all
6233 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6235 ffecom_gen_sfuncdef_ (ffesymbol s, ffeinfoBasictype bt, ffeinfoKindtype kt)
6237 ffebld expr = ffesymbol_sfexpr (s);
6241 bool charfunc = (bt == FFEINFO_basictypeCHARACTER);
6242 static bool recurse = FALSE;
6243 int old_lineno = lineno;
6244 const char *old_input_filename = input_filename;
6246 ffecom_nested_entry_ = s;
6248 /* For now, we don't have a handy pointer to where the sfunc is actually
6249 defined, though that should be easy to add to an ffesymbol. (The
6250 token/where info available might well point to the place where the type
6251 of the sfunc is declared, especially if that precedes the place where
6252 the sfunc itself is defined, which is typically the case.) We should
6253 put out a null pointer rather than point somewhere wrong, but I want to
6254 see how it works at this point. */
6256 input_filename = ffesymbol_where_filename (s);
6257 lineno = ffesymbol_where_filelinenum (s);
6259 /* Pretransform the expression so any newly discovered things belong to the
6260 outer program unit, not to the statement function. */
6262 ffecom_expr_transform_ (expr);
6264 /* Make sure no recursive invocation of this fn (a specific case of failing
6265 to pretransform an sfunc's expression, i.e. where its expression
6266 references another untransformed sfunc) happens. */
6271 push_f_function_context ();
6274 type = void_type_node;
6277 type = ffecom_tree_type[bt][kt];
6278 if (type == NULL_TREE)
6279 type = integer_type_node; /* _sym_exec_transition reports
6283 start_function (ffecom_get_identifier_ (ffesymbol_text (s)),
6284 build_function_type (type, NULL_TREE),
6285 1, /* nested/inline */
6286 0); /* TREE_PUBLIC */
6288 /* We don't worry about COMPLEX return values here, because this is
6289 entirely internal to our code, and gcc has the ability to return COMPLEX
6290 directly as a value. */
6293 { /* Prepend arg for where result goes. */
6296 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
6298 result = ffecom_get_invented_identifier ("__g77_%s", "result");
6300 ffecom_char_enhance_arg_ (&type, s); /* Ignore returned length. */
6302 type = build_pointer_type (type);
6303 result = build_decl (PARM_DECL, result, type);
6305 push_parm_decl (result);
6308 result = NULL_TREE; /* Not ref'd if !charfunc. */
6310 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (s), TRUE);
6312 store_parm_decls (0);
6314 ffecom_start_compstmt ();
6320 ffetargetCharacterSize sz = ffesymbol_size (s);
6323 result_length = build_int_2 (sz, 0);
6324 TREE_TYPE (result_length) = ffecom_f2c_ftnlen_type_node;
6326 ffecom_prepare_let_char_ (sz, expr);
6328 ffecom_prepare_end ();
6330 ffecom_let_char_ (result, result_length, sz, expr);
6331 expand_null_return ();
6335 ffecom_prepare_expr (expr);
6337 ffecom_prepare_end ();
6339 expand_return (ffecom_modify (NULL_TREE,
6340 DECL_RESULT (current_function_decl),
6341 ffecom_expr (expr)));
6345 ffecom_end_compstmt ();
6347 func = current_function_decl;
6348 finish_function (1);
6350 pop_f_function_context ();
6354 lineno = old_lineno;
6355 input_filename = old_input_filename;
6357 ffecom_nested_entry_ = NULL;
6364 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6366 ffecom_gfrt_args_ (ffecomGfrt ix)
6368 return ffecom_gfrt_argstring_[ix];
6372 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6374 ffecom_gfrt_tree_ (ffecomGfrt ix)
6376 if (ffecom_gfrt_[ix] == NULL_TREE)
6377 ffecom_make_gfrt_ (ix);
6379 return ffecom_1 (ADDR_EXPR,
6380 build_pointer_type (TREE_TYPE (ffecom_gfrt_[ix])),
6385 /* Return initialize-to-zero expression for this VAR_DECL. */
6387 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6388 /* A somewhat evil way to prevent the garbage collector
6389 from collecting 'tree' structures. */
6390 #define NUM_TRACKED_CHUNK 63
6391 static struct tree_ggc_tracker
6393 struct tree_ggc_tracker *next;
6394 tree trees[NUM_TRACKED_CHUNK];
6395 } *tracker_head = NULL;
6398 mark_tracker_head (void *arg)
6400 struct tree_ggc_tracker *head;
6403 for (head = * (struct tree_ggc_tracker **) arg;
6408 for (i = 0; i < NUM_TRACKED_CHUNK; i++)
6409 ggc_mark_tree (head->trees[i]);
6414 ffecom_save_tree_forever (tree t)
6417 if (tracker_head != NULL)
6418 for (i = 0; i < NUM_TRACKED_CHUNK; i++)
6419 if (tracker_head->trees[i] == NULL)
6421 tracker_head->trees[i] = t;
6426 /* Need to allocate a new block. */
6427 struct tree_ggc_tracker *old_head = tracker_head;
6429 tracker_head = ggc_alloc (sizeof (*tracker_head));
6430 tracker_head->next = old_head;
6431 tracker_head->trees[0] = t;
6432 for (i = 1; i < NUM_TRACKED_CHUNK; i++)
6433 tracker_head->trees[i] = NULL;
6438 ffecom_init_zero_ (tree decl)
6441 int incremental = TREE_STATIC (decl);
6442 tree type = TREE_TYPE (decl);
6446 make_decl_rtl (decl, NULL);
6447 assemble_variable (decl, TREE_PUBLIC (decl) ? 1 : 0, 0, 1);
6450 if ((TREE_CODE (type) != ARRAY_TYPE)
6451 && (TREE_CODE (type) != RECORD_TYPE)
6452 && (TREE_CODE (type) != UNION_TYPE)
6454 init = convert (type, integer_zero_node);
6455 else if (!incremental)
6457 init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
6458 TREE_CONSTANT (init) = 1;
6459 TREE_STATIC (init) = 1;
6463 assemble_zeros (int_size_in_bytes (type));
6464 init = error_mark_node;
6471 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6473 ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg,
6479 switch (ffebld_op (arg))
6481 case FFEBLD_opCONTER: /* For F90, check 0-length. */
6482 if (ffetarget_length_character1
6483 (ffebld_constant_character1
6484 (ffebld_conter (arg))) == 0)
6486 *maybe_tree = integer_zero_node;
6487 return convert (tree_type, integer_zero_node);
6490 *maybe_tree = integer_one_node;
6491 expr_tree = build_int_2 (*ffetarget_text_character1
6492 (ffebld_constant_character1
6493 (ffebld_conter (arg))),
6495 TREE_TYPE (expr_tree) = tree_type;
6498 case FFEBLD_opSYMTER:
6499 case FFEBLD_opARRAYREF:
6500 case FFEBLD_opFUNCREF:
6501 case FFEBLD_opSUBSTR:
6502 ffecom_char_args_ (&expr_tree, &length_tree, arg);
6504 if ((expr_tree == error_mark_node)
6505 || (length_tree == error_mark_node))
6507 *maybe_tree = error_mark_node;
6508 return error_mark_node;
6511 if (integer_zerop (length_tree))
6513 *maybe_tree = integer_zero_node;
6514 return convert (tree_type, integer_zero_node);
6518 = ffecom_1 (INDIRECT_REF,
6519 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
6522 = ffecom_2 (ARRAY_REF,
6523 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
6526 expr_tree = convert (tree_type, expr_tree);
6528 if (TREE_CODE (length_tree) == INTEGER_CST)
6529 *maybe_tree = integer_one_node;
6530 else /* Must check length at run time. */
6532 = ffecom_truth_value
6533 (ffecom_2 (GT_EXPR, integer_type_node,
6535 ffecom_f2c_ftnlen_zero_node));
6538 case FFEBLD_opPAREN:
6539 case FFEBLD_opCONVERT:
6540 if (ffeinfo_size (ffebld_info (arg)) == 0)
6542 *maybe_tree = integer_zero_node;
6543 return convert (tree_type, integer_zero_node);
6545 return ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
6548 case FFEBLD_opCONCATENATE:
6555 expr_left = ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
6557 expr_right = ffecom_intrinsic_ichar_ (tree_type, ffebld_right (arg),
6559 *maybe_tree = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
6562 expr_tree = ffecom_3 (COND_EXPR, tree_type,
6570 assert ("bad op in ICHAR" == NULL);
6571 return error_mark_node;
6576 /* ffecom_intrinsic_len_ -- Return length info for char arg (LEN())
6580 length_arg = ffecom_intrinsic_len_ (expr);
6582 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
6583 subexpressions by constructing the appropriate tree for the
6584 length-of-character-text argument in a calling sequence. */
6586 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6588 ffecom_intrinsic_len_ (ffebld expr)
6590 ffetargetCharacter1 val;
6593 switch (ffebld_op (expr))
6595 case FFEBLD_opCONTER:
6596 val = ffebld_constant_character1 (ffebld_conter (expr));
6597 length = build_int_2 (ffetarget_length_character1 (val), 0);
6598 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6601 case FFEBLD_opSYMTER:
6603 ffesymbol s = ffebld_symter (expr);
6606 item = ffesymbol_hook (s).decl_tree;
6607 if (item == NULL_TREE)
6609 s = ffecom_sym_transform_ (s);
6610 item = ffesymbol_hook (s).decl_tree;
6612 if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
6614 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
6615 length = ffesymbol_hook (s).length_tree;
6618 length = build_int_2 (ffesymbol_size (s), 0);
6619 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6622 else if (item == error_mark_node)
6623 length = error_mark_node;
6624 else /* FFEINFO_kindFUNCTION: */
6629 case FFEBLD_opARRAYREF:
6630 length = ffecom_intrinsic_len_ (ffebld_left (expr));
6633 case FFEBLD_opSUBSTR:
6637 ffebld thing = ffebld_right (expr);
6641 assert (ffebld_op (thing) == FFEBLD_opITEM);
6642 start = ffebld_head (thing);
6643 thing = ffebld_trail (thing);
6644 assert (ffebld_trail (thing) == NULL);
6645 end = ffebld_head (thing);
6647 length = ffecom_intrinsic_len_ (ffebld_left (expr));
6649 if (length == error_mark_node)
6658 length = convert (ffecom_f2c_ftnlen_type_node,
6664 start_tree = convert (ffecom_f2c_ftnlen_type_node,
6665 ffecom_expr (start));
6667 if (start_tree == error_mark_node)
6669 length = error_mark_node;
6675 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6676 ffecom_f2c_ftnlen_one_node,
6677 ffecom_2 (MINUS_EXPR,
6678 ffecom_f2c_ftnlen_type_node,
6684 end_tree = convert (ffecom_f2c_ftnlen_type_node,
6687 if (end_tree == error_mark_node)
6689 length = error_mark_node;
6693 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6694 ffecom_f2c_ftnlen_one_node,
6695 ffecom_2 (MINUS_EXPR,
6696 ffecom_f2c_ftnlen_type_node,
6697 end_tree, start_tree));
6703 case FFEBLD_opCONCATENATE:
6705 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6706 ffecom_intrinsic_len_ (ffebld_left (expr)),
6707 ffecom_intrinsic_len_ (ffebld_right (expr)));
6710 case FFEBLD_opFUNCREF:
6711 case FFEBLD_opCONVERT:
6712 length = build_int_2 (ffebld_size (expr), 0);
6713 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6717 assert ("bad op for single char arg expr" == NULL);
6718 length = ffecom_f2c_ftnlen_zero_node;
6722 assert (length != NULL_TREE);
6728 /* Handle CHARACTER assignments.
6730 Generates code to do the assignment. Used by ordinary assignment
6731 statement handler ffecom_let_stmt and by statement-function
6732 handler to generate code for a statement function. */
6734 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6736 ffecom_let_char_ (tree dest_tree, tree dest_length,
6737 ffetargetCharacterSize dest_size, ffebld source)
6739 ffecomConcatList_ catlist;
6744 if ((dest_tree == error_mark_node)
6745 || (dest_length == error_mark_node))
6748 assert (dest_tree != NULL_TREE);
6749 assert (dest_length != NULL_TREE);
6751 /* Source might be an opCONVERT, which just means it is a different size
6752 than the destination. Since the underlying implementation here handles
6753 that (directly or via the s_copy or s_cat run-time-library functions),
6754 we don't need the "convenience" of an opCONVERT that tells us to
6755 truncate or blank-pad, particularly since the resulting implementation
6756 would probably be slower than otherwise. */
6758 while (ffebld_op (source) == FFEBLD_opCONVERT)
6759 source = ffebld_left (source);
6761 catlist = ffecom_concat_list_new_ (source, dest_size);
6762 switch (ffecom_concat_list_count_ (catlist))
6764 case 0: /* Shouldn't happen, but in case it does... */
6765 ffecom_concat_list_kill_ (catlist);
6766 source_tree = null_pointer_node;
6767 source_length = ffecom_f2c_ftnlen_zero_node;
6768 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6769 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
6770 TREE_CHAIN (TREE_CHAIN (expr_tree))
6771 = build_tree_list (NULL_TREE, dest_length);
6772 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6773 = build_tree_list (NULL_TREE, source_length);
6775 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree, NULL_TREE);
6776 TREE_SIDE_EFFECTS (expr_tree) = 1;
6778 expand_expr_stmt (expr_tree);
6782 case 1: /* The (fairly) easy case. */
6783 ffecom_char_args_ (&source_tree, &source_length,
6784 ffecom_concat_list_expr_ (catlist, 0));
6785 ffecom_concat_list_kill_ (catlist);
6786 assert (source_tree != NULL_TREE);
6787 assert (source_length != NULL_TREE);
6789 if ((source_tree == error_mark_node)
6790 || (source_length == error_mark_node))
6796 = ffecom_1 (INDIRECT_REF,
6797 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6801 = ffecom_2 (ARRAY_REF,
6802 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6807 = ffecom_1 (INDIRECT_REF,
6808 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6812 = ffecom_2 (ARRAY_REF,
6813 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6818 expr_tree = ffecom_modify (void_type_node, dest_tree, source_tree);
6820 expand_expr_stmt (expr_tree);
6825 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6826 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
6827 TREE_CHAIN (TREE_CHAIN (expr_tree))
6828 = build_tree_list (NULL_TREE, dest_length);
6829 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6830 = build_tree_list (NULL_TREE, source_length);
6832 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree, NULL_TREE);
6833 TREE_SIDE_EFFECTS (expr_tree) = 1;
6835 expand_expr_stmt (expr_tree);
6839 default: /* Must actually concatenate things. */
6843 /* Heavy-duty concatenation. */
6846 int count = ffecom_concat_list_count_ (catlist);
6858 = ffecom_push_tempvar (ffecom_f2c_ftnlen_type_node,
6859 FFETARGET_charactersizeNONE, count, TRUE);
6860 item_array = items = ffecom_push_tempvar (ffecom_f2c_address_type_node,
6861 FFETARGET_charactersizeNONE,
6867 hook = ffebld_nonter_hook (source);
6869 assert (TREE_CODE (hook) == TREE_VEC);
6870 assert (TREE_VEC_LENGTH (hook) == 2);
6871 length_array = lengths = TREE_VEC_ELT (hook, 0);
6872 item_array = items = TREE_VEC_ELT (hook, 1);
6876 for (i = 0; i < count; ++i)
6878 ffecom_char_args_ (&citem, &clength,
6879 ffecom_concat_list_expr_ (catlist, i));
6880 if ((citem == error_mark_node)
6881 || (clength == error_mark_node))
6883 ffecom_concat_list_kill_ (catlist);
6888 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
6889 ffecom_modify (void_type_node,
6890 ffecom_2 (ARRAY_REF,
6891 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
6893 build_int_2 (i, 0)),
6897 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
6898 ffecom_modify (void_type_node,
6899 ffecom_2 (ARRAY_REF,
6900 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
6902 build_int_2 (i, 0)),
6907 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6908 TREE_CHAIN (expr_tree)
6909 = build_tree_list (NULL_TREE,
6910 ffecom_1 (ADDR_EXPR,
6911 build_pointer_type (TREE_TYPE (items)),
6913 TREE_CHAIN (TREE_CHAIN (expr_tree))
6914 = build_tree_list (NULL_TREE,
6915 ffecom_1 (ADDR_EXPR,
6916 build_pointer_type (TREE_TYPE (lengths)),
6918 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6921 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
6922 convert (ffecom_f2c_ftnlen_type_node,
6923 build_int_2 (count, 0))));
6924 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree))))
6925 = build_tree_list (NULL_TREE, dest_length);
6927 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCAT, expr_tree, NULL_TREE);
6928 TREE_SIDE_EFFECTS (expr_tree) = 1;
6930 expand_expr_stmt (expr_tree);
6933 ffecom_concat_list_kill_ (catlist);
6937 /* ffecom_make_gfrt_ -- Make initial info for run-time routine
6940 ffecom_make_gfrt_(ix);
6942 Assumes gfrt_[ix] is NULL_TREE, and replaces it with the FUNCTION_DECL
6943 for the indicated run-time routine (ix). */
6945 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6947 ffecom_make_gfrt_ (ffecomGfrt ix)
6952 switch (ffecom_gfrt_type_[ix])
6954 case FFECOM_rttypeVOID_:
6955 ttype = void_type_node;
6958 case FFECOM_rttypeVOIDSTAR_:
6959 ttype = TREE_TYPE (null_pointer_node); /* `void *'. */
6962 case FFECOM_rttypeFTNINT_:
6963 ttype = ffecom_f2c_ftnint_type_node;
6966 case FFECOM_rttypeINTEGER_:
6967 ttype = ffecom_f2c_integer_type_node;
6970 case FFECOM_rttypeLONGINT_:
6971 ttype = ffecom_f2c_longint_type_node;
6974 case FFECOM_rttypeLOGICAL_:
6975 ttype = ffecom_f2c_logical_type_node;
6978 case FFECOM_rttypeREAL_F2C_:
6979 ttype = double_type_node;
6982 case FFECOM_rttypeREAL_GNU_:
6983 ttype = float_type_node;
6986 case FFECOM_rttypeCOMPLEX_F2C_:
6987 ttype = void_type_node;
6990 case FFECOM_rttypeCOMPLEX_GNU_:
6991 ttype = ffecom_f2c_complex_type_node;
6994 case FFECOM_rttypeDOUBLE_:
6995 ttype = double_type_node;
6998 case FFECOM_rttypeDOUBLEREAL_:
6999 ttype = ffecom_f2c_doublereal_type_node;
7002 case FFECOM_rttypeDBLCMPLX_F2C_:
7003 ttype = void_type_node;
7006 case FFECOM_rttypeDBLCMPLX_GNU_:
7007 ttype = ffecom_f2c_doublecomplex_type_node;
7010 case FFECOM_rttypeCHARACTER_:
7011 ttype = void_type_node;
7016 assert ("bad rttype" == NULL);
7020 ttype = build_function_type (ttype, NULL_TREE);
7021 t = build_decl (FUNCTION_DECL,
7022 get_identifier (ffecom_gfrt_name_[ix]),
7024 DECL_EXTERNAL (t) = 1;
7025 TREE_READONLY (t) = ffecom_gfrt_const_[ix] ? 1 : 0;
7026 TREE_PUBLIC (t) = 1;
7027 TREE_THIS_VOLATILE (t) = ffecom_gfrt_volatile_[ix] ? 1 : 0;
7029 /* Sanity check: A function that's const cannot be volatile. */
7031 assert (ffecom_gfrt_const_[ix] ? !ffecom_gfrt_volatile_[ix] : 1);
7033 /* Sanity check: A function that's const cannot return complex. */
7035 assert (ffecom_gfrt_const_[ix] ? !ffecom_gfrt_complex_[ix] : 1);
7037 t = start_decl (t, TRUE);
7039 finish_decl (t, NULL_TREE, TRUE);
7041 ffecom_gfrt_[ix] = t;
7045 /* Phase 1 pass over each member of a COMMON/EQUIVALENCE group. */
7047 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7049 ffecom_member_phase1_ (ffestorag mst UNUSED, ffestorag st)
7051 ffesymbol s = ffestorag_symbol (st);
7053 if (ffesymbol_namelisted (s))
7054 ffecom_member_namelisted_ = TRUE;
7058 /* Phase 2 pass over each member of a COMMON/EQUIVALENCE group. Declare
7059 the member so debugger will see it. Otherwise nobody should be
7060 referencing the member. */
7062 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7064 ffecom_member_phase2_ (ffestorag mst, ffestorag st)
7072 || ((mt = ffestorag_hook (mst)) == NULL)
7073 || (mt == error_mark_node))
7077 || ((s = ffestorag_symbol (st)) == NULL))
7080 type = ffecom_type_localvar_ (s,
7081 ffesymbol_basictype (s),
7082 ffesymbol_kindtype (s));
7083 if (type == error_mark_node)
7086 t = build_decl (VAR_DECL,
7087 ffecom_get_identifier_ (ffesymbol_text (s)),
7090 TREE_STATIC (t) = TREE_STATIC (mt);
7091 DECL_INITIAL (t) = NULL_TREE;
7092 TREE_ASM_WRITTEN (t) = 1;
7096 = gen_rtx (MEM, TYPE_MODE (type),
7097 plus_constant (XEXP (DECL_RTL (mt), 0),
7098 ffestorag_modulo (mst)
7099 + ffestorag_offset (st)
7100 - ffestorag_offset (mst)));
7102 t = start_decl (t, FALSE);
7104 finish_decl (t, NULL_TREE, FALSE);
7108 /* Prepare source expression for assignment into a destination perhaps known
7109 to be of a specific size. */
7112 ffecom_prepare_let_char_ (ffetargetCharacterSize dest_size, ffebld source)
7114 ffecomConcatList_ catlist;
7119 tree tempvar = NULL_TREE;
7121 while (ffebld_op (source) == FFEBLD_opCONVERT)
7122 source = ffebld_left (source);
7124 catlist = ffecom_concat_list_new_ (source, dest_size);
7125 count = ffecom_concat_list_count_ (catlist);
7130 = ffecom_make_tempvar ("let_char_len", ffecom_f2c_ftnlen_type_node,
7131 FFETARGET_charactersizeNONE, count);
7133 = ffecom_make_tempvar ("let_char_item", ffecom_f2c_address_type_node,
7134 FFETARGET_charactersizeNONE, count);
7136 tempvar = make_tree_vec (2);
7137 TREE_VEC_ELT (tempvar, 0) = ltmp;
7138 TREE_VEC_ELT (tempvar, 1) = itmp;
7141 for (i = 0; i < count; ++i)
7142 ffecom_prepare_arg_ptr_to_expr (ffecom_concat_list_expr_ (catlist, i));
7144 ffecom_concat_list_kill_ (catlist);
7148 ffebld_nonter_set_hook (source, tempvar);
7149 current_binding_level->prep_state = 1;
7153 /* ffecom_push_dummy_decls_ -- Transform dummy args, push parm decls in order
7155 Ignores STAR (alternate-return) dummies. All other get exec-transitioned
7156 (which generates their trees) and then their trees get push_parm_decl'd.
7158 The second arg is TRUE if the dummies are for a statement function, in
7159 which case lengths are not pushed for character arguments (since they are
7160 always known by both the caller and the callee, though the code allows
7161 for someday permitting CHAR*(*) stmtfunc dummies). */
7163 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7165 ffecom_push_dummy_decls_ (ffebld dummy_list, bool stmtfunc)
7172 ffecom_transform_only_dummies_ = TRUE;
7174 /* First push the parms corresponding to actual dummy "contents". */
7176 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
7178 dummy = ffebld_head (dumlist);
7179 switch (ffebld_op (dummy))
7183 continue; /* Forget alternate returns. */
7188 assert (ffebld_op (dummy) == FFEBLD_opSYMTER);
7189 s = ffebld_symter (dummy);
7190 parm = ffesymbol_hook (s).decl_tree;
7191 if (parm == NULL_TREE)
7193 s = ffecom_sym_transform_ (s);
7194 parm = ffesymbol_hook (s).decl_tree;
7195 assert (parm != NULL_TREE);
7197 if (parm != error_mark_node)
7198 push_parm_decl (parm);
7201 /* Then, for CHARACTER dummies, push the parms giving their lengths. */
7203 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
7205 dummy = ffebld_head (dumlist);
7206 switch (ffebld_op (dummy))
7210 continue; /* Forget alternate returns, they mean
7216 s = ffebld_symter (dummy);
7217 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
7218 continue; /* Only looking for CHARACTER arguments. */
7219 if (stmtfunc && (ffesymbol_size (s) != FFETARGET_charactersizeNONE))
7220 continue; /* Stmtfunc arg with known size needs no
7222 if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
7223 continue; /* Only looking for variables and arrays. */
7224 parm = ffesymbol_hook (s).length_tree;
7225 assert (parm != NULL_TREE);
7226 if (parm != error_mark_node)
7227 push_parm_decl (parm);
7230 ffecom_transform_only_dummies_ = FALSE;
7234 /* ffecom_start_progunit_ -- Beginning of program unit
7236 Does GNU back end stuff necessary to teach it about the start of its
7237 equivalent of a Fortran program unit. */
7239 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7241 ffecom_start_progunit_ ()
7243 ffesymbol fn = ffecom_primary_entry_;
7245 tree id; /* Identifier (name) of function. */
7246 tree type; /* Type of function. */
7247 tree result; /* Result of function. */
7248 ffeinfoBasictype bt;
7252 ffeglobalType egt = FFEGLOBAL_type;
7255 bool altentries = (ffecom_num_entrypoints_ != 0);
7258 && (ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
7259 && (ffecom_master_bt_ == FFEINFO_basictypeNONE);
7260 bool main_program = FALSE;
7261 int old_lineno = lineno;
7262 const char *old_input_filename = input_filename;
7264 assert (fn != NULL);
7265 assert (ffesymbol_hook (fn).decl_tree == NULL_TREE);
7267 input_filename = ffesymbol_where_filename (fn);
7268 lineno = ffesymbol_where_filelinenum (fn);
7270 switch (ffecom_primary_entry_kind_)
7272 case FFEINFO_kindPROGRAM:
7273 main_program = TRUE;
7274 gt = FFEGLOBAL_typeMAIN;
7275 bt = FFEINFO_basictypeNONE;
7276 kt = FFEINFO_kindtypeNONE;
7277 type = ffecom_tree_fun_type_void;
7282 case FFEINFO_kindBLOCKDATA:
7283 gt = FFEGLOBAL_typeBDATA;
7284 bt = FFEINFO_basictypeNONE;
7285 kt = FFEINFO_kindtypeNONE;
7286 type = ffecom_tree_fun_type_void;
7291 case FFEINFO_kindFUNCTION:
7292 gt = FFEGLOBAL_typeFUNC;
7293 egt = FFEGLOBAL_typeEXT;
7294 bt = ffesymbol_basictype (fn);
7295 kt = ffesymbol_kindtype (fn);
7296 if (bt == FFEINFO_basictypeNONE)
7298 ffeimplic_establish_symbol (fn);
7299 if (ffesymbol_funcresult (fn) != NULL)
7300 ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
7301 bt = ffesymbol_basictype (fn);
7302 kt = ffesymbol_kindtype (fn);
7306 charfunc = cmplxfunc = FALSE;
7307 else if (bt == FFEINFO_basictypeCHARACTER)
7308 charfunc = TRUE, cmplxfunc = FALSE;
7309 else if ((bt == FFEINFO_basictypeCOMPLEX)
7310 && ffesymbol_is_f2c (fn)
7312 charfunc = FALSE, cmplxfunc = TRUE;
7314 charfunc = cmplxfunc = FALSE;
7316 if (multi || charfunc)
7317 type = ffecom_tree_fun_type_void;
7318 else if (ffesymbol_is_f2c (fn) && !altentries)
7319 type = ffecom_tree_fun_type[bt][kt];
7321 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
7323 if ((type == NULL_TREE)
7324 || (TREE_TYPE (type) == NULL_TREE))
7325 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */
7328 case FFEINFO_kindSUBROUTINE:
7329 gt = FFEGLOBAL_typeSUBR;
7330 egt = FFEGLOBAL_typeEXT;
7331 bt = FFEINFO_basictypeNONE;
7332 kt = FFEINFO_kindtypeNONE;
7333 if (ffecom_is_altreturning_)
7334 type = ffecom_tree_subr_type;
7336 type = ffecom_tree_fun_type_void;
7342 assert ("say what??" == NULL);
7344 case FFEINFO_kindANY:
7345 gt = FFEGLOBAL_typeANY;
7346 bt = FFEINFO_basictypeNONE;
7347 kt = FFEINFO_kindtypeNONE;
7348 type = error_mark_node;
7356 id = ffecom_get_invented_identifier ("__g77_masterfun_%s",
7357 ffesymbol_text (fn));
7359 #if FFETARGET_isENFORCED_MAIN
7360 else if (main_program)
7361 id = get_identifier (FFETARGET_nameENFORCED_MAIN_NAME);
7364 id = ffecom_get_external_identifier_ (fn);
7368 0, /* nested/inline */
7369 !altentries); /* TREE_PUBLIC */
7371 TREE_USED (current_function_decl) = 1; /* Avoid spurious warning if altentries. */
7374 && ((g = ffesymbol_global (fn)) != NULL)
7375 && ((ffeglobal_type (g) == gt)
7376 || (ffeglobal_type (g) == egt)))
7378 ffeglobal_set_hook (g, current_function_decl);
7381 /* Arg handling needs exec-transitioned ffesymbols to work with. But
7382 exec-transitioning needs current_function_decl to be filled in. So we
7383 do these things in two phases. */
7386 { /* 1st arg identifies which entrypoint. */
7387 ffecom_which_entrypoint_decl_
7388 = build_decl (PARM_DECL,
7389 ffecom_get_invented_identifier ("__g77_%s",
7390 "which_entrypoint"),
7392 push_parm_decl (ffecom_which_entrypoint_decl_);
7398 { /* Arg for result (return value). */
7403 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
7405 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
7407 type = ffecom_multi_type_node_;
7409 result = ffecom_get_invented_identifier ("__g77_%s", "result");
7411 /* Make length arg _and_ enhance type info for CHAR arg itself. */
7414 length = ffecom_char_enhance_arg_ (&type, fn);
7416 length = NULL_TREE; /* Not ref'd if !charfunc. */
7418 type = build_pointer_type (type);
7419 result = build_decl (PARM_DECL, result, type);
7421 push_parm_decl (result);
7423 ffecom_multi_retval_ = result;
7425 ffecom_func_result_ = result;
7429 push_parm_decl (length);
7430 ffecom_func_length_ = length;
7434 if (ffecom_primary_entry_is_proc_)
7437 arglist = ffecom_master_arglist_;
7439 arglist = ffesymbol_dummyargs (fn);
7440 ffecom_push_dummy_decls_ (arglist, FALSE);
7443 if (TREE_CODE (current_function_decl) != ERROR_MARK)
7444 store_parm_decls (main_program ? 1 : 0);
7446 ffecom_start_compstmt ();
7447 /* Disallow temp vars at this level. */
7448 current_binding_level->prep_state = 2;
7450 lineno = old_lineno;
7451 input_filename = old_input_filename;
7453 /* This handles any symbols still untransformed, in case -g specified.
7454 This used to be done in ffecom_finish_progunit, but it turns out to
7455 be necessary to do it here so that statement functions are
7456 expanded before code. But don't bother for BLOCK DATA. */
7458 if (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
7459 ffesymbol_drive (ffecom_finish_symbol_transform_);
7463 /* ffecom_sym_transform_ -- Transform FFE sym into backend sym
7466 ffecom_sym_transform_(s);
7468 The ffesymbol_hook info for s is updated with appropriate backend info
7471 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7473 ffecom_sym_transform_ (ffesymbol s)
7475 tree t; /* Transformed thingy. */
7476 tree tlen; /* Length if CHAR*(*). */
7477 bool addr; /* Is t the address of the thingy? */
7478 ffeinfoBasictype bt;
7481 int old_lineno = lineno;
7482 const char *old_input_filename = input_filename;
7484 /* Must ensure special ASSIGN variables are declared at top of outermost
7485 block, else they'll end up in the innermost block when their first
7486 ASSIGN is seen, which leaves them out of scope when they're the
7487 subject of a GOTO or I/O statement.
7489 We make this variable even if -fugly-assign. Just let it go unused,
7490 in case it turns out there are cases where we really want to use this
7491 variable anyway (e.g. ASSIGN to INTEGER*2 variable). */
7493 if (! ffecom_transform_only_dummies_
7494 && ffesymbol_assigned (s)
7495 && ! ffesymbol_hook (s).assign_tree)
7496 s = ffecom_sym_transform_assign_ (s);
7498 if (ffesymbol_sfdummyparent (s) == NULL)
7500 input_filename = ffesymbol_where_filename (s);
7501 lineno = ffesymbol_where_filelinenum (s);
7505 ffesymbol sf = ffesymbol_sfdummyparent (s);
7507 input_filename = ffesymbol_where_filename (sf);
7508 lineno = ffesymbol_where_filelinenum (sf);
7511 bt = ffeinfo_basictype (ffebld_info (s));
7512 kt = ffeinfo_kindtype (ffebld_info (s));
7518 switch (ffesymbol_kind (s))
7520 case FFEINFO_kindNONE:
7521 switch (ffesymbol_where (s))
7523 case FFEINFO_whereDUMMY: /* Subroutine or function. */
7524 assert (ffecom_transform_only_dummies_);
7526 /* Before 0.4, this could be ENTITY/DUMMY, but see
7527 ffestu_sym_end_transition -- no longer true (in particular, if
7528 it could be an ENTITY, it _will_ be made one, so that
7529 possibility won't come through here). So we never make length
7530 arg for CHARACTER type. */
7532 t = build_decl (PARM_DECL,
7533 ffecom_get_identifier_ (ffesymbol_text (s)),
7534 ffecom_tree_ptr_to_subr_type);
7536 DECL_ARTIFICIAL (t) = 1;
7541 case FFEINFO_whereGLOBAL: /* Subroutine or function. */
7542 assert (!ffecom_transform_only_dummies_);
7544 if (((g = ffesymbol_global (s)) != NULL)
7545 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
7546 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
7547 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
7548 && (ffeglobal_hook (g) != NULL_TREE)
7549 && ffe_is_globals ())
7551 t = ffeglobal_hook (g);
7555 t = build_decl (FUNCTION_DECL,
7556 ffecom_get_external_identifier_ (s),
7557 ffecom_tree_subr_type); /* Assume subr. */
7558 DECL_EXTERNAL (t) = 1;
7559 TREE_PUBLIC (t) = 1;
7561 t = start_decl (t, FALSE);
7562 finish_decl (t, NULL_TREE, FALSE);
7565 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
7566 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
7567 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
7568 ffeglobal_set_hook (g, t);
7570 ffecom_save_tree_forever (t);
7575 assert ("NONE where unexpected" == NULL);
7577 case FFEINFO_whereANY:
7582 case FFEINFO_kindENTITY:
7583 switch (ffeinfo_where (ffesymbol_info (s)))
7586 case FFEINFO_whereCONSTANT:
7587 /* ~~Debugging info needed? */
7588 assert (!ffecom_transform_only_dummies_);
7589 t = error_mark_node; /* Shouldn't ever see this in expr. */
7592 case FFEINFO_whereLOCAL:
7593 assert (!ffecom_transform_only_dummies_);
7596 ffestorag st = ffesymbol_storage (s);
7600 && (ffestorag_size (st) == 0))
7602 t = error_mark_node;
7606 type = ffecom_type_localvar_ (s, bt, kt);
7608 if (type == error_mark_node)
7610 t = error_mark_node;
7615 && (ffestorag_parent (st) != NULL))
7616 { /* Child of EQUIVALENCE parent. */
7619 ffetargetOffset offset;
7621 est = ffestorag_parent (st);
7622 ffecom_transform_equiv_ (est);
7624 et = ffestorag_hook (est);
7625 assert (et != NULL_TREE);
7627 if (! TREE_STATIC (et))
7628 put_var_into_stack (et);
7630 offset = ffestorag_modulo (est)
7631 + ffestorag_offset (ffesymbol_storage (s))
7632 - ffestorag_offset (est);
7634 ffecom_debug_kludge_ (et, "EQUIVALENCE", s, type, offset);
7636 /* (t_type *) (((char *) &et) + offset) */
7638 t = convert (string_type_node, /* (char *) */
7639 ffecom_1 (ADDR_EXPR,
7640 build_pointer_type (TREE_TYPE (et)),
7642 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
7644 build_int_2 (offset, 0));
7645 t = convert (build_pointer_type (type),
7647 TREE_CONSTANT (t) = staticp (et);
7654 bool init = ffesymbol_is_init (s);
7656 t = build_decl (VAR_DECL,
7657 ffecom_get_identifier_ (ffesymbol_text (s)),
7661 || ffesymbol_namelisted (s)
7662 #ifdef FFECOM_sizeMAXSTACKITEM
7664 && (ffestorag_size (st) > FFECOM_sizeMAXSTACKITEM))
7666 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
7667 && (ffecom_primary_entry_kind_
7668 != FFEINFO_kindBLOCKDATA)
7669 && (ffesymbol_is_save (s) || ffe_is_saveall ())))
7670 TREE_STATIC (t) = !ffesymbol_attr (s, FFESYMBOL_attrADJUSTABLE);
7672 TREE_STATIC (t) = 0; /* No need to make static. */
7674 if (init || ffe_is_init_local_zero ())
7675 DECL_INITIAL (t) = error_mark_node;
7677 /* Keep -Wunused from complaining about var if it
7678 is used as sfunc arg or DATA implied-DO. */
7679 if (ffesymbol_attrs (s) & FFESYMBOL_attrsSFARG)
7680 DECL_IN_SYSTEM_HEADER (t) = 1;
7682 t = start_decl (t, FALSE);
7686 if (ffesymbol_init (s) != NULL)
7687 initexpr = ffecom_expr (ffesymbol_init (s));
7689 initexpr = ffecom_init_zero_ (t);
7691 else if (ffe_is_init_local_zero ())
7692 initexpr = ffecom_init_zero_ (t);
7694 initexpr = NULL_TREE; /* Not ref'd if !init. */
7696 finish_decl (t, initexpr, FALSE);
7698 if (st != NULL && DECL_SIZE (t) != error_mark_node)
7700 assert (TREE_CODE (DECL_SIZE_UNIT (t)) == INTEGER_CST);
7701 assert (0 == compare_tree_int (DECL_SIZE_UNIT (t),
7702 ffestorag_size (st)));
7708 case FFEINFO_whereRESULT:
7709 assert (!ffecom_transform_only_dummies_);
7711 if (bt == FFEINFO_basictypeCHARACTER)
7712 { /* Result is already in list of dummies, use
7714 t = ffecom_func_result_;
7715 tlen = ffecom_func_length_;
7719 if ((ffecom_num_entrypoints_ == 0)
7720 && (bt == FFEINFO_basictypeCOMPLEX)
7721 && (ffesymbol_is_f2c (ffecom_primary_entry_)))
7722 { /* Result is already in list of dummies, use
7724 t = ffecom_func_result_;
7728 if (ffecom_func_result_ != NULL_TREE)
7730 t = ffecom_func_result_;
7733 if ((ffecom_num_entrypoints_ != 0)
7734 && (ffecom_master_bt_ == FFEINFO_basictypeNONE))
7736 assert (ffecom_multi_retval_ != NULL_TREE);
7737 t = ffecom_1 (INDIRECT_REF, ffecom_multi_type_node_,
7738 ffecom_multi_retval_);
7739 t = ffecom_2 (COMPONENT_REF, ffecom_tree_type[bt][kt],
7740 t, ffecom_multi_fields_[bt][kt]);
7745 t = build_decl (VAR_DECL,
7746 ffecom_get_identifier_ (ffesymbol_text (s)),
7747 ffecom_tree_type[bt][kt]);
7748 TREE_STATIC (t) = 0; /* Put result on stack. */
7749 t = start_decl (t, FALSE);
7750 finish_decl (t, NULL_TREE, FALSE);
7752 ffecom_func_result_ = t;
7756 case FFEINFO_whereDUMMY:
7764 bool adjustable = FALSE; /* Conditionally adjustable? */
7766 type = ffecom_tree_type[bt][kt];
7767 if (ffesymbol_sfdummyparent (s) != NULL)
7769 if (current_function_decl == ffecom_outer_function_decl_)
7770 { /* Exec transition before sfunc
7771 context; get it later. */
7774 t = ffecom_get_identifier_ (ffesymbol_text
7775 (ffesymbol_sfdummyparent (s)));
7778 t = ffecom_get_identifier_ (ffesymbol_text (s));
7780 assert (ffecom_transform_only_dummies_);
7782 old_sizes = get_pending_sizes ();
7783 put_pending_sizes (old_sizes);
7785 if (bt == FFEINFO_basictypeCHARACTER)
7786 tlen = ffecom_char_enhance_arg_ (&type, s);
7787 type = ffecom_check_size_overflow_ (s, type, TRUE);
7789 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
7791 if (type == error_mark_node)
7794 dim = ffebld_head (dl);
7795 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
7796 if ((ffebld_left (dim) == NULL) || ffecom_doing_entry_)
7797 low = ffecom_integer_one_node;
7799 low = ffecom_expr (ffebld_left (dim));
7800 assert (ffebld_right (dim) != NULL);
7801 if ((ffebld_op (ffebld_right (dim)) == FFEBLD_opSTAR)
7802 || ffecom_doing_entry_)
7804 /* Used to just do high=low. But for ffecom_tree_
7805 canonize_ref_, it probably is important to correctly
7806 assess the size. E.g. given COMPLEX C(*),CFUNC and
7807 C(2)=CFUNC(C), overlap can happen, while it can't
7808 for, say, C(1)=CFUNC(C(2)). */
7809 /* Even more recently used to set to INT_MAX, but that
7810 broke when some overflow checking went into the back
7811 end. Now we just leave the upper bound unspecified. */
7815 high = ffecom_expr (ffebld_right (dim));
7817 /* Determine whether array is conditionally adjustable,
7818 to decide whether back-end magic is needed.
7820 Normally the front end uses the back-end function
7821 variable_size to wrap SAVE_EXPR's around expressions
7822 affecting the size/shape of an array so that the
7823 size/shape info doesn't change during execution
7824 of the compiled code even though variables and
7825 functions referenced in those expressions might.
7827 variable_size also makes sure those saved expressions
7828 get evaluated immediately upon entry to the
7829 compiled procedure -- the front end normally doesn't
7830 have to worry about that.
7832 However, there is a problem with this that affects
7833 g77's implementation of entry points, and that is
7834 that it is _not_ true that each invocation of the
7835 compiled procedure is permitted to evaluate
7836 array size/shape info -- because it is possible
7837 that, for some invocations, that info is invalid (in
7838 which case it is "promised" -- i.e. a violation of
7839 the Fortran standard -- that the compiled code
7840 won't reference the array or its size/shape
7841 during that particular invocation).
7843 To phrase this in C terms, consider this gcc function:
7845 void foo (int *n, float (*a)[*n])
7847 // a is "pointer to array ...", fyi.
7850 Suppose that, for some invocations, it is permitted
7851 for a caller of foo to do this:
7855 Now the _written_ code for foo can take such a call
7856 into account by either testing explicitly for whether
7857 (a == NULL) || (n == NULL) -- presumably it is
7858 not permitted to reference *a in various fashions
7859 if (n == NULL) I suppose -- or it can avoid it by
7860 looking at other info (other arguments, static/global
7863 However, this won't work in gcc 2.5.8 because it'll
7864 automatically emit the code to save the "*n"
7865 expression, which'll yield a NULL dereference for
7866 the "foo (NULL, NULL)" call, something the code
7867 for foo cannot prevent.
7869 g77 definitely needs to avoid executing such
7870 code anytime the pointer to the adjustable array
7871 is NULL, because even if its bounds expressions
7872 don't have any references to possible "absent"
7873 variables like "*n" -- say all variable references
7874 are to COMMON variables, i.e. global (though in C,
7875 local static could actually make sense) -- the
7876 expressions could yield other run-time problems
7877 for allowably "dead" values in those variables.
7879 For example, let's consider a more complicated
7885 void foo (float (*a)[i/j])
7890 The above is (essentially) quite valid for Fortran
7891 but, again, for a call like "foo (NULL);", it is
7892 permitted for i and j to be undefined when the
7893 call is made. If j happened to be zero, for
7894 example, emitting the code to evaluate "i/j"
7895 could result in a run-time error.
7897 Offhand, though I don't have my F77 or F90
7898 standards handy, it might even be valid for a
7899 bounds expression to contain a function reference,
7900 in which case I doubt it is permitted for an
7901 implementation to invoke that function in the
7902 Fortran case involved here (invocation of an
7903 alternate ENTRY point that doesn't have the adjustable
7904 array as one of its arguments).
7906 So, the code that the compiler would normally emit
7907 to preevaluate the size/shape info for an
7908 adjustable array _must not_ be executed at run time
7909 in certain cases. Specifically, for Fortran,
7910 the case is when the pointer to the adjustable
7911 array == NULL. (For gnu-ish C, it might be nice
7912 for the source code itself to specify an expression
7913 that, if TRUE, inhibits execution of the code. Or
7914 reverse the sense for elegance.)
7916 (Note that g77 could use a different test than NULL,
7917 actually, since it happens to always pass an
7918 integer to the called function that specifies which
7919 entry point is being invoked. Hmm, this might
7920 solve the next problem.)
7922 One way a user could, I suppose, write "foo" so
7923 it works is to insert COND_EXPR's for the
7924 size/shape info so the dangerous stuff isn't
7925 actually done, as in:
7927 void foo (int *n, float (*a)[(a == NULL) ? 0 : *n])
7932 The next problem is that the front end needs to
7933 be able to tell the back end about the array's
7934 decl _before_ it tells it about the conditional
7935 expression to inhibit evaluation of size/shape info,
7938 To solve this, the front end needs to be able
7939 to give the back end the expression to inhibit
7940 generation of the preevaluation code _after_
7941 it makes the decl for the adjustable array.
7943 Until then, the above example using the COND_EXPR
7944 doesn't pass muster with gcc because the "(a == NULL)"
7945 part has a reference to "a", which is still
7946 undefined at that point.
7948 g77 will therefore use a different mechanism in the
7952 && ((TREE_CODE (low) != INTEGER_CST)
7953 || (high && TREE_CODE (high) != INTEGER_CST)))
7956 #if 0 /* Old approach -- see below. */
7957 if (TREE_CODE (low) != INTEGER_CST)
7958 low = ffecom_3 (COND_EXPR, integer_type_node,
7959 ffecom_adjarray_passed_ (s),
7961 ffecom_integer_zero_node);
7963 if (high && TREE_CODE (high) != INTEGER_CST)
7964 high = ffecom_3 (COND_EXPR, integer_type_node,
7965 ffecom_adjarray_passed_ (s),
7967 ffecom_integer_zero_node);
7970 /* ~~~gcc/stor-layout.c (layout_type) should do this,
7971 probably. Fixes 950302-1.f. */
7973 if (TREE_CODE (low) != INTEGER_CST)
7974 low = variable_size (low);
7976 /* ~~~Similarly, this fixes dumb0.f. The C front end
7977 does this, which is why dumb0.c would work. */
7979 if (high && TREE_CODE (high) != INTEGER_CST)
7980 high = variable_size (high);
7985 build_range_type (ffecom_integer_type_node,
7987 type = ffecom_check_size_overflow_ (s, type, TRUE);
7990 if (type == error_mark_node)
7992 t = error_mark_node;
7996 if ((ffesymbol_sfdummyparent (s) == NULL)
7997 || (ffesymbol_basictype (s) == FFEINFO_basictypeCHARACTER))
7999 type = build_pointer_type (type);
8003 t = build_decl (PARM_DECL, t, type);
8005 DECL_ARTIFICIAL (t) = 1;
8008 /* If this arg is present in every entry point's list of
8009 dummy args, then we're done. */
8011 if (ffesymbol_numentries (s)
8012 == (ffecom_num_entrypoints_ + 1))
8017 /* If variable_size in stor-layout has been called during
8018 the above, then get_pending_sizes should have the
8019 yet-to-be-evaluated saved expressions pending.
8020 Make the whole lot of them get emitted, conditionally
8021 on whether the array decl ("t" above) is not NULL. */
8024 tree sizes = get_pending_sizes ();
8029 tem = TREE_CHAIN (tem))
8031 tree temv = TREE_VALUE (tem);
8037 = ffecom_2 (COMPOUND_EXPR,
8046 = ffecom_3 (COND_EXPR,
8053 convert (TREE_TYPE (sizes),
8054 integer_zero_node));
8055 sizes = ffecom_save_tree (sizes);
8058 = tree_cons (NULL_TREE, sizes, tem);
8062 put_pending_sizes (sizes);
8068 && (ffesymbol_numentries (s)
8069 != ffecom_num_entrypoints_ + 1))
8071 = ffecom_2 (NE_EXPR, integer_type_node,
8077 && (ffesymbol_numentries (s)
8078 != ffecom_num_entrypoints_ + 1))
8080 ffebad_start (FFEBAD_MISSING_ADJARRAY_UNSUPPORTED);
8081 ffebad_here (0, ffesymbol_where_line (s),
8082 ffesymbol_where_column (s));
8083 ffebad_string (ffesymbol_text (s));
8092 case FFEINFO_whereCOMMON:
8097 ffestorag st = ffesymbol_storage (s);
8100 cs = ffesymbol_common (s); /* The COMMON area itself. */
8101 if (st != NULL) /* Else not laid out. */
8103 ffecom_transform_common_ (cs);
8104 st = ffesymbol_storage (s);
8107 type = ffecom_type_localvar_ (s, bt, kt);
8109 cg = ffesymbol_global (cs); /* The global COMMON info. */
8111 || (ffeglobal_type (cg) != FFEGLOBAL_typeCOMMON))
8114 ct = ffeglobal_hook (cg); /* The common area's tree. */
8116 if ((ct == NULL_TREE)
8118 || (type == error_mark_node))
8119 t = error_mark_node;
8122 ffetargetOffset offset;
8125 cst = ffestorag_parent (st);
8126 assert (cst == ffesymbol_storage (cs));
8128 offset = ffestorag_modulo (cst)
8129 + ffestorag_offset (st)
8130 - ffestorag_offset (cst);
8132 ffecom_debug_kludge_ (ct, "COMMON", s, type, offset);
8134 /* (t_type *) (((char *) &ct) + offset) */
8136 t = convert (string_type_node, /* (char *) */
8137 ffecom_1 (ADDR_EXPR,
8138 build_pointer_type (TREE_TYPE (ct)),
8140 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
8142 build_int_2 (offset, 0));
8143 t = convert (build_pointer_type (type),
8145 TREE_CONSTANT (t) = 1;
8152 case FFEINFO_whereIMMEDIATE:
8153 case FFEINFO_whereGLOBAL:
8154 case FFEINFO_whereFLEETING:
8155 case FFEINFO_whereFLEETING_CADDR:
8156 case FFEINFO_whereFLEETING_IADDR:
8157 case FFEINFO_whereINTRINSIC:
8158 case FFEINFO_whereCONSTANT_SUBOBJECT:
8160 assert ("ENTITY where unheard of" == NULL);
8162 case FFEINFO_whereANY:
8163 t = error_mark_node;
8168 case FFEINFO_kindFUNCTION:
8169 switch (ffeinfo_where (ffesymbol_info (s)))
8171 case FFEINFO_whereLOCAL: /* Me. */
8172 assert (!ffecom_transform_only_dummies_);
8173 t = current_function_decl;
8176 case FFEINFO_whereGLOBAL:
8177 assert (!ffecom_transform_only_dummies_);
8179 if (((g = ffesymbol_global (s)) != NULL)
8180 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8181 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8182 && (ffeglobal_hook (g) != NULL_TREE)
8183 && ffe_is_globals ())
8185 t = ffeglobal_hook (g);
8189 if (ffesymbol_is_f2c (s)
8190 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
8191 t = ffecom_tree_fun_type[bt][kt];
8193 t = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
8195 t = build_decl (FUNCTION_DECL,
8196 ffecom_get_external_identifier_ (s),
8198 DECL_EXTERNAL (t) = 1;
8199 TREE_PUBLIC (t) = 1;
8201 t = start_decl (t, FALSE);
8202 finish_decl (t, NULL_TREE, FALSE);
8205 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8206 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8207 ffeglobal_set_hook (g, t);
8209 ffecom_save_tree_forever (t);
8213 case FFEINFO_whereDUMMY:
8214 assert (ffecom_transform_only_dummies_);
8216 if (ffesymbol_is_f2c (s)
8217 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
8218 t = ffecom_tree_ptr_to_fun_type[bt][kt];
8220 t = build_pointer_type
8221 (build_function_type (ffecom_tree_type[bt][kt], NULL_TREE));
8223 t = build_decl (PARM_DECL,
8224 ffecom_get_identifier_ (ffesymbol_text (s)),
8227 DECL_ARTIFICIAL (t) = 1;
8232 case FFEINFO_whereCONSTANT: /* Statement function. */
8233 assert (!ffecom_transform_only_dummies_);
8234 t = ffecom_gen_sfuncdef_ (s, bt, kt);
8237 case FFEINFO_whereINTRINSIC:
8238 assert (!ffecom_transform_only_dummies_);
8239 break; /* Let actual references generate their
8243 assert ("FUNCTION where unheard of" == NULL);
8245 case FFEINFO_whereANY:
8246 t = error_mark_node;
8251 case FFEINFO_kindSUBROUTINE:
8252 switch (ffeinfo_where (ffesymbol_info (s)))
8254 case FFEINFO_whereLOCAL: /* Me. */
8255 assert (!ffecom_transform_only_dummies_);
8256 t = current_function_decl;
8259 case FFEINFO_whereGLOBAL:
8260 assert (!ffecom_transform_only_dummies_);
8262 if (((g = ffesymbol_global (s)) != NULL)
8263 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8264 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8265 && (ffeglobal_hook (g) != NULL_TREE)
8266 && ffe_is_globals ())
8268 t = ffeglobal_hook (g);
8272 t = build_decl (FUNCTION_DECL,
8273 ffecom_get_external_identifier_ (s),
8274 ffecom_tree_subr_type);
8275 DECL_EXTERNAL (t) = 1;
8276 TREE_PUBLIC (t) = 1;
8278 t = start_decl (t, FALSE);
8279 finish_decl (t, NULL_TREE, FALSE);
8282 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8283 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8284 ffeglobal_set_hook (g, t);
8286 ffecom_save_tree_forever (t);
8290 case FFEINFO_whereDUMMY:
8291 assert (ffecom_transform_only_dummies_);
8293 t = build_decl (PARM_DECL,
8294 ffecom_get_identifier_ (ffesymbol_text (s)),
8295 ffecom_tree_ptr_to_subr_type);
8297 DECL_ARTIFICIAL (t) = 1;
8302 case FFEINFO_whereINTRINSIC:
8303 assert (!ffecom_transform_only_dummies_);
8304 break; /* Let actual references generate their
8308 assert ("SUBROUTINE where unheard of" == NULL);
8310 case FFEINFO_whereANY:
8311 t = error_mark_node;
8316 case FFEINFO_kindPROGRAM:
8317 switch (ffeinfo_where (ffesymbol_info (s)))
8319 case FFEINFO_whereLOCAL: /* Me. */
8320 assert (!ffecom_transform_only_dummies_);
8321 t = current_function_decl;
8324 case FFEINFO_whereCOMMON:
8325 case FFEINFO_whereDUMMY:
8326 case FFEINFO_whereGLOBAL:
8327 case FFEINFO_whereRESULT:
8328 case FFEINFO_whereFLEETING:
8329 case FFEINFO_whereFLEETING_CADDR:
8330 case FFEINFO_whereFLEETING_IADDR:
8331 case FFEINFO_whereIMMEDIATE:
8332 case FFEINFO_whereINTRINSIC:
8333 case FFEINFO_whereCONSTANT:
8334 case FFEINFO_whereCONSTANT_SUBOBJECT:
8336 assert ("PROGRAM where unheard of" == NULL);
8338 case FFEINFO_whereANY:
8339 t = error_mark_node;
8344 case FFEINFO_kindBLOCKDATA:
8345 switch (ffeinfo_where (ffesymbol_info (s)))
8347 case FFEINFO_whereLOCAL: /* Me. */
8348 assert (!ffecom_transform_only_dummies_);
8349 t = current_function_decl;
8352 case FFEINFO_whereGLOBAL:
8353 assert (!ffecom_transform_only_dummies_);
8355 t = build_decl (FUNCTION_DECL,
8356 ffecom_get_external_identifier_ (s),
8357 ffecom_tree_blockdata_type);
8358 DECL_EXTERNAL (t) = 1;
8359 TREE_PUBLIC (t) = 1;
8361 t = start_decl (t, FALSE);
8362 finish_decl (t, NULL_TREE, FALSE);
8364 ffecom_save_tree_forever (t);
8368 case FFEINFO_whereCOMMON:
8369 case FFEINFO_whereDUMMY:
8370 case FFEINFO_whereRESULT:
8371 case FFEINFO_whereFLEETING:
8372 case FFEINFO_whereFLEETING_CADDR:
8373 case FFEINFO_whereFLEETING_IADDR:
8374 case FFEINFO_whereIMMEDIATE:
8375 case FFEINFO_whereINTRINSIC:
8376 case FFEINFO_whereCONSTANT:
8377 case FFEINFO_whereCONSTANT_SUBOBJECT:
8379 assert ("BLOCKDATA where unheard of" == NULL);
8381 case FFEINFO_whereANY:
8382 t = error_mark_node;
8387 case FFEINFO_kindCOMMON:
8388 switch (ffeinfo_where (ffesymbol_info (s)))
8390 case FFEINFO_whereLOCAL:
8391 assert (!ffecom_transform_only_dummies_);
8392 ffecom_transform_common_ (s);
8395 case FFEINFO_whereNONE:
8396 case FFEINFO_whereCOMMON:
8397 case FFEINFO_whereDUMMY:
8398 case FFEINFO_whereGLOBAL:
8399 case FFEINFO_whereRESULT:
8400 case FFEINFO_whereFLEETING:
8401 case FFEINFO_whereFLEETING_CADDR:
8402 case FFEINFO_whereFLEETING_IADDR:
8403 case FFEINFO_whereIMMEDIATE:
8404 case FFEINFO_whereINTRINSIC:
8405 case FFEINFO_whereCONSTANT:
8406 case FFEINFO_whereCONSTANT_SUBOBJECT:
8408 assert ("COMMON where unheard of" == NULL);
8410 case FFEINFO_whereANY:
8411 t = error_mark_node;
8416 case FFEINFO_kindCONSTRUCT:
8417 switch (ffeinfo_where (ffesymbol_info (s)))
8419 case FFEINFO_whereLOCAL:
8420 assert (!ffecom_transform_only_dummies_);
8423 case FFEINFO_whereNONE:
8424 case FFEINFO_whereCOMMON:
8425 case FFEINFO_whereDUMMY:
8426 case FFEINFO_whereGLOBAL:
8427 case FFEINFO_whereRESULT:
8428 case FFEINFO_whereFLEETING:
8429 case FFEINFO_whereFLEETING_CADDR:
8430 case FFEINFO_whereFLEETING_IADDR:
8431 case FFEINFO_whereIMMEDIATE:
8432 case FFEINFO_whereINTRINSIC:
8433 case FFEINFO_whereCONSTANT:
8434 case FFEINFO_whereCONSTANT_SUBOBJECT:
8436 assert ("CONSTRUCT where unheard of" == NULL);
8438 case FFEINFO_whereANY:
8439 t = error_mark_node;
8444 case FFEINFO_kindNAMELIST:
8445 switch (ffeinfo_where (ffesymbol_info (s)))
8447 case FFEINFO_whereLOCAL:
8448 assert (!ffecom_transform_only_dummies_);
8449 t = ffecom_transform_namelist_ (s);
8452 case FFEINFO_whereNONE:
8453 case FFEINFO_whereCOMMON:
8454 case FFEINFO_whereDUMMY:
8455 case FFEINFO_whereGLOBAL:
8456 case FFEINFO_whereRESULT:
8457 case FFEINFO_whereFLEETING:
8458 case FFEINFO_whereFLEETING_CADDR:
8459 case FFEINFO_whereFLEETING_IADDR:
8460 case FFEINFO_whereIMMEDIATE:
8461 case FFEINFO_whereINTRINSIC:
8462 case FFEINFO_whereCONSTANT:
8463 case FFEINFO_whereCONSTANT_SUBOBJECT:
8465 assert ("NAMELIST where unheard of" == NULL);
8467 case FFEINFO_whereANY:
8468 t = error_mark_node;
8474 assert ("kind unheard of" == NULL);
8476 case FFEINFO_kindANY:
8477 t = error_mark_node;
8481 ffesymbol_hook (s).decl_tree = t;
8482 ffesymbol_hook (s).length_tree = tlen;
8483 ffesymbol_hook (s).addr = addr;
8485 lineno = old_lineno;
8486 input_filename = old_input_filename;
8492 /* Transform into ASSIGNable symbol.
8494 Symbol has already been transformed, but for whatever reason, the
8495 resulting decl_tree has been deemed not usable for an ASSIGN target.
8496 (E.g. it isn't wide enough to hold a pointer.) So, here we invent
8497 another local symbol of type void * and stuff that in the assign_tree
8498 argument. The F77/F90 standards allow this implementation. */
8500 #if FFECOM_targetCURRENT == FFECOM_targetGCC
8502 ffecom_sym_transform_assign_ (ffesymbol s)
8504 tree t; /* Transformed thingy. */
8505 int old_lineno = lineno;
8506 const char *old_input_filename = input_filename;
8508 if (ffesymbol_sfdummyparent (s) == NULL)
8510 input_filename = ffesymbol_where_filename (s);
8511 lineno = ffesymbol_where_filelinenum (s);
8515 ffesymbol sf = ffesymbol_sfdummyparent (s);
8517 input_filename = ffesymbol_where_filename (sf);
8518 lineno = ffesymbol_where_filelinenum (sf);
8521 assert (!ffecom_transform_only_dummies_);
8523 t = build_decl (VAR_DECL,
8524 ffecom_get_invented_identifier ("__g77_ASSIGN_%s",
8525 ffesymbol_text (s)),
8526 TREE_TYPE (null_pointer_node));
8528 switch (ffesymbol_where (s))
8530 case FFEINFO_whereLOCAL:
8531 /* Unlike for regular vars, SAVE status is easy to determine for
8532 ASSIGNed vars, since there's no initialization, there's no
8533 effective storage association (so "SAVE J" does not apply to
8534 K even given "EQUIVALENCE (J,K)"), there's no size issue
8535 to worry about, etc. */
8536 if ((ffesymbol_is_save (s) || ffe_is_saveall ())
8537 && (ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
8538 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA))
8539 TREE_STATIC (t) = 1; /* SAVEd in proc, make static. */
8541 TREE_STATIC (t) = 0; /* No need to make static. */
8544 case FFEINFO_whereCOMMON:
8545 TREE_STATIC (t) = 1; /* Assume COMMONs always SAVEd. */
8548 case FFEINFO_whereDUMMY:
8549 /* Note that twinning a DUMMY means the caller won't see
8550 the ASSIGNed value. But both F77 and F90 allow implementations
8551 to do this, i.e. disallow Fortran code that would try and
8552 take advantage of actually putting a label into a variable
8553 via a dummy argument (or any other storage association, for
8555 TREE_STATIC (t) = 0;
8559 TREE_STATIC (t) = 0;
8563 t = start_decl (t, FALSE);
8564 finish_decl (t, NULL_TREE, FALSE);
8566 ffesymbol_hook (s).assign_tree = t;
8568 lineno = old_lineno;
8569 input_filename = old_input_filename;
8575 /* Implement COMMON area in back end.
8577 Because COMMON-based variables can be referenced in the dimension
8578 expressions of dummy (adjustable) arrays, and because dummies
8579 (in the gcc back end) need to be put in the outer binding level
8580 of a function (which has two binding levels, the outer holding
8581 the dummies and the inner holding the other vars), special care
8582 must be taken to handle COMMON areas.
8584 The current strategy is basically to always tell the back end about
8585 the COMMON area as a top-level external reference to just a block
8586 of storage of the master type of that area (e.g. integer, real,
8587 character, whatever -- not a structure). As a distinct action,
8588 if initial values are provided, tell the back end about the area
8589 as a top-level non-external (initialized) area and remember not to
8590 allow further initialization or expansion of the area. Meanwhile,
8591 if no initialization happens at all, tell the back end about
8592 the largest size we've seen declared so the space does get reserved.
8593 (This function doesn't handle all that stuff, but it does some
8594 of the important things.)
8596 Meanwhile, for COMMON variables themselves, just keep creating
8597 references like *((float *) (&common_area + offset)) each time
8598 we reference the variable. In other words, don't make a VAR_DECL
8599 or any kind of component reference (like we used to do before 0.4),
8600 though we might do that as well just for debugging purposes (and
8601 stuff the rtl with the appropriate offset expression). */
8603 #if FFECOM_targetCURRENT == FFECOM_targetGCC
8605 ffecom_transform_common_ (ffesymbol s)
8607 ffestorag st = ffesymbol_storage (s);
8608 ffeglobal g = ffesymbol_global (s);
8613 bool is_init = ffestorag_is_init (st);
8615 assert (st != NULL);
8618 || (ffeglobal_type (g) != FFEGLOBAL_typeCOMMON))
8621 /* First update the size of the area in global terms. */
8623 ffeglobal_size_common (s, ffestorag_size (st));
8625 if (!ffeglobal_common_init (g))
8626 is_init = FALSE; /* No explicit init, don't let erroneous joins init. */
8628 cbt = ffeglobal_hook (g);
8630 /* If we already have declared this common block for a previous program
8631 unit, and either we already initialized it or we don't have new
8632 initialization for it, just return what we have without changing it. */
8634 if ((cbt != NULL_TREE)
8636 || !DECL_EXTERNAL (cbt)))
8638 if (st->hook == NULL) ffestorag_set_hook (st, cbt);
8642 /* Process inits. */
8646 if (ffestorag_init (st) != NULL)
8650 /* Set the padding for the expression, so ffecom_expr
8651 knows to insert that many zeros. */
8652 switch (ffebld_op (sexp = ffestorag_init (st)))
8654 case FFEBLD_opCONTER:
8655 ffebld_conter_set_pad (sexp, ffestorag_modulo (st));
8658 case FFEBLD_opARRTER:
8659 ffebld_arrter_set_pad (sexp, ffestorag_modulo (st));
8662 case FFEBLD_opACCTER:
8663 ffebld_accter_set_pad (sexp, ffestorag_modulo (st));
8667 assert ("bad op for cmn init (pad)" == NULL);
8671 init = ffecom_expr (sexp);
8672 if (init == error_mark_node)
8673 { /* Hopefully the back end complained! */
8675 if (cbt != NULL_TREE)
8680 init = error_mark_node;
8685 /* cbtype must be permanently allocated! */
8687 /* Allocate the MAX of the areas so far, seen filewide. */
8688 high = build_int_2 ((ffeglobal_common_size (g)
8689 + ffeglobal_common_pad (g)) - 1, 0);
8690 TREE_TYPE (high) = ffecom_integer_type_node;
8693 cbtype = build_array_type (char_type_node,
8694 build_range_type (integer_type_node,
8698 cbtype = build_array_type (char_type_node, NULL_TREE);
8700 if (cbt == NULL_TREE)
8703 = build_decl (VAR_DECL,
8704 ffecom_get_external_identifier_ (s),
8706 TREE_STATIC (cbt) = 1;
8707 TREE_PUBLIC (cbt) = 1;
8712 TREE_TYPE (cbt) = cbtype;
8714 DECL_EXTERNAL (cbt) = init ? 0 : 1;
8715 DECL_INITIAL (cbt) = init ? error_mark_node : NULL_TREE;
8717 cbt = start_decl (cbt, TRUE);
8718 if (ffeglobal_hook (g) != NULL)
8719 assert (cbt == ffeglobal_hook (g));
8721 assert (!init || !DECL_EXTERNAL (cbt));
8723 /* Make sure that any type can live in COMMON and be referenced
8724 without getting a bus error. We could pick the most restrictive
8725 alignment of all entities actually placed in the COMMON, but
8726 this seems easy enough. */
8728 DECL_ALIGN (cbt) = BIGGEST_ALIGNMENT;
8729 DECL_USER_ALIGN (cbt) = 0;
8731 if (is_init && (ffestorag_init (st) == NULL))
8732 init = ffecom_init_zero_ (cbt);
8734 finish_decl (cbt, init, TRUE);
8737 ffestorag_set_init (st, ffebld_new_any ());
8741 assert (DECL_SIZE_UNIT (cbt) != NULL_TREE);
8742 assert (TREE_CODE (DECL_SIZE_UNIT (cbt)) == INTEGER_CST);
8743 assert (0 == compare_tree_int (DECL_SIZE_UNIT (cbt),
8744 (ffeglobal_common_size (g)
8745 + ffeglobal_common_pad (g))));
8748 ffeglobal_set_hook (g, cbt);
8750 ffestorag_set_hook (st, cbt);
8752 ffecom_save_tree_forever (cbt);
8756 /* Make master area for local EQUIVALENCE. */
8758 #if FFECOM_targetCURRENT == FFECOM_targetGCC
8760 ffecom_transform_equiv_ (ffestorag eqst)
8766 bool is_init = ffestorag_is_init (eqst);
8768 assert (eqst != NULL);
8770 eqt = ffestorag_hook (eqst);
8772 if (eqt != NULL_TREE)
8775 /* Process inits. */
8779 if (ffestorag_init (eqst) != NULL)
8783 /* Set the padding for the expression, so ffecom_expr
8784 knows to insert that many zeros. */
8785 switch (ffebld_op (sexp = ffestorag_init (eqst)))
8787 case FFEBLD_opCONTER:
8788 ffebld_conter_set_pad (sexp, ffestorag_modulo (eqst));
8791 case FFEBLD_opARRTER:
8792 ffebld_arrter_set_pad (sexp, ffestorag_modulo (eqst));
8795 case FFEBLD_opACCTER:
8796 ffebld_accter_set_pad (sexp, ffestorag_modulo (eqst));
8800 assert ("bad op for eqv init (pad)" == NULL);
8804 init = ffecom_expr (sexp);
8805 if (init == error_mark_node)
8806 init = NULL_TREE; /* Hopefully the back end complained! */
8809 init = error_mark_node;
8811 else if (ffe_is_init_local_zero ())
8812 init = error_mark_node;
8816 ffecom_member_namelisted_ = FALSE;
8817 ffestorag_drive (ffestorag_list_equivs (eqst),
8818 &ffecom_member_phase1_,
8821 high = build_int_2 ((ffestorag_size (eqst)
8822 + ffestorag_modulo (eqst)) - 1, 0);
8823 TREE_TYPE (high) = ffecom_integer_type_node;
8825 eqtype = build_array_type (char_type_node,
8826 build_range_type (ffecom_integer_type_node,
8827 ffecom_integer_zero_node,
8830 eqt = build_decl (VAR_DECL,
8831 ffecom_get_invented_identifier ("__g77_equiv_%s",
8833 (ffestorag_symbol (eqst))),
8835 DECL_EXTERNAL (eqt) = 0;
8837 || ffecom_member_namelisted_
8838 #ifdef FFECOM_sizeMAXSTACKITEM
8839 || (ffestorag_size (eqst) > FFECOM_sizeMAXSTACKITEM)
8841 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
8842 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
8843 && (ffestorag_is_save (eqst) || ffe_is_saveall ())))
8844 TREE_STATIC (eqt) = 1;
8846 TREE_STATIC (eqt) = 0;
8847 TREE_PUBLIC (eqt) = 0;
8848 TREE_ADDRESSABLE (eqt) = 1; /* Ensure non-register allocation */
8849 DECL_CONTEXT (eqt) = current_function_decl;
8851 DECL_INITIAL (eqt) = error_mark_node;
8853 DECL_INITIAL (eqt) = NULL_TREE;
8855 eqt = start_decl (eqt, FALSE);
8857 /* Make sure that any type can live in EQUIVALENCE and be referenced
8858 without getting a bus error. We could pick the most restrictive
8859 alignment of all entities actually placed in the EQUIVALENCE, but
8860 this seems easy enough. */
8862 DECL_ALIGN (eqt) = BIGGEST_ALIGNMENT;
8863 DECL_USER_ALIGN (eqt) = 0;
8865 if ((!is_init && ffe_is_init_local_zero ())
8866 || (is_init && (ffestorag_init (eqst) == NULL)))
8867 init = ffecom_init_zero_ (eqt);
8869 finish_decl (eqt, init, FALSE);
8872 ffestorag_set_init (eqst, ffebld_new_any ());
8875 assert (TREE_CODE (DECL_SIZE_UNIT (eqt)) == INTEGER_CST);
8876 assert (0 == compare_tree_int (DECL_SIZE_UNIT (eqt),
8877 (ffestorag_size (eqst)
8878 + ffestorag_modulo (eqst))));
8881 ffestorag_set_hook (eqst, eqt);
8883 ffestorag_drive (ffestorag_list_equivs (eqst),
8884 &ffecom_member_phase2_,
8889 /* Implement NAMELIST in back end. See f2c/format.c for more info. */
8891 #if FFECOM_targetCURRENT == FFECOM_targetGCC
8893 ffecom_transform_namelist_ (ffesymbol s)
8896 tree nmltype = ffecom_type_namelist_ ();
8904 static int mynumber = 0;
8906 nmlt = build_decl (VAR_DECL,
8907 ffecom_get_invented_identifier ("__g77_namelist_%d",
8910 TREE_STATIC (nmlt) = 1;
8911 DECL_INITIAL (nmlt) = error_mark_node;
8913 nmlt = start_decl (nmlt, FALSE);
8915 /* Process inits. */
8917 i = strlen (ffesymbol_text (s));
8919 high = build_int_2 (i, 0);
8920 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
8922 nameinit = ffecom_build_f2c_string_ (i + 1,
8923 ffesymbol_text (s));
8924 TREE_TYPE (nameinit)
8925 = build_type_variant
8928 build_range_type (ffecom_f2c_ftnlen_type_node,
8929 ffecom_f2c_ftnlen_one_node,
8932 TREE_CONSTANT (nameinit) = 1;
8933 TREE_STATIC (nameinit) = 1;
8934 nameinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (nameinit)),
8937 varsinit = ffecom_vardesc_array_ (s);
8938 varsinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (varsinit)),
8940 TREE_CONSTANT (varsinit) = 1;
8941 TREE_STATIC (varsinit) = 1;
8946 for (i = 0, b = ffesymbol_namelist (s); b != NULL; b = ffebld_trail (b))
8949 nvarsinit = build_int_2 (i, 0);
8950 TREE_TYPE (nvarsinit) = integer_type_node;
8951 TREE_CONSTANT (nvarsinit) = 1;
8952 TREE_STATIC (nvarsinit) = 1;
8954 nmlinits = build_tree_list ((field = TYPE_FIELDS (nmltype)), nameinit);
8955 TREE_CHAIN (nmlinits) = build_tree_list ((field = TREE_CHAIN (field)),
8957 TREE_CHAIN (TREE_CHAIN (nmlinits))
8958 = build_tree_list ((field = TREE_CHAIN (field)), nvarsinit);
8960 nmlinits = build (CONSTRUCTOR, nmltype, NULL_TREE, nmlinits);
8961 TREE_CONSTANT (nmlinits) = 1;
8962 TREE_STATIC (nmlinits) = 1;
8964 finish_decl (nmlt, nmlinits, FALSE);
8966 nmlt = ffecom_1 (ADDR_EXPR, build_pointer_type (nmltype), nmlt);
8973 /* A subroutine of ffecom_tree_canonize_ref_. The incoming tree is
8974 analyzed on the assumption it is calculating a pointer to be
8975 indirected through. It must return the proper decl and offset,
8976 taking into account different units of measurements for offsets. */
8978 #if FFECOM_targetCURRENT == FFECOM_targetGCC
8980 ffecom_tree_canonize_ptr_ (tree *decl, tree *offset,
8983 switch (TREE_CODE (t))
8987 case NON_LVALUE_EXPR:
8988 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
8992 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
8993 if ((*decl == NULL_TREE)
8994 || (*decl == error_mark_node))
8997 if (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST)
8999 /* An offset into COMMON. */
9000 *offset = fold (build (PLUS_EXPR, TREE_TYPE (*offset),
9001 *offset, TREE_OPERAND (t, 1)));
9002 /* Convert offset (presumably in bytes) into canonical units
9003 (presumably bits). */
9004 *offset = size_binop (MULT_EXPR,
9005 convert (bitsizetype, *offset),
9006 TYPE_SIZE (TREE_TYPE (TREE_TYPE (t))));
9009 /* Not a COMMON reference, so an unrecognized pattern. */
9010 *decl = error_mark_node;
9015 *offset = bitsize_zero_node;
9019 if (TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL)
9021 /* A reference to COMMON. */
9022 *decl = TREE_OPERAND (t, 0);
9023 *offset = bitsize_zero_node;
9028 /* Not a COMMON reference, so an unrecognized pattern. */
9029 *decl = error_mark_node;
9035 /* Given a tree that is possibly intended for use as an lvalue, return
9036 information representing a canonical view of that tree as a decl, an
9037 offset into that decl, and a size for the lvalue.
9039 If there's no applicable decl, NULL_TREE is returned for the decl,
9040 and the other fields are left undefined.
9042 If the tree doesn't fit the recognizable forms, an ERROR_MARK node
9043 is returned for the decl, and the other fields are left undefined.
9045 Otherwise, the decl returned currently is either a VAR_DECL or a
9048 The offset returned is always valid, but of course not necessarily
9049 a constant, and not necessarily converted into the appropriate
9050 type, leaving that up to the caller (so as to avoid that overhead
9051 if the decls being looked at are different anyway).
9053 If the size cannot be determined (e.g. an adjustable array),
9054 an ERROR_MARK node is returned for the size. Otherwise, the
9055 size returned is valid, not necessarily a constant, and not
9056 necessarily converted into the appropriate type as with the
9059 Note that the offset and size expressions are expressed in the
9060 base storage units (usually bits) rather than in the units of
9061 the type of the decl, because two decls with different types
9062 might overlap but with apparently non-overlapping array offsets,
9063 whereas converting the array offsets to consistant offsets will
9064 reveal the overlap. */
9066 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9068 ffecom_tree_canonize_ref_ (tree *decl, tree *offset,
9071 /* The default path is to report a nonexistant decl. */
9077 switch (TREE_CODE (t))
9080 case IDENTIFIER_NODE:
9089 case TRUNC_DIV_EXPR:
9091 case FLOOR_DIV_EXPR:
9092 case ROUND_DIV_EXPR:
9093 case TRUNC_MOD_EXPR:
9095 case FLOOR_MOD_EXPR:
9096 case ROUND_MOD_EXPR:
9098 case EXACT_DIV_EXPR:
9099 case FIX_TRUNC_EXPR:
9101 case FIX_FLOOR_EXPR:
9102 case FIX_ROUND_EXPR:
9117 case BIT_ANDTC_EXPR:
9119 case TRUTH_ANDIF_EXPR:
9120 case TRUTH_ORIF_EXPR:
9121 case TRUTH_AND_EXPR:
9123 case TRUTH_XOR_EXPR:
9124 case TRUTH_NOT_EXPR:
9144 *offset = bitsize_zero_node;
9145 *size = TYPE_SIZE (TREE_TYPE (t));
9150 tree array = TREE_OPERAND (t, 0);
9151 tree element = TREE_OPERAND (t, 1);
9154 if ((array == NULL_TREE)
9155 || (element == NULL_TREE))
9157 *decl = error_mark_node;
9161 ffecom_tree_canonize_ref_ (decl, &init_offset, size,
9163 if ((*decl == NULL_TREE)
9164 || (*decl == error_mark_node))
9167 /* Calculate ((element - base) * NBBY) + init_offset. */
9168 *offset = fold (build (MINUS_EXPR, TREE_TYPE (element),
9170 TYPE_MIN_VALUE (TYPE_DOMAIN
9171 (TREE_TYPE (array)))));
9173 *offset = size_binop (MULT_EXPR,
9174 convert (bitsizetype, *offset),
9175 TYPE_SIZE (TREE_TYPE (TREE_TYPE (array))));
9177 *offset = size_binop (PLUS_EXPR, init_offset, *offset);
9179 *size = TYPE_SIZE (TREE_TYPE (t));
9185 /* Most of this code is to handle references to COMMON. And so
9186 far that is useful only for calling library functions, since
9187 external (user) functions might reference common areas. But
9188 even calling an external function, it's worthwhile to decode
9189 COMMON references because if not storing into COMMON, we don't
9190 want COMMON-based arguments to gratuitously force use of a
9193 *size = TYPE_SIZE (TREE_TYPE (t));
9195 ffecom_tree_canonize_ptr_ (decl, offset,
9196 TREE_OPERAND (t, 0));
9203 case NON_LVALUE_EXPR:
9206 case COND_EXPR: /* More cases than we can handle. */
9208 case REFERENCE_EXPR:
9209 case PREDECREMENT_EXPR:
9210 case PREINCREMENT_EXPR:
9211 case POSTDECREMENT_EXPR:
9212 case POSTINCREMENT_EXPR:
9215 *decl = error_mark_node;
9221 /* Do divide operation appropriate to type of operands. */
9223 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9225 ffecom_tree_divide_ (tree tree_type, tree left, tree right,
9226 tree dest_tree, ffebld dest, bool *dest_used,
9229 if ((left == error_mark_node)
9230 || (right == error_mark_node))
9231 return error_mark_node;
9233 switch (TREE_CODE (tree_type))
9236 return ffecom_2 (TRUNC_DIV_EXPR, tree_type,
9241 if (! optimize_size)
9242 return ffecom_2 (RDIV_EXPR, tree_type,
9248 if (TREE_TYPE (tree_type)
9249 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9250 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */
9252 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */
9254 left = ffecom_1 (ADDR_EXPR,
9255 build_pointer_type (TREE_TYPE (left)),
9257 left = build_tree_list (NULL_TREE, left);
9258 right = ffecom_1 (ADDR_EXPR,
9259 build_pointer_type (TREE_TYPE (right)),
9261 right = build_tree_list (NULL_TREE, right);
9262 TREE_CHAIN (left) = right;
9264 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9265 ffecom_gfrt_kindtype (ix),
9266 ffe_is_f2c_library (),
9269 dest_tree, dest, dest_used,
9270 NULL_TREE, TRUE, hook);
9278 if (TREE_TYPE (TYPE_FIELDS (tree_type))
9279 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9280 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */
9282 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */
9284 left = ffecom_1 (ADDR_EXPR,
9285 build_pointer_type (TREE_TYPE (left)),
9287 left = build_tree_list (NULL_TREE, left);
9288 right = ffecom_1 (ADDR_EXPR,
9289 build_pointer_type (TREE_TYPE (right)),
9291 right = build_tree_list (NULL_TREE, right);
9292 TREE_CHAIN (left) = right;
9294 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9295 ffecom_gfrt_kindtype (ix),
9296 ffe_is_f2c_library (),
9299 dest_tree, dest, dest_used,
9300 NULL_TREE, TRUE, hook);
9305 return ffecom_2 (RDIV_EXPR, tree_type,
9312 /* Build type info for non-dummy variable. */
9314 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9316 ffecom_type_localvar_ (ffesymbol s, ffeinfoBasictype bt,
9325 type = ffecom_tree_type[bt][kt];
9326 if (bt == FFEINFO_basictypeCHARACTER)
9328 hight = build_int_2 (ffesymbol_size (s), 0);
9329 TREE_TYPE (hight) = ffecom_f2c_ftnlen_type_node;
9334 build_range_type (ffecom_f2c_ftnlen_type_node,
9335 ffecom_f2c_ftnlen_one_node,
9337 type = ffecom_check_size_overflow_ (s, type, FALSE);
9340 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
9342 if (type == error_mark_node)
9345 dim = ffebld_head (dl);
9346 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
9348 if (ffebld_left (dim) == NULL)
9349 lowt = integer_one_node;
9351 lowt = ffecom_expr (ffebld_left (dim));
9353 if (TREE_CODE (lowt) != INTEGER_CST)
9354 lowt = variable_size (lowt);
9356 assert (ffebld_right (dim) != NULL);
9357 hight = ffecom_expr (ffebld_right (dim));
9359 if (TREE_CODE (hight) != INTEGER_CST)
9360 hight = variable_size (hight);
9362 type = build_array_type (type,
9363 build_range_type (ffecom_integer_type_node,
9365 type = ffecom_check_size_overflow_ (s, type, FALSE);
9372 /* Build Namelist type. */
9374 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9376 ffecom_type_namelist_ ()
9378 static tree type = NULL_TREE;
9380 if (type == NULL_TREE)
9382 static tree namefield, varsfield, nvarsfield;
9385 vardesctype = ffecom_type_vardesc_ ();
9387 type = make_node (RECORD_TYPE);
9389 vardesctype = build_pointer_type (build_pointer_type (vardesctype));
9391 namefield = ffecom_decl_field (type, NULL_TREE, "name",
9393 varsfield = ffecom_decl_field (type, namefield, "vars", vardesctype);
9394 nvarsfield = ffecom_decl_field (type, varsfield, "nvars",
9397 TYPE_FIELDS (type) = namefield;
9400 ggc_add_tree_root (&type, 1);
9408 /* Build Vardesc type. */
9410 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9412 ffecom_type_vardesc_ ()
9414 static tree type = NULL_TREE;
9415 static tree namefield, addrfield, dimsfield, typefield;
9417 if (type == NULL_TREE)
9419 type = make_node (RECORD_TYPE);
9421 namefield = ffecom_decl_field (type, NULL_TREE, "name",
9423 addrfield = ffecom_decl_field (type, namefield, "addr",
9425 dimsfield = ffecom_decl_field (type, addrfield, "dims",
9426 ffecom_f2c_ptr_to_ftnlen_type_node);
9427 typefield = ffecom_decl_field (type, dimsfield, "type",
9430 TYPE_FIELDS (type) = namefield;
9433 ggc_add_tree_root (&type, 1);
9441 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9443 ffecom_vardesc_ (ffebld expr)
9447 assert (ffebld_op (expr) == FFEBLD_opSYMTER);
9448 s = ffebld_symter (expr);
9450 if (ffesymbol_hook (s).vardesc_tree == NULL_TREE)
9453 tree vardesctype = ffecom_type_vardesc_ ();
9461 static int mynumber = 0;
9463 var = build_decl (VAR_DECL,
9464 ffecom_get_invented_identifier ("__g77_vardesc_%d",
9467 TREE_STATIC (var) = 1;
9468 DECL_INITIAL (var) = error_mark_node;
9470 var = start_decl (var, FALSE);
9472 /* Process inits. */
9474 nameinit = ffecom_build_f2c_string_ ((i = strlen (ffesymbol_text (s)))
9476 ffesymbol_text (s));
9477 TREE_TYPE (nameinit)
9478 = build_type_variant
9481 build_range_type (integer_type_node,
9483 build_int_2 (i, 0))),
9485 TREE_CONSTANT (nameinit) = 1;
9486 TREE_STATIC (nameinit) = 1;
9487 nameinit = ffecom_1 (ADDR_EXPR,
9488 build_pointer_type (TREE_TYPE (nameinit)),
9491 addrinit = ffecom_arg_ptr_to_expr (expr, &typeinit);
9493 dimsinit = ffecom_vardesc_dims_ (s);
9495 if (typeinit == NULL_TREE)
9497 ffeinfoBasictype bt = ffesymbol_basictype (s);
9498 ffeinfoKindtype kt = ffesymbol_kindtype (s);
9499 int tc = ffecom_f2c_typecode (bt, kt);
9502 typeinit = build_int_2 (tc, (tc < 0) ? -1 : 0);
9505 typeinit = ffecom_1 (NEGATE_EXPR, TREE_TYPE (typeinit), typeinit);
9507 varinits = build_tree_list ((field = TYPE_FIELDS (vardesctype)),
9509 TREE_CHAIN (varinits) = build_tree_list ((field = TREE_CHAIN (field)),
9511 TREE_CHAIN (TREE_CHAIN (varinits))
9512 = build_tree_list ((field = TREE_CHAIN (field)), dimsinit);
9513 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (varinits)))
9514 = build_tree_list ((field = TREE_CHAIN (field)), typeinit);
9516 varinits = build (CONSTRUCTOR, vardesctype, NULL_TREE, varinits);
9517 TREE_CONSTANT (varinits) = 1;
9518 TREE_STATIC (varinits) = 1;
9520 finish_decl (var, varinits, FALSE);
9522 var = ffecom_1 (ADDR_EXPR, build_pointer_type (vardesctype), var);
9524 ffesymbol_hook (s).vardesc_tree = var;
9527 return ffesymbol_hook (s).vardesc_tree;
9531 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9533 ffecom_vardesc_array_ (ffesymbol s)
9537 tree item = NULL_TREE;
9540 static int mynumber = 0;
9542 for (i = 0, list = NULL_TREE, b = ffesymbol_namelist (s);
9544 b = ffebld_trail (b), ++i)
9548 t = ffecom_vardesc_ (ffebld_head (b));
9550 if (list == NULL_TREE)
9551 list = item = build_tree_list (NULL_TREE, t);
9554 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
9555 item = TREE_CHAIN (item);
9559 item = build_array_type (build_pointer_type (ffecom_type_vardesc_ ()),
9560 build_range_type (integer_type_node,
9562 build_int_2 (i, 0)));
9563 list = build (CONSTRUCTOR, item, NULL_TREE, list);
9564 TREE_CONSTANT (list) = 1;
9565 TREE_STATIC (list) = 1;
9567 var = ffecom_get_invented_identifier ("__g77_vardesc_array_%d", mynumber++);
9568 var = build_decl (VAR_DECL, var, item);
9569 TREE_STATIC (var) = 1;
9570 DECL_INITIAL (var) = error_mark_node;
9571 var = start_decl (var, FALSE);
9572 finish_decl (var, list, FALSE);
9578 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9580 ffecom_vardesc_dims_ (ffesymbol s)
9582 if (ffesymbol_dims (s) == NULL)
9583 return convert (ffecom_f2c_ptr_to_ftnlen_type_node,
9591 tree item = NULL_TREE;
9595 tree baseoff = NULL_TREE;
9596 static int mynumber = 0;
9598 numdim = build_int_2 ((int) ffesymbol_rank (s), 0);
9599 TREE_TYPE (numdim) = ffecom_f2c_ftnlen_type_node;
9601 numelem = ffecom_expr (ffesymbol_arraysize (s));
9602 TREE_TYPE (numelem) = ffecom_f2c_ftnlen_type_node;
9605 backlist = NULL_TREE;
9606 for (b = ffesymbol_dims (s), e = ffesymbol_extents (s);
9608 b = ffebld_trail (b), e = ffebld_trail (e))
9614 if (ffebld_trail (b) == NULL)
9618 t = convert (ffecom_f2c_ftnlen_type_node,
9619 ffecom_expr (ffebld_head (e)));
9621 if (list == NULL_TREE)
9622 list = item = build_tree_list (NULL_TREE, t);
9625 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
9626 item = TREE_CHAIN (item);
9630 if (ffebld_left (ffebld_head (b)) == NULL)
9631 low = ffecom_integer_one_node;
9633 low = ffecom_expr (ffebld_left (ffebld_head (b)));
9634 low = convert (ffecom_f2c_ftnlen_type_node, low);
9636 back = build_tree_list (low, t);
9637 TREE_CHAIN (back) = backlist;
9641 for (item = backlist; item != NULL_TREE; item = TREE_CHAIN (item))
9643 if (TREE_VALUE (item) == NULL_TREE)
9644 baseoff = TREE_PURPOSE (item);
9646 baseoff = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
9647 TREE_PURPOSE (item),
9648 ffecom_2 (MULT_EXPR,
9649 ffecom_f2c_ftnlen_type_node,
9654 /* backlist now dead, along with all TREE_PURPOSEs on it. */
9656 baseoff = build_tree_list (NULL_TREE, baseoff);
9657 TREE_CHAIN (baseoff) = list;
9659 numelem = build_tree_list (NULL_TREE, numelem);
9660 TREE_CHAIN (numelem) = baseoff;
9662 numdim = build_tree_list (NULL_TREE, numdim);
9663 TREE_CHAIN (numdim) = numelem;
9665 item = build_array_type (ffecom_f2c_ftnlen_type_node,
9666 build_range_type (integer_type_node,
9669 ((int) ffesymbol_rank (s)
9671 list = build (CONSTRUCTOR, item, NULL_TREE, numdim);
9672 TREE_CONSTANT (list) = 1;
9673 TREE_STATIC (list) = 1;
9675 var = ffecom_get_invented_identifier ("__g77_dims_%d", mynumber++);
9676 var = build_decl (VAR_DECL, var, item);
9677 TREE_STATIC (var) = 1;
9678 DECL_INITIAL (var) = error_mark_node;
9679 var = start_decl (var, FALSE);
9680 finish_decl (var, list, FALSE);
9682 var = ffecom_1 (ADDR_EXPR, build_pointer_type (item), var);
9689 /* Essentially does a "fold (build1 (code, type, node))" while checking
9690 for certain housekeeping things.
9692 NOTE: for building an ADDR_EXPR around a FUNCTION_DECL, use
9693 ffecom_1_fn instead. */
9695 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9697 ffecom_1 (enum tree_code code, tree type, tree node)
9701 if ((node == error_mark_node)
9702 || (type == error_mark_node))
9703 return error_mark_node;
9705 if (code == ADDR_EXPR)
9707 if (!mark_addressable (node))
9708 assert ("can't mark_addressable this node!" == NULL);
9711 switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
9716 item = build (COMPONENT_REF, type, node, TYPE_FIELDS (TREE_TYPE (node)));
9720 item = build (COMPONENT_REF, type, node, TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (node))));
9725 if (TREE_CODE (type) != RECORD_TYPE)
9727 item = build1 (code, type, node);
9730 node = ffecom_stabilize_aggregate_ (node);
9731 realtype = TREE_TYPE (TYPE_FIELDS (type));
9733 ffecom_2 (COMPLEX_EXPR, type,
9734 ffecom_1 (NEGATE_EXPR, realtype,
9735 ffecom_1 (REALPART_EXPR, realtype,
9737 ffecom_1 (NEGATE_EXPR, realtype,
9738 ffecom_1 (IMAGPART_EXPR, realtype,
9743 item = build1 (code, type, node);
9747 if (TREE_SIDE_EFFECTS (node))
9748 TREE_SIDE_EFFECTS (item) = 1;
9749 if ((code == ADDR_EXPR) && staticp (node))
9750 TREE_CONSTANT (item) = 1;
9755 /* Like ffecom_1 (ADDR_EXPR, TREE_TYPE (node), node), except
9756 handles TREE_CODE (node) == FUNCTION_DECL. In particular,
9757 does not set TREE_ADDRESSABLE (because calling an inline
9758 function does not mean the function needs to be separately
9761 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9763 ffecom_1_fn (tree node)
9768 if (node == error_mark_node)
9769 return error_mark_node;
9771 type = build_type_variant (TREE_TYPE (node),
9772 TREE_READONLY (node),
9773 TREE_THIS_VOLATILE (node));
9774 item = build1 (ADDR_EXPR,
9775 build_pointer_type (type), node);
9776 if (TREE_SIDE_EFFECTS (node))
9777 TREE_SIDE_EFFECTS (item) = 1;
9779 TREE_CONSTANT (item) = 1;
9784 /* Essentially does a "fold (build (code, type, node1, node2))" while
9785 checking for certain housekeeping things. */
9787 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9789 ffecom_2 (enum tree_code code, tree type, tree node1,
9794 if ((node1 == error_mark_node)
9795 || (node2 == error_mark_node)
9796 || (type == error_mark_node))
9797 return error_mark_node;
9799 switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
9801 tree a, b, c, d, realtype;
9804 assert ("no CONJ_EXPR support yet" == NULL);
9805 return error_mark_node;
9808 item = build_tree_list (TYPE_FIELDS (type), node1);
9809 TREE_CHAIN (item) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), node2);
9810 item = build (CONSTRUCTOR, type, NULL_TREE, item);
9814 if (TREE_CODE (type) != RECORD_TYPE)
9816 item = build (code, type, node1, node2);
9819 node1 = ffecom_stabilize_aggregate_ (node1);
9820 node2 = ffecom_stabilize_aggregate_ (node2);
9821 realtype = TREE_TYPE (TYPE_FIELDS (type));
9823 ffecom_2 (COMPLEX_EXPR, type,
9824 ffecom_2 (PLUS_EXPR, realtype,
9825 ffecom_1 (REALPART_EXPR, realtype,
9827 ffecom_1 (REALPART_EXPR, realtype,
9829 ffecom_2 (PLUS_EXPR, realtype,
9830 ffecom_1 (IMAGPART_EXPR, realtype,
9832 ffecom_1 (IMAGPART_EXPR, realtype,
9837 if (TREE_CODE (type) != RECORD_TYPE)
9839 item = build (code, type, node1, node2);
9842 node1 = ffecom_stabilize_aggregate_ (node1);
9843 node2 = ffecom_stabilize_aggregate_ (node2);
9844 realtype = TREE_TYPE (TYPE_FIELDS (type));
9846 ffecom_2 (COMPLEX_EXPR, type,
9847 ffecom_2 (MINUS_EXPR, realtype,
9848 ffecom_1 (REALPART_EXPR, realtype,
9850 ffecom_1 (REALPART_EXPR, realtype,
9852 ffecom_2 (MINUS_EXPR, realtype,
9853 ffecom_1 (IMAGPART_EXPR, realtype,
9855 ffecom_1 (IMAGPART_EXPR, realtype,
9860 if (TREE_CODE (type) != RECORD_TYPE)
9862 item = build (code, type, node1, node2);
9865 node1 = ffecom_stabilize_aggregate_ (node1);
9866 node2 = ffecom_stabilize_aggregate_ (node2);
9867 realtype = TREE_TYPE (TYPE_FIELDS (type));
9868 a = save_expr (ffecom_1 (REALPART_EXPR, realtype,
9870 b = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
9872 c = save_expr (ffecom_1 (REALPART_EXPR, realtype,
9874 d = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
9877 ffecom_2 (COMPLEX_EXPR, type,
9878 ffecom_2 (MINUS_EXPR, realtype,
9879 ffecom_2 (MULT_EXPR, realtype,
9882 ffecom_2 (MULT_EXPR, realtype,
9885 ffecom_2 (PLUS_EXPR, realtype,
9886 ffecom_2 (MULT_EXPR, realtype,
9889 ffecom_2 (MULT_EXPR, realtype,
9895 if ((TREE_CODE (node1) != RECORD_TYPE)
9896 && (TREE_CODE (node2) != RECORD_TYPE))
9898 item = build (code, type, node1, node2);
9901 assert (TREE_CODE (node1) == RECORD_TYPE);
9902 assert (TREE_CODE (node2) == RECORD_TYPE);
9903 node1 = ffecom_stabilize_aggregate_ (node1);
9904 node2 = ffecom_stabilize_aggregate_ (node2);
9905 realtype = TREE_TYPE (TYPE_FIELDS (type));
9907 ffecom_2 (TRUTH_ANDIF_EXPR, type,
9908 ffecom_2 (code, type,
9909 ffecom_1 (REALPART_EXPR, realtype,
9911 ffecom_1 (REALPART_EXPR, realtype,
9913 ffecom_2 (code, type,
9914 ffecom_1 (IMAGPART_EXPR, realtype,
9916 ffecom_1 (IMAGPART_EXPR, realtype,
9921 if ((TREE_CODE (node1) != RECORD_TYPE)
9922 && (TREE_CODE (node2) != RECORD_TYPE))
9924 item = build (code, type, node1, node2);
9927 assert (TREE_CODE (node1) == RECORD_TYPE);
9928 assert (TREE_CODE (node2) == RECORD_TYPE);
9929 node1 = ffecom_stabilize_aggregate_ (node1);
9930 node2 = ffecom_stabilize_aggregate_ (node2);
9931 realtype = TREE_TYPE (TYPE_FIELDS (type));
9933 ffecom_2 (TRUTH_ORIF_EXPR, type,
9934 ffecom_2 (code, type,
9935 ffecom_1 (REALPART_EXPR, realtype,
9937 ffecom_1 (REALPART_EXPR, realtype,
9939 ffecom_2 (code, type,
9940 ffecom_1 (IMAGPART_EXPR, realtype,
9942 ffecom_1 (IMAGPART_EXPR, realtype,
9947 item = build (code, type, node1, node2);
9951 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2))
9952 TREE_SIDE_EFFECTS (item) = 1;
9957 /* ffecom_2pass_advise_entrypoint -- Advise that there's this entrypoint
9959 ffesymbol s; // the ENTRY point itself
9960 if (ffecom_2pass_advise_entrypoint(s))
9961 // the ENTRY point has been accepted
9963 Does whatever compiler needs to do when it learns about the entrypoint,
9964 like determine the return type of the master function, count the
9965 number of entrypoints, etc. Returns FALSE if the return type is
9966 not compatible with the return type(s) of other entrypoint(s).
9968 NOTE: for every call to this fn that returns TRUE, _do_entrypoint must
9969 later (after _finish_progunit) be called with the same entrypoint(s)
9970 as passed to this fn for which TRUE was returned.
9973 Return FALSE if the return type conflicts with previous entrypoints. */
9975 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9977 ffecom_2pass_advise_entrypoint (ffesymbol entry)
9979 ffebld list; /* opITEM. */
9980 ffebld mlist; /* opITEM. */
9981 ffebld plist; /* opITEM. */
9982 ffebld arg; /* ffebld_head(opITEM). */
9983 ffebld item; /* opITEM. */
9984 ffesymbol s; /* ffebld_symter(arg). */
9985 ffeinfoBasictype bt = ffesymbol_basictype (entry);
9986 ffeinfoKindtype kt = ffesymbol_kindtype (entry);
9987 ffetargetCharacterSize size = ffesymbol_size (entry);
9990 if (ffecom_num_entrypoints_ == 0)
9991 { /* First entrypoint, make list of main
9992 arglist's dummies. */
9993 assert (ffecom_primary_entry_ != NULL);
9995 ffecom_master_bt_ = ffesymbol_basictype (ffecom_primary_entry_);
9996 ffecom_master_kt_ = ffesymbol_kindtype (ffecom_primary_entry_);
9997 ffecom_master_size_ = ffesymbol_size (ffecom_primary_entry_);
9999 for (plist = NULL, list = ffesymbol_dummyargs (ffecom_primary_entry_);
10001 list = ffebld_trail (list))
10003 arg = ffebld_head (list);
10004 if (ffebld_op (arg) != FFEBLD_opSYMTER)
10005 continue; /* Alternate return or some such thing. */
10006 item = ffebld_new_item (arg, NULL);
10008 ffecom_master_arglist_ = item;
10010 ffebld_set_trail (plist, item);
10015 /* If necessary, scan entry arglist for alternate returns. Do this scan
10016 apparently redundantly (it's done below to UNIONize the arglists) so
10017 that we don't complain about RETURN 1 if an offending ENTRY is the only
10018 one with an alternate return. */
10020 if (!ffecom_is_altreturning_)
10022 for (list = ffesymbol_dummyargs (entry);
10024 list = ffebld_trail (list))
10026 arg = ffebld_head (list);
10027 if (ffebld_op (arg) == FFEBLD_opSTAR)
10029 ffecom_is_altreturning_ = TRUE;
10035 /* Now check type compatibility. */
10037 switch (ffecom_master_bt_)
10039 case FFEINFO_basictypeNONE:
10040 ok = (bt != FFEINFO_basictypeCHARACTER);
10043 case FFEINFO_basictypeCHARACTER:
10045 = (bt == FFEINFO_basictypeCHARACTER)
10046 && (kt == ffecom_master_kt_)
10047 && (size == ffecom_master_size_);
10050 case FFEINFO_basictypeANY:
10051 return FALSE; /* Just don't bother. */
10054 if (bt == FFEINFO_basictypeCHARACTER)
10060 if ((bt != ffecom_master_bt_) || (kt != ffecom_master_kt_))
10062 ffecom_master_bt_ = FFEINFO_basictypeNONE;
10063 ffecom_master_kt_ = FFEINFO_kindtypeNONE;
10070 ffebad_start (FFEBAD_ENTRY_CONFLICTS);
10071 ffest_ffebad_here_current_stmt (0);
10073 return FALSE; /* Can't handle entrypoint. */
10076 /* Entrypoint type compatible with previous types. */
10078 ++ffecom_num_entrypoints_;
10080 /* Master-arg-list = UNION(Master-arg-list,entry-arg-list). */
10082 for (list = ffesymbol_dummyargs (entry);
10084 list = ffebld_trail (list))
10086 arg = ffebld_head (list);
10087 if (ffebld_op (arg) != FFEBLD_opSYMTER)
10088 continue; /* Alternate return or some such thing. */
10089 s = ffebld_symter (arg);
10090 for (plist = NULL, mlist = ffecom_master_arglist_;
10092 plist = mlist, mlist = ffebld_trail (mlist))
10093 { /* plist points to previous item for easy
10094 appending of arg. */
10095 if (ffebld_symter (ffebld_head (mlist)) == s)
10096 break; /* Already have this arg in the master list. */
10099 continue; /* Already have this arg in the master list. */
10101 /* Append this arg to the master list. */
10103 item = ffebld_new_item (arg, NULL);
10105 ffecom_master_arglist_ = item;
10107 ffebld_set_trail (plist, item);
10114 /* ffecom_2pass_do_entrypoint -- Do compilation of entrypoint
10116 ffesymbol s; // the ENTRY point itself
10117 ffecom_2pass_do_entrypoint(s);
10119 Does whatever compiler needs to do to make the entrypoint actually
10120 happen. Must be called for each entrypoint after
10121 ffecom_finish_progunit is called. */
10123 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10125 ffecom_2pass_do_entrypoint (ffesymbol entry)
10127 static int mfn_num = 0;
10128 static int ent_num;
10130 if (mfn_num != ffecom_num_fns_)
10131 { /* First entrypoint for this program unit. */
10133 mfn_num = ffecom_num_fns_;
10134 ffecom_do_entry_ (ffecom_primary_entry_, 0);
10139 --ffecom_num_entrypoints_;
10141 ffecom_do_entry_ (entry, ent_num);
10146 /* Essentially does a "fold (build (code, type, node1, node2))" while
10147 checking for certain housekeeping things. Always sets
10148 TREE_SIDE_EFFECTS. */
10150 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10152 ffecom_2s (enum tree_code code, tree type, tree node1,
10157 if ((node1 == error_mark_node)
10158 || (node2 == error_mark_node)
10159 || (type == error_mark_node))
10160 return error_mark_node;
10162 item = build (code, type, node1, node2);
10163 TREE_SIDE_EFFECTS (item) = 1;
10164 return fold (item);
10168 /* Essentially does a "fold (build (code, type, node1, node2, node3))" while
10169 checking for certain housekeeping things. */
10171 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10173 ffecom_3 (enum tree_code code, tree type, tree node1,
10174 tree node2, tree node3)
10178 if ((node1 == error_mark_node)
10179 || (node2 == error_mark_node)
10180 || (node3 == error_mark_node)
10181 || (type == error_mark_node))
10182 return error_mark_node;
10184 item = build (code, type, node1, node2, node3);
10185 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2)
10186 || (node3 != NULL_TREE && TREE_SIDE_EFFECTS (node3)))
10187 TREE_SIDE_EFFECTS (item) = 1;
10188 return fold (item);
10192 /* Essentially does a "fold (build (code, type, node1, node2, node3))" while
10193 checking for certain housekeeping things. Always sets
10194 TREE_SIDE_EFFECTS. */
10196 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10198 ffecom_3s (enum tree_code code, tree type, tree node1,
10199 tree node2, tree node3)
10203 if ((node1 == error_mark_node)
10204 || (node2 == error_mark_node)
10205 || (node3 == error_mark_node)
10206 || (type == error_mark_node))
10207 return error_mark_node;
10209 item = build (code, type, node1, node2, node3);
10210 TREE_SIDE_EFFECTS (item) = 1;
10211 return fold (item);
10216 /* ffecom_arg_expr -- Transform argument expr into gcc tree
10218 See use by ffecom_list_expr.
10220 If expression is NULL, returns an integer zero tree. If it is not
10221 a CHARACTER expression, returns whatever ffecom_expr
10222 returns and sets the length return value to NULL_TREE. Otherwise
10223 generates code to evaluate the character expression, returns the proper
10224 pointer to the result, but does NOT set the length return value to a tree
10225 that specifies the length of the result. (In other words, the length
10226 variable is always set to NULL_TREE, because a length is never passed.)
10229 Don't set returned length, since nobody needs it (yet; someday if
10230 we allow CHARACTER*(*) dummies to statement functions, we'll need
10233 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10235 ffecom_arg_expr (ffebld expr, tree *length)
10239 *length = NULL_TREE;
10242 return integer_zero_node;
10244 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10245 return ffecom_expr (expr);
10247 return ffecom_arg_ptr_to_expr (expr, &ign);
10251 /* Transform expression into constant argument-pointer-to-expression tree.
10253 If the expression can be transformed into a argument-pointer-to-expression
10254 tree that is constant, that is done, and the tree returned. Else
10255 NULL_TREE is returned.
10257 That way, a caller can attempt to provide compile-time initialization
10258 of a variable and, if that fails, *then* choose to start a new block
10259 and resort to using temporaries, as appropriate. */
10262 ffecom_arg_ptr_to_const_expr (ffebld expr, tree *length)
10265 return integer_zero_node;
10267 if (ffebld_op (expr) == FFEBLD_opANY)
10270 *length = error_mark_node;
10271 return error_mark_node;
10274 if (ffebld_arity (expr) == 0
10275 && (ffebld_op (expr) != FFEBLD_opSYMTER
10276 || ffebld_where (expr) == FFEINFO_whereCOMMON
10277 || ffebld_where (expr) == FFEINFO_whereGLOBAL
10278 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
10282 t = ffecom_arg_ptr_to_expr (expr, length);
10283 assert (TREE_CONSTANT (t));
10284 assert (! length || TREE_CONSTANT (*length));
10289 && ffebld_size (expr) != FFETARGET_charactersizeNONE)
10290 *length = build_int_2 (ffebld_size (expr), 0);
10292 *length = NULL_TREE;
10296 /* ffecom_arg_ptr_to_expr -- Transform argument expr into gcc tree
10298 See use by ffecom_list_ptr_to_expr.
10300 If expression is NULL, returns an integer zero tree. If it is not
10301 a CHARACTER expression, returns whatever ffecom_ptr_to_expr
10302 returns and sets the length return value to NULL_TREE. Otherwise
10303 generates code to evaluate the character expression, returns the proper
10304 pointer to the result, AND sets the length return value to a tree that
10305 specifies the length of the result.
10307 If the length argument is NULL, this is a slightly special
10308 case of building a FORMAT expression, that is, an expression that
10309 will be used at run time without regard to length. For the current
10310 implementation, which uses the libf2c library, this means it is nice
10311 to append a null byte to the end of the expression, where feasible,
10312 to make sure any diagnostic about the FORMAT string terminates at
10315 For now, treat %REF(char-expr) as the same as char-expr with a NULL
10316 length argument. This might even be seen as a feature, if a null
10317 byte can always be appended. */
10319 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10321 ffecom_arg_ptr_to_expr (ffebld expr, tree *length)
10325 ffecomConcatList_ catlist;
10327 if (length != NULL)
10328 *length = NULL_TREE;
10331 return integer_zero_node;
10333 switch (ffebld_op (expr))
10335 case FFEBLD_opPERCENT_VAL:
10336 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10337 return ffecom_expr (ffebld_left (expr));
10342 temp_exp = ffecom_arg_ptr_to_expr (ffebld_left (expr), &temp_length);
10343 if (temp_exp == error_mark_node)
10344 return error_mark_node;
10346 return ffecom_1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (temp_exp)),
10350 case FFEBLD_opPERCENT_REF:
10351 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10352 return ffecom_ptr_to_expr (ffebld_left (expr));
10353 if (length != NULL)
10355 ign_length = NULL_TREE;
10356 length = &ign_length;
10358 expr = ffebld_left (expr);
10361 case FFEBLD_opPERCENT_DESCR:
10362 switch (ffeinfo_basictype (ffebld_info (expr)))
10364 #ifdef PASS_HOLLERITH_BY_DESCRIPTOR
10365 case FFEINFO_basictypeHOLLERITH:
10367 case FFEINFO_basictypeCHARACTER:
10368 break; /* Passed by descriptor anyway. */
10371 item = ffecom_ptr_to_expr (expr);
10372 if (item != error_mark_node)
10373 *length = TYPE_SIZE (TREE_TYPE (TREE_TYPE (item)));
10382 #ifdef PASS_HOLLERITH_BY_DESCRIPTOR
10383 if ((ffeinfo_basictype (ffebld_info (expr)) == FFEINFO_basictypeHOLLERITH)
10384 && (length != NULL))
10385 { /* Pass Hollerith by descriptor. */
10386 ffetargetHollerith h;
10388 assert (ffebld_op (expr) == FFEBLD_opCONTER);
10389 h = ffebld_cu_val_hollerith (ffebld_constant_union
10390 (ffebld_conter (expr)));
10392 = build_int_2 (h.length, 0);
10393 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
10397 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10398 return ffecom_ptr_to_expr (expr);
10400 assert (ffeinfo_kindtype (ffebld_info (expr))
10401 == FFEINFO_kindtypeCHARACTER1);
10403 while (ffebld_op (expr) == FFEBLD_opPAREN)
10404 expr = ffebld_left (expr);
10406 catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
10407 switch (ffecom_concat_list_count_ (catlist))
10409 case 0: /* Shouldn't happen, but in case it does... */
10410 if (length != NULL)
10412 *length = ffecom_f2c_ftnlen_zero_node;
10413 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
10415 ffecom_concat_list_kill_ (catlist);
10416 return null_pointer_node;
10418 case 1: /* The (fairly) easy case. */
10419 if (length == NULL)
10420 ffecom_char_args_with_null_ (&item, &ign_length,
10421 ffecom_concat_list_expr_ (catlist, 0));
10423 ffecom_char_args_ (&item, length,
10424 ffecom_concat_list_expr_ (catlist, 0));
10425 ffecom_concat_list_kill_ (catlist);
10426 assert (item != NULL_TREE);
10429 default: /* Must actually concatenate things. */
10434 int count = ffecom_concat_list_count_ (catlist);
10445 ffetargetCharacterSize sz;
10447 sz = ffecom_concat_list_maxlen_ (catlist);
10449 assert (sz != FFETARGET_charactersizeNONE);
10454 = ffecom_push_tempvar (ffecom_f2c_ftnlen_type_node,
10455 FFETARGET_charactersizeNONE, count, TRUE);
10458 = ffecom_push_tempvar (ffecom_f2c_address_type_node,
10459 FFETARGET_charactersizeNONE, count, TRUE);
10460 temporary = ffecom_push_tempvar (char_type_node,
10466 hook = ffebld_nonter_hook (expr);
10468 assert (TREE_CODE (hook) == TREE_VEC);
10469 assert (TREE_VEC_LENGTH (hook) == 3);
10470 length_array = lengths = TREE_VEC_ELT (hook, 0);
10471 item_array = items = TREE_VEC_ELT (hook, 1);
10472 temporary = TREE_VEC_ELT (hook, 2);
10476 known_length = ffecom_f2c_ftnlen_zero_node;
10478 for (i = 0; i < count; ++i)
10481 && (length == NULL))
10482 ffecom_char_args_with_null_ (&citem, &clength,
10483 ffecom_concat_list_expr_ (catlist, i));
10485 ffecom_char_args_ (&citem, &clength,
10486 ffecom_concat_list_expr_ (catlist, i));
10487 if ((citem == error_mark_node)
10488 || (clength == error_mark_node))
10490 ffecom_concat_list_kill_ (catlist);
10491 *length = error_mark_node;
10492 return error_mark_node;
10496 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
10497 ffecom_modify (void_type_node,
10498 ffecom_2 (ARRAY_REF,
10499 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
10501 build_int_2 (i, 0)),
10504 clength = ffecom_save_tree (clength);
10505 if (length != NULL)
10507 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
10511 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
10512 ffecom_modify (void_type_node,
10513 ffecom_2 (ARRAY_REF,
10514 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
10516 build_int_2 (i, 0)),
10521 temporary = ffecom_1 (ADDR_EXPR,
10522 build_pointer_type (TREE_TYPE (temporary)),
10525 item = build_tree_list (NULL_TREE, temporary);
10527 = build_tree_list (NULL_TREE,
10528 ffecom_1 (ADDR_EXPR,
10529 build_pointer_type (TREE_TYPE (items)),
10531 TREE_CHAIN (TREE_CHAIN (item))
10532 = build_tree_list (NULL_TREE,
10533 ffecom_1 (ADDR_EXPR,
10534 build_pointer_type (TREE_TYPE (lengths)),
10536 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
10539 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
10540 convert (ffecom_f2c_ftnlen_type_node,
10541 build_int_2 (count, 0))));
10542 num = build_int_2 (sz, 0);
10543 TREE_TYPE (num) = ffecom_f2c_ftnlen_type_node;
10544 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item))))
10545 = build_tree_list (NULL_TREE, num);
10547 item = ffecom_call_gfrt (FFECOM_gfrtCAT, item, NULL_TREE);
10548 TREE_SIDE_EFFECTS (item) = 1;
10549 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (temporary),
10553 if (length != NULL)
10554 *length = known_length;
10557 ffecom_concat_list_kill_ (catlist);
10558 assert (item != NULL_TREE);
10563 /* Generate call to run-time function.
10565 The first arg is the GNU Fortran Run-Time function index, the second
10566 arg is the list of arguments to pass to it. Returned is the expression
10567 (WITHOUT TREE_SIDE_EFFECTS set!) that makes the call and returns the
10568 result (which may be void). */
10570 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10572 ffecom_call_gfrt (ffecomGfrt ix, tree args, tree hook)
10574 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
10575 ffecom_gfrt_kindtype (ix),
10576 ffe_is_f2c_library () && ffecom_gfrt_complex_[ix],
10577 NULL_TREE, args, NULL_TREE, NULL,
10578 NULL, NULL_TREE, TRUE, hook);
10582 /* Transform constant-union to tree. */
10584 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10586 ffecom_constantunion (ffebldConstantUnion *cu, ffeinfoBasictype bt,
10587 ffeinfoKindtype kt, tree tree_type)
10593 case FFEINFO_basictypeINTEGER:
10599 #if FFETARGET_okINTEGER1
10600 case FFEINFO_kindtypeINTEGER1:
10601 val = ffebld_cu_val_integer1 (*cu);
10605 #if FFETARGET_okINTEGER2
10606 case FFEINFO_kindtypeINTEGER2:
10607 val = ffebld_cu_val_integer2 (*cu);
10611 #if FFETARGET_okINTEGER3
10612 case FFEINFO_kindtypeINTEGER3:
10613 val = ffebld_cu_val_integer3 (*cu);
10617 #if FFETARGET_okINTEGER4
10618 case FFEINFO_kindtypeINTEGER4:
10619 val = ffebld_cu_val_integer4 (*cu);
10624 assert ("bad INTEGER constant kind type" == NULL);
10625 /* Fall through. */
10626 case FFEINFO_kindtypeANY:
10627 return error_mark_node;
10629 item = build_int_2 (val, (val < 0) ? -1 : 0);
10630 TREE_TYPE (item) = tree_type;
10634 case FFEINFO_basictypeLOGICAL:
10640 #if FFETARGET_okLOGICAL1
10641 case FFEINFO_kindtypeLOGICAL1:
10642 val = ffebld_cu_val_logical1 (*cu);
10646 #if FFETARGET_okLOGICAL2
10647 case FFEINFO_kindtypeLOGICAL2:
10648 val = ffebld_cu_val_logical2 (*cu);
10652 #if FFETARGET_okLOGICAL3
10653 case FFEINFO_kindtypeLOGICAL3:
10654 val = ffebld_cu_val_logical3 (*cu);
10658 #if FFETARGET_okLOGICAL4
10659 case FFEINFO_kindtypeLOGICAL4:
10660 val = ffebld_cu_val_logical4 (*cu);
10665 assert ("bad LOGICAL constant kind type" == NULL);
10666 /* Fall through. */
10667 case FFEINFO_kindtypeANY:
10668 return error_mark_node;
10670 item = build_int_2 (val, (val < 0) ? -1 : 0);
10671 TREE_TYPE (item) = tree_type;
10675 case FFEINFO_basictypeREAL:
10677 REAL_VALUE_TYPE val;
10681 #if FFETARGET_okREAL1
10682 case FFEINFO_kindtypeREAL1:
10683 val = ffetarget_value_real1 (ffebld_cu_val_real1 (*cu));
10687 #if FFETARGET_okREAL2
10688 case FFEINFO_kindtypeREAL2:
10689 val = ffetarget_value_real2 (ffebld_cu_val_real2 (*cu));
10693 #if FFETARGET_okREAL3
10694 case FFEINFO_kindtypeREAL3:
10695 val = ffetarget_value_real3 (ffebld_cu_val_real3 (*cu));
10699 #if FFETARGET_okREAL4
10700 case FFEINFO_kindtypeREAL4:
10701 val = ffetarget_value_real4 (ffebld_cu_val_real4 (*cu));
10706 assert ("bad REAL constant kind type" == NULL);
10707 /* Fall through. */
10708 case FFEINFO_kindtypeANY:
10709 return error_mark_node;
10711 item = build_real (tree_type, val);
10715 case FFEINFO_basictypeCOMPLEX:
10717 REAL_VALUE_TYPE real;
10718 REAL_VALUE_TYPE imag;
10719 tree el_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
10723 #if FFETARGET_okCOMPLEX1
10724 case FFEINFO_kindtypeREAL1:
10725 real = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).real);
10726 imag = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).imaginary);
10730 #if FFETARGET_okCOMPLEX2
10731 case FFEINFO_kindtypeREAL2:
10732 real = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).real);
10733 imag = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).imaginary);
10737 #if FFETARGET_okCOMPLEX3
10738 case FFEINFO_kindtypeREAL3:
10739 real = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).real);
10740 imag = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).imaginary);
10744 #if FFETARGET_okCOMPLEX4
10745 case FFEINFO_kindtypeREAL4:
10746 real = ffetarget_value_real4 (ffebld_cu_val_complex4 (*cu).real);
10747 imag = ffetarget_value_real4 (ffebld_cu_val_complex4 (*cu).imaginary);
10752 assert ("bad REAL constant kind type" == NULL);
10753 /* Fall through. */
10754 case FFEINFO_kindtypeANY:
10755 return error_mark_node;
10757 item = ffecom_build_complex_constant_ (tree_type,
10758 build_real (el_type, real),
10759 build_real (el_type, imag));
10763 case FFEINFO_basictypeCHARACTER:
10764 { /* Happens only in DATA and similar contexts. */
10765 ffetargetCharacter1 val;
10769 #if FFETARGET_okCHARACTER1
10770 case FFEINFO_kindtypeLOGICAL1:
10771 val = ffebld_cu_val_character1 (*cu);
10776 assert ("bad CHARACTER constant kind type" == NULL);
10777 /* Fall through. */
10778 case FFEINFO_kindtypeANY:
10779 return error_mark_node;
10781 item = build_string (ffetarget_length_character1 (val),
10782 ffetarget_text_character1 (val));
10784 = build_type_variant (build_array_type (char_type_node,
10786 (integer_type_node,
10789 (ffetarget_length_character1
10795 case FFEINFO_basictypeHOLLERITH:
10797 ffetargetHollerith h;
10799 h = ffebld_cu_val_hollerith (*cu);
10801 /* If not at least as wide as default INTEGER, widen it. */
10802 if (h.length >= FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE)
10803 item = build_string (h.length, h.text);
10806 char str[FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE];
10808 memcpy (str, h.text, h.length);
10809 memset (&str[h.length], ' ',
10810 FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE
10812 item = build_string (FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE,
10816 = build_type_variant (build_array_type (char_type_node,
10818 (integer_type_node,
10826 case FFEINFO_basictypeTYPELESS:
10828 ffetargetInteger1 ival;
10829 ffetargetTypeless tless;
10832 tless = ffebld_cu_val_typeless (*cu);
10833 error = ffetarget_convert_integer1_typeless (&ival, tless);
10834 assert (error == FFEBAD);
10836 item = build_int_2 ((int) ival, 0);
10841 assert ("not yet on constant type" == NULL);
10842 /* Fall through. */
10843 case FFEINFO_basictypeANY:
10844 return error_mark_node;
10847 TREE_CONSTANT (item) = 1;
10854 /* Transform expression into constant tree.
10856 If the expression can be transformed into a tree that is constant,
10857 that is done, and the tree returned. Else NULL_TREE is returned.
10859 That way, a caller can attempt to provide compile-time initialization
10860 of a variable and, if that fails, *then* choose to start a new block
10861 and resort to using temporaries, as appropriate. */
10864 ffecom_const_expr (ffebld expr)
10867 return integer_zero_node;
10869 if (ffebld_op (expr) == FFEBLD_opANY)
10870 return error_mark_node;
10872 if (ffebld_arity (expr) == 0
10873 && (ffebld_op (expr) != FFEBLD_opSYMTER
10875 /* ~~Enable once common/equivalence is handled properly? */
10876 || ffebld_where (expr) == FFEINFO_whereCOMMON
10878 || ffebld_where (expr) == FFEINFO_whereGLOBAL
10879 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
10883 t = ffecom_expr (expr);
10884 assert (TREE_CONSTANT (t));
10891 /* Handy way to make a field in a struct/union. */
10893 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10895 ffecom_decl_field (tree context, tree prevfield,
10896 const char *name, tree type)
10900 field = build_decl (FIELD_DECL, get_identifier (name), type);
10901 DECL_CONTEXT (field) = context;
10902 DECL_ALIGN (field) = 0;
10903 DECL_USER_ALIGN (field) = 0;
10904 if (prevfield != NULL_TREE)
10905 TREE_CHAIN (prevfield) = field;
10913 ffecom_close_include (FILE *f)
10915 #if FFECOM_GCC_INCLUDE
10916 ffecom_close_include_ (f);
10921 ffecom_decode_include_option (char *spec)
10923 #if FFECOM_GCC_INCLUDE
10924 return ffecom_decode_include_option_ (spec);
10930 /* End a compound statement (block). */
10932 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10934 ffecom_end_compstmt (void)
10936 return bison_rule_compstmt_ ();
10938 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
10940 /* ffecom_end_transition -- Perform end transition on all symbols
10942 ffecom_end_transition();
10944 Calls ffecom_sym_end_transition for each global and local symbol. */
10947 ffecom_end_transition ()
10949 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10953 if (ffe_is_ffedebug ())
10954 fprintf (dmpout, "; end_stmt_transition\n");
10956 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10957 ffecom_list_blockdata_ = NULL;
10958 ffecom_list_common_ = NULL;
10961 ffesymbol_drive (ffecom_sym_end_transition);
10962 if (ffe_is_ffedebug ())
10964 ffestorag_report ();
10965 #if FFECOM_targetCURRENT == FFECOM_targetFFE
10966 ffesymbol_report_all ();
10970 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10971 ffecom_start_progunit_ ();
10973 for (item = ffecom_list_blockdata_;
10975 item = ffebld_trail (item))
10982 static int number = 0;
10984 callee = ffebld_head (item);
10985 s = ffebld_symter (callee);
10986 t = ffesymbol_hook (s).decl_tree;
10987 if (t == NULL_TREE)
10989 s = ffecom_sym_transform_ (s);
10990 t = ffesymbol_hook (s).decl_tree;
10993 dt = build_pointer_type (TREE_TYPE (t));
10995 var = build_decl (VAR_DECL,
10996 ffecom_get_invented_identifier ("__g77_forceload_%d",
10999 DECL_EXTERNAL (var) = 0;
11000 TREE_STATIC (var) = 1;
11001 TREE_PUBLIC (var) = 0;
11002 DECL_INITIAL (var) = error_mark_node;
11003 TREE_USED (var) = 1;
11005 var = start_decl (var, FALSE);
11007 t = ffecom_1 (ADDR_EXPR, dt, t);
11009 finish_decl (var, t, FALSE);
11012 /* This handles any COMMON areas that weren't referenced but have, for
11013 example, important initial data. */
11015 for (item = ffecom_list_common_;
11017 item = ffebld_trail (item))
11018 ffecom_transform_common_ (ffebld_symter (ffebld_head (item)));
11020 ffecom_list_common_ = NULL;
11024 /* ffecom_exec_transition -- Perform exec transition on all symbols
11026 ffecom_exec_transition();
11028 Calls ffecom_sym_exec_transition for each global and local symbol.
11029 Make sure error updating not inhibited. */
11032 ffecom_exec_transition ()
11036 if (ffe_is_ffedebug ())
11037 fprintf (dmpout, "; exec_stmt_transition\n");
11039 inhibited = ffebad_inhibit ();
11040 ffebad_set_inhibit (FALSE);
11042 ffesymbol_drive (ffecom_sym_exec_transition); /* Don't retract! */
11043 ffeequiv_exec_transition (); /* Handle all pending EQUIVALENCEs. */
11044 if (ffe_is_ffedebug ())
11046 ffestorag_report ();
11047 #if FFECOM_targetCURRENT == FFECOM_targetFFE
11048 ffesymbol_report_all ();
11053 ffebad_set_inhibit (TRUE);
11056 /* Handle assignment statement.
11058 Convert dest and source using ffecom_expr, then join them
11059 with an ASSIGN op and pass the whole thing to expand_expr_stmt. */
11061 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11063 ffecom_expand_let_stmt (ffebld dest, ffebld source)
11070 if (ffeinfo_basictype (ffebld_info (dest)) != FFEINFO_basictypeCHARACTER)
11075 /* This attempts to replicate the test below, but must not be
11076 true when the test below is false. (Always err on the side
11077 of creating unused temporaries, to avoid ICEs.) */
11078 if (ffebld_op (dest) != FFEBLD_opSYMTER
11079 || ((dest_tree = ffesymbol_hook (ffebld_symter (dest)).decl_tree)
11080 && (TREE_CODE (dest_tree) != VAR_DECL
11081 || TREE_ADDRESSABLE (dest_tree))))
11083 ffecom_prepare_expr_ (source, dest);
11088 ffecom_prepare_expr_ (source, NULL);
11092 ffecom_prepare_expr_w (NULL_TREE, dest);
11094 /* For COMPLEX assignment like C1=C2, if partial overlap is possible,
11095 create a temporary through which the assignment is to take place,
11096 since MODIFY_EXPR doesn't handle partial overlap properly. */
11097 if (ffebld_basictype (dest) == FFEINFO_basictypeCOMPLEX
11098 && ffecom_possible_partial_overlap_ (dest, source))
11100 assign_temp = ffecom_make_tempvar ("complex_let",
11102 [ffebld_basictype (dest)]
11103 [ffebld_kindtype (dest)],
11104 FFETARGET_charactersizeNONE,
11108 assign_temp = NULL_TREE;
11110 ffecom_prepare_end ();
11112 dest_tree = ffecom_expr_w (NULL_TREE, dest);
11113 if (dest_tree == error_mark_node)
11116 if ((TREE_CODE (dest_tree) != VAR_DECL)
11117 || TREE_ADDRESSABLE (dest_tree))
11118 source_tree = ffecom_expr_ (source, dest_tree, dest, &dest_used,
11122 assert (! dest_used);
11124 source_tree = ffecom_expr (source);
11126 if (source_tree == error_mark_node)
11130 expr_tree = source_tree;
11131 else if (assign_temp)
11134 /* The back end understands a conceptual move (evaluate source;
11135 store into dest), so use that, in case it can determine
11136 that it is going to use, say, two registers as temporaries
11137 anyway. So don't use the temp (and someday avoid generating
11138 it, once this code starts triggering regularly). */
11139 expr_tree = ffecom_2s (MOVE_EXPR, void_type_node,
11143 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11146 expand_expr_stmt (expr_tree);
11147 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11153 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11157 expand_expr_stmt (expr_tree);
11161 ffecom_prepare_let_char_ (ffebld_size_known (dest), source);
11162 ffecom_prepare_expr_w (NULL_TREE, dest);
11164 ffecom_prepare_end ();
11166 ffecom_char_args_ (&dest_tree, &dest_length, dest);
11167 ffecom_let_char_ (dest_tree, dest_length, ffebld_size_known (dest),
11172 /* ffecom_expr -- Transform expr into gcc tree
11175 ffebld expr; // FFE expression.
11176 tree = ffecom_expr(expr);
11178 Recursive descent on expr while making corresponding tree nodes and
11179 attaching type info and such. */
11181 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11183 ffecom_expr (ffebld expr)
11185 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, FALSE, FALSE);
11189 /* Like ffecom_expr, but return tree usable for assigned GOTO or FORMAT. */
11191 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11193 ffecom_expr_assign (ffebld expr)
11195 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE);
11199 /* Like ffecom_expr_rw, but return tree usable for ASSIGN. */
11201 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11203 ffecom_expr_assign_w (ffebld expr)
11205 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE);
11209 /* Transform expr for use as into read/write tree and stabilize the
11210 reference. Not for use on CHARACTER expressions.
11212 Recursive descent on expr while making corresponding tree nodes and
11213 attaching type info and such. */
11215 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11217 ffecom_expr_rw (tree type, ffebld expr)
11219 assert (expr != NULL);
11220 /* Different target types not yet supported. */
11221 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
11223 return stabilize_reference (ffecom_expr (expr));
11227 /* Transform expr for use as into write tree and stabilize the
11228 reference. Not for use on CHARACTER expressions.
11230 Recursive descent on expr while making corresponding tree nodes and
11231 attaching type info and such. */
11233 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11235 ffecom_expr_w (tree type, ffebld expr)
11237 assert (expr != NULL);
11238 /* Different target types not yet supported. */
11239 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
11241 return stabilize_reference (ffecom_expr (expr));
11245 /* Do global stuff. */
11247 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11249 ffecom_finish_compile ()
11251 assert (ffecom_outer_function_decl_ == NULL_TREE);
11252 assert (current_function_decl == NULL_TREE);
11254 ffeglobal_drive (ffecom_finish_global_);
11258 /* Public entry point for front end to access finish_decl. */
11260 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11262 ffecom_finish_decl (tree decl, tree init, bool is_top_level)
11264 assert (!is_top_level);
11265 finish_decl (decl, init, FALSE);
11269 /* Finish a program unit. */
11271 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11273 ffecom_finish_progunit ()
11275 ffecom_end_compstmt ();
11277 ffecom_previous_function_decl_ = current_function_decl;
11278 ffecom_which_entrypoint_decl_ = NULL_TREE;
11280 finish_function (0);
11285 /* Wrapper for get_identifier. pattern is sprintf-like. */
11287 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11289 ffecom_get_invented_identifier (const char *pattern, ...)
11295 va_start (ap, pattern);
11296 if (vasprintf (&nam, pattern, ap) == 0)
11299 decl = get_identifier (nam);
11301 IDENTIFIER_INVENTED (decl) = 1;
11306 ffecom_gfrt_basictype (ffecomGfrt gfrt)
11308 assert (gfrt < FFECOM_gfrt);
11310 switch (ffecom_gfrt_type_[gfrt])
11312 case FFECOM_rttypeVOID_:
11313 case FFECOM_rttypeVOIDSTAR_:
11314 return FFEINFO_basictypeNONE;
11316 case FFECOM_rttypeFTNINT_:
11317 return FFEINFO_basictypeINTEGER;
11319 case FFECOM_rttypeINTEGER_:
11320 return FFEINFO_basictypeINTEGER;
11322 case FFECOM_rttypeLONGINT_:
11323 return FFEINFO_basictypeINTEGER;
11325 case FFECOM_rttypeLOGICAL_:
11326 return FFEINFO_basictypeLOGICAL;
11328 case FFECOM_rttypeREAL_F2C_:
11329 case FFECOM_rttypeREAL_GNU_:
11330 return FFEINFO_basictypeREAL;
11332 case FFECOM_rttypeCOMPLEX_F2C_:
11333 case FFECOM_rttypeCOMPLEX_GNU_:
11334 return FFEINFO_basictypeCOMPLEX;
11336 case FFECOM_rttypeDOUBLE_:
11337 case FFECOM_rttypeDOUBLEREAL_:
11338 return FFEINFO_basictypeREAL;
11340 case FFECOM_rttypeDBLCMPLX_F2C_:
11341 case FFECOM_rttypeDBLCMPLX_GNU_:
11342 return FFEINFO_basictypeCOMPLEX;
11344 case FFECOM_rttypeCHARACTER_:
11345 return FFEINFO_basictypeCHARACTER;
11348 return FFEINFO_basictypeANY;
11353 ffecom_gfrt_kindtype (ffecomGfrt gfrt)
11355 assert (gfrt < FFECOM_gfrt);
11357 switch (ffecom_gfrt_type_[gfrt])
11359 case FFECOM_rttypeVOID_:
11360 case FFECOM_rttypeVOIDSTAR_:
11361 return FFEINFO_kindtypeNONE;
11363 case FFECOM_rttypeFTNINT_:
11364 return FFEINFO_kindtypeINTEGER1;
11366 case FFECOM_rttypeINTEGER_:
11367 return FFEINFO_kindtypeINTEGER1;
11369 case FFECOM_rttypeLONGINT_:
11370 return FFEINFO_kindtypeINTEGER4;
11372 case FFECOM_rttypeLOGICAL_:
11373 return FFEINFO_kindtypeLOGICAL1;
11375 case FFECOM_rttypeREAL_F2C_:
11376 case FFECOM_rttypeREAL_GNU_:
11377 return FFEINFO_kindtypeREAL1;
11379 case FFECOM_rttypeCOMPLEX_F2C_:
11380 case FFECOM_rttypeCOMPLEX_GNU_:
11381 return FFEINFO_kindtypeREAL1;
11383 case FFECOM_rttypeDOUBLE_:
11384 case FFECOM_rttypeDOUBLEREAL_:
11385 return FFEINFO_kindtypeREAL2;
11387 case FFECOM_rttypeDBLCMPLX_F2C_:
11388 case FFECOM_rttypeDBLCMPLX_GNU_:
11389 return FFEINFO_kindtypeREAL2;
11391 case FFECOM_rttypeCHARACTER_:
11392 return FFEINFO_kindtypeCHARACTER1;
11395 return FFEINFO_kindtypeANY;
11409 tree double_ftype_double;
11410 tree float_ftype_float;
11411 tree ldouble_ftype_ldouble;
11412 tree ffecom_tree_ptr_to_fun_type_void;
11414 /* This block of code comes from the now-obsolete cktyps.c. It checks
11415 whether the compiler environment is buggy in known ways, some of which
11416 would, if not explicitly checked here, result in subtle bugs in g77. */
11418 if (ffe_is_do_internal_checks ())
11420 static char names[][12]
11422 {"bar", "bletch", "foo", "foobar"};
11427 name = bsearch ("foo", &names[0], ARRAY_SIZE (names), sizeof (names[0]),
11428 (int (*)(const void *, const void *)) strcmp);
11429 if (name != (char *) &names[2])
11431 assert ("bsearch doesn't work, #define FFEPROJ_BSEARCH 0 in proj.h"
11436 ul = strtoul ("123456789", NULL, 10);
11437 if (ul != 123456789L)
11439 assert ("strtoul doesn't have enough range, #define FFEPROJ_STRTOUL 0\
11440 in proj.h" == NULL);
11444 fl = atof ("56.789");
11445 if ((fl < 56.788) || (fl > 56.79))
11447 assert ("atof not type double, fix your #include <stdio.h>"
11453 #if FFECOM_GCC_INCLUDE
11454 ffecom_initialize_char_syntax_ ();
11457 ffecom_outer_function_decl_ = NULL_TREE;
11458 current_function_decl = NULL_TREE;
11459 named_labels = NULL_TREE;
11460 current_binding_level = NULL_BINDING_LEVEL;
11461 free_binding_level = NULL_BINDING_LEVEL;
11462 /* Make the binding_level structure for global names. */
11464 global_binding_level = current_binding_level;
11465 current_binding_level->prep_state = 2;
11467 build_common_tree_nodes (1);
11469 /* Define `int' and `char' first so that dbx will output them first. */
11470 pushdecl (build_decl (TYPE_DECL, get_identifier ("int"),
11471 integer_type_node));
11472 pushdecl (build_decl (TYPE_DECL, get_identifier ("char"),
11474 pushdecl (build_decl (TYPE_DECL, get_identifier ("long int"),
11475 long_integer_type_node));
11476 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned int"),
11477 unsigned_type_node));
11478 pushdecl (build_decl (TYPE_DECL, get_identifier ("long unsigned int"),
11479 long_unsigned_type_node));
11480 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long int"),
11481 long_long_integer_type_node));
11482 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long unsigned int"),
11483 long_long_unsigned_type_node));
11484 pushdecl (build_decl (TYPE_DECL, get_identifier ("short int"),
11485 short_integer_type_node));
11486 pushdecl (build_decl (TYPE_DECL, get_identifier ("short unsigned int"),
11487 short_unsigned_type_node));
11489 /* Set the sizetype before we make other types. This *should* be the
11490 first type we create. */
11493 (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE))));
11494 ffecom_typesize_pointer_
11495 = TREE_INT_CST_LOW (TYPE_SIZE (sizetype)) / BITS_PER_UNIT;
11497 build_common_tree_nodes_2 (0);
11499 /* Define both `signed char' and `unsigned char'. */
11500 pushdecl (build_decl (TYPE_DECL, get_identifier ("signed char"),
11501 signed_char_type_node));
11503 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned char"),
11504 unsigned_char_type_node));
11506 pushdecl (build_decl (TYPE_DECL, get_identifier ("float"),
11508 pushdecl (build_decl (TYPE_DECL, get_identifier ("double"),
11509 double_type_node));
11510 pushdecl (build_decl (TYPE_DECL, get_identifier ("long double"),
11511 long_double_type_node));
11513 /* For now, override what build_common_tree_nodes has done. */
11514 complex_integer_type_node = ffecom_make_complex_type_ (integer_type_node);
11515 complex_float_type_node = ffecom_make_complex_type_ (float_type_node);
11516 complex_double_type_node = ffecom_make_complex_type_ (double_type_node);
11517 complex_long_double_type_node
11518 = ffecom_make_complex_type_ (long_double_type_node);
11520 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex int"),
11521 complex_integer_type_node));
11522 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex float"),
11523 complex_float_type_node));
11524 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex double"),
11525 complex_double_type_node));
11526 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex long double"),
11527 complex_long_double_type_node));
11529 pushdecl (build_decl (TYPE_DECL, get_identifier ("void"),
11531 /* We are not going to have real types in C with less than byte alignment,
11532 so we might as well not have any types that claim to have it. */
11533 TYPE_ALIGN (void_type_node) = BITS_PER_UNIT;
11534 TYPE_USER_ALIGN (void_type_node) = 0;
11536 string_type_node = build_pointer_type (char_type_node);
11538 ffecom_tree_fun_type_void
11539 = build_function_type (void_type_node, NULL_TREE);
11541 ffecom_tree_ptr_to_fun_type_void
11542 = build_pointer_type (ffecom_tree_fun_type_void);
11544 endlink = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
11547 = build_function_type (float_type_node,
11548 tree_cons (NULL_TREE, float_type_node, endlink));
11550 double_ftype_double
11551 = build_function_type (double_type_node,
11552 tree_cons (NULL_TREE, double_type_node, endlink));
11554 ldouble_ftype_ldouble
11555 = build_function_type (long_double_type_node,
11556 tree_cons (NULL_TREE, long_double_type_node,
11559 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11560 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11562 ffecom_tree_type[i][j] = NULL_TREE;
11563 ffecom_tree_fun_type[i][j] = NULL_TREE;
11564 ffecom_tree_ptr_to_fun_type[i][j] = NULL_TREE;
11565 ffecom_f2c_typecode_[i][j] = -1;
11568 /* Set up standard g77 types. Note that INTEGER and LOGICAL are set
11569 to size FLOAT_TYPE_SIZE because they have to be the same size as
11570 REAL, which also is FLOAT_TYPE_SIZE, according to the standard.
11571 Compiler options and other such stuff that change the ways these
11572 types are set should not affect this particular setup. */
11574 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1]
11575 = t = make_signed_type (FLOAT_TYPE_SIZE);
11576 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer"),
11578 type = ffetype_new ();
11580 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER1,
11582 ffetype_set_ams (type,
11583 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11584 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11585 ffetype_set_star (base_type,
11586 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11588 ffetype_set_kind (base_type, 1, type);
11589 ffecom_typesize_integer1_ = ffetype_size (type);
11590 assert (ffetype_size (type) == sizeof (ffetargetInteger1));
11592 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER1]
11593 = t = make_unsigned_type (FLOAT_TYPE_SIZE); /* HOLLERITH means unsigned. */
11594 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned"),
11597 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER2]
11598 = t = make_signed_type (CHAR_TYPE_SIZE);
11599 pushdecl (build_decl (TYPE_DECL, get_identifier ("byte"),
11601 type = ffetype_new ();
11602 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER2,
11604 ffetype_set_ams (type,
11605 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11606 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11607 ffetype_set_star (base_type,
11608 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11610 ffetype_set_kind (base_type, 3, type);
11611 assert (ffetype_size (type) == sizeof (ffetargetInteger2));
11613 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER2]
11614 = t = make_unsigned_type (CHAR_TYPE_SIZE);
11615 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned byte"),
11618 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER3]
11619 = t = make_signed_type (CHAR_TYPE_SIZE * 2);
11620 pushdecl (build_decl (TYPE_DECL, get_identifier ("word"),
11622 type = ffetype_new ();
11623 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER3,
11625 ffetype_set_ams (type,
11626 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11627 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11628 ffetype_set_star (base_type,
11629 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11631 ffetype_set_kind (base_type, 6, type);
11632 assert (ffetype_size (type) == sizeof (ffetargetInteger3));
11634 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER3]
11635 = t = make_unsigned_type (CHAR_TYPE_SIZE * 2);
11636 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned word"),
11639 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER4]
11640 = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
11641 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer4"),
11643 type = ffetype_new ();
11644 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER4,
11646 ffetype_set_ams (type,
11647 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11648 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11649 ffetype_set_star (base_type,
11650 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11652 ffetype_set_kind (base_type, 2, type);
11653 assert (ffetype_size (type) == sizeof (ffetargetInteger4));
11655 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER4]
11656 = t = make_unsigned_type (FLOAT_TYPE_SIZE * 2);
11657 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned4"),
11661 if (ffe_is_do_internal_checks ()
11662 && LONG_TYPE_SIZE != FLOAT_TYPE_SIZE
11663 && LONG_TYPE_SIZE != CHAR_TYPE_SIZE
11664 && LONG_TYPE_SIZE != SHORT_TYPE_SIZE
11665 && LONG_TYPE_SIZE != LONG_LONG_TYPE_SIZE)
11667 fprintf (stderr, "Sorry, no g77 support for LONG_TYPE_SIZE (%d bits) yet.\n",
11672 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL1]
11673 = t = make_signed_type (FLOAT_TYPE_SIZE);
11674 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical"),
11676 type = ffetype_new ();
11678 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL1,
11680 ffetype_set_ams (type,
11681 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11682 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11683 ffetype_set_star (base_type,
11684 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11686 ffetype_set_kind (base_type, 1, type);
11687 assert (ffetype_size (type) == sizeof (ffetargetLogical1));
11689 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL2]
11690 = t = make_signed_type (CHAR_TYPE_SIZE);
11691 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical2"),
11693 type = ffetype_new ();
11694 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL2,
11696 ffetype_set_ams (type,
11697 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11698 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11699 ffetype_set_star (base_type,
11700 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11702 ffetype_set_kind (base_type, 3, type);
11703 assert (ffetype_size (type) == sizeof (ffetargetLogical2));
11705 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL3]
11706 = t = make_signed_type (CHAR_TYPE_SIZE * 2);
11707 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical3"),
11709 type = ffetype_new ();
11710 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL3,
11712 ffetype_set_ams (type,
11713 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11714 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11715 ffetype_set_star (base_type,
11716 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11718 ffetype_set_kind (base_type, 6, type);
11719 assert (ffetype_size (type) == sizeof (ffetargetLogical3));
11721 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL4]
11722 = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
11723 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical4"),
11725 type = ffetype_new ();
11726 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL4,
11728 ffetype_set_ams (type,
11729 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11730 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11731 ffetype_set_star (base_type,
11732 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11734 ffetype_set_kind (base_type, 2, type);
11735 assert (ffetype_size (type) == sizeof (ffetargetLogical4));
11737 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
11738 = t = make_node (REAL_TYPE);
11739 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE;
11740 pushdecl (build_decl (TYPE_DECL, get_identifier ("real"),
11743 type = ffetype_new ();
11745 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREAL1,
11747 ffetype_set_ams (type,
11748 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11749 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11750 ffetype_set_star (base_type,
11751 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11753 ffetype_set_kind (base_type, 1, type);
11754 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
11755 = FFETARGET_f2cTYREAL;
11756 assert (ffetype_size (type) == sizeof (ffetargetReal1));
11758 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREALDOUBLE]
11759 = t = make_node (REAL_TYPE);
11760 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE * 2; /* Always twice REAL. */
11761 pushdecl (build_decl (TYPE_DECL, get_identifier ("double precision"),
11764 type = ffetype_new ();
11765 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREALDOUBLE,
11767 ffetype_set_ams (type,
11768 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11769 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11770 ffetype_set_star (base_type,
11771 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11773 ffetype_set_kind (base_type, 2, type);
11774 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]
11775 = FFETARGET_f2cTYDREAL;
11776 assert (ffetype_size (type) == sizeof (ffetargetReal2));
11778 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
11779 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]);
11780 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex"),
11782 type = ffetype_new ();
11784 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREAL1,
11786 ffetype_set_ams (type,
11787 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11788 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11789 ffetype_set_star (base_type,
11790 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11792 ffetype_set_kind (base_type, 1, type);
11793 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
11794 = FFETARGET_f2cTYCOMPLEX;
11795 assert (ffetype_size (type) == sizeof (ffetargetComplex1));
11797 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREALDOUBLE]
11798 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]);
11799 pushdecl (build_decl (TYPE_DECL, get_identifier ("double complex"),
11801 type = ffetype_new ();
11802 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREALDOUBLE,
11804 ffetype_set_ams (type,
11805 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11806 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11807 ffetype_set_star (base_type,
11808 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11810 ffetype_set_kind (base_type, 2,
11812 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL2]
11813 = FFETARGET_f2cTYDCOMPLEX;
11814 assert (ffetype_size (type) == sizeof (ffetargetComplex2));
11816 /* Make function and ptr-to-function types for non-CHARACTER types. */
11818 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11819 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11821 if ((t = ffecom_tree_type[i][j]) != NULL_TREE)
11823 if (i == FFEINFO_basictypeINTEGER)
11825 /* Figure out the smallest INTEGER type that can hold
11826 a pointer on this machine. */
11827 if (GET_MODE_SIZE (TYPE_MODE (t))
11828 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
11830 if ((ffecom_pointer_kind_ == FFEINFO_kindtypeNONE)
11831 || (GET_MODE_SIZE (TYPE_MODE (ffecom_tree_type[i][ffecom_pointer_kind_]))
11832 > GET_MODE_SIZE (TYPE_MODE (t))))
11833 ffecom_pointer_kind_ = j;
11836 else if (i == FFEINFO_basictypeCOMPLEX)
11837 t = void_type_node;
11838 /* For f2c compatibility, REAL functions are really
11839 implemented as DOUBLE PRECISION. */
11840 else if ((i == FFEINFO_basictypeREAL)
11841 && (j == FFEINFO_kindtypeREAL1))
11842 t = ffecom_tree_type
11843 [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2];
11845 t = ffecom_tree_fun_type[i][j] = build_function_type (t,
11847 ffecom_tree_ptr_to_fun_type[i][j] = build_pointer_type (t);
11851 /* Set up pointer types. */
11853 if (ffecom_pointer_kind_ == FFEINFO_basictypeNONE)
11854 fatal_error ("no INTEGER type can hold a pointer on this configuration");
11855 else if (0 && ffe_is_do_internal_checks ())
11856 fprintf (stderr, "Pointer type kt=%d\n", ffecom_pointer_kind_);
11857 ffetype_set_kind (ffeinfo_type (FFEINFO_basictypeINTEGER,
11858 FFEINFO_kindtypeINTEGERDEFAULT),
11860 ffeinfo_type (FFEINFO_basictypeINTEGER,
11861 ffecom_pointer_kind_));
11863 if (ffe_is_ugly_assign ())
11864 ffecom_label_kind_ = ffecom_pointer_kind_; /* Require ASSIGN etc to this. */
11866 ffecom_label_kind_ = FFEINFO_kindtypeINTEGERDEFAULT;
11867 if (0 && ffe_is_do_internal_checks ())
11868 fprintf (stderr, "Label type kt=%d\n", ffecom_label_kind_);
11870 ffecom_integer_type_node
11871 = ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1];
11872 ffecom_integer_zero_node = convert (ffecom_integer_type_node,
11873 integer_zero_node);
11874 ffecom_integer_one_node = convert (ffecom_integer_type_node,
11877 /* Yes, the "FLOAT_TYPE_SIZE" references below are intentional.
11878 Turns out that by TYLONG, runtime/libI77/lio.h really means
11879 "whatever size an ftnint is". For consistency and sanity,
11880 com.h and runtime/f2c.h.in agree that flag, ftnint, and ftlen
11881 all are INTEGER, which we also make out of whatever back-end
11882 integer type is FLOAT_TYPE_SIZE bits wide. This change, from
11883 LONG_TYPE_SIZE, for TYLONG and TYLOGICAL, was necessary to
11884 accommodate machines like the Alpha. Note that this suggests
11885 f2c and libf2c are missing a distinction perhaps needed on
11886 some machines between "int" and "long int". -- burley 0.5.5 950215 */
11888 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, FLOAT_TYPE_SIZE,
11889 FFETARGET_f2cTYLONG);
11890 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, SHORT_TYPE_SIZE,
11891 FFETARGET_f2cTYSHORT);
11892 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, CHAR_TYPE_SIZE,
11893 FFETARGET_f2cTYINT1);
11894 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, LONG_LONG_TYPE_SIZE,
11895 FFETARGET_f2cTYQUAD);
11896 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, FLOAT_TYPE_SIZE,
11897 FFETARGET_f2cTYLOGICAL);
11898 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, SHORT_TYPE_SIZE,
11899 FFETARGET_f2cTYLOGICAL2);
11900 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, CHAR_TYPE_SIZE,
11901 FFETARGET_f2cTYLOGICAL1);
11902 /* ~~~Not really such a type in libf2c, e.g. I/O support? */
11903 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, LONG_LONG_TYPE_SIZE,
11904 FFETARGET_f2cTYQUAD);
11906 /* CHARACTER stuff is all special-cased, so it is not handled in the above
11907 loop. CHARACTER items are built as arrays of unsigned char. */
11909 ffecom_tree_type[FFEINFO_basictypeCHARACTER]
11910 [FFEINFO_kindtypeCHARACTER1] = t = char_type_node;
11911 type = ffetype_new ();
11913 ffeinfo_set_type (FFEINFO_basictypeCHARACTER,
11914 FFEINFO_kindtypeCHARACTER1,
11916 ffetype_set_ams (type,
11917 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11918 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11919 ffetype_set_kind (base_type, 1, type);
11920 assert (ffetype_size (type)
11921 == sizeof (((ffetargetCharacter1) { 0, NULL }).text[0]));
11923 ffecom_tree_fun_type[FFEINFO_basictypeCHARACTER]
11924 [FFEINFO_kindtypeCHARACTER1] = ffecom_tree_fun_type_void;
11925 ffecom_tree_ptr_to_fun_type[FFEINFO_basictypeCHARACTER]
11926 [FFEINFO_kindtypeCHARACTER1]
11927 = ffecom_tree_ptr_to_fun_type_void;
11928 ffecom_f2c_typecode_[FFEINFO_basictypeCHARACTER][FFEINFO_kindtypeCHARACTER1]
11929 = FFETARGET_f2cTYCHAR;
11931 ffecom_f2c_typecode_[FFEINFO_basictypeANY][FFEINFO_kindtypeANY]
11934 /* Make multi-return-value type and fields. */
11936 ffecom_multi_type_node_ = make_node (UNION_TYPE);
11940 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11941 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11945 if (ffecom_tree_type[i][j] == NULL_TREE)
11946 continue; /* Not supported. */
11947 sprintf (&name[0], "bt_%s_kt_%s",
11948 ffeinfo_basictype_string ((ffeinfoBasictype) i),
11949 ffeinfo_kindtype_string ((ffeinfoKindtype) j));
11950 ffecom_multi_fields_[i][j] = build_decl (FIELD_DECL,
11951 get_identifier (name),
11952 ffecom_tree_type[i][j]);
11953 DECL_CONTEXT (ffecom_multi_fields_[i][j])
11954 = ffecom_multi_type_node_;
11955 DECL_ALIGN (ffecom_multi_fields_[i][j]) = 0;
11956 DECL_USER_ALIGN (ffecom_multi_fields_[i][j]) = 0;
11957 TREE_CHAIN (ffecom_multi_fields_[i][j]) = field;
11958 field = ffecom_multi_fields_[i][j];
11961 TYPE_FIELDS (ffecom_multi_type_node_) = field;
11962 layout_type (ffecom_multi_type_node_);
11964 /* Subroutines usually return integer because they might have alternate
11967 ffecom_tree_subr_type
11968 = build_function_type (integer_type_node, NULL_TREE);
11969 ffecom_tree_ptr_to_subr_type
11970 = build_pointer_type (ffecom_tree_subr_type);
11971 ffecom_tree_blockdata_type
11972 = build_function_type (void_type_node, NULL_TREE);
11974 builtin_function ("__builtin_sqrtf", float_ftype_float,
11975 BUILT_IN_FSQRT, BUILT_IN_NORMAL, "sqrtf");
11976 builtin_function ("__builtin_fsqrt", double_ftype_double,
11977 BUILT_IN_FSQRT, BUILT_IN_NORMAL, "sqrt");
11978 builtin_function ("__builtin_sqrtl", ldouble_ftype_ldouble,
11979 BUILT_IN_FSQRT, BUILT_IN_NORMAL, "sqrtl");
11980 builtin_function ("__builtin_sinf", float_ftype_float,
11981 BUILT_IN_SIN, BUILT_IN_NORMAL, "sinf");
11982 builtin_function ("__builtin_sin", double_ftype_double,
11983 BUILT_IN_SIN, BUILT_IN_NORMAL, "sin");
11984 builtin_function ("__builtin_sinl", ldouble_ftype_ldouble,
11985 BUILT_IN_SIN, BUILT_IN_NORMAL, "sinl");
11986 builtin_function ("__builtin_cosf", float_ftype_float,
11987 BUILT_IN_COS, BUILT_IN_NORMAL, "cosf");
11988 builtin_function ("__builtin_cos", double_ftype_double,
11989 BUILT_IN_COS, BUILT_IN_NORMAL, "cos");
11990 builtin_function ("__builtin_cosl", ldouble_ftype_ldouble,
11991 BUILT_IN_COS, BUILT_IN_NORMAL, "cosl");
11994 pedantic_lvalues = FALSE;
11997 ffecom_f2c_make_type_ (&ffecom_f2c_integer_type_node,
12000 ffecom_f2c_make_type_ (&ffecom_f2c_address_type_node,
12003 ffecom_f2c_make_type_ (&ffecom_f2c_real_type_node,
12006 ffecom_f2c_make_type_ (&ffecom_f2c_doublereal_type_node,
12007 FFECOM_f2cDOUBLEREAL,
12009 ffecom_f2c_make_type_ (&ffecom_f2c_complex_type_node,
12012 ffecom_f2c_make_type_ (&ffecom_f2c_doublecomplex_type_node,
12013 FFECOM_f2cDOUBLECOMPLEX,
12015 ffecom_f2c_make_type_ (&ffecom_f2c_longint_type_node,
12018 ffecom_f2c_make_type_ (&ffecom_f2c_logical_type_node,
12021 ffecom_f2c_make_type_ (&ffecom_f2c_flag_type_node,
12024 ffecom_f2c_make_type_ (&ffecom_f2c_ftnlen_type_node,
12027 ffecom_f2c_make_type_ (&ffecom_f2c_ftnint_type_node,
12031 ffecom_f2c_ftnlen_zero_node
12032 = convert (ffecom_f2c_ftnlen_type_node, integer_zero_node);
12034 ffecom_f2c_ftnlen_one_node
12035 = convert (ffecom_f2c_ftnlen_type_node, integer_one_node);
12037 ffecom_f2c_ftnlen_two_node = build_int_2 (2, 0);
12038 TREE_TYPE (ffecom_f2c_ftnlen_two_node) = ffecom_integer_type_node;
12040 ffecom_f2c_ptr_to_ftnlen_type_node
12041 = build_pointer_type (ffecom_f2c_ftnlen_type_node);
12043 ffecom_f2c_ptr_to_ftnint_type_node
12044 = build_pointer_type (ffecom_f2c_ftnint_type_node);
12046 ffecom_f2c_ptr_to_integer_type_node
12047 = build_pointer_type (ffecom_f2c_integer_type_node);
12049 ffecom_f2c_ptr_to_real_type_node
12050 = build_pointer_type (ffecom_f2c_real_type_node);
12052 ffecom_float_zero_ = build_real (float_type_node, dconst0);
12053 ffecom_double_zero_ = build_real (double_type_node, dconst0);
12055 REAL_VALUE_TYPE point_5;
12057 #ifdef REAL_ARITHMETIC
12058 REAL_ARITHMETIC (point_5, RDIV_EXPR, dconst1, dconst2);
12062 ffecom_float_half_ = build_real (float_type_node, point_5);
12063 ffecom_double_half_ = build_real (double_type_node, point_5);
12066 /* Do "extern int xargc;". */
12068 ffecom_tree_xargc_ = build_decl (VAR_DECL,
12069 get_identifier ("f__xargc"),
12070 integer_type_node);
12071 DECL_EXTERNAL (ffecom_tree_xargc_) = 1;
12072 TREE_STATIC (ffecom_tree_xargc_) = 1;
12073 TREE_PUBLIC (ffecom_tree_xargc_) = 1;
12074 ffecom_tree_xargc_ = start_decl (ffecom_tree_xargc_, FALSE);
12075 finish_decl (ffecom_tree_xargc_, NULL_TREE, FALSE);
12077 #if 0 /* This is being fixed, and seems to be working now. */
12078 if ((FLOAT_TYPE_SIZE != 32)
12079 || (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))) != 32))
12081 warning ("configuration: REAL, INTEGER, and LOGICAL are %d bits wide,",
12082 (int) FLOAT_TYPE_SIZE);
12083 warning ("and pointers are %d bits wide, but g77 doesn't yet work",
12084 (int) TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))));
12085 warning ("properly unless they all are 32 bits wide.");
12086 warning ("Please keep this in mind before you report bugs. g77 should");
12087 warning ("support non-32-bit machines better as of version 0.6.");
12091 #if 0 /* Code in ste.c that would crash has been commented out. */
12092 if (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)
12093 < TYPE_PRECISION (string_type_node))
12094 /* I/O will probably crash. */
12095 warning ("configuration: char * holds %d bits, but ftnlen only %d",
12096 TYPE_PRECISION (string_type_node),
12097 TYPE_PRECISION (ffecom_f2c_ftnlen_type_node));
12100 #if 0 /* ASSIGN-related stuff has been changed to accommodate this. */
12101 if (TYPE_PRECISION (ffecom_integer_type_node)
12102 < TYPE_PRECISION (string_type_node))
12103 /* ASSIGN 10 TO I will crash. */
12104 warning ("configuration: char * holds %d bits, but INTEGER only %d --\n\
12105 ASSIGN statement might fail",
12106 TYPE_PRECISION (string_type_node),
12107 TYPE_PRECISION (ffecom_integer_type_node));
12112 /* ffecom_init_2 -- Initialize
12114 ffecom_init_2(); */
12116 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12120 assert (ffecom_outer_function_decl_ == NULL_TREE);
12121 assert (current_function_decl == NULL_TREE);
12122 assert (ffecom_which_entrypoint_decl_ == NULL_TREE);
12124 ffecom_master_arglist_ = NULL;
12126 ffecom_primary_entry_ = NULL;
12127 ffecom_is_altreturning_ = FALSE;
12128 ffecom_func_result_ = NULL_TREE;
12129 ffecom_multi_retval_ = NULL_TREE;
12133 /* ffecom_list_expr -- Transform list of exprs into gcc tree
12136 ffebld expr; // FFE opITEM list.
12137 tree = ffecom_list_expr(expr);
12139 List of actual args is transformed into corresponding gcc backend list. */
12141 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12143 ffecom_list_expr (ffebld expr)
12146 tree *plist = &list;
12147 tree trail = NULL_TREE; /* Append char length args here. */
12148 tree *ptrail = &trail;
12151 while (expr != NULL)
12153 tree texpr = ffecom_arg_expr (ffebld_head (expr), &length);
12155 if (texpr == error_mark_node)
12156 return error_mark_node;
12158 *plist = build_tree_list (NULL_TREE, texpr);
12159 plist = &TREE_CHAIN (*plist);
12160 expr = ffebld_trail (expr);
12161 if (length != NULL_TREE)
12163 *ptrail = build_tree_list (NULL_TREE, length);
12164 ptrail = &TREE_CHAIN (*ptrail);
12174 /* ffecom_list_ptr_to_expr -- Transform list of exprs into gcc tree
12177 ffebld expr; // FFE opITEM list.
12178 tree = ffecom_list_ptr_to_expr(expr);
12180 List of actual args is transformed into corresponding gcc backend list for
12181 use in calling an external procedure (vs. a statement function). */
12183 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12185 ffecom_list_ptr_to_expr (ffebld expr)
12188 tree *plist = &list;
12189 tree trail = NULL_TREE; /* Append char length args here. */
12190 tree *ptrail = &trail;
12193 while (expr != NULL)
12195 tree texpr = ffecom_arg_ptr_to_expr (ffebld_head (expr), &length);
12197 if (texpr == error_mark_node)
12198 return error_mark_node;
12200 *plist = build_tree_list (NULL_TREE, texpr);
12201 plist = &TREE_CHAIN (*plist);
12202 expr = ffebld_trail (expr);
12203 if (length != NULL_TREE)
12205 *ptrail = build_tree_list (NULL_TREE, length);
12206 ptrail = &TREE_CHAIN (*ptrail);
12216 /* Obtain gcc's LABEL_DECL tree for label. */
12218 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12220 ffecom_lookup_label (ffelab label)
12224 if (ffelab_hook (label) == NULL_TREE)
12226 char labelname[16];
12228 switch (ffelab_type (label))
12230 case FFELAB_typeLOOPEND:
12231 case FFELAB_typeNOTLOOP:
12232 case FFELAB_typeENDIF:
12233 sprintf (labelname, "%" ffelabValue_f "u", ffelab_value (label));
12234 glabel = build_decl (LABEL_DECL, get_identifier (labelname),
12236 DECL_CONTEXT (glabel) = current_function_decl;
12237 DECL_MODE (glabel) = VOIDmode;
12240 case FFELAB_typeFORMAT:
12241 glabel = build_decl (VAR_DECL,
12242 ffecom_get_invented_identifier
12243 ("__g77_format_%d", (int) ffelab_value (label)),
12244 build_type_variant (build_array_type
12248 TREE_CONSTANT (glabel) = 1;
12249 TREE_STATIC (glabel) = 1;
12250 DECL_CONTEXT (glabel) = current_function_decl;
12251 DECL_INITIAL (glabel) = NULL;
12252 make_decl_rtl (glabel, NULL);
12253 expand_decl (glabel);
12255 ffecom_save_tree_forever (glabel);
12259 case FFELAB_typeANY:
12260 glabel = error_mark_node;
12264 assert ("bad label type" == NULL);
12268 ffelab_set_hook (label, glabel);
12272 glabel = ffelab_hook (label);
12279 /* Stabilizes the arguments. Don't use this if the lhs and rhs come from
12280 a single source specification (as in the fourth argument of MVBITS).
12281 If the type is NULL_TREE, the type of lhs is used to make the type of
12282 the MODIFY_EXPR. */
12284 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12286 ffecom_modify (tree newtype, tree lhs,
12289 if (lhs == error_mark_node || rhs == error_mark_node)
12290 return error_mark_node;
12292 if (newtype == NULL_TREE)
12293 newtype = TREE_TYPE (lhs);
12295 if (TREE_SIDE_EFFECTS (lhs))
12296 lhs = stabilize_reference (lhs);
12298 return ffecom_2s (MODIFY_EXPR, newtype, lhs, rhs);
12303 /* Register source file name. */
12306 ffecom_file (const char *name)
12308 #if FFECOM_GCC_INCLUDE
12309 ffecom_file_ (name);
12313 /* ffecom_notify_init_storage -- An aggregate storage is now fully init'ed
12316 ffecom_notify_init_storage(st);
12318 Gets called when all possible units in an aggregate storage area (a LOCAL
12319 with equivalences or a COMMON) have been initialized. The initialization
12320 info either is in ffestorag_init or, if that is NULL,
12321 ffestorag_accretion:
12323 ffestorag_init may contain an opCONTER or opARRTER. opCONTER may occur
12324 even for an array if the array is one element in length!
12326 ffestorag_accretion will contain an opACCTER. It is much like an
12327 opARRTER except it has an ffebit object in it instead of just a size.
12328 The back end can use the info in the ffebit object, if it wants, to
12329 reduce the amount of actual initialization, but in any case it should
12330 kill the ffebit object when done. Also, set accretion to NULL but
12331 init to a non-NULL value.
12333 After performing initialization, DO NOT set init to NULL, because that'll
12334 tell the front end it is ok for more initialization to happen. Instead,
12335 set init to an opANY expression or some such thing that you can use to
12336 tell that you've already initialized the object.
12339 Support two-pass FFE. */
12342 ffecom_notify_init_storage (ffestorag st)
12344 ffebld init; /* The initialization expression. */
12345 #if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12346 ffetargetOffset size; /* The size of the entity. */
12347 ffetargetAlign pad; /* Its initial padding. */
12350 if (ffestorag_init (st) == NULL)
12352 init = ffestorag_accretion (st);
12353 assert (init != NULL);
12354 ffestorag_set_accretion (st, NULL);
12355 ffestorag_set_accretes (st, 0);
12357 #if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12358 /* For GNU backend, just turn ACCTER into ARRTER and proceed. */
12359 size = ffebld_accter_size (init);
12360 pad = ffebld_accter_pad (init);
12361 ffebit_kill (ffebld_accter_bits (init));
12362 ffebld_set_op (init, FFEBLD_opARRTER);
12363 ffebld_set_arrter (init, ffebld_accter (init));
12364 ffebld_arrter_set_size (init, size);
12365 ffebld_arrter_set_pad (init, size);
12369 ffestorag_set_init (st, init);
12374 init = ffestorag_init (st);
12377 #if FFECOM_ONEPASS /* Process the inits, wipe 'em out. */
12378 ffestorag_set_init (st, ffebld_new_any ());
12380 if (ffebld_op (init) == FFEBLD_opANY)
12381 return; /* Oh, we already did this! */
12383 #if FFECOM_targetCURRENT == FFECOM_targetFFE
12387 if (ffestorag_symbol (st) != NULL)
12388 s = ffestorag_symbol (st);
12390 s = ffestorag_typesymbol (st);
12392 fprintf (dmpout, "= initialize_storage \"%s\" ",
12393 (s != NULL) ? ffesymbol_text (s) : "(unnamed)");
12394 ffebld_dump (init);
12395 fputc ('\n', dmpout);
12399 #endif /* if FFECOM_ONEPASS */
12402 /* ffecom_notify_init_symbol -- A symbol is now fully init'ed
12405 ffecom_notify_init_symbol(s);
12407 Gets called when all possible units in a symbol (not placed in COMMON
12408 or involved in EQUIVALENCE, unless it as yet has no ffestorag object)
12409 have been initialized. The initialization info either is in
12410 ffesymbol_init or, if that is NULL, ffesymbol_accretion:
12412 ffesymbol_init may contain an opCONTER or opARRTER. opCONTER may occur
12413 even for an array if the array is one element in length!
12415 ffesymbol_accretion will contain an opACCTER. It is much like an
12416 opARRTER except it has an ffebit object in it instead of just a size.
12417 The back end can use the info in the ffebit object, if it wants, to
12418 reduce the amount of actual initialization, but in any case it should
12419 kill the ffebit object when done. Also, set accretion to NULL but
12420 init to a non-NULL value.
12422 After performing initialization, DO NOT set init to NULL, because that'll
12423 tell the front end it is ok for more initialization to happen. Instead,
12424 set init to an opANY expression or some such thing that you can use to
12425 tell that you've already initialized the object.
12428 Support two-pass FFE. */
12431 ffecom_notify_init_symbol (ffesymbol s)
12433 ffebld init; /* The initialization expression. */
12434 #if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12435 ffetargetOffset size; /* The size of the entity. */
12436 ffetargetAlign pad; /* Its initial padding. */
12439 if (ffesymbol_storage (s) == NULL)
12440 return; /* Do nothing until COMMON/EQUIVALENCE
12441 possibilities checked. */
12443 if ((ffesymbol_init (s) == NULL)
12444 && ((init = ffesymbol_accretion (s)) != NULL))
12446 ffesymbol_set_accretion (s, NULL);
12447 ffesymbol_set_accretes (s, 0);
12449 #if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12450 /* For GNU backend, just turn ACCTER into ARRTER and proceed. */
12451 size = ffebld_accter_size (init);
12452 pad = ffebld_accter_pad (init);
12453 ffebit_kill (ffebld_accter_bits (init));
12454 ffebld_set_op (init, FFEBLD_opARRTER);
12455 ffebld_set_arrter (init, ffebld_accter (init));
12456 ffebld_arrter_set_size (init, size);
12457 ffebld_arrter_set_pad (init, size);
12461 ffesymbol_set_init (s, init);
12466 init = ffesymbol_init (s);
12470 ffesymbol_set_init (s, ffebld_new_any ());
12472 if (ffebld_op (init) == FFEBLD_opANY)
12473 return; /* Oh, we already did this! */
12475 #if FFECOM_targetCURRENT == FFECOM_targetFFE
12476 fprintf (dmpout, "= initialize_symbol \"%s\" ", ffesymbol_text (s));
12477 ffebld_dump (init);
12478 fputc ('\n', dmpout);
12481 #endif /* if FFECOM_ONEPASS */
12484 /* ffecom_notify_primary_entry -- Learn which is the primary entry point
12487 ffecom_notify_primary_entry(s);
12489 Gets called when implicit or explicit PROGRAM statement seen or when
12490 FUNCTION, SUBROUTINE, or BLOCK DATA statement seen, with the primary
12491 global symbol that serves as the entry point. */
12494 ffecom_notify_primary_entry (ffesymbol s)
12496 ffecom_primary_entry_ = s;
12497 ffecom_primary_entry_kind_ = ffesymbol_kind (s);
12499 if ((ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
12500 || (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE))
12501 ffecom_primary_entry_is_proc_ = TRUE;
12503 ffecom_primary_entry_is_proc_ = FALSE;
12505 if (!ffe_is_silent ())
12507 if (ffecom_primary_entry_kind_ == FFEINFO_kindPROGRAM)
12508 fprintf (stderr, "%s:\n", ffesymbol_text (s));
12510 fprintf (stderr, " %s:\n", ffesymbol_text (s));
12513 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12514 if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
12519 for (list = ffesymbol_dummyargs (s);
12521 list = ffebld_trail (list))
12523 arg = ffebld_head (list);
12524 if (ffebld_op (arg) == FFEBLD_opSTAR)
12526 ffecom_is_altreturning_ = TRUE;
12535 ffecom_open_include (char *name, ffewhereLine l, ffewhereColumn c)
12537 #if FFECOM_GCC_INCLUDE
12538 return ffecom_open_include_ (name, l, c);
12540 return fopen (name, "r");
12544 /* ffecom_ptr_to_expr -- Transform expr into gcc tree with & in front
12547 ffebld expr; // FFE expression.
12548 tree = ffecom_ptr_to_expr(expr);
12550 Like ffecom_expr, but sticks address-of in front of most things. */
12552 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12554 ffecom_ptr_to_expr (ffebld expr)
12557 ffeinfoBasictype bt;
12558 ffeinfoKindtype kt;
12561 assert (expr != NULL);
12563 switch (ffebld_op (expr))
12565 case FFEBLD_opSYMTER:
12566 s = ffebld_symter (expr);
12567 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
12571 ix = ffeintrin_gfrt_indirect (ffebld_symter_implementation (expr));
12572 assert (ix != FFECOM_gfrt);
12573 if ((item = ffecom_gfrt_[ix]) == NULL_TREE)
12575 ffecom_make_gfrt_ (ix);
12576 item = ffecom_gfrt_[ix];
12581 item = ffesymbol_hook (s).decl_tree;
12582 if (item == NULL_TREE)
12584 s = ffecom_sym_transform_ (s);
12585 item = ffesymbol_hook (s).decl_tree;
12588 assert (item != NULL);
12589 if (item == error_mark_node)
12591 if (!ffesymbol_hook (s).addr)
12592 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12596 case FFEBLD_opARRAYREF:
12597 return ffecom_arrayref_ (NULL_TREE, expr, 1);
12599 case FFEBLD_opCONTER:
12601 bt = ffeinfo_basictype (ffebld_info (expr));
12602 kt = ffeinfo_kindtype (ffebld_info (expr));
12604 item = ffecom_constantunion (&ffebld_constant_union
12605 (ffebld_conter (expr)), bt, kt,
12606 ffecom_tree_type[bt][kt]);
12607 if (item == error_mark_node)
12608 return error_mark_node;
12609 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12614 return error_mark_node;
12617 bt = ffeinfo_basictype (ffebld_info (expr));
12618 kt = ffeinfo_kindtype (ffebld_info (expr));
12620 item = ffecom_expr (expr);
12621 if (item == error_mark_node)
12622 return error_mark_node;
12624 /* The back end currently optimizes a bit too zealously for us, in that
12625 we fail JCB001 if the following block of code is omitted. It checks
12626 to see if the transformed expression is a symbol or array reference,
12627 and encloses it in a SAVE_EXPR if that is the case. */
12630 if ((TREE_CODE (item) == VAR_DECL)
12631 || (TREE_CODE (item) == PARM_DECL)
12632 || (TREE_CODE (item) == RESULT_DECL)
12633 || (TREE_CODE (item) == INDIRECT_REF)
12634 || (TREE_CODE (item) == ARRAY_REF)
12635 || (TREE_CODE (item) == COMPONENT_REF)
12637 || (TREE_CODE (item) == OFFSET_REF)
12639 || (TREE_CODE (item) == BUFFER_REF)
12640 || (TREE_CODE (item) == REALPART_EXPR)
12641 || (TREE_CODE (item) == IMAGPART_EXPR))
12643 item = ffecom_save_tree (item);
12646 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12651 assert ("fall-through error" == NULL);
12652 return error_mark_node;
12656 /* Obtain a temp var with given data type.
12658 size is FFETARGET_charactersizeNONE for a non-CHARACTER type
12659 or >= 0 for a CHARACTER type.
12661 elements is -1 for a scalar or > 0 for an array of type. */
12663 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12665 ffecom_make_tempvar (const char *commentary, tree type,
12666 ffetargetCharacterSize size, int elements)
12669 static int mynumber;
12671 assert (current_binding_level->prep_state < 2);
12673 if (type == error_mark_node)
12674 return error_mark_node;
12676 if (size != FFETARGET_charactersizeNONE)
12677 type = build_array_type (type,
12678 build_range_type (ffecom_f2c_ftnlen_type_node,
12679 ffecom_f2c_ftnlen_one_node,
12680 build_int_2 (size, 0)));
12681 if (elements != -1)
12682 type = build_array_type (type,
12683 build_range_type (integer_type_node,
12685 build_int_2 (elements - 1,
12687 t = build_decl (VAR_DECL,
12688 ffecom_get_invented_identifier ("__g77_%s_%d",
12693 t = start_decl (t, FALSE);
12694 finish_decl (t, NULL_TREE, FALSE);
12700 /* Prepare argument pointer to expression.
12702 Like ffecom_prepare_expr, except for expressions to be evaluated
12703 via ffecom_arg_ptr_to_expr. */
12706 ffecom_prepare_arg_ptr_to_expr (ffebld expr)
12708 /* ~~For now, it seems to be the same thing. */
12709 ffecom_prepare_expr (expr);
12713 /* End of preparations. */
12716 ffecom_prepare_end (void)
12718 int prep_state = current_binding_level->prep_state;
12720 assert (prep_state < 2);
12721 current_binding_level->prep_state = 2;
12723 return (prep_state == 1) ? TRUE : FALSE;
12726 /* Prepare expression.
12728 This is called before any code is generated for the current block.
12729 It scans the expression, declares any temporaries that might be needed
12730 during evaluation of the expression, and stores those temporaries in
12731 the appropriate "hook" fields of the expression. `dest', if not NULL,
12732 specifies the destination that ffecom_expr_ will see, in case that
12733 helps avoid generating unused temporaries.
12735 ~~Improve to avoid allocating unused temporaries by taking `dest'
12736 into account vis-a-vis aliasing requirements of complex/character
12740 ffecom_prepare_expr_ (ffebld expr, ffebld dest UNUSED)
12742 ffeinfoBasictype bt;
12743 ffeinfoKindtype kt;
12744 ffetargetCharacterSize sz;
12745 tree tempvar = NULL_TREE;
12747 assert (current_binding_level->prep_state < 2);
12752 bt = ffeinfo_basictype (ffebld_info (expr));
12753 kt = ffeinfo_kindtype (ffebld_info (expr));
12754 sz = ffeinfo_size (ffebld_info (expr));
12756 /* Generate whatever temporaries are needed to represent the result
12757 of the expression. */
12759 if (bt == FFEINFO_basictypeCHARACTER)
12761 while (ffebld_op (expr) == FFEBLD_opPAREN)
12762 expr = ffebld_left (expr);
12765 switch (ffebld_op (expr))
12768 /* Don't make temps for SYMTER, CONTER, etc. */
12769 if (ffebld_arity (expr) == 0)
12774 case FFEINFO_basictypeCOMPLEX:
12775 if (ffebld_op (expr) == FFEBLD_opFUNCREF)
12779 if (ffebld_op (ffebld_left (expr)) != FFEBLD_opSYMTER)
12782 s = ffebld_symter (ffebld_left (expr));
12783 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT
12784 || (ffesymbol_where (s) != FFEINFO_whereINTRINSIC
12785 && ! ffesymbol_is_f2c (s))
12786 || (ffesymbol_where (s) == FFEINFO_whereINTRINSIC
12787 && ! ffe_is_f2c_library ()))
12790 else if (ffebld_op (expr) == FFEBLD_opPOWER)
12792 /* Requires special treatment. There's no POW_CC function
12793 in libg2c, so POW_ZZ is used, which means we always
12794 need a double-complex temp, not a single-complex. */
12795 kt = FFEINFO_kindtypeREAL2;
12797 else if (ffebld_op (expr) != FFEBLD_opDIVIDE)
12798 /* The other ops don't need temps for complex operands. */
12801 /* ~~~Avoid making temps for some intrinsics, such as AIMAG(C),
12802 REAL(C). See 19990325-0.f, routine `check', for cases. */
12803 tempvar = ffecom_make_tempvar ("complex",
12805 [FFEINFO_basictypeCOMPLEX][kt],
12806 FFETARGET_charactersizeNONE,
12810 case FFEINFO_basictypeCHARACTER:
12811 if (ffebld_op (expr) != FFEBLD_opFUNCREF)
12814 if (sz == FFETARGET_charactersizeNONE)
12815 /* ~~Kludge alert! This should someday be fixed. */
12818 tempvar = ffecom_make_tempvar ("char", char_type_node, sz, -1);
12827 case FFEBLD_opPOWER:
12830 tree rtmp, ltmp, result;
12832 ltype = ffecom_type_expr (ffebld_left (expr));
12833 rtype = ffecom_type_expr (ffebld_right (expr));
12835 rtmp = ffecom_make_tempvar (rtype, FFETARGET_charactersizeNONE, -1);
12836 ltmp = ffecom_make_tempvar (ltype, FFETARGET_charactersizeNONE, -1);
12837 result = ffecom_make_tempvar (ltype, FFETARGET_charactersizeNONE, -1);
12839 tempvar = make_tree_vec (3);
12840 TREE_VEC_ELT (tempvar, 0) = rtmp;
12841 TREE_VEC_ELT (tempvar, 1) = ltmp;
12842 TREE_VEC_ELT (tempvar, 2) = result;
12847 case FFEBLD_opCONCATENATE:
12849 /* This gets special handling, because only one set of temps
12850 is needed for a tree of these -- the tree is treated as
12851 a flattened list of concatenations when generating code. */
12853 ffecomConcatList_ catlist;
12854 tree ltmp, itmp, result;
12858 catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
12859 count = ffecom_concat_list_count_ (catlist);
12864 = ffecom_make_tempvar ("concat_len",
12865 ffecom_f2c_ftnlen_type_node,
12866 FFETARGET_charactersizeNONE, count);
12868 = ffecom_make_tempvar ("concat_item",
12869 ffecom_f2c_address_type_node,
12870 FFETARGET_charactersizeNONE, count);
12872 = ffecom_make_tempvar ("concat_res",
12874 ffecom_concat_list_maxlen_ (catlist),
12877 tempvar = make_tree_vec (3);
12878 TREE_VEC_ELT (tempvar, 0) = ltmp;
12879 TREE_VEC_ELT (tempvar, 1) = itmp;
12880 TREE_VEC_ELT (tempvar, 2) = result;
12883 for (i = 0; i < count; ++i)
12884 ffecom_prepare_arg_ptr_to_expr (ffecom_concat_list_expr_ (catlist,
12887 ffecom_concat_list_kill_ (catlist);
12891 ffebld_nonter_set_hook (expr, tempvar);
12892 current_binding_level->prep_state = 1;
12897 case FFEBLD_opCONVERT:
12898 if (bt == FFEINFO_basictypeCHARACTER
12899 && ((ffebld_size_known (ffebld_left (expr))
12900 == FFETARGET_charactersizeNONE)
12901 || (ffebld_size_known (ffebld_left (expr)) >= sz)))
12902 tempvar = ffecom_make_tempvar ("convert", char_type_node, sz, -1);
12908 ffebld_nonter_set_hook (expr, tempvar);
12909 current_binding_level->prep_state = 1;
12912 /* Prepare subexpressions for this expr. */
12914 switch (ffebld_op (expr))
12916 case FFEBLD_opPERCENT_LOC:
12917 ffecom_prepare_ptr_to_expr (ffebld_left (expr));
12920 case FFEBLD_opPERCENT_VAL:
12921 case FFEBLD_opPERCENT_REF:
12922 ffecom_prepare_expr (ffebld_left (expr));
12925 case FFEBLD_opPERCENT_DESCR:
12926 ffecom_prepare_arg_ptr_to_expr (ffebld_left (expr));
12929 case FFEBLD_opITEM:
12935 item = ffebld_trail (item))
12936 if (ffebld_head (item) != NULL)
12937 ffecom_prepare_expr (ffebld_head (item));
12942 /* Need to handle character conversion specially. */
12943 switch (ffebld_arity (expr))
12946 ffecom_prepare_expr (ffebld_left (expr));
12947 ffecom_prepare_expr (ffebld_right (expr));
12951 ffecom_prepare_expr (ffebld_left (expr));
12962 /* Prepare expression for reading and writing.
12964 Like ffecom_prepare_expr, except for expressions to be evaluated
12965 via ffecom_expr_rw. */
12968 ffecom_prepare_expr_rw (tree type, ffebld expr)
12970 /* This is all we support for now. */
12971 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
12973 /* ~~For now, it seems to be the same thing. */
12974 ffecom_prepare_expr (expr);
12978 /* Prepare expression for writing.
12980 Like ffecom_prepare_expr, except for expressions to be evaluated
12981 via ffecom_expr_w. */
12984 ffecom_prepare_expr_w (tree type, ffebld expr)
12986 /* This is all we support for now. */
12987 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
12989 /* ~~For now, it seems to be the same thing. */
12990 ffecom_prepare_expr (expr);
12994 /* Prepare expression for returning.
12996 Like ffecom_prepare_expr, except for expressions to be evaluated
12997 via ffecom_return_expr. */
13000 ffecom_prepare_return_expr (ffebld expr)
13002 assert (current_binding_level->prep_state < 2);
13004 if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE
13005 && ffecom_is_altreturning_
13007 ffecom_prepare_expr (expr);
13010 /* Prepare pointer to expression.
13012 Like ffecom_prepare_expr, except for expressions to be evaluated
13013 via ffecom_ptr_to_expr. */
13016 ffecom_prepare_ptr_to_expr (ffebld expr)
13018 /* ~~For now, it seems to be the same thing. */
13019 ffecom_prepare_expr (expr);
13023 /* Transform expression into constant pointer-to-expression tree.
13025 If the expression can be transformed into a pointer-to-expression tree
13026 that is constant, that is done, and the tree returned. Else NULL_TREE
13029 That way, a caller can attempt to provide compile-time initialization
13030 of a variable and, if that fails, *then* choose to start a new block
13031 and resort to using temporaries, as appropriate. */
13034 ffecom_ptr_to_const_expr (ffebld expr)
13037 return integer_zero_node;
13039 if (ffebld_op (expr) == FFEBLD_opANY)
13040 return error_mark_node;
13042 if (ffebld_arity (expr) == 0
13043 && (ffebld_op (expr) != FFEBLD_opSYMTER
13044 || ffebld_where (expr) == FFEINFO_whereCOMMON
13045 || ffebld_where (expr) == FFEINFO_whereGLOBAL
13046 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
13050 t = ffecom_ptr_to_expr (expr);
13051 assert (TREE_CONSTANT (t));
13058 /* ffecom_return_expr -- Returns return-value expr given alt return expr
13060 tree rtn; // NULL_TREE means use expand_null_return()
13061 ffebld expr; // NULL if no alt return expr to RETURN stmt
13062 rtn = ffecom_return_expr(expr);
13064 Based on the program unit type and other info (like return function
13065 type, return master function type when alternate ENTRY points,
13066 whether subroutine has any alternate RETURN points, etc), returns the
13067 appropriate expression to be returned to the caller, or NULL_TREE
13068 meaning no return value or the caller expects it to be returned somewhere
13069 else (which is handled by other parts of this module). */
13071 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13073 ffecom_return_expr (ffebld expr)
13077 switch (ffecom_primary_entry_kind_)
13079 case FFEINFO_kindPROGRAM:
13080 case FFEINFO_kindBLOCKDATA:
13084 case FFEINFO_kindSUBROUTINE:
13085 if (!ffecom_is_altreturning_)
13086 rtn = NULL_TREE; /* No alt returns, never an expr. */
13087 else if (expr == NULL)
13088 rtn = integer_zero_node;
13090 rtn = ffecom_expr (expr);
13093 case FFEINFO_kindFUNCTION:
13094 if ((ffecom_multi_retval_ != NULL_TREE)
13095 || (ffesymbol_basictype (ffecom_primary_entry_)
13096 == FFEINFO_basictypeCHARACTER)
13097 || ((ffesymbol_basictype (ffecom_primary_entry_)
13098 == FFEINFO_basictypeCOMPLEX)
13099 && (ffecom_num_entrypoints_ == 0)
13100 && ffesymbol_is_f2c (ffecom_primary_entry_)))
13101 { /* Value is returned by direct assignment
13102 into (implicit) dummy. */
13106 rtn = ffecom_func_result_;
13108 /* Spurious error if RETURN happens before first reference! So elide
13109 this code. In particular, for debugging registry, rtn should always
13110 be non-null after all, but TREE_USED won't be set until we encounter
13111 a reference in the code. Perfectly okay (but weird) code that,
13112 e.g., has "GOTO 20;10 RETURN;20 RTN=0;GOTO 10", would result in
13113 this diagnostic for no reason. Have people use -O -Wuninitialized
13114 and leave it to the back end to find obviously weird cases. */
13116 /* Used to "assert(rtn != NULL_TREE);" here, but it's kind of a valid
13117 situation; if the return value has never been referenced, it won't
13118 have a tree under 2pass mode. */
13119 if ((rtn == NULL_TREE)
13120 || !TREE_USED (rtn))
13122 ffebad_start (FFEBAD_RETURN_VALUE_UNSET);
13123 ffebad_here (0, ffesymbol_where_line (ffecom_primary_entry_),
13124 ffesymbol_where_column (ffecom_primary_entry_));
13125 ffebad_string (ffesymbol_text (ffesymbol_funcresult
13126 (ffecom_primary_entry_)));
13133 assert ("bad unit kind" == NULL);
13134 case FFEINFO_kindANY:
13135 rtn = error_mark_node;
13143 /* Do save_expr only if tree is not error_mark_node. */
13145 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13147 ffecom_save_tree (tree t)
13149 return save_expr (t);
13153 /* Start a compound statement (block). */
13155 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13157 ffecom_start_compstmt (void)
13159 bison_rule_pushlevel_ ();
13161 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
13163 /* Public entry point for front end to access start_decl. */
13165 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13167 ffecom_start_decl (tree decl, bool is_initialized)
13169 DECL_INITIAL (decl) = is_initialized ? error_mark_node : NULL_TREE;
13170 return start_decl (decl, FALSE);
13174 /* ffecom_sym_commit -- Symbol's state being committed to reality
13177 ffecom_sym_commit(s);
13179 Does whatever the backend needs when a symbol is committed after having
13180 been backtrackable for a period of time. */
13182 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13184 ffecom_sym_commit (ffesymbol s UNUSED)
13186 assert (!ffesymbol_retractable ());
13190 /* ffecom_sym_end_transition -- Perform end transition on all symbols
13192 ffecom_sym_end_transition();
13194 Does backend-specific stuff and also calls ffest_sym_end_transition
13195 to do the necessary FFE stuff.
13197 Backtracking is never enabled when this fn is called, so don't worry
13201 ffecom_sym_end_transition (ffesymbol s)
13205 assert (!ffesymbol_retractable ());
13207 s = ffest_sym_end_transition (s);
13209 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13210 if ((ffesymbol_kind (s) == FFEINFO_kindBLOCKDATA)
13211 && (ffesymbol_where (s) == FFEINFO_whereGLOBAL))
13213 ffecom_list_blockdata_
13214 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
13215 FFEINTRIN_specNONE,
13216 FFEINTRIN_impNONE),
13217 ffecom_list_blockdata_);
13221 /* This is where we finally notice that a symbol has partial initialization
13222 and finalize it. */
13224 if (ffesymbol_accretion (s) != NULL)
13226 assert (ffesymbol_init (s) == NULL);
13227 ffecom_notify_init_symbol (s);
13229 else if (((st = ffesymbol_storage (s)) != NULL)
13230 && ((st = ffestorag_parent (st)) != NULL)
13231 && (ffestorag_accretion (st) != NULL))
13233 assert (ffestorag_init (st) == NULL);
13234 ffecom_notify_init_storage (st);
13237 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13238 if ((ffesymbol_kind (s) == FFEINFO_kindCOMMON)
13239 && (ffesymbol_where (s) == FFEINFO_whereLOCAL)
13240 && (ffesymbol_storage (s) != NULL))
13242 ffecom_list_common_
13243 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
13244 FFEINTRIN_specNONE,
13245 FFEINTRIN_impNONE),
13246 ffecom_list_common_);
13253 /* ffecom_sym_exec_transition -- Perform exec transition on all symbols
13255 ffecom_sym_exec_transition();
13257 Does backend-specific stuff and also calls ffest_sym_exec_transition
13258 to do the necessary FFE stuff.
13260 See the long-winded description in ffecom_sym_learned for info
13261 on handling the situation where backtracking is inhibited. */
13264 ffecom_sym_exec_transition (ffesymbol s)
13266 s = ffest_sym_exec_transition (s);
13271 /* ffecom_sym_learned -- Initial or more info gained on symbol after exec
13274 s = ffecom_sym_learned(s);
13276 Called when a new symbol is seen after the exec transition or when more
13277 info (perhaps) is gained for an UNCERTAIN symbol. The symbol state when
13278 it arrives here is that all its latest info is updated already, so its
13279 state may be UNCERTAIN or UNDERSTOOD, it might already have the hook
13280 field filled in if its gone through here or exec_transition first, and
13283 The backend probably wants to check ffesymbol_retractable() to see if
13284 backtracking is in effect. If so, the FFE's changes to the symbol may
13285 be retracted (undone) or committed (ratified), at which time the
13286 appropriate ffecom_sym_retract or _commit function will be called
13289 If the backend has its own backtracking mechanism, great, use it so that
13290 committal is a simple operation. Though it doesn't make much difference,
13291 I suppose: the reason for tentative symbol evolution in the FFE is to
13292 enable error detection in weird incorrect statements early and to disable
13293 incorrect error detection on a correct statement. The backend is not
13294 likely to introduce any information that'll get involved in these
13295 considerations, so it is probably just fine that the implementation
13296 model for this fn and for _exec_transition is to not do anything
13297 (besides the required FFE stuff) if ffesymbol_retractable() returns TRUE
13298 and instead wait until ffecom_sym_commit is called (which it never
13299 will be as long as we're using ambiguity-detecting statement analysis in
13300 the FFE, which we are initially to shake out the code, but don't depend
13301 on this), otherwise go ahead and do whatever is needed.
13303 In essence, then, when this fn and _exec_transition get called while
13304 backtracking is enabled, a general mechanism would be to flag which (or
13305 both) of these were called (and in what order? neat question as to what
13306 might happen that I'm too lame to think through right now) and then when
13307 _commit is called reproduce the original calling sequence, if any, for
13308 the two fns (at which point backtracking will, of course, be disabled). */
13311 ffecom_sym_learned (ffesymbol s)
13313 ffestorag_exec_layout (s);
13318 /* ffecom_sym_retract -- Symbol's state being retracted from reality
13321 ffecom_sym_retract(s);
13323 Does whatever the backend needs when a symbol is retracted after having
13324 been backtrackable for a period of time. */
13326 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13328 ffecom_sym_retract (ffesymbol s UNUSED)
13330 assert (!ffesymbol_retractable ());
13332 #if 0 /* GCC doesn't commit any backtrackable sins,
13333 so nothing needed here. */
13334 switch (ffesymbol_hook (s).state)
13336 case 0: /* nothing happened yet. */
13339 case 1: /* exec transition happened. */
13342 case 2: /* learned happened. */
13345 case 3: /* learned then exec. */
13348 case 4: /* exec then learned. */
13352 assert ("bad hook state" == NULL);
13359 /* Create temporary gcc label. */
13361 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13363 ffecom_temp_label ()
13366 static int mynumber = 0;
13368 glabel = build_decl (LABEL_DECL,
13369 ffecom_get_invented_identifier ("__g77_label_%d",
13372 DECL_CONTEXT (glabel) = current_function_decl;
13373 DECL_MODE (glabel) = VOIDmode;
13379 /* Return an expression that is usable as an arg in a conditional context
13380 (IF, DO WHILE, .NOT., and so on).
13382 Use the one provided for the back end as of >2.6.0. */
13384 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13386 ffecom_truth_value (tree expr)
13388 return truthvalue_conversion (expr);
13392 /* Return the inversion of a truth value (the inversion of what
13393 ffecom_truth_value builds).
13395 Apparently invert_truthvalue, which is properly in the back end, is
13396 enough for now, so just use it. */
13398 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13400 ffecom_truth_value_invert (tree expr)
13402 return invert_truthvalue (ffecom_truth_value (expr));
13407 /* Return the tree that is the type of the expression, as would be
13408 returned in TREE_TYPE(ffecom_expr(expr)), without otherwise
13409 transforming the expression, generating temporaries, etc. */
13412 ffecom_type_expr (ffebld expr)
13414 ffeinfoBasictype bt;
13415 ffeinfoKindtype kt;
13418 assert (expr != NULL);
13420 bt = ffeinfo_basictype (ffebld_info (expr));
13421 kt = ffeinfo_kindtype (ffebld_info (expr));
13422 tree_type = ffecom_tree_type[bt][kt];
13424 switch (ffebld_op (expr))
13426 case FFEBLD_opCONTER:
13427 case FFEBLD_opSYMTER:
13428 case FFEBLD_opARRAYREF:
13429 case FFEBLD_opUPLUS:
13430 case FFEBLD_opPAREN:
13431 case FFEBLD_opUMINUS:
13433 case FFEBLD_opSUBTRACT:
13434 case FFEBLD_opMULTIPLY:
13435 case FFEBLD_opDIVIDE:
13436 case FFEBLD_opPOWER:
13438 case FFEBLD_opFUNCREF:
13439 case FFEBLD_opSUBRREF:
13443 case FFEBLD_opNEQV:
13445 case FFEBLD_opCONVERT:
13452 case FFEBLD_opPERCENT_LOC:
13455 case FFEBLD_opACCTER:
13456 case FFEBLD_opARRTER:
13457 case FFEBLD_opITEM:
13458 case FFEBLD_opSTAR:
13459 case FFEBLD_opBOUNDS:
13460 case FFEBLD_opREPEAT:
13461 case FFEBLD_opLABTER:
13462 case FFEBLD_opLABTOK:
13463 case FFEBLD_opIMPDO:
13464 case FFEBLD_opCONCATENATE:
13465 case FFEBLD_opSUBSTR:
13467 assert ("bad op for ffecom_type_expr" == NULL);
13468 /* Fall through. */
13470 return error_mark_node;
13474 /* Return PARM_DECL for arg#1 of master fn containing alternate ENTRY points
13476 If the PARM_DECL already exists, return it, else create it. It's an
13477 integer_type_node argument for the master function that implements a
13478 subroutine or function with more than one entrypoint and is bound at
13479 run time with the entrypoint number (0 for SUBROUTINE/FUNCTION, 1 for
13480 first ENTRY statement, and so on). */
13482 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13484 ffecom_which_entrypoint_decl ()
13486 assert (ffecom_which_entrypoint_decl_ != NULL_TREE);
13488 return ffecom_which_entrypoint_decl_;
13493 /* The following sections consists of private and public functions
13494 that have the same names and perform roughly the same functions
13495 as counterparts in the C front end. Changes in the C front end
13496 might affect how things should be done here. Only functions
13497 needed by the back end should be public here; the rest should
13498 be private (static in the C sense). Functions needed by other
13499 g77 front-end modules should be accessed by them via public
13500 ffecom_* names, which should themselves call private versions
13501 in this section so the private versions are easy to recognize
13502 when upgrading to a new gcc and finding interesting changes
13505 Functions named after rule "foo:" in c-parse.y are named
13506 "bison_rule_foo_" so they are easy to find. */
13508 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13511 bison_rule_pushlevel_ ()
13513 emit_line_note (input_filename, lineno);
13515 clear_last_expr ();
13516 expand_start_bindings (0);
13520 bison_rule_compstmt_ ()
13523 int keep = kept_level_p ();
13525 /* Make the temps go away. */
13527 current_binding_level->names = NULL_TREE;
13529 emit_line_note (input_filename, lineno);
13530 expand_end_bindings (getdecls (), keep, 0);
13531 t = poplevel (keep, 1, 0);
13536 /* Return a definition for a builtin function named NAME and whose data type
13537 is TYPE. TYPE should be a function type with argument types.
13538 FUNCTION_CODE tells later passes how to compile calls to this function.
13539 See tree.h for its possible values.
13541 If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME,
13542 the name to be called if we can't opencode the function. */
13545 builtin_function (const char *name, tree type, int function_code,
13546 enum built_in_class class,
13547 const char *library_name)
13549 tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
13550 DECL_EXTERNAL (decl) = 1;
13551 TREE_PUBLIC (decl) = 1;
13553 DECL_ASSEMBLER_NAME (decl) = get_identifier (library_name);
13554 make_decl_rtl (decl, NULL_PTR);
13556 DECL_BUILT_IN_CLASS (decl) = class;
13557 DECL_FUNCTION_CODE (decl) = function_code;
13562 /* Handle when a new declaration NEWDECL
13563 has the same name as an old one OLDDECL
13564 in the same binding contour.
13565 Prints an error message if appropriate.
13567 If safely possible, alter OLDDECL to look like NEWDECL, and return 1.
13568 Otherwise, return 0. */
13571 duplicate_decls (tree newdecl, tree olddecl)
13573 int types_match = 1;
13574 int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
13575 && DECL_INITIAL (newdecl) != 0);
13576 tree oldtype = TREE_TYPE (olddecl);
13577 tree newtype = TREE_TYPE (newdecl);
13579 if (olddecl == newdecl)
13582 if (TREE_CODE (newtype) == ERROR_MARK
13583 || TREE_CODE (oldtype) == ERROR_MARK)
13586 /* New decl is completely inconsistent with the old one =>
13587 tell caller to replace the old one.
13588 This is always an error except in the case of shadowing a builtin. */
13589 if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
13592 /* For real parm decl following a forward decl,
13593 return 1 so old decl will be reused. */
13594 if (types_match && TREE_CODE (newdecl) == PARM_DECL
13595 && TREE_ASM_WRITTEN (olddecl) && ! TREE_ASM_WRITTEN (newdecl))
13598 /* The new declaration is the same kind of object as the old one.
13599 The declarations may partially match. Print warnings if they don't
13600 match enough. Ultimately, copy most of the information from the new
13601 decl to the old one, and keep using the old one. */
13603 if (TREE_CODE (olddecl) == FUNCTION_DECL
13604 && DECL_BUILT_IN (olddecl))
13606 /* A function declaration for a built-in function. */
13607 if (!TREE_PUBLIC (newdecl))
13609 else if (!types_match)
13611 /* Accept the return type of the new declaration if same modes. */
13612 tree oldreturntype = TREE_TYPE (TREE_TYPE (olddecl));
13613 tree newreturntype = TREE_TYPE (TREE_TYPE (newdecl));
13615 if (TYPE_MODE (oldreturntype) == TYPE_MODE (newreturntype))
13617 /* Function types may be shared, so we can't just modify
13618 the return type of olddecl's function type. */
13620 = build_function_type (newreturntype,
13621 TYPE_ARG_TYPES (TREE_TYPE (olddecl)));
13625 TREE_TYPE (olddecl) = newtype;
13631 else if (TREE_CODE (olddecl) == FUNCTION_DECL
13632 && DECL_SOURCE_LINE (olddecl) == 0)
13634 /* A function declaration for a predeclared function
13635 that isn't actually built in. */
13636 if (!TREE_PUBLIC (newdecl))
13638 else if (!types_match)
13640 /* If the types don't match, preserve volatility indication.
13641 Later on, we will discard everything else about the
13642 default declaration. */
13643 TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
13647 /* Copy all the DECL_... slots specified in the new decl
13648 except for any that we copy here from the old type.
13650 Past this point, we don't change OLDTYPE and NEWTYPE
13651 even if we change the types of NEWDECL and OLDDECL. */
13655 /* Merge the data types specified in the two decls. */
13656 if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl))
13657 TREE_TYPE (newdecl)
13658 = TREE_TYPE (olddecl)
13659 = TREE_TYPE (newdecl);
13661 /* Lay the type out, unless already done. */
13662 if (oldtype != TREE_TYPE (newdecl))
13664 if (TREE_TYPE (newdecl) != error_mark_node)
13665 layout_type (TREE_TYPE (newdecl));
13666 if (TREE_CODE (newdecl) != FUNCTION_DECL
13667 && TREE_CODE (newdecl) != TYPE_DECL
13668 && TREE_CODE (newdecl) != CONST_DECL)
13669 layout_decl (newdecl, 0);
13673 /* Since the type is OLDDECL's, make OLDDECL's size go with. */
13674 DECL_SIZE (newdecl) = DECL_SIZE (olddecl);
13675 DECL_SIZE_UNIT (newdecl) = DECL_SIZE_UNIT (olddecl);
13676 if (TREE_CODE (olddecl) != FUNCTION_DECL)
13677 if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
13679 DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
13680 DECL_USER_ALIGN (newdecl) |= DECL_USER_ALIGN (olddecl);
13684 /* Keep the old rtl since we can safely use it. */
13685 DECL_RTL (newdecl) = DECL_RTL (olddecl);
13687 /* Merge the type qualifiers. */
13688 if (DECL_BUILT_IN_NONANSI (olddecl) && TREE_THIS_VOLATILE (olddecl)
13689 && !TREE_THIS_VOLATILE (newdecl))
13690 TREE_THIS_VOLATILE (olddecl) = 0;
13691 if (TREE_READONLY (newdecl))
13692 TREE_READONLY (olddecl) = 1;
13693 if (TREE_THIS_VOLATILE (newdecl))
13695 TREE_THIS_VOLATILE (olddecl) = 1;
13696 if (TREE_CODE (newdecl) == VAR_DECL)
13697 make_var_volatile (newdecl);
13700 /* Keep source location of definition rather than declaration.
13701 Likewise, keep decl at outer scope. */
13702 if ((DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0)
13703 || (DECL_CONTEXT (newdecl) != 0 && DECL_CONTEXT (olddecl) == 0))
13705 DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl);
13706 DECL_SOURCE_FILE (newdecl) = DECL_SOURCE_FILE (olddecl);
13708 if (DECL_CONTEXT (olddecl) == 0
13709 && TREE_CODE (newdecl) != FUNCTION_DECL)
13710 DECL_CONTEXT (newdecl) = 0;
13713 /* Merge the unused-warning information. */
13714 if (DECL_IN_SYSTEM_HEADER (olddecl))
13715 DECL_IN_SYSTEM_HEADER (newdecl) = 1;
13716 else if (DECL_IN_SYSTEM_HEADER (newdecl))
13717 DECL_IN_SYSTEM_HEADER (olddecl) = 1;
13719 /* Merge the initialization information. */
13720 if (DECL_INITIAL (newdecl) == 0)
13721 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
13723 /* Merge the section attribute.
13724 We want to issue an error if the sections conflict but that must be
13725 done later in decl_attributes since we are called before attributes
13727 if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
13728 DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
13731 if (TREE_CODE (newdecl) == FUNCTION_DECL)
13733 DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
13734 DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
13738 /* If cannot merge, then use the new type and qualifiers,
13739 and don't preserve the old rtl. */
13742 TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
13743 TREE_READONLY (olddecl) = TREE_READONLY (newdecl);
13744 TREE_THIS_VOLATILE (olddecl) = TREE_THIS_VOLATILE (newdecl);
13745 TREE_SIDE_EFFECTS (olddecl) = TREE_SIDE_EFFECTS (newdecl);
13748 /* Merge the storage class information. */
13749 /* For functions, static overrides non-static. */
13750 if (TREE_CODE (newdecl) == FUNCTION_DECL)
13752 TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl);
13753 /* This is since we don't automatically
13754 copy the attributes of NEWDECL into OLDDECL. */
13755 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
13756 /* If this clears `static', clear it in the identifier too. */
13757 if (! TREE_PUBLIC (olddecl))
13758 TREE_PUBLIC (DECL_NAME (olddecl)) = 0;
13760 if (DECL_EXTERNAL (newdecl))
13762 TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
13763 DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
13764 /* An extern decl does not override previous storage class. */
13765 TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
13769 TREE_STATIC (olddecl) = TREE_STATIC (newdecl);
13770 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
13773 /* If either decl says `inline', this fn is inline,
13774 unless its definition was passed already. */
13775 if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == 0)
13776 DECL_INLINE (olddecl) = 1;
13777 DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
13779 /* Get rid of any built-in function if new arg types don't match it
13780 or if we have a function definition. */
13781 if (TREE_CODE (newdecl) == FUNCTION_DECL
13782 && DECL_BUILT_IN (olddecl)
13783 && (!types_match || new_is_definition))
13785 TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
13786 DECL_BUILT_IN_CLASS (olddecl) = NOT_BUILT_IN;
13789 /* If redeclaring a builtin function, and not a definition,
13791 Also preserve various other info from the definition. */
13792 if (TREE_CODE (newdecl) == FUNCTION_DECL && !new_is_definition)
13794 if (DECL_BUILT_IN (olddecl))
13796 DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
13797 DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
13800 DECL_FRAME_SIZE (newdecl) = DECL_FRAME_SIZE (olddecl);
13802 DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
13803 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
13804 DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
13805 DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
13808 /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
13809 But preserve olddecl's DECL_UID. */
13811 register unsigned olddecl_uid = DECL_UID (olddecl);
13813 memcpy ((char *) olddecl + sizeof (struct tree_common),
13814 (char *) newdecl + sizeof (struct tree_common),
13815 sizeof (struct tree_decl) - sizeof (struct tree_common));
13816 DECL_UID (olddecl) = olddecl_uid;
13822 /* Finish processing of a declaration;
13823 install its initial value.
13824 If the length of an array type is not known before,
13825 it must be determined now, from the initial value, or it is an error. */
13828 finish_decl (tree decl, tree init, bool is_top_level)
13830 register tree type = TREE_TYPE (decl);
13831 int was_incomplete = (DECL_SIZE (decl) == 0);
13832 bool at_top_level = (current_binding_level == global_binding_level);
13833 bool top_level = is_top_level || at_top_level;
13835 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
13837 assert (!is_top_level || !at_top_level);
13839 if (TREE_CODE (decl) == PARM_DECL)
13840 assert (init == NULL_TREE);
13841 /* Remember that PARM_DECL doesn't have a DECL_INITIAL field per se -- it
13842 overlaps DECL_ARG_TYPE. */
13843 else if (init == NULL_TREE)
13844 assert (DECL_INITIAL (decl) == NULL_TREE);
13846 assert (DECL_INITIAL (decl) == error_mark_node);
13848 if (init != NULL_TREE)
13850 if (TREE_CODE (decl) != TYPE_DECL)
13851 DECL_INITIAL (decl) = init;
13854 /* typedef foo = bar; store the type of bar as the type of foo. */
13855 TREE_TYPE (decl) = TREE_TYPE (init);
13856 DECL_INITIAL (decl) = init = 0;
13860 /* Deduce size of array from initialization, if not already known */
13862 if (TREE_CODE (type) == ARRAY_TYPE
13863 && TYPE_DOMAIN (type) == 0
13864 && TREE_CODE (decl) != TYPE_DECL)
13866 assert (top_level);
13867 assert (was_incomplete);
13869 layout_decl (decl, 0);
13872 if (TREE_CODE (decl) == VAR_DECL)
13874 if (DECL_SIZE (decl) == NULL_TREE
13875 && TYPE_SIZE (TREE_TYPE (decl)) != NULL_TREE)
13876 layout_decl (decl, 0);
13878 if (DECL_SIZE (decl) == NULL_TREE
13879 && (TREE_STATIC (decl)
13881 /* A static variable with an incomplete type is an error if it is
13882 initialized. Also if it is not file scope. Otherwise, let it
13883 through, but if it is not `extern' then it may cause an error
13885 (DECL_INITIAL (decl) != 0 || DECL_CONTEXT (decl) != 0)
13887 /* An automatic variable with an incomplete type is an error. */
13888 !DECL_EXTERNAL (decl)))
13890 assert ("storage size not known" == NULL);
13894 if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
13895 && (DECL_SIZE (decl) != 0)
13896 && (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST))
13898 assert ("storage size not constant" == NULL);
13903 /* Output the assembler code and/or RTL code for variables and functions,
13904 unless the type is an undefined structure or union. If not, it will get
13905 done when the type is completed. */
13907 if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
13909 rest_of_decl_compilation (decl, NULL,
13910 DECL_CONTEXT (decl) == 0,
13913 if (DECL_CONTEXT (decl) != 0)
13915 /* Recompute the RTL of a local array now if it used to be an
13916 incomplete type. */
13918 && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
13920 /* If we used it already as memory, it must stay in memory. */
13921 TREE_ADDRESSABLE (decl) = TREE_USED (decl);
13922 /* If it's still incomplete now, no init will save it. */
13923 if (DECL_SIZE (decl) == 0)
13924 DECL_INITIAL (decl) = 0;
13925 expand_decl (decl);
13927 /* Compute and store the initial value. */
13928 if (TREE_CODE (decl) != FUNCTION_DECL)
13929 expand_decl_init (decl);
13932 else if (TREE_CODE (decl) == TYPE_DECL)
13934 rest_of_decl_compilation (decl, NULL_PTR,
13935 DECL_CONTEXT (decl) == 0,
13939 /* At the end of a declaration, throw away any variable type sizes of types
13940 defined inside that declaration. There is no use computing them in the
13941 following function definition. */
13942 if (current_binding_level == global_binding_level)
13943 get_pending_sizes ();
13946 /* Finish up a function declaration and compile that function
13947 all the way to assembler language output. The free the storage
13948 for the function definition.
13950 This is called after parsing the body of the function definition.
13952 NESTED is nonzero if the function being finished is nested in another. */
13955 finish_function (int nested)
13957 register tree fndecl = current_function_decl;
13959 assert (fndecl != NULL_TREE);
13960 if (TREE_CODE (fndecl) != ERROR_MARK)
13963 assert (DECL_CONTEXT (fndecl) != NULL_TREE);
13965 assert (DECL_CONTEXT (fndecl) == NULL_TREE);
13968 /* TREE_READONLY (fndecl) = 1;
13969 This caused &foo to be of type ptr-to-const-function
13970 which then got a warning when stored in a ptr-to-function variable. */
13972 poplevel (1, 0, 1);
13974 if (TREE_CODE (fndecl) != ERROR_MARK)
13976 BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
13978 /* Must mark the RESULT_DECL as being in this function. */
13980 DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
13982 /* Obey `register' declarations if `setjmp' is called in this fn. */
13983 /* Generate rtl for function exit. */
13984 expand_function_end (input_filename, lineno, 0);
13986 /* If this is a nested function, protect the local variables in the stack
13987 above us from being collected while we're compiling this function. */
13989 ggc_push_context ();
13991 /* Run the optimizers and output the assembler code for this function. */
13992 rest_of_compilation (fndecl);
13994 /* Undo the GC context switch. */
13996 ggc_pop_context ();
13999 if (TREE_CODE (fndecl) != ERROR_MARK
14001 && DECL_SAVED_INSNS (fndecl) == 0)
14003 /* Stop pointing to the local nodes about to be freed. */
14004 /* But DECL_INITIAL must remain nonzero so we know this was an actual
14005 function definition. */
14006 /* For a nested function, this is done in pop_f_function_context. */
14007 /* If rest_of_compilation set this to 0, leave it 0. */
14008 if (DECL_INITIAL (fndecl) != 0)
14009 DECL_INITIAL (fndecl) = error_mark_node;
14010 DECL_ARGUMENTS (fndecl) = 0;
14015 /* Let the error reporting routines know that we're outside a function.
14016 For a nested function, this value is used in pop_c_function_context
14017 and then reset via pop_function_context. */
14018 ffecom_outer_function_decl_ = current_function_decl = NULL;
14022 /* Plug-in replacement for identifying the name of a decl and, for a
14023 function, what we call it in diagnostics. For now, "program unit"
14024 should suffice, since it's a bit of a hassle to figure out which
14025 of several kinds of things it is. Note that it could conceivably
14026 be a statement function, which probably isn't really a program unit
14027 per se, but if that comes up, it should be easy to check (being a
14028 nested function and all). */
14030 static const char *
14031 lang_printable_name (tree decl, int v)
14033 /* Just to keep GCC quiet about the unused variable.
14034 In theory, differing values of V should produce different
14039 if (TREE_CODE (decl) == ERROR_MARK)
14040 return "erroneous code";
14041 return IDENTIFIER_POINTER (DECL_NAME (decl));
14045 /* g77's function to print out name of current function that caused
14050 lang_print_error_function (const char *file)
14052 static ffeglobal last_g = NULL;
14053 static ffesymbol last_s = NULL;
14058 if ((ffecom_primary_entry_ == NULL)
14059 || (ffesymbol_global (ffecom_primary_entry_) == NULL))
14067 g = ffesymbol_global (ffecom_primary_entry_);
14068 if (ffecom_nested_entry_ == NULL)
14070 s = ffecom_primary_entry_;
14071 switch (ffesymbol_kind (s))
14073 case FFEINFO_kindFUNCTION:
14077 case FFEINFO_kindSUBROUTINE:
14078 kind = "subroutine";
14081 case FFEINFO_kindPROGRAM:
14085 case FFEINFO_kindBLOCKDATA:
14086 kind = "block-data";
14090 kind = ffeinfo_kind_message (ffesymbol_kind (s));
14096 s = ffecom_nested_entry_;
14097 kind = "statement function";
14101 if ((last_g != g) || (last_s != s))
14104 fprintf (stderr, "%s: ", file);
14107 fprintf (stderr, "Outside of any program unit:\n");
14110 const char *name = ffesymbol_text (s);
14112 fprintf (stderr, "In %s `%s':\n", kind, name);
14121 /* Similar to `lookup_name' but look only at current binding level. */
14124 lookup_name_current_level (tree name)
14128 if (current_binding_level == global_binding_level)
14129 return IDENTIFIER_GLOBAL_VALUE (name);
14131 if (IDENTIFIER_LOCAL_VALUE (name) == 0)
14134 for (t = current_binding_level->names; t; t = TREE_CHAIN (t))
14135 if (DECL_NAME (t) == name)
14141 /* Create a new `struct binding_level'. */
14143 static struct binding_level *
14144 make_binding_level ()
14147 return (struct binding_level *) xmalloc (sizeof (struct binding_level));
14150 /* Save and restore the variables in this file and elsewhere
14151 that keep track of the progress of compilation of the current function.
14152 Used for nested functions. */
14156 struct f_function *next;
14158 tree shadowed_labels;
14159 struct binding_level *binding_level;
14162 struct f_function *f_function_chain;
14164 /* Restore the variables used during compilation of a C function. */
14167 pop_f_function_context ()
14169 struct f_function *p = f_function_chain;
14172 /* Bring back all the labels that were shadowed. */
14173 for (link = shadowed_labels; link; link = TREE_CHAIN (link))
14174 if (DECL_NAME (TREE_VALUE (link)) != 0)
14175 IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)))
14176 = TREE_VALUE (link);
14178 if (current_function_decl != error_mark_node
14179 && DECL_SAVED_INSNS (current_function_decl) == 0)
14181 /* Stop pointing to the local nodes about to be freed. */
14182 /* But DECL_INITIAL must remain nonzero so we know this was an actual
14183 function definition. */
14184 DECL_INITIAL (current_function_decl) = error_mark_node;
14185 DECL_ARGUMENTS (current_function_decl) = 0;
14188 pop_function_context ();
14190 f_function_chain = p->next;
14192 named_labels = p->named_labels;
14193 shadowed_labels = p->shadowed_labels;
14194 current_binding_level = p->binding_level;
14199 /* Save and reinitialize the variables
14200 used during compilation of a C function. */
14203 push_f_function_context ()
14205 struct f_function *p
14206 = (struct f_function *) xmalloc (sizeof (struct f_function));
14208 push_function_context ();
14210 p->next = f_function_chain;
14211 f_function_chain = p;
14213 p->named_labels = named_labels;
14214 p->shadowed_labels = shadowed_labels;
14215 p->binding_level = current_binding_level;
14219 push_parm_decl (tree parm)
14221 int old_immediate_size_expand = immediate_size_expand;
14223 /* Don't try computing parm sizes now -- wait till fn is called. */
14225 immediate_size_expand = 0;
14227 /* Fill in arg stuff. */
14229 DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
14230 DECL_ARG_TYPE_AS_WRITTEN (parm) = TREE_TYPE (parm);
14231 TREE_READONLY (parm) = 1; /* All implementation args are read-only. */
14233 parm = pushdecl (parm);
14235 immediate_size_expand = old_immediate_size_expand;
14237 finish_decl (parm, NULL_TREE, FALSE);
14240 /* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL, if appropriate. */
14243 pushdecl_top_level (x)
14247 register struct binding_level *b = current_binding_level;
14248 register tree f = current_function_decl;
14250 current_binding_level = global_binding_level;
14251 current_function_decl = NULL_TREE;
14253 current_binding_level = b;
14254 current_function_decl = f;
14258 /* Store the list of declarations of the current level.
14259 This is done for the parameter declarations of a function being defined,
14260 after they are modified in the light of any missing parameters. */
14266 return current_binding_level->names = decls;
14269 /* Store the parameter declarations into the current function declaration.
14270 This is called after parsing the parameter declarations, before
14271 digesting the body of the function.
14273 For an old-style definition, modify the function's type
14274 to specify at least the number of arguments. */
14277 store_parm_decls (int is_main_program UNUSED)
14279 register tree fndecl = current_function_decl;
14281 if (fndecl == error_mark_node)
14284 /* This is a chain of PARM_DECLs from old-style parm declarations. */
14285 DECL_ARGUMENTS (fndecl) = storedecls (nreverse (getdecls ()));
14287 /* Initialize the RTL code for the function. */
14289 init_function_start (fndecl, input_filename, lineno);
14291 /* Set up parameters and prepare for return, for the function. */
14293 expand_function_start (fndecl, 0);
14297 start_decl (tree decl, bool is_top_level)
14300 bool at_top_level = (current_binding_level == global_binding_level);
14301 bool top_level = is_top_level || at_top_level;
14303 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
14305 assert (!is_top_level || !at_top_level);
14307 if (DECL_INITIAL (decl) != NULL_TREE)
14309 assert (DECL_INITIAL (decl) == error_mark_node);
14310 assert (!DECL_EXTERNAL (decl));
14312 else if (top_level)
14313 assert ((TREE_STATIC (decl) == 1) || DECL_EXTERNAL (decl) == 1);
14315 /* For Fortran, we by default put things in .common when possible. */
14316 DECL_COMMON (decl) = 1;
14318 /* Add this decl to the current binding level. TEM may equal DECL or it may
14319 be a previous decl of the same name. */
14321 tem = pushdecl_top_level (decl);
14323 tem = pushdecl (decl);
14325 /* For a local variable, define the RTL now. */
14327 /* But not if this is a duplicate decl and we preserved the rtl from the
14328 previous one (which may or may not happen). */
14329 && DECL_RTL (tem) == 0)
14331 if (TYPE_SIZE (TREE_TYPE (tem)) != 0)
14333 else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
14334 && DECL_INITIAL (tem) != 0)
14341 /* Create the FUNCTION_DECL for a function definition.
14342 DECLSPECS and DECLARATOR are the parts of the declaration;
14343 they describe the function's name and the type it returns,
14344 but twisted together in a fashion that parallels the syntax of C.
14346 This function creates a binding context for the function body
14347 as well as setting up the FUNCTION_DECL in current_function_decl.
14349 Returns 1 on success. If the DECLARATOR is not suitable for a function
14350 (it defines a datum instead), we return 0, which tells
14351 yyparse to report a parse error.
14353 NESTED is nonzero for a function nested within another function. */
14356 start_function (tree name, tree type, int nested, int public)
14360 int old_immediate_size_expand = immediate_size_expand;
14363 shadowed_labels = 0;
14365 /* Don't expand any sizes in the return type of the function. */
14366 immediate_size_expand = 0;
14371 assert (current_function_decl != NULL_TREE);
14372 assert (DECL_CONTEXT (current_function_decl) == NULL_TREE);
14376 assert (current_function_decl == NULL_TREE);
14379 if (TREE_CODE (type) == ERROR_MARK)
14380 decl1 = current_function_decl = error_mark_node;
14383 decl1 = build_decl (FUNCTION_DECL,
14386 TREE_PUBLIC (decl1) = public ? 1 : 0;
14388 DECL_INLINE (decl1) = 1;
14389 TREE_STATIC (decl1) = 1;
14390 DECL_EXTERNAL (decl1) = 0;
14392 announce_function (decl1);
14394 /* Make the init_value nonzero so pushdecl knows this is not tentative.
14395 error_mark_node is replaced below (in poplevel) with the BLOCK. */
14396 DECL_INITIAL (decl1) = error_mark_node;
14398 /* Record the decl so that the function name is defined. If we already have
14399 a decl for this name, and it is a FUNCTION_DECL, use the old decl. */
14401 current_function_decl = pushdecl (decl1);
14405 ffecom_outer_function_decl_ = current_function_decl;
14408 current_binding_level->prep_state = 2;
14410 if (TREE_CODE (current_function_decl) != ERROR_MARK)
14412 make_decl_rtl (current_function_decl, NULL);
14414 restype = TREE_TYPE (TREE_TYPE (current_function_decl));
14415 DECL_RESULT (current_function_decl)
14416 = build_decl (RESULT_DECL, NULL_TREE, restype);
14419 if (!nested && (TREE_CODE (current_function_decl) != ERROR_MARK))
14420 TREE_ADDRESSABLE (current_function_decl) = 1;
14422 immediate_size_expand = old_immediate_size_expand;
14425 /* Here are the public functions the GNU back end needs. */
14428 convert (type, expr)
14431 register tree e = expr;
14432 register enum tree_code code = TREE_CODE (type);
14434 if (type == TREE_TYPE (e)
14435 || TREE_CODE (e) == ERROR_MARK)
14437 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
14438 return fold (build1 (NOP_EXPR, type, e));
14439 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
14440 || code == ERROR_MARK)
14441 return error_mark_node;
14442 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
14444 assert ("void value not ignored as it ought to be" == NULL);
14445 return error_mark_node;
14447 if (code == VOID_TYPE)
14448 return build1 (CONVERT_EXPR, type, e);
14449 if ((code != RECORD_TYPE)
14450 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
14451 e = ffecom_1 (REALPART_EXPR, TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e))),
14453 if (code == INTEGER_TYPE || code == ENUMERAL_TYPE)
14454 return fold (convert_to_integer (type, e));
14455 if (code == POINTER_TYPE)
14456 return fold (convert_to_pointer (type, e));
14457 if (code == REAL_TYPE)
14458 return fold (convert_to_real (type, e));
14459 if (code == COMPLEX_TYPE)
14460 return fold (convert_to_complex (type, e));
14461 if (code == RECORD_TYPE)
14462 return fold (ffecom_convert_to_complex_ (type, e));
14464 assert ("conversion to non-scalar type requested" == NULL);
14465 return error_mark_node;
14468 /* integrate_decl_tree calls this function, but since we don't use the
14469 DECL_LANG_SPECIFIC field, this is a no-op. */
14472 copy_lang_decl (node)
14477 /* Return the list of declarations of the current level.
14478 Note that this list is in reverse order unless/until
14479 you nreverse it; and when you do nreverse it, you must
14480 store the result back using `storedecls' or you will lose. */
14485 return current_binding_level->names;
14488 /* Nonzero if we are currently in the global binding level. */
14491 global_bindings_p ()
14493 return current_binding_level == global_binding_level;
14496 /* Print an error message for invalid use of an incomplete type.
14497 VALUE is the expression that was used (or 0 if that isn't known)
14498 and TYPE is the type that was invalid. */
14501 incomplete_type_error (value, type)
14505 if (TREE_CODE (type) == ERROR_MARK)
14508 assert ("incomplete type?!?" == NULL);
14511 /* Mark ARG for GC. */
14513 mark_binding_level (void *arg)
14515 struct binding_level *level = *(struct binding_level **) arg;
14519 ggc_mark_tree (level->names);
14520 ggc_mark_tree (level->blocks);
14521 ggc_mark_tree (level->this_block);
14522 level = level->level_chain;
14527 init_decl_processing ()
14529 static tree *const tree_roots[] = {
14530 ¤t_function_decl,
14532 &ffecom_tree_fun_type_void,
14533 &ffecom_integer_zero_node,
14534 &ffecom_integer_one_node,
14535 &ffecom_tree_subr_type,
14536 &ffecom_tree_ptr_to_subr_type,
14537 &ffecom_tree_blockdata_type,
14538 &ffecom_tree_xargc_,
14539 &ffecom_f2c_integer_type_node,
14540 &ffecom_f2c_ptr_to_integer_type_node,
14541 &ffecom_f2c_address_type_node,
14542 &ffecom_f2c_real_type_node,
14543 &ffecom_f2c_ptr_to_real_type_node,
14544 &ffecom_f2c_doublereal_type_node,
14545 &ffecom_f2c_complex_type_node,
14546 &ffecom_f2c_doublecomplex_type_node,
14547 &ffecom_f2c_longint_type_node,
14548 &ffecom_f2c_logical_type_node,
14549 &ffecom_f2c_flag_type_node,
14550 &ffecom_f2c_ftnlen_type_node,
14551 &ffecom_f2c_ftnlen_zero_node,
14552 &ffecom_f2c_ftnlen_one_node,
14553 &ffecom_f2c_ftnlen_two_node,
14554 &ffecom_f2c_ptr_to_ftnlen_type_node,
14555 &ffecom_f2c_ftnint_type_node,
14556 &ffecom_f2c_ptr_to_ftnint_type_node,
14557 &ffecom_outer_function_decl_,
14558 &ffecom_previous_function_decl_,
14559 &ffecom_which_entrypoint_decl_,
14560 &ffecom_float_zero_,
14561 &ffecom_float_half_,
14562 &ffecom_double_zero_,
14563 &ffecom_double_half_,
14564 &ffecom_func_result_,
14565 &ffecom_func_length_,
14566 &ffecom_multi_type_node_,
14567 &ffecom_multi_retval_,
14575 /* Record our roots. */
14576 for (i = 0; i < ARRAY_SIZE (tree_roots); i++)
14577 ggc_add_tree_root (tree_roots[i], 1);
14578 ggc_add_tree_root (&ffecom_tree_type[0][0],
14579 FFEINFO_basictype*FFEINFO_kindtype);
14580 ggc_add_tree_root (&ffecom_tree_fun_type[0][0],
14581 FFEINFO_basictype*FFEINFO_kindtype);
14582 ggc_add_tree_root (&ffecom_tree_ptr_to_fun_type[0][0],
14583 FFEINFO_basictype*FFEINFO_kindtype);
14584 ggc_add_tree_root (ffecom_gfrt_, FFECOM_gfrt);
14585 ggc_add_root (¤t_binding_level, 1, sizeof current_binding_level,
14586 mark_binding_level);
14587 ggc_add_root (&free_binding_level, 1, sizeof current_binding_level,
14588 mark_binding_level);
14589 ggc_add_root (&tracker_head, 1, sizeof tracker_head, mark_tracker_head);
14595 init_parse (filename)
14596 const char *filename;
14598 /* Open input file. */
14599 if (filename == 0 || !strcmp (filename, "-"))
14602 filename = "stdin";
14605 finput = fopen (filename, "r");
14607 fatal_io_error ("can't open %s", filename);
14609 #ifdef IO_BUFFER_SIZE
14610 setvbuf (finput, (char *) xmalloc (IO_BUFFER_SIZE), _IOFBF, IO_BUFFER_SIZE);
14613 /* Make identifier nodes long enough for the language-specific slots. */
14614 set_identifier_size (sizeof (struct lang_identifier));
14615 decl_printable_name = lang_printable_name;
14617 print_error_function = lang_print_error_function;
14629 /* Delete the node BLOCK from the current binding level.
14630 This is used for the block inside a stmt expr ({...})
14631 so that the block can be reinserted where appropriate. */
14634 delete_block (block)
14638 if (current_binding_level->blocks == block)
14639 current_binding_level->blocks = TREE_CHAIN (block);
14640 for (t = current_binding_level->blocks; t;)
14642 if (TREE_CHAIN (t) == block)
14643 TREE_CHAIN (t) = TREE_CHAIN (block);
14645 t = TREE_CHAIN (t);
14647 TREE_CHAIN (block) = NULL;
14648 /* Clear TREE_USED which is always set by poplevel.
14649 The flag is set again if insert_block is called. */
14650 TREE_USED (block) = 0;
14654 insert_block (block)
14657 TREE_USED (block) = 1;
14658 current_binding_level->blocks
14659 = chainon (current_binding_level->blocks, block);
14662 /* Each front end provides its own. */
14663 static void ffe_init PARAMS ((void));
14664 static void ffe_finish PARAMS ((void));
14665 static void ffe_init_options PARAMS ((void));
14667 struct lang_hooks lang_hooks = {ffe_init,
14671 NULL /* post_options */};
14673 /* used by print-tree.c */
14676 lang_print_xnode (file, node, indent)
14686 ffe_terminate_0 ();
14688 if (ffe_is_ffedebug ())
14689 malloc_pool_display (malloc_pool_image ());
14698 /* Return the typed-based alias set for T, which may be an expression
14699 or a type. Return -1 if we don't do anything special. */
14702 lang_get_alias_set (t)
14703 tree t ATTRIBUTE_UNUSED;
14705 /* We do not wish to use alias-set based aliasing at all. Used in the
14706 extreme (every object with its own set, with equivalences recorded)
14707 it might be helpful, but there are problems when it comes to inlining.
14708 We get on ok with flag_argument_noalias, and alias-set aliasing does
14709 currently limit how stack slots can be reused, which is a lose. */
14714 ffe_init_options ()
14716 /* Set default options for Fortran. */
14717 flag_move_all_movables = 1;
14718 flag_reduce_all_givs = 1;
14719 flag_argument_noalias = 2;
14720 flag_errno_math = 0;
14721 flag_complex_divide_method = 1;
14727 /* If the file is output from cpp, it should contain a first line
14728 `# 1 "real-filename"', and the current design of gcc (toplev.c
14729 in particular and the way it sets up information relied on by
14730 INCLUDE) requires that we read this now, and store the
14731 "real-filename" info in master_input_filename. Ask the lexer
14732 to try doing this. */
14733 ffelex_hash_kludge (finput);
14737 mark_addressable (exp)
14740 register tree x = exp;
14742 switch (TREE_CODE (x))
14745 case COMPONENT_REF:
14747 x = TREE_OPERAND (x, 0);
14751 TREE_ADDRESSABLE (x) = 1;
14758 if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x)
14759 && DECL_NONLOCAL (x))
14761 if (TREE_PUBLIC (x))
14763 assert ("address of global register var requested" == NULL);
14766 assert ("address of register variable requested" == NULL);
14768 else if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x))
14770 if (TREE_PUBLIC (x))
14772 assert ("address of global register var requested" == NULL);
14775 assert ("address of register var requested" == NULL);
14777 put_var_into_stack (x);
14780 case FUNCTION_DECL:
14781 TREE_ADDRESSABLE (x) = 1;
14782 #if 0 /* poplevel deals with this now. */
14783 if (DECL_CONTEXT (x) == 0)
14784 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;
14792 /* If DECL has a cleanup, build and return that cleanup here.
14793 This is a callback called by expand_expr. */
14796 maybe_build_cleanup (decl)
14799 /* There are no cleanups in Fortran. */
14803 /* Exit a binding level.
14804 Pop the level off, and restore the state of the identifier-decl mappings
14805 that were in effect when this level was entered.
14807 If KEEP is nonzero, this level had explicit declarations, so
14808 and create a "block" (a BLOCK node) for the level
14809 to record its declarations and subblocks for symbol table output.
14811 If FUNCTIONBODY is nonzero, this level is the body of a function,
14812 so create a block as if KEEP were set and also clear out all
14815 If REVERSE is nonzero, reverse the order of decls before putting
14816 them into the BLOCK. */
14819 poplevel (keep, reverse, functionbody)
14824 register tree link;
14825 /* The chain of decls was accumulated in reverse order.
14826 Put it into forward order, just for cleanliness. */
14828 tree subblocks = current_binding_level->blocks;
14831 int block_previously_created;
14833 /* Get the decls in the order they were written.
14834 Usually current_binding_level->names is in reverse order.
14835 But parameter decls were previously put in forward order. */
14838 current_binding_level->names
14839 = decls = nreverse (current_binding_level->names);
14841 decls = current_binding_level->names;
14843 /* Output any nested inline functions within this block
14844 if they weren't already output. */
14846 for (decl = decls; decl; decl = TREE_CHAIN (decl))
14847 if (TREE_CODE (decl) == FUNCTION_DECL
14848 && ! TREE_ASM_WRITTEN (decl)
14849 && DECL_INITIAL (decl) != 0
14850 && TREE_ADDRESSABLE (decl))
14852 /* If this decl was copied from a file-scope decl
14853 on account of a block-scope extern decl,
14854 propagate TREE_ADDRESSABLE to the file-scope decl.
14856 DECL_ABSTRACT_ORIGIN can be set to itself if warn_return_type is
14857 true, since then the decl goes through save_for_inline_copying. */
14858 if (DECL_ABSTRACT_ORIGIN (decl) != 0
14859 && DECL_ABSTRACT_ORIGIN (decl) != decl)
14860 TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
14861 else if (DECL_SAVED_INSNS (decl) != 0)
14863 push_function_context ();
14864 output_inline_function (decl);
14865 pop_function_context ();
14869 /* If there were any declarations or structure tags in that level,
14870 or if this level is a function body,
14871 create a BLOCK to record them for the life of this function. */
14874 block_previously_created = (current_binding_level->this_block != 0);
14875 if (block_previously_created)
14876 block = current_binding_level->this_block;
14877 else if (keep || functionbody)
14878 block = make_node (BLOCK);
14881 BLOCK_VARS (block) = decls;
14882 BLOCK_SUBBLOCKS (block) = subblocks;
14885 /* In each subblock, record that this is its superior. */
14887 for (link = subblocks; link; link = TREE_CHAIN (link))
14888 BLOCK_SUPERCONTEXT (link) = block;
14890 /* Clear out the meanings of the local variables of this level. */
14892 for (link = decls; link; link = TREE_CHAIN (link))
14894 if (DECL_NAME (link) != 0)
14896 /* If the ident. was used or addressed via a local extern decl,
14897 don't forget that fact. */
14898 if (DECL_EXTERNAL (link))
14900 if (TREE_USED (link))
14901 TREE_USED (DECL_NAME (link)) = 1;
14902 if (TREE_ADDRESSABLE (link))
14903 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1;
14905 IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = 0;
14909 /* If the level being exited is the top level of a function,
14910 check over all the labels, and clear out the current
14911 (function local) meanings of their names. */
14915 /* If this is the top level block of a function,
14916 the vars are the function's parameters.
14917 Don't leave them in the BLOCK because they are
14918 found in the FUNCTION_DECL instead. */
14920 BLOCK_VARS (block) = 0;
14923 /* Pop the current level, and free the structure for reuse. */
14926 register struct binding_level *level = current_binding_level;
14927 current_binding_level = current_binding_level->level_chain;
14929 level->level_chain = free_binding_level;
14930 free_binding_level = level;
14933 /* Dispose of the block that we just made inside some higher level. */
14935 && current_function_decl != error_mark_node)
14936 DECL_INITIAL (current_function_decl) = block;
14939 if (!block_previously_created)
14940 current_binding_level->blocks
14941 = chainon (current_binding_level->blocks, block);
14943 /* If we did not make a block for the level just exited,
14944 any blocks made for inner levels
14945 (since they cannot be recorded as subblocks in that level)
14946 must be carried forward so they will later become subblocks
14947 of something else. */
14948 else if (subblocks)
14949 current_binding_level->blocks
14950 = chainon (current_binding_level->blocks, subblocks);
14953 TREE_USED (block) = 1;
14958 print_lang_decl (file, node, indent)
14966 print_lang_identifier (file, node, indent)
14971 print_node (file, "global", IDENTIFIER_GLOBAL_VALUE (node), indent + 4);
14972 print_node (file, "local", IDENTIFIER_LOCAL_VALUE (node), indent + 4);
14976 print_lang_statistics ()
14981 print_lang_type (file, node, indent)
14988 /* Record a decl-node X as belonging to the current lexical scope.
14989 Check for errors (such as an incompatible declaration for the same
14990 name already seen in the same scope).
14992 Returns either X or an old decl for the same name.
14993 If an old decl is returned, it may have been smashed
14994 to agree with what X says. */
15001 register tree name = DECL_NAME (x);
15002 register struct binding_level *b = current_binding_level;
15004 if ((TREE_CODE (x) == FUNCTION_DECL)
15005 && (DECL_INITIAL (x) == 0)
15006 && DECL_EXTERNAL (x))
15007 DECL_CONTEXT (x) = NULL_TREE;
15009 DECL_CONTEXT (x) = current_function_decl;
15013 if (IDENTIFIER_INVENTED (name))
15016 DECL_ARTIFICIAL (x) = 1;
15018 DECL_IN_SYSTEM_HEADER (x) = 1;
15021 t = lookup_name_current_level (name);
15023 assert ((t == NULL_TREE) || (DECL_CONTEXT (x) == NULL_TREE));
15025 /* Don't push non-parms onto list for parms until we understand
15026 why we're doing this and whether it works. */
15028 assert ((b == global_binding_level)
15029 || !ffecom_transform_only_dummies_
15030 || TREE_CODE (x) == PARM_DECL);
15032 if ((t != NULL_TREE) && duplicate_decls (x, t))
15035 /* If we are processing a typedef statement, generate a whole new
15036 ..._TYPE node (which will be just an variant of the existing
15037 ..._TYPE node with identical properties) and then install the
15038 TYPE_DECL node generated to represent the typedef name as the
15039 TYPE_NAME of this brand new (duplicate) ..._TYPE node.
15041 The whole point here is to end up with a situation where each and every
15042 ..._TYPE node the compiler creates will be uniquely associated with
15043 AT MOST one node representing a typedef name. This way, even though
15044 the compiler substitutes corresponding ..._TYPE nodes for TYPE_DECL
15045 (i.e. "typedef name") nodes very early on, later parts of the
15046 compiler can always do the reverse translation and get back the
15047 corresponding typedef name. For example, given:
15049 typedef struct S MY_TYPE; MY_TYPE object;
15051 Later parts of the compiler might only know that `object' was of type
15052 `struct S' if it were not for code just below. With this code
15053 however, later parts of the compiler see something like:
15055 struct S' == struct S typedef struct S' MY_TYPE; struct S' object;
15057 And they can then deduce (from the node for type struct S') that the
15058 original object declaration was:
15062 Being able to do this is important for proper support of protoize, and
15063 also for generating precise symbolic debugging information which
15064 takes full account of the programmer's (typedef) vocabulary.
15066 Obviously, we don't want to generate a duplicate ..._TYPE node if the
15067 TYPE_DECL node that we are now processing really represents a
15068 standard built-in type.
15070 Since all standard types are effectively declared at line zero in the
15071 source file, we can easily check to see if we are working on a
15072 standard type by checking the current value of lineno. */
15074 if (TREE_CODE (x) == TYPE_DECL)
15076 if (DECL_SOURCE_LINE (x) == 0)
15078 if (TYPE_NAME (TREE_TYPE (x)) == 0)
15079 TYPE_NAME (TREE_TYPE (x)) = x;
15081 else if (TREE_TYPE (x) != error_mark_node)
15083 tree tt = TREE_TYPE (x);
15085 tt = build_type_copy (tt);
15086 TYPE_NAME (tt) = x;
15087 TREE_TYPE (x) = tt;
15091 /* This name is new in its binding level. Install the new declaration
15093 if (b == global_binding_level)
15094 IDENTIFIER_GLOBAL_VALUE (name) = x;
15096 IDENTIFIER_LOCAL_VALUE (name) = x;
15099 /* Put decls on list in reverse order. We will reverse them later if
15101 TREE_CHAIN (x) = b->names;
15107 /* Nonzero if the current level needs to have a BLOCK made. */
15114 for (decl = current_binding_level->names;
15116 decl = TREE_CHAIN (decl))
15118 if (TREE_USED (decl) || TREE_CODE (decl) != VAR_DECL
15119 || (DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl)))
15120 /* Currently, there aren't supposed to be non-artificial names
15121 at other than the top block for a function -- they're
15122 believed to always be temps. But it's wise to check anyway. */
15128 /* Enter a new binding level.
15129 If TAG_TRANSPARENT is nonzero, do so only for the name space of variables,
15130 not for that of tags. */
15133 pushlevel (tag_transparent)
15134 int tag_transparent;
15136 register struct binding_level *newlevel = NULL_BINDING_LEVEL;
15138 assert (! tag_transparent);
15140 if (current_binding_level == global_binding_level)
15145 /* Reuse or create a struct for this binding level. */
15147 if (free_binding_level)
15149 newlevel = free_binding_level;
15150 free_binding_level = free_binding_level->level_chain;
15154 newlevel = make_binding_level ();
15157 /* Add this level to the front of the chain (stack) of levels that
15160 *newlevel = clear_binding_level;
15161 newlevel->level_chain = current_binding_level;
15162 current_binding_level = newlevel;
15165 /* Set the BLOCK node for the innermost scope
15166 (the one we are currently in). */
15170 register tree block;
15172 current_binding_level->this_block = block;
15173 current_binding_level->names = chainon (current_binding_level->names,
15174 BLOCK_VARS (block));
15175 current_binding_level->blocks = chainon (current_binding_level->blocks,
15176 BLOCK_SUBBLOCKS (block));
15179 /* ~~gcc/tree.h *should* declare this, because toplev.c references it. */
15181 /* Can't 'yydebug' a front end not generated by yacc/bison! */
15184 set_yydebug (value)
15188 fprintf (stderr, "warning: no yacc/bison-generated output to debug!\n");
15192 signed_or_unsigned_type (unsignedp, type)
15198 if (! INTEGRAL_TYPE_P (type))
15200 if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node))
15201 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15202 if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
15203 return unsignedp ? unsigned_type_node : integer_type_node;
15204 if (TYPE_PRECISION (type) == TYPE_PRECISION (short_integer_type_node))
15205 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15206 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_integer_type_node))
15207 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15208 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_long_integer_type_node))
15209 return (unsignedp ? long_long_unsigned_type_node
15210 : long_long_integer_type_node);
15212 type2 = type_for_size (TYPE_PRECISION (type), unsignedp);
15213 if (type2 == NULL_TREE)
15223 tree type1 = TYPE_MAIN_VARIANT (type);
15224 ffeinfoKindtype kt;
15227 if (type1 == unsigned_char_type_node || type1 == char_type_node)
15228 return signed_char_type_node;
15229 if (type1 == unsigned_type_node)
15230 return integer_type_node;
15231 if (type1 == short_unsigned_type_node)
15232 return short_integer_type_node;
15233 if (type1 == long_unsigned_type_node)
15234 return long_integer_type_node;
15235 if (type1 == long_long_unsigned_type_node)
15236 return long_long_integer_type_node;
15237 #if 0 /* gcc/c-* files only */
15238 if (type1 == unsigned_intDI_type_node)
15239 return intDI_type_node;
15240 if (type1 == unsigned_intSI_type_node)
15241 return intSI_type_node;
15242 if (type1 == unsigned_intHI_type_node)
15243 return intHI_type_node;
15244 if (type1 == unsigned_intQI_type_node)
15245 return intQI_type_node;
15248 type2 = type_for_size (TYPE_PRECISION (type1), 0);
15249 if (type2 != NULL_TREE)
15252 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15254 type2 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
15256 if (type1 == type2)
15257 return ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15263 /* Prepare expr to be an argument of a TRUTH_NOT_EXPR,
15264 or validate its data type for an `if' or `while' statement or ?..: exp.
15266 This preparation consists of taking the ordinary
15267 representation of an expression expr and producing a valid tree
15268 boolean expression describing whether expr is nonzero. We could
15269 simply always do build_binary_op (NE_EXPR, expr, integer_zero_node, 1),
15270 but we optimize comparisons, &&, ||, and !.
15272 The resulting type should always be `integer_type_node'. */
15275 truthvalue_conversion (expr)
15278 if (TREE_CODE (expr) == ERROR_MARK)
15281 #if 0 /* This appears to be wrong for C++. */
15282 /* These really should return error_mark_node after 2.4 is stable.
15283 But not all callers handle ERROR_MARK properly. */
15284 switch (TREE_CODE (TREE_TYPE (expr)))
15287 error ("struct type value used where scalar is required");
15288 return integer_zero_node;
15291 error ("union type value used where scalar is required");
15292 return integer_zero_node;
15295 error ("array type value used where scalar is required");
15296 return integer_zero_node;
15303 switch (TREE_CODE (expr))
15305 /* It is simpler and generates better code to have only TRUTH_*_EXPR
15306 or comparison expressions as truth values at this level. */
15308 case COMPONENT_REF:
15309 /* A one-bit unsigned bit-field is already acceptable. */
15310 if (1 == TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (expr, 1)))
15311 && TREE_UNSIGNED (TREE_OPERAND (expr, 1)))
15317 /* It is simpler and generates better code to have only TRUTH_*_EXPR
15318 or comparison expressions as truth values at this level. */
15320 if (integer_zerop (TREE_OPERAND (expr, 1)))
15321 return build_unary_op (TRUTH_NOT_EXPR, TREE_OPERAND (expr, 0), 0);
15323 case NE_EXPR: case LE_EXPR: case GE_EXPR: case LT_EXPR: case GT_EXPR:
15324 case TRUTH_ANDIF_EXPR:
15325 case TRUTH_ORIF_EXPR:
15326 case TRUTH_AND_EXPR:
15327 case TRUTH_OR_EXPR:
15328 case TRUTH_XOR_EXPR:
15329 TREE_TYPE (expr) = integer_type_node;
15336 return integer_zerop (expr) ? integer_zero_node : integer_one_node;
15339 return real_zerop (expr) ? integer_zero_node : integer_one_node;
15342 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 0)))
15343 return build (COMPOUND_EXPR, integer_type_node,
15344 TREE_OPERAND (expr, 0), integer_one_node);
15346 return integer_one_node;
15349 return ffecom_2 ((TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
15350 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
15352 truthvalue_conversion (TREE_OPERAND (expr, 0)),
15353 truthvalue_conversion (TREE_OPERAND (expr, 1)));
15359 /* These don't change whether an object is non-zero or zero. */
15360 return truthvalue_conversion (TREE_OPERAND (expr, 0));
15364 /* These don't change whether an object is zero or non-zero, but
15365 we can't ignore them if their second arg has side-effects. */
15366 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
15367 return build (COMPOUND_EXPR, integer_type_node, TREE_OPERAND (expr, 1),
15368 truthvalue_conversion (TREE_OPERAND (expr, 0)));
15370 return truthvalue_conversion (TREE_OPERAND (expr, 0));
15373 /* Distribute the conversion into the arms of a COND_EXPR. */
15374 return fold (build (COND_EXPR, integer_type_node, TREE_OPERAND (expr, 0),
15375 truthvalue_conversion (TREE_OPERAND (expr, 1)),
15376 truthvalue_conversion (TREE_OPERAND (expr, 2))));
15379 /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
15380 since that affects how `default_conversion' will behave. */
15381 if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE
15382 || TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE)
15384 /* fall through... */
15386 /* If this is widening the argument, we can ignore it. */
15387 if (TYPE_PRECISION (TREE_TYPE (expr))
15388 >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))
15389 return truthvalue_conversion (TREE_OPERAND (expr, 0));
15393 /* With IEEE arithmetic, x - x may not equal 0, so we can't optimize
15395 if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
15396 && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE)
15398 /* fall through... */
15400 /* This and MINUS_EXPR can be changed into a comparison of the
15402 if (TREE_TYPE (TREE_OPERAND (expr, 0))
15403 == TREE_TYPE (TREE_OPERAND (expr, 1)))
15404 return ffecom_2 (NE_EXPR, integer_type_node,
15405 TREE_OPERAND (expr, 0),
15406 TREE_OPERAND (expr, 1));
15407 return ffecom_2 (NE_EXPR, integer_type_node,
15408 TREE_OPERAND (expr, 0),
15409 fold (build1 (NOP_EXPR,
15410 TREE_TYPE (TREE_OPERAND (expr, 0)),
15411 TREE_OPERAND (expr, 1))));
15414 if (integer_onep (TREE_OPERAND (expr, 1)))
15419 #if 0 /* No such thing in Fortran. */
15420 if (warn_parentheses && C_EXP_ORIGINAL_CODE (expr) == MODIFY_EXPR)
15421 warning ("suggest parentheses around assignment used as truth value");
15429 if (TREE_CODE (TREE_TYPE (expr)) == COMPLEX_TYPE)
15431 ((TREE_SIDE_EFFECTS (expr)
15432 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
15434 truthvalue_conversion (ffecom_1 (REALPART_EXPR,
15435 TREE_TYPE (TREE_TYPE (expr)),
15437 truthvalue_conversion (ffecom_1 (IMAGPART_EXPR,
15438 TREE_TYPE (TREE_TYPE (expr)),
15441 return ffecom_2 (NE_EXPR, integer_type_node,
15443 convert (TREE_TYPE (expr), integer_zero_node));
15447 type_for_mode (mode, unsignedp)
15448 enum machine_mode mode;
15455 if (mode == TYPE_MODE (integer_type_node))
15456 return unsignedp ? unsigned_type_node : integer_type_node;
15458 if (mode == TYPE_MODE (signed_char_type_node))
15459 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15461 if (mode == TYPE_MODE (short_integer_type_node))
15462 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15464 if (mode == TYPE_MODE (long_integer_type_node))
15465 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15467 if (mode == TYPE_MODE (long_long_integer_type_node))
15468 return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
15470 #if HOST_BITS_PER_WIDE_INT >= 64
15471 if (mode == TYPE_MODE (intTI_type_node))
15472 return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
15475 if (mode == TYPE_MODE (float_type_node))
15476 return float_type_node;
15478 if (mode == TYPE_MODE (double_type_node))
15479 return double_type_node;
15481 if (mode == TYPE_MODE (build_pointer_type (char_type_node)))
15482 return build_pointer_type (char_type_node);
15484 if (mode == TYPE_MODE (build_pointer_type (integer_type_node)))
15485 return build_pointer_type (integer_type_node);
15487 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
15488 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
15490 if (((t = ffecom_tree_type[i][j]) != NULL_TREE)
15491 && (mode == TYPE_MODE (t)))
15493 if ((i == FFEINFO_basictypeINTEGER) && unsignedp)
15494 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][j];
15504 type_for_size (bits, unsignedp)
15508 ffeinfoKindtype kt;
15511 if (bits == TYPE_PRECISION (integer_type_node))
15512 return unsignedp ? unsigned_type_node : integer_type_node;
15514 if (bits == TYPE_PRECISION (signed_char_type_node))
15515 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15517 if (bits == TYPE_PRECISION (short_integer_type_node))
15518 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15520 if (bits == TYPE_PRECISION (long_integer_type_node))
15521 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15523 if (bits == TYPE_PRECISION (long_long_integer_type_node))
15524 return (unsignedp ? long_long_unsigned_type_node
15525 : long_long_integer_type_node);
15527 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15529 type_node = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15531 if ((type_node != NULL_TREE) && (bits == TYPE_PRECISION (type_node)))
15532 return unsignedp ? ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt]
15540 unsigned_type (type)
15543 tree type1 = TYPE_MAIN_VARIANT (type);
15544 ffeinfoKindtype kt;
15547 if (type1 == signed_char_type_node || type1 == char_type_node)
15548 return unsigned_char_type_node;
15549 if (type1 == integer_type_node)
15550 return unsigned_type_node;
15551 if (type1 == short_integer_type_node)
15552 return short_unsigned_type_node;
15553 if (type1 == long_integer_type_node)
15554 return long_unsigned_type_node;
15555 if (type1 == long_long_integer_type_node)
15556 return long_long_unsigned_type_node;
15557 #if 0 /* gcc/c-* files only */
15558 if (type1 == intDI_type_node)
15559 return unsigned_intDI_type_node;
15560 if (type1 == intSI_type_node)
15561 return unsigned_intSI_type_node;
15562 if (type1 == intHI_type_node)
15563 return unsigned_intHI_type_node;
15564 if (type1 == intQI_type_node)
15565 return unsigned_intQI_type_node;
15568 type2 = type_for_size (TYPE_PRECISION (type1), 1);
15569 if (type2 != NULL_TREE)
15572 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15574 type2 = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15576 if (type1 == type2)
15577 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
15585 union tree_node *t ATTRIBUTE_UNUSED;
15587 if (TREE_CODE (t) == IDENTIFIER_NODE)
15589 struct lang_identifier *i = (struct lang_identifier *) t;
15590 ggc_mark_tree (IDENTIFIER_GLOBAL_VALUE (i));
15591 ggc_mark_tree (IDENTIFIER_LOCAL_VALUE (i));
15592 ggc_mark_tree (IDENTIFIER_LABEL_VALUE (i));
15594 else if (TYPE_P (t) && TYPE_LANG_SPECIFIC (t))
15595 ggc_mark (TYPE_LANG_SPECIFIC (t));
15598 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
15600 #if FFECOM_GCC_INCLUDE
15602 /* From gcc/cccp.c, the code to handle -I. */
15604 /* Skip leading "./" from a directory name.
15605 This may yield the empty string, which represents the current directory. */
15607 static const char *
15608 skip_redundant_dir_prefix (const char *dir)
15610 while (dir[0] == '.' && dir[1] == '/')
15611 for (dir += 2; *dir == '/'; dir++)
15613 if (dir[0] == '.' && !dir[1])
15618 /* The file_name_map structure holds a mapping of file names for a
15619 particular directory. This mapping is read from the file named
15620 FILE_NAME_MAP_FILE in that directory. Such a file can be used to
15621 map filenames on a file system with severe filename restrictions,
15622 such as DOS. The format of the file name map file is just a series
15623 of lines with two tokens on each line. The first token is the name
15624 to map, and the second token is the actual name to use. */
15626 struct file_name_map
15628 struct file_name_map *map_next;
15633 #define FILE_NAME_MAP_FILE "header.gcc"
15635 /* Current maximum length of directory names in the search path
15636 for include files. (Altered as we get more of them.) */
15638 static int max_include_len = 0;
15640 struct file_name_list
15642 struct file_name_list *next;
15644 /* Mapping of file names for this directory. */
15645 struct file_name_map *name_map;
15646 /* Non-zero if name_map is valid. */
15650 static struct file_name_list *include = NULL; /* First dir to search */
15651 static struct file_name_list *last_include = NULL; /* Last in chain */
15653 /* I/O buffer structure.
15654 The `fname' field is nonzero for source files and #include files
15655 and for the dummy text used for -D and -U.
15656 It is zero for rescanning results of macro expansion
15657 and for expanding macro arguments. */
15658 #define INPUT_STACK_MAX 400
15659 static struct file_buf {
15661 /* Filename specified with #line command. */
15662 const char *nominal_fname;
15663 /* Record where in the search path this file was found.
15664 For #include_next. */
15665 struct file_name_list *dir;
15667 ffewhereColumn column;
15668 } instack[INPUT_STACK_MAX];
15670 static int last_error_tick = 0; /* Incremented each time we print it. */
15671 static int input_file_stack_tick = 0; /* Incremented when status changes. */
15673 /* Current nesting level of input sources.
15674 `instack[indepth]' is the level currently being read. */
15675 static int indepth = -1;
15677 typedef struct file_buf FILE_BUF;
15679 typedef unsigned char U_CHAR;
15681 /* table to tell if char can be part of a C identifier. */
15682 U_CHAR is_idchar[256];
15683 /* table to tell if char can be first char of a c identifier. */
15684 U_CHAR is_idstart[256];
15685 /* table to tell if c is horizontal space. */
15686 U_CHAR is_hor_space[256];
15687 /* table to tell if c is horizontal or vertical space. */
15688 static U_CHAR is_space[256];
15690 #define SKIP_WHITE_SPACE(p) do { while (is_hor_space[*p]) p++; } while (0)
15691 #define SKIP_ALL_WHITE_SPACE(p) do { while (is_space[*p]) p++; } while (0)
15693 /* Nonzero means -I- has been seen,
15694 so don't look for #include "foo" the source-file directory. */
15695 static int ignore_srcdir;
15697 #ifndef INCLUDE_LEN_FUDGE
15698 #define INCLUDE_LEN_FUDGE 0
15701 static void append_include_chain (struct file_name_list *first,
15702 struct file_name_list *last);
15703 static FILE *open_include_file (char *filename,
15704 struct file_name_list *searchptr);
15705 static void print_containing_files (ffebadSeverity sev);
15706 static const char *skip_redundant_dir_prefix (const char *);
15707 static char *read_filename_string (int ch, FILE *f);
15708 static struct file_name_map *read_name_map (const char *dirname);
15710 /* Append a chain of `struct file_name_list's
15711 to the end of the main include chain.
15712 FIRST is the beginning of the chain to append, and LAST is the end. */
15715 append_include_chain (first, last)
15716 struct file_name_list *first, *last;
15718 struct file_name_list *dir;
15720 if (!first || !last)
15726 last_include->next = first;
15728 for (dir = first; ; dir = dir->next) {
15729 int len = strlen (dir->fname) + INCLUDE_LEN_FUDGE;
15730 if (len > max_include_len)
15731 max_include_len = len;
15737 last_include = last;
15740 /* Try to open include file FILENAME. SEARCHPTR is the directory
15741 being tried from the include file search path. This function maps
15742 filenames on file systems based on information read by
15746 open_include_file (filename, searchptr)
15748 struct file_name_list *searchptr;
15750 register struct file_name_map *map;
15751 register char *from;
15754 if (searchptr && ! searchptr->got_name_map)
15756 searchptr->name_map = read_name_map (searchptr->fname
15757 ? searchptr->fname : ".");
15758 searchptr->got_name_map = 1;
15761 /* First check the mapping for the directory we are using. */
15762 if (searchptr && searchptr->name_map)
15765 if (searchptr->fname)
15766 from += strlen (searchptr->fname) + 1;
15767 for (map = searchptr->name_map; map; map = map->map_next)
15769 if (! strcmp (map->map_from, from))
15771 /* Found a match. */
15772 return fopen (map->map_to, "r");
15777 /* Try to find a mapping file for the particular directory we are
15778 looking in. Thus #include <sys/types.h> will look up sys/types.h
15779 in /usr/include/header.gcc and look up types.h in
15780 /usr/include/sys/header.gcc. */
15781 p = strrchr (filename, '/');
15782 #ifdef DIR_SEPARATOR
15783 if (! p) p = strrchr (filename, DIR_SEPARATOR);
15785 char *tmp = strrchr (filename, DIR_SEPARATOR);
15786 if (tmp != NULL && tmp > p) p = tmp;
15792 && searchptr->fname
15793 && strlen (searchptr->fname) == (size_t) (p - filename)
15794 && ! strncmp (searchptr->fname, filename, (int) (p - filename)))
15796 /* FILENAME is in SEARCHPTR, which we've already checked. */
15797 return fopen (filename, "r");
15803 map = read_name_map (".");
15807 dir = (char *) xmalloc (p - filename + 1);
15808 memcpy (dir, filename, p - filename);
15809 dir[p - filename] = '\0';
15811 map = read_name_map (dir);
15814 for (; map; map = map->map_next)
15815 if (! strcmp (map->map_from, from))
15816 return fopen (map->map_to, "r");
15818 return fopen (filename, "r");
15821 /* Print the file names and line numbers of the #include
15822 commands which led to the current file. */
15825 print_containing_files (ffebadSeverity sev)
15827 FILE_BUF *ip = NULL;
15833 /* If stack of files hasn't changed since we last printed
15834 this info, don't repeat it. */
15835 if (last_error_tick == input_file_stack_tick)
15838 for (i = indepth; i >= 0; i--)
15839 if (instack[i].fname != NULL) {
15844 /* Give up if we don't find a source file. */
15848 /* Find the other, outer source files. */
15849 for (i--; i >= 0; i--)
15850 if (instack[i].fname != NULL)
15856 str1 = "In file included";
15868 ffebad_start_msg ("%A from %B at %0%C", sev);
15869 ffebad_here (0, ip->line, ip->column);
15870 ffebad_string (str1);
15871 ffebad_string (ip->nominal_fname);
15872 ffebad_string (str2);
15876 /* Record we have printed the status as of this time. */
15877 last_error_tick = input_file_stack_tick;
15880 /* Read a space delimited string of unlimited length from a stdio
15884 read_filename_string (ch, f)
15892 set = alloc = xmalloc (len + 1);
15893 if (! is_space[ch])
15896 while ((ch = getc (f)) != EOF && ! is_space[ch])
15898 if (set - alloc == len)
15901 alloc = xrealloc (alloc, len + 1);
15902 set = alloc + len / 2;
15912 /* Read the file name map file for DIRNAME. */
15914 static struct file_name_map *
15915 read_name_map (dirname)
15916 const char *dirname;
15918 /* This structure holds a linked list of file name maps, one per
15920 struct file_name_map_list
15922 struct file_name_map_list *map_list_next;
15923 char *map_list_name;
15924 struct file_name_map *map_list_map;
15926 static struct file_name_map_list *map_list;
15927 register struct file_name_map_list *map_list_ptr;
15931 int separator_needed;
15933 dirname = skip_redundant_dir_prefix (dirname);
15935 for (map_list_ptr = map_list; map_list_ptr;
15936 map_list_ptr = map_list_ptr->map_list_next)
15937 if (! strcmp (map_list_ptr->map_list_name, dirname))
15938 return map_list_ptr->map_list_map;
15940 map_list_ptr = ((struct file_name_map_list *)
15941 xmalloc (sizeof (struct file_name_map_list)));
15942 map_list_ptr->map_list_name = xstrdup (dirname);
15943 map_list_ptr->map_list_map = NULL;
15945 dirlen = strlen (dirname);
15946 separator_needed = dirlen != 0 && dirname[dirlen - 1] != '/';
15947 name = (char *) xmalloc (dirlen + strlen (FILE_NAME_MAP_FILE) + 2);
15948 strcpy (name, dirname);
15949 name[dirlen] = '/';
15950 strcpy (name + dirlen + separator_needed, FILE_NAME_MAP_FILE);
15951 f = fopen (name, "r");
15954 map_list_ptr->map_list_map = NULL;
15959 while ((ch = getc (f)) != EOF)
15962 struct file_name_map *ptr;
15966 from = read_filename_string (ch, f);
15967 while ((ch = getc (f)) != EOF && is_hor_space[ch])
15969 to = read_filename_string (ch, f);
15971 ptr = ((struct file_name_map *)
15972 xmalloc (sizeof (struct file_name_map)));
15973 ptr->map_from = from;
15975 /* Make the real filename absolute. */
15980 ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
15981 strcpy (ptr->map_to, dirname);
15982 ptr->map_to[dirlen] = '/';
15983 strcpy (ptr->map_to + dirlen + separator_needed, to);
15987 ptr->map_next = map_list_ptr->map_list_map;
15988 map_list_ptr->map_list_map = ptr;
15990 while ((ch = getc (f)) != '\n')
15997 map_list_ptr->map_list_next = map_list;
15998 map_list = map_list_ptr;
16000 return map_list_ptr->map_list_map;
16004 ffecom_file_ (const char *name)
16008 /* Do partial setup of input buffer for the sake of generating
16009 early #line directives (when -g is in effect). */
16011 fp = &instack[++indepth];
16012 memset ((char *) fp, 0, sizeof (FILE_BUF));
16015 fp->nominal_fname = fp->fname = name;
16018 /* Initialize syntactic classifications of characters. */
16021 ffecom_initialize_char_syntax_ ()
16026 * Set up is_idchar and is_idstart tables. These should be
16027 * faster than saying (is_alpha (c) || c == '_'), etc.
16028 * Set up these things before calling any routines tthat
16031 for (i = 'a'; i <= 'z'; i++) {
16032 is_idchar[i - 'a' + 'A'] = 1;
16034 is_idstart[i - 'a' + 'A'] = 1;
16037 for (i = '0'; i <= '9'; i++)
16039 is_idchar['_'] = 1;
16040 is_idstart['_'] = 1;
16042 /* horizontal space table */
16043 is_hor_space[' '] = 1;
16044 is_hor_space['\t'] = 1;
16045 is_hor_space['\v'] = 1;
16046 is_hor_space['\f'] = 1;
16047 is_hor_space['\r'] = 1;
16050 is_space['\t'] = 1;
16051 is_space['\v'] = 1;
16052 is_space['\f'] = 1;
16053 is_space['\n'] = 1;
16054 is_space['\r'] = 1;
16058 ffecom_close_include_ (FILE *f)
16063 input_file_stack_tick++;
16065 ffewhere_line_kill (instack[indepth].line);
16066 ffewhere_column_kill (instack[indepth].column);
16070 ffecom_decode_include_option_ (char *spec)
16072 struct file_name_list *dirtmp;
16074 if (! ignore_srcdir && !strcmp (spec, "-"))
16078 dirtmp = (struct file_name_list *)
16079 xmalloc (sizeof (struct file_name_list));
16080 dirtmp->next = 0; /* New one goes on the end */
16081 dirtmp->fname = spec;
16082 dirtmp->got_name_map = 0;
16084 error ("Directory name must immediately follow -I");
16086 append_include_chain (dirtmp, dirtmp);
16091 /* Open INCLUDEd file. */
16094 ffecom_open_include_ (char *name, ffewhereLine l, ffewhereColumn c)
16097 size_t flen = strlen (fbeg);
16098 struct file_name_list *search_start = include; /* Chain of dirs to search */
16099 struct file_name_list dsp[1]; /* First in chain, if #include "..." */
16100 struct file_name_list *searchptr = 0;
16101 char *fname; /* Dynamically allocated fname buffer */
16108 dsp[0].fname = NULL;
16110 /* If -I- was specified, don't search current dir, only spec'd ones. */
16111 if (!ignore_srcdir)
16113 for (fp = &instack[indepth]; fp >= instack; fp--)
16119 if ((nam = fp->nominal_fname) != NULL)
16121 /* Found a named file. Figure out dir of the file,
16122 and put it in front of the search list. */
16123 dsp[0].next = search_start;
16124 search_start = dsp;
16126 ep = strrchr (nam, '/');
16127 #ifdef DIR_SEPARATOR
16128 if (ep == NULL) ep = strrchr (nam, DIR_SEPARATOR);
16130 char *tmp = strrchr (nam, DIR_SEPARATOR);
16131 if (tmp != NULL && tmp > ep) ep = tmp;
16135 ep = strrchr (nam, ']');
16136 if (ep == NULL) ep = strrchr (nam, '>');
16137 if (ep == NULL) ep = strrchr (nam, ':');
16138 if (ep != NULL) ep++;
16143 dsp[0].fname = (char *) xmalloc (n + 1);
16144 strncpy (dsp[0].fname, nam, n);
16145 dsp[0].fname[n] = '\0';
16146 if (n + INCLUDE_LEN_FUDGE > max_include_len)
16147 max_include_len = n + INCLUDE_LEN_FUDGE;
16150 dsp[0].fname = NULL; /* Current directory */
16151 dsp[0].got_name_map = 0;
16157 /* Allocate this permanently, because it gets stored in the definitions
16159 fname = xmalloc (max_include_len + flen + 4);
16160 /* + 2 above for slash and terminating null. */
16161 /* + 2 added for '.h' on VMS (to support '#include filename') (NOT USED
16164 /* If specified file name is absolute, just open it. */
16167 #ifdef DIR_SEPARATOR
16168 || *fbeg == DIR_SEPARATOR
16172 strncpy (fname, (char *) fbeg, flen);
16174 f = open_include_file (fname, NULL_PTR);
16180 /* Search directory path, trying to open the file.
16181 Copy each filename tried into FNAME. */
16183 for (searchptr = search_start; searchptr; searchptr = searchptr->next)
16185 if (searchptr->fname)
16187 /* The empty string in a search path is ignored.
16188 This makes it possible to turn off entirely
16189 a standard piece of the list. */
16190 if (searchptr->fname[0] == 0)
16192 strcpy (fname, skip_redundant_dir_prefix (searchptr->fname));
16193 if (fname[0] && fname[strlen (fname) - 1] != '/')
16194 strcat (fname, "/");
16195 fname[strlen (fname) + flen] = 0;
16200 strncat (fname, fbeg, flen);
16202 /* Change this 1/2 Unix 1/2 VMS file specification into a
16203 full VMS file specification */
16204 if (searchptr->fname && (searchptr->fname[0] != 0))
16206 /* Fix up the filename */
16207 hack_vms_include_specification (fname);
16211 /* This is a normal VMS filespec, so use it unchanged. */
16212 strncpy (fname, (char *) fbeg, flen);
16214 #if 0 /* Not for g77. */
16215 /* if it's '#include filename', add the missing .h */
16216 if (strchr (fname, '.') == NULL)
16217 strcat (fname, ".h");
16221 f = open_include_file (fname, searchptr);
16223 if (f == NULL && errno == EACCES)
16225 print_containing_files (FFEBAD_severityWARNING);
16226 ffebad_start_msg ("At %0, INCLUDE file %A exists, but is not readable",
16227 FFEBAD_severityWARNING);
16228 ffebad_string (fname);
16229 ffebad_here (0, l, c);
16240 /* A file that was not found. */
16242 strncpy (fname, (char *) fbeg, flen);
16244 print_containing_files (ffebad_severity (FFEBAD_OPEN_INCLUDE));
16245 ffebad_start (FFEBAD_OPEN_INCLUDE);
16246 ffebad_here (0, l, c);
16247 ffebad_string (fname);
16251 if (dsp[0].fname != NULL)
16252 free (dsp[0].fname);
16257 if (indepth >= (INPUT_STACK_MAX - 1))
16259 print_containing_files (FFEBAD_severityFATAL);
16260 ffebad_start_msg ("At %0, INCLUDE nesting too deep",
16261 FFEBAD_severityFATAL);
16262 ffebad_string (fname);
16263 ffebad_here (0, l, c);
16268 instack[indepth].line = ffewhere_line_use (l);
16269 instack[indepth].column = ffewhere_column_use (c);
16271 fp = &instack[indepth + 1];
16272 memset ((char *) fp, 0, sizeof (FILE_BUF));
16273 fp->nominal_fname = fp->fname = fname;
16274 fp->dir = searchptr;
16277 input_file_stack_tick++;
16281 #endif /* FFECOM_GCC_INCLUDE */
16283 /**INDENT* (Do not reformat this comment even with -fca option.)
16284 Data-gathering files: Given the source file listed below, compiled with
16285 f2c I obtained the output file listed after that, and from the output
16286 file I derived the above code.
16288 -------- (begin input file to f2c)
16294 double precision D1,D2
16296 call getem(A1,A2,C1,C2,I1,I2,R1,R2,D1,D2)
16323 c FFEINTRIN_impACOS
16324 call fooR(ACOS(R1))
16325 c FFEINTRIN_impAIMAG
16326 call fooR(AIMAG(C1))
16327 c FFEINTRIN_impAINT
16328 call fooR(AINT(R1))
16329 c FFEINTRIN_impALOG
16330 call fooR(ALOG(R1))
16331 c FFEINTRIN_impALOG10
16332 call fooR(ALOG10(R1))
16333 c FFEINTRIN_impAMAX0
16334 call fooR(AMAX0(I1,I2))
16335 c FFEINTRIN_impAMAX1
16336 call fooR(AMAX1(R1,R2))
16337 c FFEINTRIN_impAMIN0
16338 call fooR(AMIN0(I1,I2))
16339 c FFEINTRIN_impAMIN1
16340 call fooR(AMIN1(R1,R2))
16341 c FFEINTRIN_impAMOD
16342 call fooR(AMOD(R1,R2))
16343 c FFEINTRIN_impANINT
16344 call fooR(ANINT(R1))
16345 c FFEINTRIN_impASIN
16346 call fooR(ASIN(R1))
16347 c FFEINTRIN_impATAN
16348 call fooR(ATAN(R1))
16349 c FFEINTRIN_impATAN2
16350 call fooR(ATAN2(R1,R2))
16351 c FFEINTRIN_impCABS
16352 call fooR(CABS(C1))
16353 c FFEINTRIN_impCCOS
16354 call fooC(CCOS(C1))
16355 c FFEINTRIN_impCEXP
16356 call fooC(CEXP(C1))
16357 c FFEINTRIN_impCHAR
16358 call fooA(CHAR(I1))
16359 c FFEINTRIN_impCLOG
16360 call fooC(CLOG(C1))
16361 c FFEINTRIN_impCONJG
16362 call fooC(CONJG(C1))
16365 c FFEINTRIN_impCOSH
16366 call fooR(COSH(R1))
16367 c FFEINTRIN_impCSIN
16368 call fooC(CSIN(C1))
16369 c FFEINTRIN_impCSQRT
16370 call fooC(CSQRT(C1))
16371 c FFEINTRIN_impDABS
16372 call fooD(DABS(D1))
16373 c FFEINTRIN_impDACOS
16374 call fooD(DACOS(D1))
16375 c FFEINTRIN_impDASIN
16376 call fooD(DASIN(D1))
16377 c FFEINTRIN_impDATAN
16378 call fooD(DATAN(D1))
16379 c FFEINTRIN_impDATAN2
16380 call fooD(DATAN2(D1,D2))
16381 c FFEINTRIN_impDCOS
16382 call fooD(DCOS(D1))
16383 c FFEINTRIN_impDCOSH
16384 call fooD(DCOSH(D1))
16385 c FFEINTRIN_impDDIM
16386 call fooD(DDIM(D1,D2))
16387 c FFEINTRIN_impDEXP
16388 call fooD(DEXP(D1))
16390 call fooR(DIM(R1,R2))
16391 c FFEINTRIN_impDINT
16392 call fooD(DINT(D1))
16393 c FFEINTRIN_impDLOG
16394 call fooD(DLOG(D1))
16395 c FFEINTRIN_impDLOG10
16396 call fooD(DLOG10(D1))
16397 c FFEINTRIN_impDMAX1
16398 call fooD(DMAX1(D1,D2))
16399 c FFEINTRIN_impDMIN1
16400 call fooD(DMIN1(D1,D2))
16401 c FFEINTRIN_impDMOD
16402 call fooD(DMOD(D1,D2))
16403 c FFEINTRIN_impDNINT
16404 call fooD(DNINT(D1))
16405 c FFEINTRIN_impDPROD
16406 call fooD(DPROD(R1,R2))
16407 c FFEINTRIN_impDSIGN
16408 call fooD(DSIGN(D1,D2))
16409 c FFEINTRIN_impDSIN
16410 call fooD(DSIN(D1))
16411 c FFEINTRIN_impDSINH
16412 call fooD(DSINH(D1))
16413 c FFEINTRIN_impDSQRT
16414 call fooD(DSQRT(D1))
16415 c FFEINTRIN_impDTAN
16416 call fooD(DTAN(D1))
16417 c FFEINTRIN_impDTANH
16418 call fooD(DTANH(D1))
16421 c FFEINTRIN_impIABS
16422 call fooI(IABS(I1))
16423 c FFEINTRIN_impICHAR
16424 call fooI(ICHAR(A1))
16425 c FFEINTRIN_impIDIM
16426 call fooI(IDIM(I1,I2))
16427 c FFEINTRIN_impIDNINT
16428 call fooI(IDNINT(D1))
16429 c FFEINTRIN_impINDEX
16430 call fooI(INDEX(A1,A2))
16431 c FFEINTRIN_impISIGN
16432 call fooI(ISIGN(I1,I2))
16436 call fooL(LGE(A1,A2))
16438 call fooL(LGT(A1,A2))
16440 call fooL(LLE(A1,A2))
16442 call fooL(LLT(A1,A2))
16443 c FFEINTRIN_impMAX0
16444 call fooI(MAX0(I1,I2))
16445 c FFEINTRIN_impMAX1
16446 call fooI(MAX1(R1,R2))
16447 c FFEINTRIN_impMIN0
16448 call fooI(MIN0(I1,I2))
16449 c FFEINTRIN_impMIN1
16450 call fooI(MIN1(R1,R2))
16452 call fooI(MOD(I1,I2))
16453 c FFEINTRIN_impNINT
16454 call fooI(NINT(R1))
16455 c FFEINTRIN_impSIGN
16456 call fooR(SIGN(R1,R2))
16459 c FFEINTRIN_impSINH
16460 call fooR(SINH(R1))
16461 c FFEINTRIN_impSQRT
16462 call fooR(SQRT(R1))
16465 c FFEINTRIN_impTANH
16466 call fooR(TANH(R1))
16467 c FFEINTRIN_imp_CMPLX_C
16468 call fooC(cmplx(C1,C2))
16469 c FFEINTRIN_imp_CMPLX_D
16470 call fooZ(cmplx(D1,D2))
16471 c FFEINTRIN_imp_CMPLX_I
16472 call fooC(cmplx(I1,I2))
16473 c FFEINTRIN_imp_CMPLX_R
16474 call fooC(cmplx(R1,R2))
16475 c FFEINTRIN_imp_DBLE_C
16476 call fooD(dble(C1))
16477 c FFEINTRIN_imp_DBLE_D
16478 call fooD(dble(D1))
16479 c FFEINTRIN_imp_DBLE_I
16480 call fooD(dble(I1))
16481 c FFEINTRIN_imp_DBLE_R
16482 call fooD(dble(R1))
16483 c FFEINTRIN_imp_INT_C
16485 c FFEINTRIN_imp_INT_D
16487 c FFEINTRIN_imp_INT_I
16489 c FFEINTRIN_imp_INT_R
16491 c FFEINTRIN_imp_REAL_C
16492 call fooR(real(C1))
16493 c FFEINTRIN_imp_REAL_D
16494 call fooR(real(D1))
16495 c FFEINTRIN_imp_REAL_I
16496 call fooR(real(I1))
16497 c FFEINTRIN_imp_REAL_R
16498 call fooR(real(R1))
16500 c FFEINTRIN_imp_INT_D:
16502 c FFEINTRIN_specIDINT
16503 call fooI(IDINT(D1))
16505 c FFEINTRIN_imp_INT_R:
16507 c FFEINTRIN_specIFIX
16508 call fooI(IFIX(R1))
16509 c FFEINTRIN_specINT
16512 c FFEINTRIN_imp_REAL_D:
16514 c FFEINTRIN_specSNGL
16515 call fooR(SNGL(D1))
16517 c FFEINTRIN_imp_REAL_I:
16519 c FFEINTRIN_specFLOAT
16520 call fooR(FLOAT(I1))
16521 c FFEINTRIN_specREAL
16522 call fooR(REAL(I1))
16525 -------- (end input file to f2c)
16527 -------- (begin output from providing above input file as input to:
16528 -------- `f2c | gcc -E -C - | sed -e "s:/[*]*://:g" -e "s:[*]*[/]://:g" \
16529 -------- -e "s:^#.*$::g"')
16531 // -- translated by f2c (version 19950223).
16532 You must link the resulting object file with the libraries:
16533 -lf2c -lm (in that order)
16537 // f2c.h -- Standard Fortran to C header file //
16539 /// barf [ba:rf] 2. "He suggested using FORTRAN, and everybody barfed."
16541 - From The Shogakukan DICTIONARY OF NEW ENGLISH (Second edition) //
16546 // F2C_INTEGER will normally be `int' but would be `long' on 16-bit systems //
16547 // we assume short, float are OK //
16548 typedef long int // long int // integer;
16549 typedef char *address;
16550 typedef short int shortint;
16551 typedef float real;
16552 typedef double doublereal;
16553 typedef struct { real r, i; } complex;
16554 typedef struct { doublereal r, i; } doublecomplex;
16555 typedef long int // long int // logical;
16556 typedef short int shortlogical;
16557 typedef char logical1;
16558 typedef char integer1;
16559 // typedef long long longint; // // system-dependent //
16564 // Extern is for use with -E //
16578 typedef long int // int or long int // flag;
16579 typedef long int // int or long int // ftnlen;
16580 typedef long int // int or long int // ftnint;
16583 //external read, write//
16592 //internal read, write//
16622 //rewind, backspace, endfile//
16634 ftnint *inex; //parameters in standard's order//
16660 union Multitype { // for multiple entry points //
16671 typedef union Multitype Multitype;
16673 typedef long Long; // No longer used; formerly in Namelist //
16675 struct Vardesc { // for Namelist //
16681 typedef struct Vardesc Vardesc;
16688 typedef struct Namelist Namelist;
16697 // procedure parameter types for -A and -C++ //
16702 typedef int // Unknown procedure type // (*U_fp)();
16703 typedef shortint (*J_fp)();
16704 typedef integer (*I_fp)();
16705 typedef real (*R_fp)();
16706 typedef doublereal (*D_fp)(), (*E_fp)();
16707 typedef // Complex // void (*C_fp)();
16708 typedef // Double Complex // void (*Z_fp)();
16709 typedef logical (*L_fp)();
16710 typedef shortlogical (*K_fp)();
16711 typedef // Character // void (*H_fp)();
16712 typedef // Subroutine // int (*S_fp)();
16714 // E_fp is for real functions when -R is not specified //
16715 typedef void C_f; // complex function //
16716 typedef void H_f; // character function //
16717 typedef void Z_f; // double complex function //
16718 typedef doublereal E_f; // real function with -R not specified //
16720 // undef any lower-case symbols that your C compiler predefines, e.g.: //
16723 // (No such symbols should be defined in a strict ANSI C compiler.
16724 We can avoid trouble with f2c-translated code by using
16725 gcc -ansi [-traditional].) //
16749 // Main program // MAIN__()
16751 // System generated locals //
16754 doublereal d__1, d__2;
16756 doublecomplex z__1, z__2, z__3;
16760 // Builtin functions //
16763 double pow_ri(), pow_di();
16767 double acos(), r_imag(), r_int(), log(), r_lg10(), r_mod(), r_nint(),
16768 asin(), atan(), atan2(), c_abs();
16769 void c_cos(), c_exp(), c_log(), r_cnjg();
16770 double cos(), cosh();
16771 void c_sin(), c_sqrt();
16772 double d_dim(), exp(), r_dim(), d_int(), d_lg10(), d_mod(), d_nint(),
16773 d_sign(), sin(), sinh(), sqrt(), tan(), tanh();
16774 integer i_dim(), i_dnnt(), i_indx(), i_sign(), i_len();
16775 logical l_ge(), l_gt(), l_le(), l_lt();
16779 // Local variables //
16780 extern // Subroutine // int fooa_(), fooc_(), food_(), fooi_(), foor_(),
16781 fool_(), fooz_(), getem_();
16782 static char a1[10], a2[10];
16783 static complex c1, c2;
16784 static doublereal d1, d2;
16785 static integer i1, i2;
16786 static real r1, r2;
16789 getem_(a1, a2, &c1, &c2, &i1, &i2, &r1, &r2, &d1, &d2, 10L, 10L);
16797 d__1 = (doublereal) i1;
16798 q__1.r = c1.r / d__1, q__1.i = c1.i / d__1;
16808 c_div(&q__1, &c1, &c2);
16810 q__1.r = c1.r / r1, q__1.i = c1.i / r1;
16812 z__1.r = c1.r / d1, z__1.i = c1.i / d1;
16815 i__1 = pow_ii(&i1, &i2);
16817 r__1 = pow_ri(&r1, &i1);
16819 d__1 = pow_di(&d1, &i1);
16821 pow_ci(&q__1, &c1, &i1);
16823 d__1 = (doublereal) r1;
16824 d__2 = (doublereal) r2;
16825 r__1 = pow_dd(&d__1, &d__2);
16827 d__2 = (doublereal) r1;
16828 d__1 = pow_dd(&d__2, &d1);
16830 d__1 = pow_dd(&d1, &d2);
16832 d__2 = (doublereal) r1;
16833 d__1 = pow_dd(&d1, &d__2);
16835 z__2.r = c1.r, z__2.i = c1.i;
16836 z__3.r = c2.r, z__3.i = c2.i;
16837 pow_zz(&z__1, &z__2, &z__3);
16838 q__1.r = z__1.r, q__1.i = z__1.i;
16840 z__2.r = c1.r, z__2.i = c1.i;
16841 z__3.r = r1, z__3.i = 0.;
16842 pow_zz(&z__1, &z__2, &z__3);
16843 q__1.r = z__1.r, q__1.i = z__1.i;
16845 z__2.r = c1.r, z__2.i = c1.i;
16846 z__3.r = d1, z__3.i = 0.;
16847 pow_zz(&z__1, &z__2, &z__3);
16849 // FFEINTRIN_impABS //
16850 r__1 = (doublereal)(( r1 ) >= 0 ? ( r1 ) : -( r1 )) ;
16852 // FFEINTRIN_impACOS //
16855 // FFEINTRIN_impAIMAG //
16856 r__1 = r_imag(&c1);
16858 // FFEINTRIN_impAINT //
16861 // FFEINTRIN_impALOG //
16864 // FFEINTRIN_impALOG10 //
16865 r__1 = r_lg10(&r1);
16867 // FFEINTRIN_impAMAX0 //
16868 r__1 = (real) (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
16870 // FFEINTRIN_impAMAX1 //
16871 r__1 = (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
16873 // FFEINTRIN_impAMIN0 //
16874 r__1 = (real) (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
16876 // FFEINTRIN_impAMIN1 //
16877 r__1 = (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
16879 // FFEINTRIN_impAMOD //
16880 r__1 = r_mod(&r1, &r2);
16882 // FFEINTRIN_impANINT //
16883 r__1 = r_nint(&r1);
16885 // FFEINTRIN_impASIN //
16888 // FFEINTRIN_impATAN //
16891 // FFEINTRIN_impATAN2 //
16892 r__1 = atan2(r1, r2);
16894 // FFEINTRIN_impCABS //
16897 // FFEINTRIN_impCCOS //
16900 // FFEINTRIN_impCEXP //
16903 // FFEINTRIN_impCHAR //
16904 *(unsigned char *)&ch__1[0] = i1;
16906 // FFEINTRIN_impCLOG //
16909 // FFEINTRIN_impCONJG //
16910 r_cnjg(&q__1, &c1);
16912 // FFEINTRIN_impCOS //
16915 // FFEINTRIN_impCOSH //
16918 // FFEINTRIN_impCSIN //
16921 // FFEINTRIN_impCSQRT //
16922 c_sqrt(&q__1, &c1);
16924 // FFEINTRIN_impDABS //
16925 d__1 = (( d1 ) >= 0 ? ( d1 ) : -( d1 )) ;
16927 // FFEINTRIN_impDACOS //
16930 // FFEINTRIN_impDASIN //
16933 // FFEINTRIN_impDATAN //
16936 // FFEINTRIN_impDATAN2 //
16937 d__1 = atan2(d1, d2);
16939 // FFEINTRIN_impDCOS //
16942 // FFEINTRIN_impDCOSH //
16945 // FFEINTRIN_impDDIM //
16946 d__1 = d_dim(&d1, &d2);
16948 // FFEINTRIN_impDEXP //
16951 // FFEINTRIN_impDIM //
16952 r__1 = r_dim(&r1, &r2);
16954 // FFEINTRIN_impDINT //
16957 // FFEINTRIN_impDLOG //
16960 // FFEINTRIN_impDLOG10 //
16961 d__1 = d_lg10(&d1);
16963 // FFEINTRIN_impDMAX1 //
16964 d__1 = (( d1 ) >= ( d2 ) ? ( d1 ) : ( d2 )) ;
16966 // FFEINTRIN_impDMIN1 //
16967 d__1 = (( d1 ) <= ( d2 ) ? ( d1 ) : ( d2 )) ;
16969 // FFEINTRIN_impDMOD //
16970 d__1 = d_mod(&d1, &d2);
16972 // FFEINTRIN_impDNINT //
16973 d__1 = d_nint(&d1);
16975 // FFEINTRIN_impDPROD //
16976 d__1 = (doublereal) r1 * r2;
16978 // FFEINTRIN_impDSIGN //
16979 d__1 = d_sign(&d1, &d2);
16981 // FFEINTRIN_impDSIN //
16984 // FFEINTRIN_impDSINH //
16987 // FFEINTRIN_impDSQRT //
16990 // FFEINTRIN_impDTAN //
16993 // FFEINTRIN_impDTANH //
16996 // FFEINTRIN_impEXP //
16999 // FFEINTRIN_impIABS //
17000 i__1 = (( i1 ) >= 0 ? ( i1 ) : -( i1 )) ;
17002 // FFEINTRIN_impICHAR //
17003 i__1 = *(unsigned char *)a1;
17005 // FFEINTRIN_impIDIM //
17006 i__1 = i_dim(&i1, &i2);
17008 // FFEINTRIN_impIDNINT //
17009 i__1 = i_dnnt(&d1);
17011 // FFEINTRIN_impINDEX //
17012 i__1 = i_indx(a1, a2, 10L, 10L);
17014 // FFEINTRIN_impISIGN //
17015 i__1 = i_sign(&i1, &i2);
17017 // FFEINTRIN_impLEN //
17018 i__1 = i_len(a1, 10L);
17020 // FFEINTRIN_impLGE //
17021 L__1 = l_ge(a1, a2, 10L, 10L);
17023 // FFEINTRIN_impLGT //
17024 L__1 = l_gt(a1, a2, 10L, 10L);
17026 // FFEINTRIN_impLLE //
17027 L__1 = l_le(a1, a2, 10L, 10L);
17029 // FFEINTRIN_impLLT //
17030 L__1 = l_lt(a1, a2, 10L, 10L);
17032 // FFEINTRIN_impMAX0 //
17033 i__1 = (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
17035 // FFEINTRIN_impMAX1 //
17036 i__1 = (integer) (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
17038 // FFEINTRIN_impMIN0 //
17039 i__1 = (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
17041 // FFEINTRIN_impMIN1 //
17042 i__1 = (integer) (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
17044 // FFEINTRIN_impMOD //
17047 // FFEINTRIN_impNINT //
17048 i__1 = i_nint(&r1);
17050 // FFEINTRIN_impSIGN //
17051 r__1 = r_sign(&r1, &r2);
17053 // FFEINTRIN_impSIN //
17056 // FFEINTRIN_impSINH //
17059 // FFEINTRIN_impSQRT //
17062 // FFEINTRIN_impTAN //
17065 // FFEINTRIN_impTANH //
17068 // FFEINTRIN_imp_CMPLX_C //
17071 q__1.r = r__1, q__1.i = r__2;
17073 // FFEINTRIN_imp_CMPLX_D //
17074 z__1.r = d1, z__1.i = d2;
17076 // FFEINTRIN_imp_CMPLX_I //
17079 q__1.r = r__1, q__1.i = r__2;
17081 // FFEINTRIN_imp_CMPLX_R //
17082 q__1.r = r1, q__1.i = r2;
17084 // FFEINTRIN_imp_DBLE_C //
17085 d__1 = (doublereal) c1.r;
17087 // FFEINTRIN_imp_DBLE_D //
17090 // FFEINTRIN_imp_DBLE_I //
17091 d__1 = (doublereal) i1;
17093 // FFEINTRIN_imp_DBLE_R //
17094 d__1 = (doublereal) r1;
17096 // FFEINTRIN_imp_INT_C //
17097 i__1 = (integer) c1.r;
17099 // FFEINTRIN_imp_INT_D //
17100 i__1 = (integer) d1;
17102 // FFEINTRIN_imp_INT_I //
17105 // FFEINTRIN_imp_INT_R //
17106 i__1 = (integer) r1;
17108 // FFEINTRIN_imp_REAL_C //
17111 // FFEINTRIN_imp_REAL_D //
17114 // FFEINTRIN_imp_REAL_I //
17117 // FFEINTRIN_imp_REAL_R //
17121 // FFEINTRIN_imp_INT_D: //
17123 // FFEINTRIN_specIDINT //
17124 i__1 = (integer) d1;
17127 // FFEINTRIN_imp_INT_R: //
17129 // FFEINTRIN_specIFIX //
17130 i__1 = (integer) r1;
17132 // FFEINTRIN_specINT //
17133 i__1 = (integer) r1;
17136 // FFEINTRIN_imp_REAL_D: //
17138 // FFEINTRIN_specSNGL //
17142 // FFEINTRIN_imp_REAL_I: //
17144 // FFEINTRIN_specFLOAT //
17147 // FFEINTRIN_specREAL //
17153 -------- (end output file from f2c)