]> gcc.gnu.org Git - gcc.git/blame - gcc/f/com.c
argv.c, [...]: Improve manual formatting.
[gcc.git] / gcc / f / com.c
CommitLineData
5ff904cd 1/* com.c -- Implementation File (module.c template V1.0)
0d5d970b 2 Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001
06ceef4e 3 Free Software Foundation, Inc.
25d7717e 4 Contributed by James Craig Burley.
5ff904cd
JL
5
6This file is part of GNU Fortran.
7
8GNU Fortran is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; either version 2, or (at your option)
11any later version.
12
13GNU Fortran is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with GNU Fortran; see the file COPYING. If not, write to
20the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
2102111-1307, USA.
22
23 Related Modules:
24 None
25
26 Description:
27 Contains compiler-specific functions.
28
29 Modifications:
30*/
31
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.
39
40 Building expressions generally seems quite easy, but building decls
41 has been challenging and is undergoing revision. gcc has several
42 kinds of decls:
43
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)
52
53 g77 has a set of functions that somewhat parallels the gcc front end
54 when it comes to building decls:
55
56 Internal Function (one we define, not just declare as extern):
5ff904cd
JL
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);
c7e4ee3a 62 ffecom_start_compstmt ();
5ff904cd 63 // for stmts and decls inside function, do appropriate things;
c7e4ee3a 64 ffecom_end_compstmt ();
5ff904cd
JL
65 finish_function (is_nested);
66 if (is_nested) pop_f_function_context ();
5ff904cd
JL
67
68 Everything Else:
5ff904cd
JL
69 tree d;
70 tree init;
5ff904cd
JL
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);
5ff904cd
JL
78
79*/
80
81/* Include files. */
82
95a1b676 83#include "proj.h"
5ff904cd 84#if FFECOM_targetCURRENT == FFECOM_targetGCC
15a40ced
ZW
85#include "flags.h"
86#include "rtl.h"
87#include "toplev.h"
88#include "tree.h"
89#include "output.h" /* Must follow tree.h so TREE_CODE is defined! */
90#include "convert.h"
91#include "ggc.h"
46f018e1 92#include "diagnostic.h"
17ed6335 93#include "langhooks.h"
5ff904cd
JL
94#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
95
96#define FFECOM_GCC_INCLUDE 1 /* Enable -I. */
97
5ff904cd
JL
98/* VMS-specific definitions */
99#ifdef VMS
100#include <descrip.h>
101#define O_RDONLY 0 /* Open arg for Read/Only */
102#define O_WRONLY 1 /* Open arg for Write/Only */
103#define read(fd,buf,size) VMS_read (fd,buf,size)
104#define write(fd,buf,size) VMS_write (fd,buf,size)
105#define open(fname,mode,prot) VMS_open (fname,mode,prot)
106#define fopen(fname,mode) VMS_fopen (fname,mode)
107#define freopen(fname,mode,ofile) VMS_freopen (fname,mode,ofile)
108#define strncat(dst,src,cnt) VMS_strncat (dst,src,cnt)
109#define fstat(fd,stbuf) VMS_fstat (fd,stbuf)
110static int VMS_fstat (), VMS_stat ();
111static char * VMS_strncat ();
112static int VMS_read ();
113static int VMS_write ();
114static int VMS_open ();
115static FILE * VMS_fopen ();
116static FILE * VMS_freopen ();
117static void hack_vms_include_specification ();
118typedef struct { unsigned :16, :16, :16; } vms_ino_t;
119#define ino_t vms_ino_t
120#define INCLUDE_LEN_FUDGE 10 /* leave room for VMS syntax conversion */
5ff904cd
JL
121#endif /* VMS */
122
5ff904cd
JL
123#define FFECOM_DETERMINE_TYPES 1 /* for com.h */
124#include "com.h"
125#include "bad.h"
126#include "bld.h"
127#include "equiv.h"
128#include "expr.h"
129#include "implic.h"
130#include "info.h"
131#include "malloc.h"
132#include "src.h"
133#include "st.h"
134#include "storag.h"
135#include "symbol.h"
136#include "target.h"
137#include "top.h"
138#include "type.h"
139
140/* Externals defined here. */
141
5ff904cd
JL
142#if FFECOM_targetCURRENT == FFECOM_targetGCC
143
c7e4ee3a
CB
144/* ~~gcc/tree.h *should* declare this, because toplev.c and dwarfout.c
145 reference it. */
5ff904cd 146
f425a887 147const char * const language_string = "GNU F77";
5ff904cd 148
77f77701
DB
149/* Stream for reading from the input file. */
150FILE *finput;
151
5ff904cd
JL
152/* These definitions parallel those in c-decl.c so that code from that
153 module can be used pretty much as is. Much of these defs aren't
154 otherwise used, i.e. by g77 code per se, except some of them are used
155 to build some of them that are. The ones that are global (i.e. not
156 "static") are those that ste.c and such might use (directly
157 or by using com macros that reference them in their definitions). */
158
5ff904cd
JL
159tree string_type_node;
160
5ff904cd
JL
161/* The rest of these are inventions for g77, though there might be
162 similar things in the C front end. As they are found, these
163 inventions should be renamed to be canonical. Note that only
164 the ones currently required to be global are so. */
165
166static tree ffecom_tree_fun_type_void;
5ff904cd
JL
167
168tree ffecom_integer_type_node; /* Abbrev for _tree_type[blah][blah]. */
169tree ffecom_integer_zero_node; /* Like *_*_* with g77's integer type. */
170tree ffecom_integer_one_node; /* " */
171tree ffecom_tree_type[FFEINFO_basictype][FFEINFO_kindtype];
172
173/* _fun_type things are the f2c-specific versions. For -fno-f2c,
174 just use build_function_type and build_pointer_type on the
175 appropriate _tree_type array element. */
176
177static tree ffecom_tree_fun_type[FFEINFO_basictype][FFEINFO_kindtype];
178static tree ffecom_tree_ptr_to_fun_type[FFEINFO_basictype][FFEINFO_kindtype];
179static tree ffecom_tree_subr_type;
180static tree ffecom_tree_ptr_to_subr_type;
181static tree ffecom_tree_blockdata_type;
182
183static tree ffecom_tree_xargc_;
184
185ffecomSymbol ffecom_symbol_null_
186=
187{
188 NULL_TREE,
189 NULL_TREE,
190 NULL_TREE,
0816ebdd
KG
191 NULL_TREE,
192 false
5ff904cd
JL
193};
194ffeinfoKindtype ffecom_pointer_kind_ = FFEINFO_basictypeNONE;
195ffeinfoKindtype ffecom_label_kind_ = FFEINFO_basictypeNONE;
196
197int ffecom_f2c_typecode_[FFEINFO_basictype][FFEINFO_kindtype];
198tree ffecom_f2c_integer_type_node;
199tree ffecom_f2c_ptr_to_integer_type_node;
200tree ffecom_f2c_address_type_node;
201tree ffecom_f2c_real_type_node;
202tree ffecom_f2c_ptr_to_real_type_node;
203tree ffecom_f2c_doublereal_type_node;
204tree ffecom_f2c_complex_type_node;
205tree ffecom_f2c_doublecomplex_type_node;
206tree ffecom_f2c_longint_type_node;
207tree ffecom_f2c_logical_type_node;
208tree ffecom_f2c_flag_type_node;
209tree ffecom_f2c_ftnlen_type_node;
210tree ffecom_f2c_ftnlen_zero_node;
211tree ffecom_f2c_ftnlen_one_node;
212tree ffecom_f2c_ftnlen_two_node;
213tree ffecom_f2c_ptr_to_ftnlen_type_node;
214tree ffecom_f2c_ftnint_type_node;
215tree ffecom_f2c_ptr_to_ftnint_type_node;
216#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
217
218/* Simple definitions and enumerations. */
219
220#ifndef FFECOM_sizeMAXSTACKITEM
221#define FFECOM_sizeMAXSTACKITEM 32*1024 /* Keep user-declared things
222 larger than this # bytes
223 off stack if possible. */
224#endif
225
226/* For systems that have large enough stacks, they should define
227 this to 0, and here, for ease of use later on, we just undefine
228 it if it is 0. */
229
230#if FFECOM_sizeMAXSTACKITEM == 0
231#undef FFECOM_sizeMAXSTACKITEM
232#endif
233
234typedef enum
235 {
236 FFECOM_rttypeVOID_,
6d433196 237 FFECOM_rttypeVOIDSTAR_, /* C's `void *' type. */
795232f7
JL
238 FFECOM_rttypeFTNINT_, /* f2c's `ftnint' type. */
239 FFECOM_rttypeINTEGER_, /* f2c's `integer' type. */
240 FFECOM_rttypeLONGINT_, /* f2c's `longint' type. */
241 FFECOM_rttypeLOGICAL_, /* f2c's `logical' type. */
242 FFECOM_rttypeREAL_F2C_, /* f2c's `real' returned as `double'. */
243 FFECOM_rttypeREAL_GNU_, /* `real' returned as such. */
5ff904cd 244 FFECOM_rttypeCOMPLEX_F2C_, /* f2c's `complex' returned via 1st arg. */
795232f7 245 FFECOM_rttypeCOMPLEX_GNU_, /* f2c's `complex' returned directly. */
5ff904cd 246 FFECOM_rttypeDOUBLE_, /* C's `double' type. */
795232f7 247 FFECOM_rttypeDOUBLEREAL_, /* f2c's `doublereal' type. */
5ff904cd 248 FFECOM_rttypeDBLCMPLX_F2C_, /* f2c's `doublecomplex' returned via 1st arg. */
795232f7 249 FFECOM_rttypeDBLCMPLX_GNU_, /* f2c's `doublecomplex' returned directly. */
5ff904cd
JL
250 FFECOM_rttypeCHARACTER_, /* f2c `char *'/`ftnlen' pair. */
251 FFECOM_rttype_
252 } ffecomRttype_;
253
254/* Internal typedefs. */
255
256#if FFECOM_targetCURRENT == FFECOM_targetGCC
257typedef struct _ffecom_concat_list_ ffecomConcatList_;
5ff904cd
JL
258#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
259
260/* Private include files. */
261
262
263/* Internal structure definitions. */
264
265#if FFECOM_targetCURRENT == FFECOM_targetGCC
266struct _ffecom_concat_list_
267 {
268 ffebld *exprs;
269 int count;
270 int max;
271 ffetargetCharacterSize minlen;
272 ffetargetCharacterSize maxlen;
273 };
5ff904cd
JL
274#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
275
276/* Static functions (internal). */
277
278#if FFECOM_targetCURRENT == FFECOM_targetGCC
26f096f9 279static tree ffecom_arglist_expr_ (const char *argstring, ffebld args);
5ff904cd
JL
280static tree ffecom_widest_expr_type_ (ffebld list);
281static bool ffecom_overlap_ (tree dest_decl, tree dest_offset,
282 tree dest_size, tree source_tree,
283 ffebld source, bool scalar_arg);
284static bool ffecom_args_overlapping_ (tree dest_tree, ffebld dest,
285 tree args, tree callee_commons,
286 bool scalar_args);
26f096f9 287static tree ffecom_build_f2c_string_ (int i, const char *s);
5ff904cd
JL
288static tree ffecom_call_ (tree fn, ffeinfoKindtype kt,
289 bool is_f2c_complex, tree type,
290 tree args, tree dest_tree,
291 ffebld dest, bool *dest_used,
c7e4ee3a 292 tree callee_commons, bool scalar_args, tree hook);
5ff904cd
JL
293static tree ffecom_call_binop_ (tree fn, ffeinfoKindtype kt,
294 bool is_f2c_complex, tree type,
295 ffebld left, ffebld right,
296 tree dest_tree, ffebld dest,
297 bool *dest_used, tree callee_commons,
95eb4fd9 298 bool scalar_args, bool ref, tree hook);
86fc7a6c
CB
299static void ffecom_char_args_x_ (tree *xitem, tree *length,
300 ffebld expr, bool with_null);
5ff904cd
JL
301static tree ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy);
302static tree ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s);
303static ffecomConcatList_
304 ffecom_concat_list_gather_ (ffecomConcatList_ catlist,
305 ffebld expr,
306 ffetargetCharacterSize max);
307static void ffecom_concat_list_kill_ (ffecomConcatList_ catlist);
308static ffecomConcatList_ ffecom_concat_list_new_ (ffebld expr,
309 ffetargetCharacterSize max);
26f096f9
KG
310static void ffecom_debug_kludge_ (tree aggr, const char *aggr_type,
311 ffesymbol member, tree member_type,
312 ffetargetOffset offset);
5ff904cd 313static void ffecom_do_entry_ (ffesymbol fn, int entrynum);
092a4ef8
RH
314static tree ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
315 bool *dest_used, bool assignp, bool widenp);
5ff904cd
JL
316static tree ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
317 ffebld dest, bool *dest_used);
c7e4ee3a 318static tree ffecom_expr_power_integer_ (ffebld expr);
5ff904cd 319static void ffecom_expr_transform_ (ffebld expr);
26f096f9 320static void ffecom_f2c_make_type_ (tree *type, int tcode, const char *name);
5ff904cd
JL
321static void ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size,
322 int code);
323static ffeglobal ffecom_finish_global_ (ffeglobal global);
324static ffesymbol ffecom_finish_symbol_transform_ (ffesymbol s);
26f096f9 325static tree ffecom_get_appended_identifier_ (char us, const char *text);
5ff904cd 326static tree ffecom_get_external_identifier_ (ffesymbol s);
26f096f9 327static tree ffecom_get_identifier_ (const char *text);
5ff904cd
JL
328static tree ffecom_gen_sfuncdef_ (ffesymbol s,
329 ffeinfoBasictype bt,
330 ffeinfoKindtype kt);
26f096f9 331static const char *ffecom_gfrt_args_ (ffecomGfrt ix);
5ff904cd
JL
332static tree ffecom_gfrt_tree_ (ffecomGfrt ix);
333static tree ffecom_init_zero_ (tree decl);
334static tree ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg,
335 tree *maybe_tree);
336static tree ffecom_intrinsic_len_ (ffebld expr);
337static void ffecom_let_char_ (tree dest_tree,
338 tree dest_length,
339 ffetargetCharacterSize dest_size,
340 ffebld source);
341static void ffecom_make_gfrt_ (ffecomGfrt ix);
342static void ffecom_member_phase1_ (ffestorag mst, ffestorag st);
5ff904cd 343static void ffecom_member_phase2_ (ffestorag mst, ffestorag st);
c7e4ee3a
CB
344static void ffecom_prepare_let_char_ (ffetargetCharacterSize dest_size,
345 ffebld source);
5ff904cd
JL
346static void ffecom_push_dummy_decls_ (ffebld dumlist,
347 bool stmtfunc);
348static void ffecom_start_progunit_ (void);
349static ffesymbol ffecom_sym_transform_ (ffesymbol s);
350static ffesymbol ffecom_sym_transform_assign_ (ffesymbol s);
351static void ffecom_transform_common_ (ffesymbol s);
352static void ffecom_transform_equiv_ (ffestorag st);
353static tree ffecom_transform_namelist_ (ffesymbol s);
354static void ffecom_tree_canonize_ptr_ (tree *decl, tree *offset,
355 tree t);
356static void ffecom_tree_canonize_ref_ (tree *decl, tree *offset,
357 tree *size, tree tree);
358static tree ffecom_tree_divide_ (tree tree_type, tree left, tree right,
359 tree dest_tree, ffebld dest,
c7e4ee3a 360 bool *dest_used, tree hook);
5ff904cd
JL
361static tree ffecom_type_localvar_ (ffesymbol s,
362 ffeinfoBasictype bt,
363 ffeinfoKindtype kt);
364static tree ffecom_type_namelist_ (void);
5ff904cd
JL
365static tree ffecom_type_vardesc_ (void);
366static tree ffecom_vardesc_ (ffebld expr);
367static tree ffecom_vardesc_array_ (ffesymbol s);
368static tree ffecom_vardesc_dims_ (ffesymbol s);
26f096f9
KG
369static tree ffecom_convert_narrow_ (tree type, tree expr);
370static tree ffecom_convert_widen_ (tree type, tree expr);
5ff904cd
JL
371#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
372
373/* These are static functions that parallel those found in the C front
374 end and thus have the same names. */
375
376#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a 377static tree bison_rule_compstmt_ (void);
5ff904cd 378static void bison_rule_pushlevel_ (void);
c7e4ee3a 379static void delete_block (tree block);
5ff904cd
JL
380static int duplicate_decls (tree newdecl, tree olddecl);
381static void finish_decl (tree decl, tree init, bool is_top_level);
382static void finish_function (int nested);
4b731ffa 383static const char *lang_printable_name (tree decl, int v);
5ff904cd
JL
384static tree lookup_name_current_level (tree name);
385static struct binding_level *make_binding_level (void);
386static void pop_f_function_context (void);
387static void push_f_function_context (void);
388static void push_parm_decl (tree parm);
389static tree pushdecl_top_level (tree decl);
c7e4ee3a 390static int kept_level_p (void);
5ff904cd
JL
391static tree storedecls (tree decls);
392static void store_parm_decls (int is_main_program);
393static tree start_decl (tree decl, bool is_top_level);
394static void start_function (tree name, tree type, int nested, int public);
395#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
396#if FFECOM_GCC_INCLUDE
b0791fa9 397static void ffecom_file_ (const char *name);
5ff904cd
JL
398static void ffecom_initialize_char_syntax_ (void);
399static void ffecom_close_include_ (FILE *f);
400static int ffecom_decode_include_option_ (char *spec);
401static FILE *ffecom_open_include_ (char *name, ffewhereLine l,
402 ffewhereColumn c);
403#endif /* FFECOM_GCC_INCLUDE */
404
405/* Static objects accessed by functions in this module. */
406
407static ffesymbol ffecom_primary_entry_ = NULL;
408static ffesymbol ffecom_nested_entry_ = NULL;
409static ffeinfoKind ffecom_primary_entry_kind_;
410static bool ffecom_primary_entry_is_proc_;
411#if FFECOM_targetCURRENT == FFECOM_targetGCC
412static tree ffecom_outer_function_decl_;
413static tree ffecom_previous_function_decl_;
414static tree ffecom_which_entrypoint_decl_;
5ff904cd
JL
415static tree ffecom_float_zero_ = NULL_TREE;
416static tree ffecom_float_half_ = NULL_TREE;
417static tree ffecom_double_zero_ = NULL_TREE;
418static tree ffecom_double_half_ = NULL_TREE;
419static tree ffecom_func_result_;/* For functions. */
420static tree ffecom_func_length_;/* For CHARACTER fns. */
421static ffebld ffecom_list_blockdata_;
422static ffebld ffecom_list_common_;
423static ffebld ffecom_master_arglist_;
424static ffeinfoBasictype ffecom_master_bt_;
425static ffeinfoKindtype ffecom_master_kt_;
426static ffetargetCharacterSize ffecom_master_size_;
427static int ffecom_num_fns_ = 0;
428static int ffecom_num_entrypoints_ = 0;
429static bool ffecom_is_altreturning_ = FALSE;
430static tree ffecom_multi_type_node_;
431static tree ffecom_multi_retval_;
432static tree
433 ffecom_multi_fields_[FFEINFO_basictype][FFEINFO_kindtype];
434static bool ffecom_member_namelisted_; /* _member_phase1_ namelisted? */
435static bool ffecom_doing_entry_ = FALSE;
436static bool ffecom_transform_only_dummies_ = FALSE;
ff852b44
CB
437static int ffecom_typesize_pointer_;
438static int ffecom_typesize_integer1_;
5ff904cd
JL
439
440/* Holds pointer-to-function expressions. */
441
442static tree ffecom_gfrt_[FFECOM_gfrt]
443=
444{
95eb4fd9 445#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) NULL_TREE,
5ff904cd
JL
446#include "com-rt.def"
447#undef DEFGFRT
448};
449
450/* Holds the external names of the functions. */
451
19dab795 452static const char *const ffecom_gfrt_name_[FFECOM_gfrt]
5ff904cd
JL
453=
454{
95eb4fd9 455#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) NAME,
5ff904cd
JL
456#include "com-rt.def"
457#undef DEFGFRT
458};
459
460/* Whether the function returns. */
461
462static bool ffecom_gfrt_volatile_[FFECOM_gfrt]
463=
464{
95eb4fd9 465#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) VOLATILE,
5ff904cd
JL
466#include "com-rt.def"
467#undef DEFGFRT
468};
469
470/* Whether the function returns type complex. */
471
472static bool ffecom_gfrt_complex_[FFECOM_gfrt]
473=
474{
95eb4fd9
TM
475#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) COMPLEX,
476#include "com-rt.def"
477#undef DEFGFRT
478};
479
480/* Whether the function is const
481 (i.e., has no side effects and only depends on its arguments). */
482
483static bool ffecom_gfrt_const_[FFECOM_gfrt]
484=
485{
486#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) CONST,
5ff904cd
JL
487#include "com-rt.def"
488#undef DEFGFRT
489};
490
491/* Type code for the function return value. */
492
493static ffecomRttype_ ffecom_gfrt_type_[FFECOM_gfrt]
494=
495{
95eb4fd9 496#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) TYPE,
5ff904cd
JL
497#include "com-rt.def"
498#undef DEFGFRT
499};
500
501/* String of codes for the function's arguments. */
502
19dab795 503static const char *const ffecom_gfrt_argstring_[FFECOM_gfrt]
5ff904cd
JL
504=
505{
95eb4fd9 506#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) ARGS,
5ff904cd
JL
507#include "com-rt.def"
508#undef DEFGFRT
509};
510#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
511
512/* Internal macros. */
513
514#if FFECOM_targetCURRENT == FFECOM_targetGCC
515
516/* We let tm.h override the types used here, to handle trivial differences
517 such as the choice of unsigned int or long unsigned int for size_t.
518 When machines start needing nontrivial differences in the size type,
519 it would be best to do something here to figure out automatically
520 from other information what type to use. */
521
ff852b44
CB
522#ifndef SIZE_TYPE
523#define SIZE_TYPE "long unsigned int"
524#endif
5ff904cd 525
5ff904cd
JL
526#define ffecom_concat_list_count_(catlist) ((catlist).count)
527#define ffecom_concat_list_expr_(catlist,i) ((catlist).exprs[(i)])
528#define ffecom_concat_list_maxlen_(catlist) ((catlist).maxlen)
529#define ffecom_concat_list_minlen_(catlist) ((catlist).minlen)
530
86fc7a6c
CB
531#define ffecom_char_args_(i,l,e) ffecom_char_args_x_((i),(l),(e),FALSE)
532#define ffecom_char_args_with_null_(i,l,e) ffecom_char_args_x_((i),(l),(e),TRUE)
533
5ff904cd
JL
534/* For each binding contour we allocate a binding_level structure
535 * which records the names defined in that contour.
536 * Contours include:
537 * 0) the global one
538 * 1) one for each function definition,
539 * where internal declarations of the parameters appear.
540 *
541 * The current meaning of a name can be found by searching the levels from
542 * the current one out to the global one.
543 */
544
545/* Note that the information in the `names' component of the global contour
546 is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers. */
547
548struct binding_level
549 {
c7e4ee3a
CB
550 /* A chain of _DECL nodes for all variables, constants, functions,
551 and typedef types. These are in the reverse of the order supplied.
552 */
5ff904cd
JL
553 tree names;
554
c7e4ee3a
CB
555 /* For each level (except not the global one),
556 a chain of BLOCK nodes for all the levels
557 that were entered and exited one level down. */
5ff904cd
JL
558 tree blocks;
559
c7e4ee3a
CB
560 /* The BLOCK node for this level, if one has been preallocated.
561 If 0, the BLOCK is allocated (if needed) when the level is popped. */
5ff904cd
JL
562 tree this_block;
563
564 /* The binding level which this one is contained in (inherits from). */
565 struct binding_level *level_chain;
c7e4ee3a
CB
566
567 /* 0: no ffecom_prepare_* functions called at this level yet;
568 1: ffecom_prepare* functions called, except not ffecom_prepare_end;
569 2: ffecom_prepare_end called. */
570 int prep_state;
5ff904cd
JL
571 };
572
573#define NULL_BINDING_LEVEL (struct binding_level *) NULL
574
575/* The binding level currently in effect. */
576
577static struct binding_level *current_binding_level;
578
579/* A chain of binding_level structures awaiting reuse. */
580
581static struct binding_level *free_binding_level;
582
583/* The outermost binding level, for names of file scope.
584 This is created when the compiler is started and exists
585 through the entire run. */
586
587static struct binding_level *global_binding_level;
588
589/* Binding level structures are initialized by copying this one. */
590
591static struct binding_level clear_binding_level
592=
c7e4ee3a 593{NULL, NULL, NULL, NULL_BINDING_LEVEL, 0};
5ff904cd
JL
594
595/* Language-dependent contents of an identifier. */
596
597struct lang_identifier
598 {
599 struct tree_identifier ignore;
600 tree global_value, local_value, label_value;
601 bool invented;
602 };
603
604/* Macros for access to language-specific slots in an identifier. */
605/* Each of these slots contains a DECL node or null. */
606
607/* This represents the value which the identifier has in the
608 file-scope namespace. */
609#define IDENTIFIER_GLOBAL_VALUE(NODE) \
610 (((struct lang_identifier *)(NODE))->global_value)
611/* This represents the value which the identifier has in the current
612 scope. */
613#define IDENTIFIER_LOCAL_VALUE(NODE) \
614 (((struct lang_identifier *)(NODE))->local_value)
615/* This represents the value which the identifier has as a label in
616 the current label scope. */
617#define IDENTIFIER_LABEL_VALUE(NODE) \
618 (((struct lang_identifier *)(NODE))->label_value)
619/* This is nonzero if the identifier was "made up" by g77 code. */
620#define IDENTIFIER_INVENTED(NODE) \
621 (((struct lang_identifier *)(NODE))->invented)
622
623/* In identifiers, C uses the following fields in a special way:
624 TREE_PUBLIC to record that there was a previous local extern decl.
625 TREE_USED to record that such a decl was used.
626 TREE_ADDRESSABLE to record that the address of such a decl was used. */
627
628/* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
629 that have names. Here so we can clear out their names' definitions
630 at the end of the function. */
631
632static tree named_labels;
633
634/* A list of LABEL_DECLs from outer contexts that are currently shadowed. */
635
636static tree shadowed_labels;
637
638#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
639\f
6b55276e
CB
640/* Return the subscript expression, modified to do range-checking.
641
642 `array' is the array to be checked against.
643 `element' is the subscript expression to check.
644 `dim' is the dimension number (starting at 0).
645 `total_dims' is the total number of dimensions (0 for CHARACTER substring).
646*/
647
648static tree
649ffecom_subscript_check_ (tree array, tree element, int dim, int total_dims,
3b304f5b 650 const char *array_name)
6b55276e
CB
651{
652 tree low = TYPE_MIN_VALUE (TYPE_DOMAIN (array));
653 tree high = TYPE_MAX_VALUE (TYPE_DOMAIN (array));
654 tree cond;
655 tree die;
656 tree args;
657
658 if (element == error_mark_node)
659 return element;
660
ff852b44
CB
661 if (TREE_TYPE (low) != TREE_TYPE (element))
662 {
663 if (TYPE_PRECISION (TREE_TYPE (low))
664 > TYPE_PRECISION (TREE_TYPE (element)))
665 element = convert (TREE_TYPE (low), element);
666 else
667 {
668 low = convert (TREE_TYPE (element), low);
669 if (high)
670 high = convert (TREE_TYPE (element), high);
671 }
672 }
673
6b55276e 674 element = ffecom_save_tree (element);
2bc21ba5 675 if (total_dims == 0)
6b55276e 676 {
2bc21ba5
GH
677 /* Special handling for substring range checks. Fortran allows the
678 end subscript < begin subscript, which means that expressions like
679 string(1:0) are valid (and yield a null string). In view of this,
680 enforce two simpler conditions:
681 1) element<=high for end-substring;
682 2) element>=low for start-substring.
683 Run-time character movement will enforce remaining conditions.
684
685 More complicated checks would be better, but present structure only
686 provides one index element at a time, so it is not possible to
687 enforce a check of both i and j in string(i:j). If it were, the
688 complete set of rules would read,
689 if ( ((j<i) && ((low<=i<=high) || (low<=j<=high))) ||
690 ((low<=i<=high) && (low<=j<=high)) )
691 ok ;
692 else
693 range error ;
694 */
695 if (dim)
696 cond = ffecom_2 (LE_EXPR, integer_type_node, element, high);
697 else
698 cond = ffecom_2 (LE_EXPR, integer_type_node, low, element);
699 }
700 else
701 {
702 /* Array reference substring range checking. */
703
704 cond = ffecom_2 (LE_EXPR, integer_type_node,
705 low,
706 element);
707 if (high)
708 {
709 cond = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
710 cond,
711 ffecom_2 (LE_EXPR, integer_type_node,
712 element,
713 high));
714 }
6b55276e
CB
715 }
716
717 {
718 int len;
719 char *proc;
720 char *var;
721 tree arg3;
722 tree arg2;
723 tree arg1;
724 tree arg4;
725
726 switch (total_dims)
727 {
728 case 0:
d4c3ec27
KG
729 var = concat (array_name, "[", (dim ? "end" : "start"),
730 "-substring]", NULL);
6b55276e 731 len = strlen (var) + 1;
3b304f5b
ZW
732 arg1 = build_string (len, var);
733 free (var);
6b55276e
CB
734 break;
735
736 case 1:
737 len = strlen (array_name) + 1;
3b304f5b 738 arg1 = build_string (len, array_name);
6b55276e
CB
739 break;
740
741 default:
742 var = xmalloc (strlen (array_name) + 40);
3b304f5b 743 sprintf (var, "%s[subscript-%d-of-%d]",
6b55276e
CB
744 array_name,
745 dim + 1, total_dims);
746 len = strlen (var) + 1;
3b304f5b
ZW
747 arg1 = build_string (len, var);
748 free (var);
6b55276e
CB
749 break;
750 }
751
6b55276e
CB
752 TREE_TYPE (arg1)
753 = build_type_variant (build_array_type (char_type_node,
754 build_range_type
755 (integer_type_node,
756 integer_one_node,
757 build_int_2 (len, 0))),
758 1, 0);
759 TREE_CONSTANT (arg1) = 1;
760 TREE_STATIC (arg1) = 1;
761 arg1 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg1)),
762 arg1);
763
764 /* s_rnge adds one to the element to print it, so bias against
765 that -- want to print a faithful *subscript* value. */
766 arg2 = convert (ffecom_f2c_ftnint_type_node,
767 ffecom_2 (MINUS_EXPR,
768 TREE_TYPE (element),
769 element,
770 convert (TREE_TYPE (element),
771 integer_one_node)));
772
d4c3ec27
KG
773 proc = concat (input_filename, "/",
774 IDENTIFIER_POINTER (DECL_NAME (current_function_decl)),
775 NULL);
776 len = strlen (proc) + 1;
6b55276e
CB
777 arg3 = build_string (len, proc);
778
779 free (proc);
780
781 TREE_TYPE (arg3)
782 = build_type_variant (build_array_type (char_type_node,
783 build_range_type
784 (integer_type_node,
785 integer_one_node,
786 build_int_2 (len, 0))),
787 1, 0);
788 TREE_CONSTANT (arg3) = 1;
789 TREE_STATIC (arg3) = 1;
790 arg3 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg3)),
791 arg3);
792
793 arg4 = convert (ffecom_f2c_ftnint_type_node,
794 build_int_2 (lineno, 0));
795
796 arg1 = build_tree_list (NULL_TREE, arg1);
797 arg2 = build_tree_list (NULL_TREE, arg2);
798 arg3 = build_tree_list (NULL_TREE, arg3);
799 arg4 = build_tree_list (NULL_TREE, arg4);
800 TREE_CHAIN (arg3) = arg4;
801 TREE_CHAIN (arg2) = arg3;
802 TREE_CHAIN (arg1) = arg2;
803
804 args = arg1;
805 }
806 die = ffecom_call_gfrt (FFECOM_gfrtRANGE,
807 args, NULL_TREE);
808 TREE_SIDE_EFFECTS (die) = 1;
809
810 element = ffecom_3 (COND_EXPR,
811 TREE_TYPE (element),
812 cond,
813 element,
814 die);
815
816 return element;
817}
818
819/* Return the computed element of an array reference.
820
ff852b44
CB
821 `item' is NULL_TREE, or the transformed pointer to the array.
822 `expr' is the original opARRAYREF expression, which is transformed
823 if `item' is NULL_TREE.
824 `want_ptr' is non-zero if a pointer to the element, instead of
6b55276e
CB
825 the element itself, is to be returned. */
826
827static tree
828ffecom_arrayref_ (tree item, ffebld expr, int want_ptr)
829{
830 ffebld dims[FFECOM_dimensionsMAX];
831 int i;
832 int total_dims;
ff852b44
CB
833 int flatten = ffe_is_flatten_arrays ();
834 int need_ptr;
6b55276e
CB
835 tree array;
836 tree element;
ff852b44
CB
837 tree tree_type;
838 tree tree_type_x;
3b304f5b 839 const char *array_name;
ff852b44
CB
840 ffetype type;
841 ffebld list;
6b55276e
CB
842
843 if (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER)
844 array_name = ffesymbol_text (ffebld_symter (ffebld_left (expr)));
845 else
846 array_name = "[expr?]";
847
848 /* Build up ARRAY_REFs in reverse order (since we're column major
849 here in Fortran land). */
850
ff852b44
CB
851 for (i = 0, list = ffebld_right (expr);
852 list != NULL;
853 ++i, list = ffebld_trail (list))
854 {
855 dims[i] = ffebld_head (list);
856 type = ffeinfo_type (ffebld_basictype (dims[i]),
857 ffebld_kindtype (dims[i]));
858 if (! flatten
859 && ffecom_typesize_pointer_ > ffecom_typesize_integer1_
860 && ffetype_size (type) > ffecom_typesize_integer1_)
861 /* E.g. ARRAY(INDEX), given INTEGER*8 INDEX, on a system with 64-bit
862 pointers and 32-bit integers. Do the full 64-bit pointer
863 arithmetic, for codes using arrays for nonstandard heap-like
864 work. */
865 flatten = 1;
866 }
6b55276e
CB
867
868 total_dims = i;
869
ff852b44
CB
870 need_ptr = want_ptr || flatten;
871
872 if (! item)
873 {
874 if (need_ptr)
875 item = ffecom_ptr_to_expr (ffebld_left (expr));
876 else
877 item = ffecom_expr (ffebld_left (expr));
878
879 if (item == error_mark_node)
880 return item;
881
882 if (ffeinfo_where (ffebld_info (expr)) == FFEINFO_whereFLEETING
883 && ! mark_addressable (item))
884 return error_mark_node;
885 }
886
887 if (item == error_mark_node)
888 return item;
889
6b55276e
CB
890 if (need_ptr)
891 {
ff852b44
CB
892 tree min;
893
6b55276e
CB
894 for (--i, array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
895 i >= 0;
896 --i, array = TYPE_MAIN_VARIANT (TREE_TYPE (array)))
897 {
ff852b44
CB
898 min = TYPE_MIN_VALUE (TYPE_DOMAIN (array));
899 element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
02f06e64 900 if (flag_bounds_check)
6b55276e
CB
901 element = ffecom_subscript_check_ (array, element, i, total_dims,
902 array_name);
ff852b44
CB
903 if (element == error_mark_node)
904 return element;
905
906 /* Widen integral arithmetic as desired while preserving
907 signedness. */
908 tree_type = TREE_TYPE (element);
909 tree_type_x = tree_type;
910 if (tree_type
911 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
912 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
913 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
914
915 if (TREE_TYPE (min) != tree_type_x)
916 min = convert (tree_type_x, min);
917 if (TREE_TYPE (element) != tree_type_x)
918 element = convert (tree_type_x, element);
919
6b55276e
CB
920 item = ffecom_2 (PLUS_EXPR,
921 build_pointer_type (TREE_TYPE (array)),
922 item,
923 size_binop (MULT_EXPR,
924 size_in_bytes (TREE_TYPE (array)),
fed3cef0
RK
925 convert (sizetype,
926 fold (build (MINUS_EXPR,
927 tree_type_x,
928 element, min)))));
6b55276e
CB
929 }
930 if (! want_ptr)
931 {
932 item = ffecom_1 (INDIRECT_REF,
933 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))),
934 item);
935 }
936 }
937 else
938 {
939 for (--i;
940 i >= 0;
941 --i)
942 {
943 array = TYPE_MAIN_VARIANT (TREE_TYPE (item));
944
945 element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
02f06e64 946 if (flag_bounds_check)
6b55276e
CB
947 element = ffecom_subscript_check_ (array, element, i, total_dims,
948 array_name);
ff852b44
CB
949 if (element == error_mark_node)
950 return element;
951
952 /* Widen integral arithmetic as desired while preserving
953 signedness. */
954 tree_type = TREE_TYPE (element);
955 tree_type_x = tree_type;
956 if (tree_type
957 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
958 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
959 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
960
961 element = convert (tree_type_x, element);
962
6b55276e
CB
963 item = ffecom_2 (ARRAY_REF,
964 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))),
965 item,
966 element);
967 }
968 }
969
970 return item;
971}
972
5ff904cd
JL
973/* This is like gcc's stabilize_reference -- in fact, most of the code
974 comes from that -- but it handles the situation where the reference
975 is going to have its subparts picked at, and it shouldn't change
976 (or trigger extra invocations of functions in the subtrees) due to
977 this. save_expr is a bit overzealous, because we don't need the
978 entire thing calculated and saved like a temp. So, for DECLs, no
979 change is needed, because these are stable aggregates, and ARRAY_REF
980 and such might well be stable too, but for things like calculations,
981 we do need to calculate a snapshot of a value before picking at it. */
982
983#if FFECOM_targetCURRENT == FFECOM_targetGCC
984static tree
985ffecom_stabilize_aggregate_ (tree ref)
986{
987 tree result;
988 enum tree_code code = TREE_CODE (ref);
989
990 switch (code)
991 {
992 case VAR_DECL:
993 case PARM_DECL:
994 case RESULT_DECL:
995 /* No action is needed in this case. */
996 return ref;
997
998 case NOP_EXPR:
999 case CONVERT_EXPR:
1000 case FLOAT_EXPR:
1001 case FIX_TRUNC_EXPR:
1002 case FIX_FLOOR_EXPR:
1003 case FIX_ROUND_EXPR:
1004 case FIX_CEIL_EXPR:
1005 result = build_nt (code, stabilize_reference (TREE_OPERAND (ref, 0)));
1006 break;
1007
1008 case INDIRECT_REF:
1009 result = build_nt (INDIRECT_REF,
1010 stabilize_reference_1 (TREE_OPERAND (ref, 0)));
1011 break;
1012
1013 case COMPONENT_REF:
1014 result = build_nt (COMPONENT_REF,
1015 stabilize_reference (TREE_OPERAND (ref, 0)),
1016 TREE_OPERAND (ref, 1));
1017 break;
1018
1019 case BIT_FIELD_REF:
1020 result = build_nt (BIT_FIELD_REF,
1021 stabilize_reference (TREE_OPERAND (ref, 0)),
1022 stabilize_reference_1 (TREE_OPERAND (ref, 1)),
1023 stabilize_reference_1 (TREE_OPERAND (ref, 2)));
1024 break;
1025
1026 case ARRAY_REF:
1027 result = build_nt (ARRAY_REF,
1028 stabilize_reference (TREE_OPERAND (ref, 0)),
1029 stabilize_reference_1 (TREE_OPERAND (ref, 1)));
1030 break;
1031
1032 case COMPOUND_EXPR:
1033 result = build_nt (COMPOUND_EXPR,
1034 stabilize_reference_1 (TREE_OPERAND (ref, 0)),
1035 stabilize_reference (TREE_OPERAND (ref, 1)));
1036 break;
1037
1038 case RTL_EXPR:
a8d0a42e 1039 abort ();
5ff904cd
JL
1040
1041
1042 default:
1043 return save_expr (ref);
1044
1045 case ERROR_MARK:
1046 return error_mark_node;
1047 }
1048
1049 TREE_TYPE (result) = TREE_TYPE (ref);
1050 TREE_READONLY (result) = TREE_READONLY (ref);
1051 TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (ref);
1052 TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (ref);
5ff904cd
JL
1053
1054 return result;
1055}
1056#endif
1057
1058/* A rip-off of gcc's convert.c convert_to_complex function,
1059 reworked to handle complex implemented as C structures
1060 (RECORD_TYPE with two fields, real and imaginary `r' and `i'). */
1061
1062#if FFECOM_targetCURRENT == FFECOM_targetGCC
1063static tree
1064ffecom_convert_to_complex_ (tree type, tree expr)
1065{
1066 register enum tree_code form = TREE_CODE (TREE_TYPE (expr));
1067 tree subtype;
1068
1069 assert (TREE_CODE (type) == RECORD_TYPE);
1070
1071 subtype = TREE_TYPE (TYPE_FIELDS (type));
1072
1073 if (form == REAL_TYPE || form == INTEGER_TYPE || form == ENUMERAL_TYPE)
1074 {
1075 expr = convert (subtype, expr);
1076 return ffecom_2 (COMPLEX_EXPR, type, expr,
1077 convert (subtype, integer_zero_node));
1078 }
1079
1080 if (form == RECORD_TYPE)
1081 {
1082 tree elt_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr)));
1083 if (TYPE_MAIN_VARIANT (elt_type) == TYPE_MAIN_VARIANT (subtype))
1084 return expr;
1085 else
1086 {
1087 expr = save_expr (expr);
1088 return ffecom_2 (COMPLEX_EXPR,
1089 type,
1090 convert (subtype,
1091 ffecom_1 (REALPART_EXPR,
1092 TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))),
1093 expr)),
1094 convert (subtype,
1095 ffecom_1 (IMAGPART_EXPR,
1096 TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))),
1097 expr)));
1098 }
1099 }
1100
1101 if (form == POINTER_TYPE || form == REFERENCE_TYPE)
1102 error ("pointer value used where a complex was expected");
1103 else
1104 error ("aggregate value used where a complex was expected");
1105
1106 return ffecom_2 (COMPLEX_EXPR, type,
1107 convert (subtype, integer_zero_node),
1108 convert (subtype, integer_zero_node));
1109}
1110#endif
1111
1112/* Like gcc's convert(), but crashes if widening might happen. */
1113
1114#if FFECOM_targetCURRENT == FFECOM_targetGCC
1115static tree
1116ffecom_convert_narrow_ (type, expr)
1117 tree type, expr;
1118{
1119 register tree e = expr;
1120 register enum tree_code code = TREE_CODE (type);
1121
1122 if (type == TREE_TYPE (e)
1123 || TREE_CODE (e) == ERROR_MARK)
1124 return e;
1125 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
1126 return fold (build1 (NOP_EXPR, type, e));
1127 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
1128 || code == ERROR_MARK)
1129 return error_mark_node;
1130 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
1131 {
1132 assert ("void value not ignored as it ought to be" == NULL);
1133 return error_mark_node;
1134 }
1135 assert (code != VOID_TYPE);
1136 if ((code != RECORD_TYPE)
1137 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
1138 assert ("converting COMPLEX to REAL" == NULL);
1139 assert (code != ENUMERAL_TYPE);
1140 if (code == INTEGER_TYPE)
1141 {
a74de6ea
CB
1142 assert ((TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE
1143 && TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)))
1144 || (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
1145 && (TYPE_PRECISION (type)
1146 == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (e))))));
5ff904cd
JL
1147 return fold (convert_to_integer (type, e));
1148 }
1149 if (code == POINTER_TYPE)
1150 {
1151 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
1152 return fold (convert_to_pointer (type, e));
1153 }
1154 if (code == REAL_TYPE)
1155 {
1156 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
1157 assert (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)));
1158 return fold (convert_to_real (type, e));
1159 }
1160 if (code == COMPLEX_TYPE)
1161 {
1162 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
1163 assert (TYPE_PRECISION (TREE_TYPE (type)) <= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
1164 return fold (convert_to_complex (type, e));
1165 }
1166 if (code == RECORD_TYPE)
1167 {
1168 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
270fc4e8
CB
1169 /* Check that at least the first field name agrees. */
1170 assert (DECL_NAME (TYPE_FIELDS (type))
1171 == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e))));
5ff904cd
JL
1172 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1173 <= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
270fc4e8
CB
1174 if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1175 == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))))
1176 return e;
5ff904cd
JL
1177 return fold (ffecom_convert_to_complex_ (type, e));
1178 }
1179
1180 assert ("conversion to non-scalar type requested" == NULL);
1181 return error_mark_node;
1182}
1183#endif
1184
1185/* Like gcc's convert(), but crashes if narrowing might happen. */
1186
1187#if FFECOM_targetCURRENT == FFECOM_targetGCC
1188static tree
1189ffecom_convert_widen_ (type, expr)
1190 tree type, expr;
1191{
1192 register tree e = expr;
1193 register enum tree_code code = TREE_CODE (type);
1194
1195 if (type == TREE_TYPE (e)
1196 || TREE_CODE (e) == ERROR_MARK)
1197 return e;
1198 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
1199 return fold (build1 (NOP_EXPR, type, e));
1200 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
1201 || code == ERROR_MARK)
1202 return error_mark_node;
1203 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
1204 {
1205 assert ("void value not ignored as it ought to be" == NULL);
1206 return error_mark_node;
1207 }
1208 assert (code != VOID_TYPE);
1209 if ((code != RECORD_TYPE)
1210 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
1211 assert ("narrowing COMPLEX to REAL" == NULL);
1212 assert (code != ENUMERAL_TYPE);
1213 if (code == INTEGER_TYPE)
1214 {
a74de6ea
CB
1215 assert ((TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE
1216 && TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)))
1217 || (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
1218 && (TYPE_PRECISION (type)
1219 == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (e))))));
5ff904cd
JL
1220 return fold (convert_to_integer (type, e));
1221 }
1222 if (code == POINTER_TYPE)
1223 {
1224 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
1225 return fold (convert_to_pointer (type, e));
1226 }
1227 if (code == REAL_TYPE)
1228 {
1229 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
1230 assert (TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)));
1231 return fold (convert_to_real (type, e));
1232 }
1233 if (code == COMPLEX_TYPE)
1234 {
1235 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
1236 assert (TYPE_PRECISION (TREE_TYPE (type)) >= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
1237 return fold (convert_to_complex (type, e));
1238 }
1239 if (code == RECORD_TYPE)
1240 {
1241 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
270fc4e8
CB
1242 /* Check that at least the first field name agrees. */
1243 assert (DECL_NAME (TYPE_FIELDS (type))
1244 == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e))));
5ff904cd
JL
1245 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1246 >= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
270fc4e8
CB
1247 if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1248 == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))))
1249 return e;
5ff904cd
JL
1250 return fold (ffecom_convert_to_complex_ (type, e));
1251 }
1252
1253 assert ("conversion to non-scalar type requested" == NULL);
1254 return error_mark_node;
1255}
1256#endif
1257
1258/* Handles making a COMPLEX type, either the standard
1259 (but buggy?) gbe way, or the safer (but less elegant?)
1260 f2c way. */
1261
1262#if FFECOM_targetCURRENT == FFECOM_targetGCC
1263static tree
1264ffecom_make_complex_type_ (tree subtype)
1265{
1266 tree type;
1267 tree realfield;
1268 tree imagfield;
1269
1270 if (ffe_is_emulate_complex ())
1271 {
1272 type = make_node (RECORD_TYPE);
1273 realfield = ffecom_decl_field (type, NULL_TREE, "r", subtype);
1274 imagfield = ffecom_decl_field (type, realfield, "i", subtype);
1275 TYPE_FIELDS (type) = realfield;
1276 layout_type (type);
1277 }
1278 else
1279 {
1280 type = make_node (COMPLEX_TYPE);
1281 TREE_TYPE (type) = subtype;
1282 layout_type (type);
1283 }
1284
1285 return type;
1286}
1287#endif
1288
1289/* Chooses either the gbe or the f2c way to build a
1290 complex constant. */
1291
1292#if FFECOM_targetCURRENT == FFECOM_targetGCC
1293static tree
1294ffecom_build_complex_constant_ (tree type, tree realpart, tree imagpart)
1295{
1296 tree bothparts;
1297
1298 if (ffe_is_emulate_complex ())
1299 {
1300 bothparts = build_tree_list (TYPE_FIELDS (type), realpart);
1301 TREE_CHAIN (bothparts) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), imagpart);
1302 bothparts = build (CONSTRUCTOR, type, NULL_TREE, bothparts);
1303 }
1304 else
1305 {
1306 bothparts = build_complex (type, realpart, imagpart);
1307 }
1308
1309 return bothparts;
1310}
1311#endif
1312
1313#if FFECOM_targetCURRENT == FFECOM_targetGCC
1314static tree
26f096f9 1315ffecom_arglist_expr_ (const char *c, ffebld expr)
5ff904cd
JL
1316{
1317 tree list;
1318 tree *plist = &list;
1319 tree trail = NULL_TREE; /* Append char length args here. */
1320 tree *ptrail = &trail;
1321 tree length;
1322 ffebld exprh;
1323 tree item;
1324 bool ptr = FALSE;
1325 tree wanted = NULL_TREE;
e2fa159e
JL
1326 static char zed[] = "0";
1327
1328 if (c == NULL)
1329 c = &zed[0];
5ff904cd
JL
1330
1331 while (expr != NULL)
1332 {
1333 if (*c != '\0')
1334 {
1335 ptr = FALSE;
1336 if (*c == '&')
1337 {
1338 ptr = TRUE;
1339 ++c;
1340 }
1341 switch (*(c++))
1342 {
1343 case '\0':
1344 ptr = TRUE;
1345 wanted = NULL_TREE;
1346 break;
1347
1348 case 'a':
1349 assert (ptr);
1350 wanted = NULL_TREE;
1351 break;
1352
1353 case 'c':
1354 wanted = ffecom_f2c_complex_type_node;
1355 break;
1356
1357 case 'd':
1358 wanted = ffecom_f2c_doublereal_type_node;
1359 break;
1360
1361 case 'e':
1362 wanted = ffecom_f2c_doublecomplex_type_node;
1363 break;
1364
1365 case 'f':
1366 wanted = ffecom_f2c_real_type_node;
1367 break;
1368
1369 case 'i':
1370 wanted = ffecom_f2c_integer_type_node;
1371 break;
1372
1373 case 'j':
1374 wanted = ffecom_f2c_longint_type_node;
1375 break;
1376
1377 default:
1378 assert ("bad argstring code" == NULL);
1379 wanted = NULL_TREE;
1380 break;
1381 }
1382 }
1383
1384 exprh = ffebld_head (expr);
1385 if (exprh == NULL)
1386 wanted = NULL_TREE;
1387
1388 if ((wanted == NULL_TREE)
1389 || (ptr
1390 && (TYPE_MODE
1391 (ffecom_tree_type[ffeinfo_basictype (ffebld_info (exprh))]
1392 [ffeinfo_kindtype (ffebld_info (exprh))])
1393 == TYPE_MODE (wanted))))
1394 *plist
1395 = build_tree_list (NULL_TREE,
1396 ffecom_arg_ptr_to_expr (exprh,
1397 &length));
1398 else
1399 {
1400 item = ffecom_arg_expr (exprh, &length);
1401 item = ffecom_convert_widen_ (wanted, item);
1402 if (ptr)
1403 {
1404 item = ffecom_1 (ADDR_EXPR,
1405 build_pointer_type (TREE_TYPE (item)),
1406 item);
1407 }
1408 *plist
1409 = build_tree_list (NULL_TREE,
1410 item);
1411 }
1412
1413 plist = &TREE_CHAIN (*plist);
1414 expr = ffebld_trail (expr);
1415 if (length != NULL_TREE)
1416 {
1417 *ptrail = build_tree_list (NULL_TREE, length);
1418 ptrail = &TREE_CHAIN (*ptrail);
1419 }
1420 }
1421
e2fa159e
JL
1422 /* We've run out of args in the call; if the implementation expects
1423 more, supply null pointers for them, which the implementation can
1424 check to see if an arg was omitted. */
1425
1426 while (*c != '\0' && *c != '0')
1427 {
1428 if (*c == '&')
1429 ++c;
1430 else
1431 assert ("missing arg to run-time routine!" == NULL);
1432
1433 switch (*(c++))
1434 {
1435 case '\0':
1436 case 'a':
1437 case 'c':
1438 case 'd':
1439 case 'e':
1440 case 'f':
1441 case 'i':
1442 case 'j':
1443 break;
1444
1445 default:
1446 assert ("bad arg string code" == NULL);
1447 break;
1448 }
1449 *plist
1450 = build_tree_list (NULL_TREE,
1451 null_pointer_node);
1452 plist = &TREE_CHAIN (*plist);
1453 }
1454
5ff904cd
JL
1455 *plist = trail;
1456
1457 return list;
1458}
1459#endif
1460
1461#if FFECOM_targetCURRENT == FFECOM_targetGCC
1462static tree
1463ffecom_widest_expr_type_ (ffebld list)
1464{
1465 ffebld item;
1466 ffebld widest = NULL;
1467 ffetype type;
1468 ffetype widest_type = NULL;
1469 tree t;
1470
1471 for (; list != NULL; list = ffebld_trail (list))
1472 {
1473 item = ffebld_head (list);
1474 if (item == NULL)
1475 continue;
1476 if ((widest != NULL)
1477 && (ffeinfo_basictype (ffebld_info (item))
1478 != ffeinfo_basictype (ffebld_info (widest))))
1479 continue;
1480 type = ffeinfo_type (ffeinfo_basictype (ffebld_info (item)),
1481 ffeinfo_kindtype (ffebld_info (item)));
1482 if ((widest == FFEINFO_kindtypeNONE)
1483 || (ffetype_size (type)
1484 > ffetype_size (widest_type)))
1485 {
1486 widest = item;
1487 widest_type = type;
1488 }
1489 }
1490
1491 assert (widest != NULL);
1492 t = ffecom_tree_type[ffeinfo_basictype (ffebld_info (widest))]
1493 [ffeinfo_kindtype (ffebld_info (widest))];
1494 assert (t != NULL_TREE);
1495 return t;
1496}
1497#endif
1498
d6cd84e0
CB
1499/* Check whether a partial overlap between two expressions is possible.
1500
1501 Can *starting* to write a portion of expr1 change the value
1502 computed (perhaps already, *partially*) by expr2?
1503
1504 Currently, this is a concern only for a COMPLEX expr1. But if it
1505 isn't in COMMON or local EQUIVALENCE, since we don't support
1506 aliasing of arguments, it isn't a concern. */
1507
1508static bool
b0791fa9 1509ffecom_possible_partial_overlap_ (ffebld expr1, ffebld expr2 ATTRIBUTE_UNUSED)
d6cd84e0
CB
1510{
1511 ffesymbol sym;
1512 ffestorag st;
1513
1514 switch (ffebld_op (expr1))
1515 {
1516 case FFEBLD_opSYMTER:
1517 sym = ffebld_symter (expr1);
1518 break;
1519
1520 case FFEBLD_opARRAYREF:
1521 if (ffebld_op (ffebld_left (expr1)) != FFEBLD_opSYMTER)
1522 return FALSE;
1523 sym = ffebld_symter (ffebld_left (expr1));
1524 break;
1525
1526 default:
1527 return FALSE;
1528 }
1529
1530 if (ffesymbol_where (sym) != FFEINFO_whereCOMMON
1531 && (ffesymbol_where (sym) != FFEINFO_whereLOCAL
1532 || ! (st = ffesymbol_storage (sym))
1533 || ! ffestorag_parent (st)))
1534 return FALSE;
1535
1536 /* It's in COMMON or local EQUIVALENCE. */
1537
1538 return TRUE;
1539}
1540
5ff904cd
JL
1541/* Check whether dest and source might overlap. ffebld versions of these
1542 might or might not be passed, will be NULL if not.
1543
1544 The test is really whether source_tree is modifiable and, if modified,
1545 might overlap destination such that the value(s) in the destination might
1546 change before it is finally modified. dest_* are the canonized
1547 destination itself. */
1548
1549#if FFECOM_targetCURRENT == FFECOM_targetGCC
1550static bool
1551ffecom_overlap_ (tree dest_decl, tree dest_offset, tree dest_size,
1552 tree source_tree, ffebld source UNUSED,
1553 bool scalar_arg)
1554{
1555 tree source_decl;
1556 tree source_offset;
1557 tree source_size;
1558 tree t;
1559
1560 if (source_tree == NULL_TREE)
1561 return FALSE;
1562
1563 switch (TREE_CODE (source_tree))
1564 {
1565 case ERROR_MARK:
1566 case IDENTIFIER_NODE:
1567 case INTEGER_CST:
1568 case REAL_CST:
1569 case COMPLEX_CST:
1570 case STRING_CST:
1571 case CONST_DECL:
1572 case VAR_DECL:
1573 case RESULT_DECL:
1574 case FIELD_DECL:
1575 case MINUS_EXPR:
1576 case MULT_EXPR:
1577 case TRUNC_DIV_EXPR:
1578 case CEIL_DIV_EXPR:
1579 case FLOOR_DIV_EXPR:
1580 case ROUND_DIV_EXPR:
1581 case TRUNC_MOD_EXPR:
1582 case CEIL_MOD_EXPR:
1583 case FLOOR_MOD_EXPR:
1584 case ROUND_MOD_EXPR:
1585 case RDIV_EXPR:
1586 case EXACT_DIV_EXPR:
1587 case FIX_TRUNC_EXPR:
1588 case FIX_CEIL_EXPR:
1589 case FIX_FLOOR_EXPR:
1590 case FIX_ROUND_EXPR:
1591 case FLOAT_EXPR:
5ff904cd
JL
1592 case NEGATE_EXPR:
1593 case MIN_EXPR:
1594 case MAX_EXPR:
1595 case ABS_EXPR:
1596 case FFS_EXPR:
1597 case LSHIFT_EXPR:
1598 case RSHIFT_EXPR:
1599 case LROTATE_EXPR:
1600 case RROTATE_EXPR:
1601 case BIT_IOR_EXPR:
1602 case BIT_XOR_EXPR:
1603 case BIT_AND_EXPR:
1604 case BIT_ANDTC_EXPR:
1605 case BIT_NOT_EXPR:
1606 case TRUTH_ANDIF_EXPR:
1607 case TRUTH_ORIF_EXPR:
1608 case TRUTH_AND_EXPR:
1609 case TRUTH_OR_EXPR:
1610 case TRUTH_XOR_EXPR:
1611 case TRUTH_NOT_EXPR:
1612 case LT_EXPR:
1613 case LE_EXPR:
1614 case GT_EXPR:
1615 case GE_EXPR:
1616 case EQ_EXPR:
1617 case NE_EXPR:
1618 case COMPLEX_EXPR:
1619 case CONJ_EXPR:
1620 case REALPART_EXPR:
1621 case IMAGPART_EXPR:
1622 case LABEL_EXPR:
1623 case COMPONENT_REF:
1624 return FALSE;
1625
1626 case COMPOUND_EXPR:
1627 return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1628 TREE_OPERAND (source_tree, 1), NULL,
1629 scalar_arg);
1630
1631 case MODIFY_EXPR:
1632 return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1633 TREE_OPERAND (source_tree, 0), NULL,
1634 scalar_arg);
1635
1636 case CONVERT_EXPR:
1637 case NOP_EXPR:
1638 case NON_LVALUE_EXPR:
1639 case PLUS_EXPR:
1640 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1641 return TRUE;
1642
1643 ffecom_tree_canonize_ptr_ (&source_decl, &source_offset,
1644 source_tree);
1645 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1646 break;
1647
1648 case COND_EXPR:
1649 return
1650 ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1651 TREE_OPERAND (source_tree, 1), NULL,
1652 scalar_arg)
1653 || ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1654 TREE_OPERAND (source_tree, 2), NULL,
1655 scalar_arg);
1656
1657
1658 case ADDR_EXPR:
1659 ffecom_tree_canonize_ref_ (&source_decl, &source_offset,
1660 &source_size,
1661 TREE_OPERAND (source_tree, 0));
1662 break;
1663
1664 case PARM_DECL:
1665 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1666 return TRUE;
1667
1668 source_decl = source_tree;
76fa6b3b 1669 source_offset = bitsize_zero_node;
5ff904cd
JL
1670 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1671 break;
1672
1673 case SAVE_EXPR:
1674 case REFERENCE_EXPR:
1675 case PREDECREMENT_EXPR:
1676 case PREINCREMENT_EXPR:
1677 case POSTDECREMENT_EXPR:
1678 case POSTINCREMENT_EXPR:
1679 case INDIRECT_REF:
1680 case ARRAY_REF:
1681 case CALL_EXPR:
1682 default:
1683 return TRUE;
1684 }
1685
1686 /* Come here when source_decl, source_offset, and source_size filled
1687 in appropriately. */
1688
1689 if (source_decl == NULL_TREE)
1690 return FALSE; /* No decl involved, so no overlap. */
1691
1692 if (source_decl != dest_decl)
1693 return FALSE; /* Different decl, no overlap. */
1694
1695 if (TREE_CODE (dest_size) == ERROR_MARK)
1696 return TRUE; /* Assignment into entire assumed-size
1697 array? Shouldn't happen.... */
1698
1699 t = ffecom_2 (LE_EXPR, integer_type_node,
1700 ffecom_2 (PLUS_EXPR, TREE_TYPE (dest_offset),
1701 dest_offset,
1702 convert (TREE_TYPE (dest_offset),
1703 dest_size)),
1704 convert (TREE_TYPE (dest_offset),
1705 source_offset));
1706
1707 if (integer_onep (t))
1708 return FALSE; /* Destination precedes source. */
1709
1710 if (!scalar_arg
1711 || (source_size == NULL_TREE)
1712 || (TREE_CODE (source_size) == ERROR_MARK)
1713 || integer_zerop (source_size))
1714 return TRUE; /* No way to tell if dest follows source. */
1715
1716 t = ffecom_2 (LE_EXPR, integer_type_node,
1717 ffecom_2 (PLUS_EXPR, TREE_TYPE (source_offset),
1718 source_offset,
1719 convert (TREE_TYPE (source_offset),
1720 source_size)),
1721 convert (TREE_TYPE (source_offset),
1722 dest_offset));
1723
1724 if (integer_onep (t))
1725 return FALSE; /* Destination follows source. */
1726
1727 return TRUE; /* Destination and source overlap. */
1728}
1729#endif
1730
1731/* Check whether dest might overlap any of a list of arguments or is
1732 in a COMMON area the callee might know about (and thus modify). */
1733
1734#if FFECOM_targetCURRENT == FFECOM_targetGCC
1735static bool
1736ffecom_args_overlapping_ (tree dest_tree, ffebld dest UNUSED,
1737 tree args, tree callee_commons,
1738 bool scalar_args)
1739{
1740 tree arg;
1741 tree dest_decl;
1742 tree dest_offset;
1743 tree dest_size;
1744
1745 ffecom_tree_canonize_ref_ (&dest_decl, &dest_offset, &dest_size,
1746 dest_tree);
1747
1748 if (dest_decl == NULL_TREE)
1749 return FALSE; /* Seems unlikely! */
1750
1751 /* If the decl cannot be determined reliably, or if its in COMMON
1752 and the callee isn't known to not futz with COMMON via other
1753 means, overlap might happen. */
1754
1755 if ((TREE_CODE (dest_decl) == ERROR_MARK)
1756 || ((callee_commons != NULL_TREE)
1757 && TREE_PUBLIC (dest_decl)))
1758 return TRUE;
1759
1760 for (; args != NULL_TREE; args = TREE_CHAIN (args))
1761 {
1762 if (((arg = TREE_VALUE (args)) != NULL_TREE)
1763 && ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1764 arg, NULL, scalar_args))
1765 return TRUE;
1766 }
1767
1768 return FALSE;
1769}
1770#endif
1771
1772/* Build a string for a variable name as used by NAMELIST. This means that
1773 if we're using the f2c library, we build an uppercase string, since
1774 f2c does this. */
1775
1776#if FFECOM_targetCURRENT == FFECOM_targetGCC
1777static tree
26f096f9 1778ffecom_build_f2c_string_ (int i, const char *s)
5ff904cd
JL
1779{
1780 if (!ffe_is_f2c_library ())
1781 return build_string (i, s);
1782
1783 {
1784 char *tmp;
26f096f9 1785 const char *p;
5ff904cd
JL
1786 char *q;
1787 char space[34];
1788 tree t;
1789
1790 if (((size_t) i) > ARRAY_SIZE (space))
1791 tmp = malloc_new_ks (malloc_pool_image (), "f2c_string", i);
1792 else
1793 tmp = &space[0];
1794
1795 for (p = s, q = tmp; *p != '\0'; ++p, ++q)
f6bbde28 1796 *q = TOUPPER (*p);
5ff904cd
JL
1797 *q = '\0';
1798
1799 t = build_string (i, tmp);
1800
1801 if (((size_t) i) > ARRAY_SIZE (space))
1802 malloc_kill_ks (malloc_pool_image (), tmp, i);
1803
1804 return t;
1805 }
1806}
1807
1808#endif
1809/* Returns CALL_EXPR or equivalent with given type (pass NULL_TREE for
1810 type to just get whatever the function returns), handling the
1811 f2c value-returning convention, if required, by prepending
1812 to the arglist a pointer to a temporary to receive the return value. */
1813
1814#if FFECOM_targetCURRENT == FFECOM_targetGCC
1815static tree
1816ffecom_call_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1817 tree type, tree args, tree dest_tree,
1818 ffebld dest, bool *dest_used, tree callee_commons,
c7e4ee3a 1819 bool scalar_args, tree hook)
5ff904cd
JL
1820{
1821 tree item;
1822 tree tempvar;
1823
1824 if (dest_used != NULL)
1825 *dest_used = FALSE;
1826
1827 if (is_f2c_complex)
1828 {
1829 if ((dest_used == NULL)
1830 || (dest == NULL)
1831 || (ffeinfo_basictype (ffebld_info (dest))
1832 != FFEINFO_basictypeCOMPLEX)
1833 || (ffeinfo_kindtype (ffebld_info (dest)) != kt)
1834 || ((type != NULL_TREE) && (TREE_TYPE (dest_tree) != type))
1835 || ffecom_args_overlapping_ (dest_tree, dest, args,
1836 callee_commons,
1837 scalar_args))
1838 {
c7e4ee3a
CB
1839#ifdef HOHO
1840 tempvar = ffecom_make_tempvar (ffecom_tree_type
5ff904cd
JL
1841 [FFEINFO_basictypeCOMPLEX][kt],
1842 FFETARGET_charactersizeNONE,
c7e4ee3a
CB
1843 -1);
1844#else
1845 tempvar = hook;
1846 assert (tempvar);
1847#endif
5ff904cd
JL
1848 }
1849 else
1850 {
1851 *dest_used = TRUE;
1852 tempvar = dest_tree;
1853 type = NULL_TREE;
1854 }
1855
1856 item
1857 = build_tree_list (NULL_TREE,
1858 ffecom_1 (ADDR_EXPR,
c7e4ee3a 1859 build_pointer_type (TREE_TYPE (tempvar)),
5ff904cd
JL
1860 tempvar));
1861 TREE_CHAIN (item) = args;
1862
1863 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1864 item, NULL_TREE);
1865
1866 if (tempvar != dest_tree)
1867 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item, tempvar);
1868 }
1869 else
1870 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1871 args, NULL_TREE);
1872
1873 if ((type != NULL_TREE) && (TREE_TYPE (item) != type))
1874 item = ffecom_convert_narrow_ (type, item);
1875
1876 return item;
1877}
1878#endif
1879
1880/* Given two arguments, transform them and make a call to the given
1881 function via ffecom_call_. */
1882
1883#if FFECOM_targetCURRENT == FFECOM_targetGCC
1884static tree
1885ffecom_call_binop_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1886 tree type, ffebld left, ffebld right,
1887 tree dest_tree, ffebld dest, bool *dest_used,
95eb4fd9 1888 tree callee_commons, bool scalar_args, bool ref, tree hook)
5ff904cd
JL
1889{
1890 tree left_tree;
1891 tree right_tree;
1892 tree left_length;
1893 tree right_length;
1894
95eb4fd9
TM
1895 if (ref)
1896 {
1897 /* Pass arguments by reference. */
1898 left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
1899 right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
1900 }
1901 else
1902 {
1903 /* Pass arguments by value. */
1904 left_tree = ffecom_arg_expr (left, &left_length);
1905 right_tree = ffecom_arg_expr (right, &right_length);
1906 }
1907
5ff904cd
JL
1908
1909 left_tree = build_tree_list (NULL_TREE, left_tree);
1910 right_tree = build_tree_list (NULL_TREE, right_tree);
1911 TREE_CHAIN (left_tree) = right_tree;
1912
1913 if (left_length != NULL_TREE)
1914 {
1915 left_length = build_tree_list (NULL_TREE, left_length);
1916 TREE_CHAIN (right_tree) = left_length;
1917 }
1918
1919 if (right_length != NULL_TREE)
1920 {
1921 right_length = build_tree_list (NULL_TREE, right_length);
1922 if (left_length != NULL_TREE)
1923 TREE_CHAIN (left_length) = right_length;
1924 else
1925 TREE_CHAIN (right_tree) = right_length;
1926 }
1927
1928 return ffecom_call_ (fn, kt, is_f2c_complex, type, left_tree,
1929 dest_tree, dest, dest_used, callee_commons,
c7e4ee3a 1930 scalar_args, hook);
5ff904cd
JL
1931}
1932#endif
1933
c7e4ee3a 1934/* Return ptr/length args for char subexpression
5ff904cd
JL
1935
1936 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
1937 subexpressions by constructing the appropriate trees for the ptr-to-
1938 character-text and length-of-character-text arguments in a calling
86fc7a6c
CB
1939 sequence.
1940
1941 Note that if with_null is TRUE, and the expression is an opCONTER,
1942 a null byte is appended to the string. */
5ff904cd
JL
1943
1944#if FFECOM_targetCURRENT == FFECOM_targetGCC
1945static void
86fc7a6c 1946ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
5ff904cd
JL
1947{
1948 tree item;
1949 tree high;
1950 ffetargetCharacter1 val;
86fc7a6c 1951 ffetargetCharacterSize newlen;
5ff904cd
JL
1952
1953 switch (ffebld_op (expr))
1954 {
1955 case FFEBLD_opCONTER:
1956 val = ffebld_constant_character1 (ffebld_conter (expr));
86fc7a6c
CB
1957 newlen = ffetarget_length_character1 (val);
1958 if (with_null)
1959 {
c7e4ee3a 1960 /* Begin FFETARGET-NULL-KLUDGE. */
86fc7a6c 1961 if (newlen != 0)
c7e4ee3a 1962 ++newlen;
86fc7a6c
CB
1963 }
1964 *length = build_int_2 (newlen, 0);
5ff904cd 1965 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
86fc7a6c 1966 high = build_int_2 (newlen, 0);
5ff904cd 1967 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
c7e4ee3a 1968 item = build_string (newlen,
5ff904cd 1969 ffetarget_text_character1 (val));
c7e4ee3a 1970 /* End FFETARGET-NULL-KLUDGE. */
5ff904cd
JL
1971 TREE_TYPE (item)
1972 = build_type_variant
1973 (build_array_type
1974 (char_type_node,
1975 build_range_type
1976 (ffecom_f2c_ftnlen_type_node,
1977 ffecom_f2c_ftnlen_one_node,
1978 high)),
1979 1, 0);
1980 TREE_CONSTANT (item) = 1;
1981 TREE_STATIC (item) = 1;
1982 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
1983 item);
1984 break;
1985
1986 case FFEBLD_opSYMTER:
1987 {
1988 ffesymbol s = ffebld_symter (expr);
1989
1990 item = ffesymbol_hook (s).decl_tree;
1991 if (item == NULL_TREE)
1992 {
1993 s = ffecom_sym_transform_ (s);
1994 item = ffesymbol_hook (s).decl_tree;
1995 }
1996 if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
1997 {
1998 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
1999 *length = ffesymbol_hook (s).length_tree;
2000 else
2001 {
2002 *length = build_int_2 (ffesymbol_size (s), 0);
2003 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2004 }
2005 }
2006 else if (item == error_mark_node)
2007 *length = error_mark_node;
c7e4ee3a
CB
2008 else
2009 /* FFEINFO_kindFUNCTION. */
5ff904cd
JL
2010 *length = NULL_TREE;
2011 if (!ffesymbol_hook (s).addr
2012 && (item != error_mark_node))
2013 item = ffecom_1 (ADDR_EXPR,
2014 build_pointer_type (TREE_TYPE (item)),
2015 item);
2016 }
2017 break;
2018
2019 case FFEBLD_opARRAYREF:
2020 {
5ff904cd 2021 ffecom_char_args_ (&item, length, ffebld_left (expr));
5ff904cd
JL
2022
2023 if (item == error_mark_node || *length == error_mark_node)
2024 {
2025 item = *length = error_mark_node;
2026 break;
2027 }
2028
6b55276e 2029 item = ffecom_arrayref_ (item, expr, 1);
5ff904cd
JL
2030 }
2031 break;
2032
2033 case FFEBLD_opSUBSTR:
2034 {
2035 ffebld start;
2036 ffebld end;
2037 ffebld thing = ffebld_right (expr);
2038 tree start_tree;
2039 tree end_tree;
3b304f5b 2040 const char *char_name;
6b55276e
CB
2041 ffebld left_symter;
2042 tree array;
5ff904cd
JL
2043
2044 assert (ffebld_op (thing) == FFEBLD_opITEM);
2045 start = ffebld_head (thing);
2046 thing = ffebld_trail (thing);
2047 assert (ffebld_trail (thing) == NULL);
2048 end = ffebld_head (thing);
2049
6b55276e
CB
2050 /* Determine name for pretty-printing range-check errors. */
2051 for (left_symter = ffebld_left (expr);
2052 left_symter && ffebld_op (left_symter) == FFEBLD_opARRAYREF;
2053 left_symter = ffebld_left (left_symter))
2054 ;
2055 if (ffebld_op (left_symter) == FFEBLD_opSYMTER)
2056 char_name = ffesymbol_text (ffebld_symter (left_symter));
2057 else
2058 char_name = "[expr?]";
2059
5ff904cd 2060 ffecom_char_args_ (&item, length, ffebld_left (expr));
5ff904cd
JL
2061
2062 if (item == error_mark_node || *length == error_mark_node)
2063 {
2064 item = *length = error_mark_node;
2065 break;
2066 }
2067
6b55276e
CB
2068 array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
2069
ff852b44
CB
2070 /* ~~~~Handle INTEGER*8 start/end, a la FFEBLD_opARRAYREF. */
2071
5ff904cd
JL
2072 if (start == NULL)
2073 {
2074 if (end == NULL)
2075 ;
2076 else
2077 {
6b55276e 2078 end_tree = ffecom_expr (end);
02f06e64 2079 if (flag_bounds_check)
6b55276e
CB
2080 end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
2081 char_name);
5ff904cd 2082 end_tree = convert (ffecom_f2c_ftnlen_type_node,
6b55276e 2083 end_tree);
5ff904cd
JL
2084
2085 if (end_tree == error_mark_node)
2086 {
2087 item = *length = error_mark_node;
2088 break;
2089 }
2090
2091 *length = end_tree;
2092 }
2093 }
2094 else
2095 {
6b55276e 2096 start_tree = ffecom_expr (start);
02f06e64 2097 if (flag_bounds_check)
6b55276e
CB
2098 start_tree = ffecom_subscript_check_ (array, start_tree, 0, 0,
2099 char_name);
5ff904cd 2100 start_tree = convert (ffecom_f2c_ftnlen_type_node,
6b55276e 2101 start_tree);
5ff904cd
JL
2102
2103 if (start_tree == error_mark_node)
2104 {
2105 item = *length = error_mark_node;
2106 break;
2107 }
2108
2109 start_tree = ffecom_save_tree (start_tree);
2110
2111 item = ffecom_2 (PLUS_EXPR, TREE_TYPE (item),
2112 item,
2113 ffecom_2 (MINUS_EXPR,
2114 TREE_TYPE (start_tree),
2115 start_tree,
2116 ffecom_f2c_ftnlen_one_node));
2117
2118 if (end == NULL)
2119 {
2120 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
2121 ffecom_f2c_ftnlen_one_node,
2122 ffecom_2 (MINUS_EXPR,
2123 ffecom_f2c_ftnlen_type_node,
2124 *length,
2125 start_tree));
2126 }
2127 else
2128 {
6b55276e 2129 end_tree = ffecom_expr (end);
02f06e64 2130 if (flag_bounds_check)
6b55276e
CB
2131 end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
2132 char_name);
5ff904cd 2133 end_tree = convert (ffecom_f2c_ftnlen_type_node,
6b55276e 2134 end_tree);
5ff904cd
JL
2135
2136 if (end_tree == error_mark_node)
2137 {
2138 item = *length = error_mark_node;
2139 break;
2140 }
2141
2142 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
2143 ffecom_f2c_ftnlen_one_node,
2144 ffecom_2 (MINUS_EXPR,
2145 ffecom_f2c_ftnlen_type_node,
2146 end_tree, start_tree));
2147 }
2148 }
2149 }
2150 break;
2151
2152 case FFEBLD_opFUNCREF:
2153 {
2154 ffesymbol s = ffebld_symter (ffebld_left (expr));
2155 tree tempvar;
2156 tree args;
2157 ffetargetCharacterSize size = ffeinfo_size (ffebld_info (expr));
2158 ffecomGfrt ix;
2159
2160 if (size == FFETARGET_charactersizeNONE)
c7e4ee3a
CB
2161 /* ~~Kludge alert! This should someday be fixed. */
2162 size = 24;
5ff904cd
JL
2163
2164 *length = build_int_2 (size, 0);
2165 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2166
2167 if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
2168 == FFEINFO_whereINTRINSIC)
2169 {
2170 if (size == 1)
c7e4ee3a
CB
2171 {
2172 /* Invocation of an intrinsic returning CHARACTER*1. */
5ff904cd
JL
2173 item = ffecom_expr_intrinsic_ (expr, NULL_TREE,
2174 NULL, NULL);
2175 break;
2176 }
2177 ix = ffeintrin_gfrt_direct (ffebld_symter_implementation (ffebld_left (expr)));
2178 assert (ix != FFECOM_gfrt);
2179 item = ffecom_gfrt_tree_ (ix);
2180 }
2181 else
2182 {
2183 ix = FFECOM_gfrt;
2184 item = ffesymbol_hook (s).decl_tree;
2185 if (item == NULL_TREE)
2186 {
2187 s = ffecom_sym_transform_ (s);
2188 item = ffesymbol_hook (s).decl_tree;
2189 }
2190 if (item == error_mark_node)
2191 {
2192 item = *length = error_mark_node;
2193 break;
2194 }
2195
2196 if (!ffesymbol_hook (s).addr)
2197 item = ffecom_1_fn (item);
2198 }
2199
c7e4ee3a 2200#ifdef HOHO
5ff904cd 2201 tempvar = ffecom_push_tempvar (char_type_node, size, -1, TRUE);
c7e4ee3a
CB
2202#else
2203 tempvar = ffebld_nonter_hook (expr);
2204 assert (tempvar);
2205#endif
5ff904cd
JL
2206 tempvar = ffecom_1 (ADDR_EXPR,
2207 build_pointer_type (TREE_TYPE (tempvar)),
2208 tempvar);
2209
5ff904cd
JL
2210 args = build_tree_list (NULL_TREE, tempvar);
2211
2212 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT) /* Sfunc args by value. */
2213 TREE_CHAIN (args) = ffecom_list_expr (ffebld_right (expr));
2214 else
2215 {
2216 TREE_CHAIN (args) = build_tree_list (NULL_TREE, *length);
2217 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
2218 {
2219 TREE_CHAIN (TREE_CHAIN (args))
2220 = ffecom_arglist_expr_ (ffecom_gfrt_args_ (ix),
2221 ffebld_right (expr));
2222 }
2223 else
2224 {
2225 TREE_CHAIN (TREE_CHAIN (args))
2226 = ffecom_list_ptr_to_expr (ffebld_right (expr));
2227 }
2228 }
2229
2230 item = ffecom_3s (CALL_EXPR,
2231 TREE_TYPE (TREE_TYPE (TREE_TYPE (item))),
2232 item, args, NULL_TREE);
2233 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item,
2234 tempvar);
5ff904cd
JL
2235 }
2236 break;
2237
2238 case FFEBLD_opCONVERT:
2239
5ff904cd 2240 ffecom_char_args_ (&item, length, ffebld_left (expr));
5ff904cd
JL
2241
2242 if (item == error_mark_node || *length == error_mark_node)
2243 {
2244 item = *length = error_mark_node;
2245 break;
2246 }
2247
2248 if ((ffebld_size_known (ffebld_left (expr))
2249 == FFETARGET_charactersizeNONE)
2250 || (ffebld_size_known (ffebld_left (expr)) < (ffebld_size (expr))))
2251 { /* Possible blank-padding needed, copy into
2252 temporary. */
2253 tree tempvar;
2254 tree args;
2255 tree newlen;
2256
c7e4ee3a
CB
2257#ifdef HOHO
2258 tempvar = ffecom_make_tempvar (char_type_node,
2259 ffebld_size (expr), -1);
2260#else
2261 tempvar = ffebld_nonter_hook (expr);
2262 assert (tempvar);
2263#endif
5ff904cd
JL
2264 tempvar = ffecom_1 (ADDR_EXPR,
2265 build_pointer_type (TREE_TYPE (tempvar)),
2266 tempvar);
2267
2268 newlen = build_int_2 (ffebld_size (expr), 0);
2269 TREE_TYPE (newlen) = ffecom_f2c_ftnlen_type_node;
2270
2271 args = build_tree_list (NULL_TREE, tempvar);
2272 TREE_CHAIN (args) = build_tree_list (NULL_TREE, item);
2273 TREE_CHAIN (TREE_CHAIN (args)) = build_tree_list (NULL_TREE, newlen);
2274 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (args)))
2275 = build_tree_list (NULL_TREE, *length);
2276
c7e4ee3a 2277 item = ffecom_call_gfrt (FFECOM_gfrtCOPY, args, NULL_TREE);
5ff904cd
JL
2278 TREE_SIDE_EFFECTS (item) = 1;
2279 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), fold (item),
2280 tempvar);
2281 *length = newlen;
2282 }
2283 else
2284 { /* Just truncate the length. */
2285 *length = build_int_2 (ffebld_size (expr), 0);
2286 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2287 }
2288 break;
2289
2290 default:
2291 assert ("bad op for single char arg expr" == NULL);
2292 item = NULL_TREE;
2293 break;
2294 }
2295
2296 *xitem = item;
2297}
2298#endif
2299
2300/* Check the size of the type to be sure it doesn't overflow the
2301 "portable" capacities of the compiler back end. `dummy' types
2302 can generally overflow the normal sizes as long as the computations
2303 themselves don't overflow. A particular target of the back end
2304 must still enforce its size requirements, though, and the back
2305 end takes care of this in stor-layout.c. */
2306
2307#if FFECOM_targetCURRENT == FFECOM_targetGCC
2308static tree
2309ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy)
2310{
2311 if (TREE_CODE (type) == ERROR_MARK)
2312 return type;
2313
2314 if (TYPE_SIZE (type) == NULL_TREE)
2315 return type;
2316
2317 if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
2318 return type;
2319
2320 if ((tree_int_cst_sgn (TYPE_SIZE (type)) < 0)
2b0c2df0
CB
2321 || (!dummy && (((TREE_INT_CST_HIGH (TYPE_SIZE (type)) != 0))
2322 || TREE_OVERFLOW (TYPE_SIZE (type)))))
5ff904cd
JL
2323 {
2324 ffebad_start (FFEBAD_ARRAY_LARGE);
2325 ffebad_string (ffesymbol_text (s));
2326 ffebad_here (0, ffesymbol_where_line (s), ffesymbol_where_column (s));
2327 ffebad_finish ();
2328
2329 return error_mark_node;
2330 }
2331
2332 return type;
2333}
2334#endif
2335
2336/* Builds a length argument (PARM_DECL). Also wraps type in an array type
2337 where the dimension info is (1:size) where <size> is ffesymbol_size(s) if
2338 known, length_arg if not known (FFETARGET_charactersizeNONE). */
2339
2340#if FFECOM_targetCURRENT == FFECOM_targetGCC
2341static tree
2342ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s)
2343{
2344 ffetargetCharacterSize sz = ffesymbol_size (s);
2345 tree highval;
2346 tree tlen;
2347 tree type = *xtype;
2348
2349 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
2350 tlen = NULL_TREE; /* A statement function, no length passed. */
2351 else
2352 {
2353 if (ffesymbol_where (s) == FFEINFO_whereDUMMY)
2354 tlen = ffecom_get_invented_identifier ("__g77_length_%s",
14657de8 2355 ffesymbol_text (s));
5ff904cd 2356 else
14657de8 2357 tlen = ffecom_get_invented_identifier ("__g77_%s", "length");
5ff904cd
JL
2358 tlen = build_decl (PARM_DECL, tlen, ffecom_f2c_ftnlen_type_node);
2359#if BUILT_FOR_270
2360 DECL_ARTIFICIAL (tlen) = 1;
2361#endif
2362 }
2363
2364 if (sz == FFETARGET_charactersizeNONE)
2365 {
2366 assert (tlen != NULL_TREE);
2b0c2df0 2367 highval = variable_size (tlen);
5ff904cd
JL
2368 }
2369 else
2370 {
2371 highval = build_int_2 (sz, 0);
2372 TREE_TYPE (highval) = ffecom_f2c_ftnlen_type_node;
2373 }
2374
2375 type = build_array_type (type,
2376 build_range_type (ffecom_f2c_ftnlen_type_node,
2377 ffecom_f2c_ftnlen_one_node,
2378 highval));
2379
2380 *xtype = type;
2381 return tlen;
2382}
2383
2384#endif
2385/* ffecom_concat_list_gather_ -- Gather list of concatenated string exprs
2386
2387 ffecomConcatList_ catlist;
2388 ffebld expr; // expr of CHARACTER basictype.
2389 ffetargetCharacterSize max; // max chars to gather or _...NONE if no max
2390 catlist = ffecom_concat_list_gather_(catlist,expr,max);
2391
2392 Scans expr for character subexpressions, updates and returns catlist
2393 accordingly. */
2394
2395#if FFECOM_targetCURRENT == FFECOM_targetGCC
2396static ffecomConcatList_
2397ffecom_concat_list_gather_ (ffecomConcatList_ catlist, ffebld expr,
2398 ffetargetCharacterSize max)
2399{
2400 ffetargetCharacterSize sz;
2401
2402recurse: /* :::::::::::::::::::: */
2403
2404 if (expr == NULL)
2405 return catlist;
2406
2407 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen >= max))
2408 return catlist; /* Don't append any more items. */
2409
2410 switch (ffebld_op (expr))
2411 {
2412 case FFEBLD_opCONTER:
2413 case FFEBLD_opSYMTER:
2414 case FFEBLD_opARRAYREF:
2415 case FFEBLD_opFUNCREF:
2416 case FFEBLD_opSUBSTR:
2417 case FFEBLD_opCONVERT: /* Callers should strip this off beforehand
2418 if they don't need to preserve it. */
2419 if (catlist.count == catlist.max)
2420 { /* Make a (larger) list. */
2421 ffebld *newx;
2422 int newmax;
2423
2424 newmax = (catlist.max == 0) ? 8 : catlist.max * 2;
2425 newx = malloc_new_ks (malloc_pool_image (), "catlist",
2426 newmax * sizeof (newx[0]));
2427 if (catlist.max != 0)
2428 {
2429 memcpy (newx, catlist.exprs, catlist.max * sizeof (newx[0]));
2430 malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2431 catlist.max * sizeof (newx[0]));
2432 }
2433 catlist.max = newmax;
2434 catlist.exprs = newx;
2435 }
2436 if ((sz = ffebld_size_known (expr)) != FFETARGET_charactersizeNONE)
2437 catlist.minlen += sz;
2438 else
2439 ++catlist.minlen; /* Not true for F90; can be 0 length. */
2440 if ((sz = ffebld_size_max (expr)) == FFETARGET_charactersizeNONE)
2441 catlist.maxlen = sz;
2442 else
2443 catlist.maxlen += sz;
2444 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen > max))
2445 { /* This item overlaps (or is beyond) the end
2446 of the destination. */
2447 switch (ffebld_op (expr))
2448 {
2449 case FFEBLD_opCONTER:
2450 case FFEBLD_opSYMTER:
2451 case FFEBLD_opARRAYREF:
2452 case FFEBLD_opFUNCREF:
2453 case FFEBLD_opSUBSTR:
c7e4ee3a
CB
2454 /* ~~Do useful truncations here. */
2455 break;
5ff904cd
JL
2456
2457 default:
2458 assert ("op changed or inconsistent switches!" == NULL);
2459 break;
2460 }
2461 }
2462 catlist.exprs[catlist.count++] = expr;
2463 return catlist;
2464
2465 case FFEBLD_opPAREN:
2466 expr = ffebld_left (expr);
2467 goto recurse; /* :::::::::::::::::::: */
2468
2469 case FFEBLD_opCONCATENATE:
2470 catlist = ffecom_concat_list_gather_ (catlist, ffebld_left (expr), max);
2471 expr = ffebld_right (expr);
2472 goto recurse; /* :::::::::::::::::::: */
2473
2474#if 0 /* Breaks passing small actual arg to larger
2475 dummy arg of sfunc */
2476 case FFEBLD_opCONVERT:
2477 expr = ffebld_left (expr);
2478 {
2479 ffetargetCharacterSize cmax;
2480
2481 cmax = catlist.len + ffebld_size_known (expr);
2482
2483 if ((max == FFETARGET_charactersizeNONE) || (max > cmax))
2484 max = cmax;
2485 }
2486 goto recurse; /* :::::::::::::::::::: */
2487#endif
2488
2489 case FFEBLD_opANY:
2490 return catlist;
2491
2492 default:
2493 assert ("bad op in _gather_" == NULL);
2494 return catlist;
2495 }
2496}
2497
2498#endif
2499/* ffecom_concat_list_kill_ -- Kill list of concatenated string exprs
2500
2501 ffecomConcatList_ catlist;
2502 ffecom_concat_list_kill_(catlist);
2503
2504 Anything allocated within the list info is deallocated. */
2505
2506#if FFECOM_targetCURRENT == FFECOM_targetGCC
2507static void
2508ffecom_concat_list_kill_ (ffecomConcatList_ catlist)
2509{
2510 if (catlist.max != 0)
2511 malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2512 catlist.max * sizeof (catlist.exprs[0]));
2513}
2514
2515#endif
c7e4ee3a 2516/* Make list of concatenated string exprs.
5ff904cd
JL
2517
2518 Returns a flattened list of concatenated subexpressions given a
2519 tree of such expressions. */
2520
2521#if FFECOM_targetCURRENT == FFECOM_targetGCC
2522static ffecomConcatList_
2523ffecom_concat_list_new_ (ffebld expr, ffetargetCharacterSize max)
2524{
2525 ffecomConcatList_ catlist;
2526
2527 catlist.maxlen = catlist.minlen = catlist.max = catlist.count = 0;
2528 return ffecom_concat_list_gather_ (catlist, expr, max);
2529}
2530
2531#endif
2532
2533/* Provide some kind of useful info on member of aggregate area,
2534 since current g77/gcc technology does not provide debug info
2535 on these members. */
2536
2537#if FFECOM_targetCURRENT == FFECOM_targetGCC
2538static void
26f096f9 2539ffecom_debug_kludge_ (tree aggr, const char *aggr_type, ffesymbol member,
5ff904cd
JL
2540 tree member_type UNUSED, ffetargetOffset offset)
2541{
2542 tree value;
2543 tree decl;
2544 int len;
2545 char *buff;
2546 char space[120];
2547#if 0
2548 tree type_id;
2549
2550 for (type_id = member_type;
2551 TREE_CODE (type_id) != IDENTIFIER_NODE;
2552 )
2553 {
2554 switch (TREE_CODE (type_id))
2555 {
2556 case INTEGER_TYPE:
2557 case REAL_TYPE:
2558 type_id = TYPE_NAME (type_id);
2559 break;
2560
2561 case ARRAY_TYPE:
2562 case COMPLEX_TYPE:
2563 type_id = TREE_TYPE (type_id);
2564 break;
2565
2566 default:
2567 assert ("no IDENTIFIER_NODE for type!" == NULL);
2568 type_id = error_mark_node;
2569 break;
2570 }
2571 }
2572#endif
2573
2574 if (ffecom_transform_only_dummies_
2575 || !ffe_is_debug_kludge ())
2576 return; /* Can't do this yet, maybe later. */
2577
2578 len = 60
2579 + strlen (aggr_type)
2580 + IDENTIFIER_LENGTH (DECL_NAME (aggr));
2581#if 0
2582 + IDENTIFIER_LENGTH (type_id);
2583#endif
2584
2585 if (((size_t) len) >= ARRAY_SIZE (space))
2586 buff = malloc_new_ks (malloc_pool_image (), "debug_kludge", len + 1);
2587 else
2588 buff = &space[0];
2589
2590 sprintf (&buff[0], "At (%s) `%s' plus %ld bytes",
2591 aggr_type,
2592 IDENTIFIER_POINTER (DECL_NAME (aggr)),
2593 (long int) offset);
2594
2595 value = build_string (len, buff);
2596 TREE_TYPE (value)
2597 = build_type_variant (build_array_type (char_type_node,
2598 build_range_type
2599 (integer_type_node,
2600 integer_one_node,
2601 build_int_2 (strlen (buff), 0))),
2602 1, 0);
2603 decl = build_decl (VAR_DECL,
2604 ffecom_get_identifier_ (ffesymbol_text (member)),
2605 TREE_TYPE (value));
2606 TREE_CONSTANT (decl) = 1;
2607 TREE_STATIC (decl) = 1;
2608 DECL_INITIAL (decl) = error_mark_node;
2609 DECL_IN_SYSTEM_HEADER (decl) = 1; /* Don't let -Wunused complain. */
2610 decl = start_decl (decl, FALSE);
2611 finish_decl (decl, value, FALSE);
2612
2613 if (buff != &space[0])
2614 malloc_kill_ks (malloc_pool_image (), buff, len + 1);
2615}
2616#endif
2617
2618/* ffecom_do_entry_ -- Do compilation of a particular entrypoint
2619
2620 ffesymbol fn; // the SUBROUTINE, FUNCTION, or ENTRY symbol itself
2621 int i; // entry# for this entrypoint (used by master fn)
2622 ffecom_do_entrypoint_(s,i);
2623
2624 Makes a public entry point that calls our private master fn (already
2625 compiled). */
2626
2627#if FFECOM_targetCURRENT == FFECOM_targetGCC
2628static void
2629ffecom_do_entry_ (ffesymbol fn, int entrynum)
2630{
2631 ffebld item;
2632 tree type; /* Type of function. */
2633 tree multi_retval; /* Var holding return value (union). */
2634 tree result; /* Var holding result. */
2635 ffeinfoBasictype bt;
2636 ffeinfoKindtype kt;
2637 ffeglobal g;
2638 ffeglobalType gt;
2639 bool charfunc; /* All entry points return same type
2640 CHARACTER. */
2641 bool cmplxfunc; /* Use f2c way of returning COMPLEX. */
2642 bool multi; /* Master fn has multiple return types. */
2643 bool altreturning = FALSE; /* This entry point has alternate returns. */
44d2eabc 2644 int old_lineno = lineno;
3b304f5b 2645 const char *old_input_filename = input_filename;
44d2eabc
JL
2646
2647 input_filename = ffesymbol_where_filename (fn);
2648 lineno = ffesymbol_where_filelinenum (fn);
5ff904cd 2649
5ff904cd
JL
2650 ffecom_doing_entry_ = TRUE; /* Don't bother with array dimensions. */
2651
2652 switch (ffecom_primary_entry_kind_)
2653 {
2654 case FFEINFO_kindFUNCTION:
2655
2656 /* Determine actual return type for function. */
2657
2658 gt = FFEGLOBAL_typeFUNC;
2659 bt = ffesymbol_basictype (fn);
2660 kt = ffesymbol_kindtype (fn);
2661 if (bt == FFEINFO_basictypeNONE)
2662 {
2663 ffeimplic_establish_symbol (fn);
2664 if (ffesymbol_funcresult (fn) != NULL)
2665 ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
2666 bt = ffesymbol_basictype (fn);
2667 kt = ffesymbol_kindtype (fn);
2668 }
2669
2670 if (bt == FFEINFO_basictypeCHARACTER)
2671 charfunc = TRUE, cmplxfunc = FALSE;
2672 else if ((bt == FFEINFO_basictypeCOMPLEX)
2673 && ffesymbol_is_f2c (fn))
2674 charfunc = FALSE, cmplxfunc = TRUE;
2675 else
2676 charfunc = cmplxfunc = FALSE;
2677
2678 if (charfunc)
2679 type = ffecom_tree_fun_type_void;
2680 else if (ffesymbol_is_f2c (fn))
2681 type = ffecom_tree_fun_type[bt][kt];
2682 else
2683 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
2684
2685 if ((type == NULL_TREE)
2686 || (TREE_TYPE (type) == NULL_TREE))
2687 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */
2688
2689 multi = (ffecom_master_bt_ == FFEINFO_basictypeNONE);
2690 break;
2691
2692 case FFEINFO_kindSUBROUTINE:
2693 gt = FFEGLOBAL_typeSUBR;
2694 bt = FFEINFO_basictypeNONE;
2695 kt = FFEINFO_kindtypeNONE;
2696 if (ffecom_is_altreturning_)
2697 { /* Am _I_ altreturning? */
2698 for (item = ffesymbol_dummyargs (fn);
2699 item != NULL;
2700 item = ffebld_trail (item))
2701 {
2702 if (ffebld_op (ffebld_head (item)) == FFEBLD_opSTAR)
2703 {
2704 altreturning = TRUE;
2705 break;
2706 }
2707 }
2708 if (altreturning)
2709 type = ffecom_tree_subr_type;
2710 else
2711 type = ffecom_tree_fun_type_void;
2712 }
2713 else
2714 type = ffecom_tree_fun_type_void;
2715 charfunc = FALSE;
2716 cmplxfunc = FALSE;
2717 multi = FALSE;
2718 break;
2719
2720 default:
2721 assert ("say what??" == NULL);
2722 /* Fall through. */
2723 case FFEINFO_kindANY:
2724 gt = FFEGLOBAL_typeANY;
2725 bt = FFEINFO_basictypeNONE;
2726 kt = FFEINFO_kindtypeNONE;
2727 type = error_mark_node;
2728 charfunc = FALSE;
2729 cmplxfunc = FALSE;
2730 multi = FALSE;
2731 break;
2732 }
2733
2734 /* build_decl uses the current lineno and input_filename to set the decl
2735 source info. So, I've putzed with ffestd and ffeste code to update that
2736 source info to point to the appropriate statement just before calling
2737 ffecom_do_entrypoint (which calls this fn). */
2738
2739 start_function (ffecom_get_external_identifier_ (fn),
2740 type,
2741 0, /* nested/inline */
2742 1); /* TREE_PUBLIC */
2743
2744 if (((g = ffesymbol_global (fn)) != NULL)
2745 && ((ffeglobal_type (g) == gt)
2746 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
2747 {
2748 ffeglobal_set_hook (g, current_function_decl);
2749 }
2750
2751 /* Reset args in master arg list so they get retransitioned. */
2752
2753 for (item = ffecom_master_arglist_;
2754 item != NULL;
2755 item = ffebld_trail (item))
2756 {
2757 ffebld arg;
2758 ffesymbol s;
2759
2760 arg = ffebld_head (item);
2761 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2762 continue; /* Alternate return or some such thing. */
2763 s = ffebld_symter (arg);
2764 ffesymbol_hook (s).decl_tree = NULL_TREE;
2765 ffesymbol_hook (s).length_tree = NULL_TREE;
2766 }
2767
2768 /* Build dummy arg list for this entry point. */
2769
5ff904cd
JL
2770 if (charfunc || cmplxfunc)
2771 { /* Prepend arg for where result goes. */
2772 tree type;
2773 tree length;
2774
2775 if (charfunc)
2776 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
2777 else
2778 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
2779
14657de8 2780 result = ffecom_get_invented_identifier ("__g77_%s", "result");
5ff904cd
JL
2781
2782 /* Make length arg _and_ enhance type info for CHAR arg itself. */
2783
2784 if (charfunc)
2785 length = ffecom_char_enhance_arg_ (&type, fn);
2786 else
2787 length = NULL_TREE; /* Not ref'd if !charfunc. */
2788
2789 type = build_pointer_type (type);
2790 result = build_decl (PARM_DECL, result, type);
2791
2792 push_parm_decl (result);
2793 ffecom_func_result_ = result;
2794
2795 if (charfunc)
2796 {
2797 push_parm_decl (length);
2798 ffecom_func_length_ = length;
2799 }
2800 }
2801 else
2802 result = DECL_RESULT (current_function_decl);
2803
2804 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (fn), FALSE);
2805
5ff904cd
JL
2806 store_parm_decls (0);
2807
c7e4ee3a
CB
2808 ffecom_start_compstmt ();
2809 /* Disallow temp vars at this level. */
2810 current_binding_level->prep_state = 2;
5ff904cd
JL
2811
2812 /* Make local var to hold return type for multi-type master fn. */
2813
2814 if (multi)
2815 {
5ff904cd 2816 multi_retval = ffecom_get_invented_identifier ("__g77_%s",
14657de8 2817 "multi_retval");
5ff904cd
JL
2818 multi_retval = build_decl (VAR_DECL, multi_retval,
2819 ffecom_multi_type_node_);
2820 multi_retval = start_decl (multi_retval, FALSE);
2821 finish_decl (multi_retval, NULL_TREE, FALSE);
5ff904cd
JL
2822 }
2823 else
2824 multi_retval = NULL_TREE; /* Not actually ref'd if !multi. */
2825
2826 /* Here we emit the actual code for the entry point. */
2827
2828 {
2829 ffebld list;
2830 ffebld arg;
2831 ffesymbol s;
2832 tree arglist = NULL_TREE;
2833 tree *plist = &arglist;
2834 tree prepend;
2835 tree call;
2836 tree actarg;
2837 tree master_fn;
2838
2839 /* Prepare actual arg list based on master arg list. */
2840
2841 for (list = ffecom_master_arglist_;
2842 list != NULL;
2843 list = ffebld_trail (list))
2844 {
2845 arg = ffebld_head (list);
2846 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2847 continue;
2848 s = ffebld_symter (arg);
702edf1d
CB
2849 if (ffesymbol_hook (s).decl_tree == NULL_TREE
2850 || ffesymbol_hook (s).decl_tree == error_mark_node)
5ff904cd
JL
2851 actarg = null_pointer_node; /* We don't have this arg. */
2852 else
2853 actarg = ffesymbol_hook (s).decl_tree;
2854 *plist = build_tree_list (NULL_TREE, actarg);
2855 plist = &TREE_CHAIN (*plist);
2856 }
2857
2858 /* This code appends the length arguments for character
2859 variables/arrays. */
2860
2861 for (list = ffecom_master_arglist_;
2862 list != NULL;
2863 list = ffebld_trail (list))
2864 {
2865 arg = ffebld_head (list);
2866 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2867 continue;
2868 s = ffebld_symter (arg);
2869 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
2870 continue; /* Only looking for CHARACTER arguments. */
2871 if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
2872 continue; /* Only looking for variables and arrays. */
702edf1d
CB
2873 if (ffesymbol_hook (s).length_tree == NULL_TREE
2874 || ffesymbol_hook (s).length_tree == error_mark_node)
5ff904cd
JL
2875 actarg = ffecom_f2c_ftnlen_zero_node; /* We don't have this arg. */
2876 else
2877 actarg = ffesymbol_hook (s).length_tree;
2878 *plist = build_tree_list (NULL_TREE, actarg);
2879 plist = &TREE_CHAIN (*plist);
2880 }
2881
2882 /* Prepend character-value return info to actual arg list. */
2883
2884 if (charfunc)
2885 {
2886 prepend = build_tree_list (NULL_TREE, ffecom_func_result_);
2887 TREE_CHAIN (prepend)
2888 = build_tree_list (NULL_TREE, ffecom_func_length_);
2889 TREE_CHAIN (TREE_CHAIN (prepend)) = arglist;
2890 arglist = prepend;
2891 }
2892
2893 /* Prepend multi-type return value to actual arg list. */
2894
2895 if (multi)
2896 {
2897 prepend
2898 = build_tree_list (NULL_TREE,
2899 ffecom_1 (ADDR_EXPR,
2900 build_pointer_type (TREE_TYPE (multi_retval)),
2901 multi_retval));
2902 TREE_CHAIN (prepend) = arglist;
2903 arglist = prepend;
2904 }
2905
2906 /* Prepend my entry-point number to the actual arg list. */
2907
2908 prepend = build_tree_list (NULL_TREE, build_int_2 (entrynum, 0));
2909 TREE_CHAIN (prepend) = arglist;
2910 arglist = prepend;
2911
2912 /* Build the call to the master function. */
2913
2914 master_fn = ffecom_1_fn (ffecom_previous_function_decl_);
2915 call = ffecom_3s (CALL_EXPR,
2916 TREE_TYPE (TREE_TYPE (TREE_TYPE (master_fn))),
2917 master_fn, arglist, NULL_TREE);
2918
2919 /* Decide whether the master function is a function or subroutine, and
2920 handle the return value for my entry point. */
2921
2922 if (charfunc || ((ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
2923 && !altreturning))
2924 {
2925 expand_expr_stmt (call);
2926 expand_null_return ();
2927 }
2928 else if (multi && cmplxfunc)
2929 {
2930 expand_expr_stmt (call);
2931 result
2932 = ffecom_1 (INDIRECT_REF,
2933 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
2934 result);
2935 result = ffecom_modify (NULL_TREE, result,
2936 ffecom_2 (COMPONENT_REF, TREE_TYPE (result),
2937 multi_retval,
2938 ffecom_multi_fields_[bt][kt]));
2939 expand_expr_stmt (result);
2940 expand_null_return ();
2941 }
2942 else if (multi)
2943 {
2944 expand_expr_stmt (call);
2945 result
2946 = ffecom_modify (NULL_TREE, result,
2947 convert (TREE_TYPE (result),
2948 ffecom_2 (COMPONENT_REF,
2949 ffecom_tree_type[bt][kt],
2950 multi_retval,
2951 ffecom_multi_fields_[bt][kt])));
2952 expand_return (result);
2953 }
2954 else if (cmplxfunc)
2955 {
2956 result
2957 = ffecom_1 (INDIRECT_REF,
2958 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
2959 result);
2960 result = ffecom_modify (NULL_TREE, result, call);
2961 expand_expr_stmt (result);
2962 expand_null_return ();
2963 }
2964 else
2965 {
2966 result = ffecom_modify (NULL_TREE,
2967 result,
2968 convert (TREE_TYPE (result),
2969 call));
2970 expand_return (result);
2971 }
5ff904cd
JL
2972 }
2973
c7e4ee3a 2974 ffecom_end_compstmt ();
5ff904cd
JL
2975
2976 finish_function (0);
2977
44d2eabc
JL
2978 lineno = old_lineno;
2979 input_filename = old_input_filename;
2980
5ff904cd
JL
2981 ffecom_doing_entry_ = FALSE;
2982}
2983
2984#endif
2985/* Transform expr into gcc tree with possible destination
2986
2987 Recursive descent on expr while making corresponding tree nodes and
2988 attaching type info and such. If destination supplied and compatible
2989 with temporary that would be made in certain cases, temporary isn't
092a4ef8 2990 made, destination used instead, and dest_used flag set TRUE. */
5ff904cd
JL
2991
2992#if FFECOM_targetCURRENT == FFECOM_targetGCC
2993static tree
092a4ef8
RH
2994ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
2995 bool *dest_used, bool assignp, bool widenp)
5ff904cd
JL
2996{
2997 tree item;
2998 tree list;
2999 tree args;
3000 ffeinfoBasictype bt;
3001 ffeinfoKindtype kt;
3002 tree t;
5ff904cd 3003 tree dt; /* decl_tree for an ffesymbol. */
092a4ef8 3004 tree tree_type, tree_type_x;
af752698 3005 tree left, right;
5ff904cd
JL
3006 ffesymbol s;
3007 enum tree_code code;
3008
3009 assert (expr != NULL);
3010
3011 if (dest_used != NULL)
3012 *dest_used = FALSE;
3013
3014 bt = ffeinfo_basictype (ffebld_info (expr));
3015 kt = ffeinfo_kindtype (ffebld_info (expr));
af752698 3016 tree_type = ffecom_tree_type[bt][kt];
5ff904cd 3017
092a4ef8
RH
3018 /* Widen integral arithmetic as desired while preserving signedness. */
3019 tree_type_x = NULL_TREE;
3020 if (widenp && tree_type
3021 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
3022 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
3023 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
3024
5ff904cd
JL
3025 switch (ffebld_op (expr))
3026 {
3027 case FFEBLD_opACCTER:
5ff904cd
JL
3028 {
3029 ffebitCount i;
3030 ffebit bits = ffebld_accter_bits (expr);
3031 ffetargetOffset source_offset = 0;
a6fa6420 3032 ffetargetOffset dest_offset = ffebld_accter_pad (expr);
5ff904cd
JL
3033 tree purpose;
3034
a6fa6420
CB
3035 assert (dest_offset == 0
3036 || (bt == FFEINFO_basictypeCHARACTER
3037 && kt == FFEINFO_kindtypeCHARACTER1));
5ff904cd
JL
3038
3039 list = item = NULL;
3040 for (;;)
3041 {
3042 ffebldConstantUnion cu;
3043 ffebitCount length;
3044 bool value;
3045 ffebldConstantArray ca = ffebld_accter (expr);
3046
3047 ffebit_test (bits, source_offset, &value, &length);
3048 if (length == 0)
3049 break;
3050
3051 if (value)
3052 {
3053 for (i = 0; i < length; ++i)
3054 {
3055 cu = ffebld_constantarray_get (ca, bt, kt,
3056 source_offset + i);
3057
3058 t = ffecom_constantunion (&cu, bt, kt, tree_type);
3059
a6fa6420
CB
3060 if (i == 0
3061 && dest_offset != 0)
3062 purpose = build_int_2 (dest_offset, 0);
5ff904cd
JL
3063 else
3064 purpose = NULL_TREE;
3065
3066 if (list == NULL_TREE)
3067 list = item = build_tree_list (purpose, t);
3068 else
3069 {
3070 TREE_CHAIN (item) = build_tree_list (purpose, t);
3071 item = TREE_CHAIN (item);
3072 }
3073 }
3074 }
3075 source_offset += length;
a6fa6420 3076 dest_offset += length;
5ff904cd
JL
3077 }
3078 }
3079
a6fa6420
CB
3080 item = build_int_2 ((ffebld_accter_size (expr)
3081 + ffebld_accter_pad (expr)) - 1, 0);
5ff904cd
JL
3082 ffebit_kill (ffebld_accter_bits (expr));
3083 TREE_TYPE (item) = ffecom_integer_type_node;
3084 item
3085 = build_array_type
3086 (tree_type,
3087 build_range_type (ffecom_integer_type_node,
3088 ffecom_integer_zero_node,
3089 item));
3090 list = build (CONSTRUCTOR, item, NULL_TREE, list);
3091 TREE_CONSTANT (list) = 1;
3092 TREE_STATIC (list) = 1;
3093 return list;
3094
3095 case FFEBLD_opARRTER:
5ff904cd
JL
3096 {
3097 ffetargetOffset i;
3098
a6fa6420
CB
3099 list = NULL_TREE;
3100 if (ffebld_arrter_pad (expr) == 0)
3101 item = NULL_TREE;
3102 else
3103 {
3104 assert (bt == FFEINFO_basictypeCHARACTER
3105 && kt == FFEINFO_kindtypeCHARACTER1);
3106
3107 /* Becomes PURPOSE first time through loop. */
3108 item = build_int_2 (ffebld_arrter_pad (expr), 0);
3109 }
3110
5ff904cd
JL
3111 for (i = 0; i < ffebld_arrter_size (expr); ++i)
3112 {
3113 ffebldConstantUnion cu
3114 = ffebld_constantarray_get (ffebld_arrter (expr), bt, kt, i);
3115
3116 t = ffecom_constantunion (&cu, bt, kt, tree_type);
3117
3118 if (list == NULL_TREE)
a6fa6420
CB
3119 /* Assume item is PURPOSE first time through loop. */
3120 list = item = build_tree_list (item, t);
5ff904cd
JL
3121 else
3122 {
3123 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
3124 item = TREE_CHAIN (item);
3125 }
3126 }
3127 }
3128
a6fa6420
CB
3129 item = build_int_2 ((ffebld_arrter_size (expr)
3130 + ffebld_arrter_pad (expr)) - 1, 0);
5ff904cd
JL
3131 TREE_TYPE (item) = ffecom_integer_type_node;
3132 item
3133 = build_array_type
3134 (tree_type,
3135 build_range_type (ffecom_integer_type_node,
a6fa6420 3136 ffecom_integer_zero_node,
5ff904cd
JL
3137 item));
3138 list = build (CONSTRUCTOR, item, NULL_TREE, list);
3139 TREE_CONSTANT (list) = 1;
3140 TREE_STATIC (list) = 1;
3141 return list;
3142
3143 case FFEBLD_opCONTER:
c264f113 3144 assert (ffebld_conter_pad (expr) == 0);
5ff904cd
JL
3145 item
3146 = ffecom_constantunion (&ffebld_constant_union (ffebld_conter (expr)),
3147 bt, kt, tree_type);
3148 return item;
3149
3150 case FFEBLD_opSYMTER:
3151 if ((ffebld_symter_generic (expr) != FFEINTRIN_genNONE)
3152 || (ffebld_symter_specific (expr) != FFEINTRIN_specNONE))
3153 return ffecom_ptr_to_expr (expr); /* Same as %REF(intrinsic). */
3154 s = ffebld_symter (expr);
3155 t = ffesymbol_hook (s).decl_tree;
3156
3157 if (assignp)
3158 { /* ASSIGN'ed-label expr. */
3159 if (ffe_is_ugly_assign ())
3160 {
3161 /* User explicitly wants ASSIGN'ed variables to be at the same
3162 memory address as the variables when used in non-ASSIGN
3163 contexts. That can make old, arcane, non-standard code
3164 work, but don't try to do it when a pointer wouldn't fit
3165 in the normal variable (take other approach, and warn,
3166 instead). */
3167
3168 if (t == NULL_TREE)
3169 {
3170 s = ffecom_sym_transform_ (s);
3171 t = ffesymbol_hook (s).decl_tree;
3172 assert (t != NULL_TREE);
3173 }
3174
3175 if (t == error_mark_node)
3176 return t;
3177
3178 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (t)))
3179 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
3180 {
3181 if (ffesymbol_hook (s).addr)
3182 t = ffecom_1 (INDIRECT_REF,
3183 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
3184 return t;
3185 }
3186
3187 if (ffesymbol_hook (s).assign_tree == NULL_TREE)
3188 {
3189 ffebad_start_msg ("ASSIGN'ed label cannot fit into `%A' at %0 -- using wider sibling",
3190 FFEBAD_severityWARNING);
3191 ffebad_string (ffesymbol_text (s));
3192 ffebad_here (0, ffesymbol_where_line (s),
3193 ffesymbol_where_column (s));
3194 ffebad_finish ();
3195 }
3196 }
3197
3198 /* Don't use the normal variable's tree for ASSIGN, though mark
3199 it as in the system header (housekeeping). Use an explicit,
3200 specially created sibling that is known to be wide enough
3201 to hold pointers to labels. */
3202
3203 if (t != NULL_TREE
3204 && TREE_CODE (t) == VAR_DECL)
3205 DECL_IN_SYSTEM_HEADER (t) = 1; /* Don't let -Wunused complain. */
3206
3207 t = ffesymbol_hook (s).assign_tree;
3208 if (t == NULL_TREE)
3209 {
3210 s = ffecom_sym_transform_assign_ (s);
3211 t = ffesymbol_hook (s).assign_tree;
3212 assert (t != NULL_TREE);
3213 }
3214 }
3215 else
3216 {
3217 if (t == NULL_TREE)
3218 {
3219 s = ffecom_sym_transform_ (s);
3220 t = ffesymbol_hook (s).decl_tree;
3221 assert (t != NULL_TREE);
3222 }
3223 if (ffesymbol_hook (s).addr)
3224 t = ffecom_1 (INDIRECT_REF,
3225 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
3226 }
3227 return t;
3228
3229 case FFEBLD_opARRAYREF:
ff852b44 3230 return ffecom_arrayref_ (NULL_TREE, expr, 0);
5ff904cd
JL
3231
3232 case FFEBLD_opUPLUS:
092a4ef8 3233 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
af752698 3234 return ffecom_1 (NOP_EXPR, tree_type, left);
5ff904cd 3235
c7e4ee3a
CB
3236 case FFEBLD_opPAREN:
3237 /* ~~~Make sure Fortran rules respected here */
092a4ef8 3238 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
af752698 3239 return ffecom_1 (NOP_EXPR, tree_type, left);
5ff904cd
JL
3240
3241 case FFEBLD_opUMINUS:
092a4ef8 3242 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3243 if (tree_type_x)
3244 {
3245 tree_type = tree_type_x;
3246 left = convert (tree_type, left);
3247 }
3248 return ffecom_1 (NEGATE_EXPR, tree_type, left);
5ff904cd
JL
3249
3250 case FFEBLD_opADD:
092a4ef8
RH
3251 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3252 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3253 if (tree_type_x)
3254 {
3255 tree_type = tree_type_x;
3256 left = convert (tree_type, left);
3257 right = convert (tree_type, right);
3258 }
3259 return ffecom_2 (PLUS_EXPR, tree_type, left, right);
5ff904cd
JL
3260
3261 case FFEBLD_opSUBTRACT:
092a4ef8
RH
3262 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3263 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3264 if (tree_type_x)
3265 {
3266 tree_type = tree_type_x;
3267 left = convert (tree_type, left);
3268 right = convert (tree_type, right);
3269 }
3270 return ffecom_2 (MINUS_EXPR, tree_type, left, right);
5ff904cd
JL
3271
3272 case FFEBLD_opMULTIPLY:
092a4ef8
RH
3273 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3274 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3275 if (tree_type_x)
3276 {
3277 tree_type = tree_type_x;
3278 left = convert (tree_type, left);
3279 right = convert (tree_type, right);
3280 }
3281 return ffecom_2 (MULT_EXPR, tree_type, left, right);
5ff904cd
JL
3282
3283 case FFEBLD_opDIVIDE:
092a4ef8
RH
3284 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3285 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3286 if (tree_type_x)
3287 {
3288 tree_type = tree_type_x;
3289 left = convert (tree_type, left);
3290 right = convert (tree_type, right);
3291 }
3292 return ffecom_tree_divide_ (tree_type, left, right,
c7e4ee3a
CB
3293 dest_tree, dest, dest_used,
3294 ffebld_nonter_hook (expr));
5ff904cd
JL
3295
3296 case FFEBLD_opPOWER:
5ff904cd
JL
3297 {
3298 ffebld left = ffebld_left (expr);
3299 ffebld right = ffebld_right (expr);
3300 ffecomGfrt code;
3301 ffeinfoKindtype rtkt;
270fc4e8 3302 ffeinfoKindtype ltkt;
95eb4fd9 3303 bool ref = TRUE;
5ff904cd
JL
3304
3305 switch (ffeinfo_basictype (ffebld_info (right)))
3306 {
95eb4fd9 3307
5ff904cd
JL
3308 case FFEINFO_basictypeINTEGER:
3309 if (1 || optimize)
3310 {
c7e4ee3a 3311 item = ffecom_expr_power_integer_ (expr);
5ff904cd
JL
3312 if (item != NULL_TREE)
3313 return item;
3314 }
3315
3316 rtkt = FFEINFO_kindtypeINTEGER1;
3317 switch (ffeinfo_basictype (ffebld_info (left)))
3318 {
3319 case FFEINFO_basictypeINTEGER:
3320 if ((ffeinfo_kindtype (ffebld_info (left))
3321 == FFEINFO_kindtypeINTEGER4)
3322 || (ffeinfo_kindtype (ffebld_info (right))
3323 == FFEINFO_kindtypeINTEGER4))
3324 {
3325 code = FFECOM_gfrtPOW_QQ;
270fc4e8 3326 ltkt = FFEINFO_kindtypeINTEGER4;
5ff904cd
JL
3327 rtkt = FFEINFO_kindtypeINTEGER4;
3328 }
3329 else
6a047254
CB
3330 {
3331 code = FFECOM_gfrtPOW_II;
3332 ltkt = FFEINFO_kindtypeINTEGER1;
3333 }
5ff904cd
JL
3334 break;
3335
3336 case FFEINFO_basictypeREAL:
3337 if (ffeinfo_kindtype (ffebld_info (left))
3338 == FFEINFO_kindtypeREAL1)
6a047254
CB
3339 {
3340 code = FFECOM_gfrtPOW_RI;
3341 ltkt = FFEINFO_kindtypeREAL1;
3342 }
5ff904cd 3343 else
6a047254
CB
3344 {
3345 code = FFECOM_gfrtPOW_DI;
3346 ltkt = FFEINFO_kindtypeREAL2;
3347 }
5ff904cd
JL
3348 break;
3349
3350 case FFEINFO_basictypeCOMPLEX:
3351 if (ffeinfo_kindtype (ffebld_info (left))
3352 == FFEINFO_kindtypeREAL1)
6a047254
CB
3353 {
3354 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */
3355 ltkt = FFEINFO_kindtypeREAL1;
3356 }
5ff904cd 3357 else
6a047254
CB
3358 {
3359 code = FFECOM_gfrtPOW_ZI; /* Overlapping result okay. */
3360 ltkt = FFEINFO_kindtypeREAL2;
3361 }
5ff904cd
JL
3362 break;
3363
3364 default:
3365 assert ("bad pow_*i" == NULL);
3366 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */
6a047254 3367 ltkt = FFEINFO_kindtypeREAL1;
5ff904cd
JL
3368 break;
3369 }
270fc4e8 3370 if (ffeinfo_kindtype (ffebld_info (left)) != ltkt)
5ff904cd 3371 left = ffeexpr_convert (left, NULL, NULL,
6a047254 3372 ffeinfo_basictype (ffebld_info (left)),
270fc4e8 3373 ltkt, 0,
5ff904cd
JL
3374 FFETARGET_charactersizeNONE,
3375 FFEEXPR_contextLET);
3376 if (ffeinfo_kindtype (ffebld_info (right)) != rtkt)
3377 right = ffeexpr_convert (right, NULL, NULL,
3378 FFEINFO_basictypeINTEGER,
3379 rtkt, 0,
3380 FFETARGET_charactersizeNONE,
3381 FFEEXPR_contextLET);
3382 break;
3383
3384 case FFEINFO_basictypeREAL:
3385 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3386 left = ffeexpr_convert (left, NULL, NULL, FFEINFO_basictypeREAL,
3387 FFEINFO_kindtypeREALDOUBLE, 0,
3388 FFETARGET_charactersizeNONE,
3389 FFEEXPR_contextLET);
3390 if (ffeinfo_kindtype (ffebld_info (right))
3391 == FFEINFO_kindtypeREAL1)
3392 right = ffeexpr_convert (right, NULL, NULL,
3393 FFEINFO_basictypeREAL,
3394 FFEINFO_kindtypeREALDOUBLE, 0,
3395 FFETARGET_charactersizeNONE,
3396 FFEEXPR_contextLET);
95eb4fd9
TM
3397 /* We used to call FFECOM_gfrtPOW_DD here,
3398 which passes arguments by reference. */
3399 code = FFECOM_gfrtL_POW;
3400 /* Pass arguments by value. */
3401 ref = FALSE;
5ff904cd
JL
3402 break;
3403
3404 case FFEINFO_basictypeCOMPLEX:
3405 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3406 left = ffeexpr_convert (left, NULL, NULL,
3407 FFEINFO_basictypeCOMPLEX,
3408 FFEINFO_kindtypeREALDOUBLE, 0,
3409 FFETARGET_charactersizeNONE,
3410 FFEEXPR_contextLET);
3411 if (ffeinfo_kindtype (ffebld_info (right))
3412 == FFEINFO_kindtypeREAL1)
3413 right = ffeexpr_convert (right, NULL, NULL,
3414 FFEINFO_basictypeCOMPLEX,
3415 FFEINFO_kindtypeREALDOUBLE, 0,
3416 FFETARGET_charactersizeNONE,
3417 FFEEXPR_contextLET);
3418 code = FFECOM_gfrtPOW_ZZ; /* Overlapping result okay. */
95eb4fd9 3419 ref = TRUE; /* Pass arguments by reference. */
5ff904cd
JL
3420 break;
3421
3422 default:
3423 assert ("bad pow_x*" == NULL);
3424 code = FFECOM_gfrtPOW_II;
3425 break;
3426 }
3427 return ffecom_call_binop_ (ffecom_gfrt_tree_ (code),
3428 ffecom_gfrt_kindtype (code),
3429 (ffe_is_f2c_library ()
3430 && ffecom_gfrt_complex_[code]),
3431 tree_type, left, right,
3432 dest_tree, dest, dest_used,
95eb4fd9 3433 NULL_TREE, FALSE, ref,
c7e4ee3a 3434 ffebld_nonter_hook (expr));
5ff904cd
JL
3435 }
3436
3437 case FFEBLD_opNOT:
5ff904cd
JL
3438 switch (bt)
3439 {
3440 case FFEINFO_basictypeLOGICAL:
83ffecd2 3441 item = ffecom_truth_value_invert (ffecom_expr (ffebld_left (expr)));
5ff904cd
JL
3442 return convert (tree_type, item);
3443
3444 case FFEINFO_basictypeINTEGER:
3445 return ffecom_1 (BIT_NOT_EXPR, tree_type,
3446 ffecom_expr (ffebld_left (expr)));
3447
3448 default:
3449 assert ("NOT bad basictype" == NULL);
3450 /* Fall through. */
3451 case FFEINFO_basictypeANY:
3452 return error_mark_node;
3453 }
3454 break;
3455
3456 case FFEBLD_opFUNCREF:
3457 assert (ffeinfo_basictype (ffebld_info (expr))
3458 != FFEINFO_basictypeCHARACTER);
3459 /* Fall through. */
3460 case FFEBLD_opSUBRREF:
5ff904cd
JL
3461 if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
3462 == FFEINFO_whereINTRINSIC)
3463 { /* Invocation of an intrinsic. */
3464 item = ffecom_expr_intrinsic_ (expr, dest_tree, dest,
3465 dest_used);
3466 return item;
3467 }
3468 s = ffebld_symter (ffebld_left (expr));
3469 dt = ffesymbol_hook (s).decl_tree;
3470 if (dt == NULL_TREE)
3471 {
3472 s = ffecom_sym_transform_ (s);
3473 dt = ffesymbol_hook (s).decl_tree;
3474 }
3475 if (dt == error_mark_node)
3476 return dt;
3477
3478 if (ffesymbol_hook (s).addr)
3479 item = dt;
3480 else
3481 item = ffecom_1_fn (dt);
3482
5ff904cd
JL
3483 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
3484 args = ffecom_list_expr (ffebld_right (expr));
3485 else
3486 args = ffecom_list_ptr_to_expr (ffebld_right (expr));
5ff904cd 3487
702edf1d
CB
3488 if (args == error_mark_node)
3489 return error_mark_node;
3490
5ff904cd
JL
3491 item = ffecom_call_ (item, kt,
3492 ffesymbol_is_f2c (s)
3493 && (bt == FFEINFO_basictypeCOMPLEX)
3494 && (ffesymbol_where (s)
3495 != FFEINFO_whereCONSTANT),
3496 tree_type,
3497 args,
3498 dest_tree, dest, dest_used,
c7e4ee3a
CB
3499 error_mark_node, FALSE,
3500 ffebld_nonter_hook (expr));
5ff904cd
JL
3501 TREE_SIDE_EFFECTS (item) = 1;
3502 return item;
3503
3504 case FFEBLD_opAND:
5ff904cd
JL
3505 switch (bt)
3506 {
3507 case FFEINFO_basictypeLOGICAL:
3508 item
3509 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3510 ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3511 ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3512 return convert (tree_type, item);
3513
3514 case FFEINFO_basictypeINTEGER:
3515 return ffecom_2 (BIT_AND_EXPR, tree_type,
3516 ffecom_expr (ffebld_left (expr)),
3517 ffecom_expr (ffebld_right (expr)));
3518
3519 default:
3520 assert ("AND bad basictype" == NULL);
3521 /* Fall through. */
3522 case FFEINFO_basictypeANY:
3523 return error_mark_node;
3524 }
3525 break;
3526
3527 case FFEBLD_opOR:
5ff904cd
JL
3528 switch (bt)
3529 {
3530 case FFEINFO_basictypeLOGICAL:
3531 item
3532 = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
3533 ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3534 ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3535 return convert (tree_type, item);
3536
3537 case FFEINFO_basictypeINTEGER:
3538 return ffecom_2 (BIT_IOR_EXPR, tree_type,
3539 ffecom_expr (ffebld_left (expr)),
3540 ffecom_expr (ffebld_right (expr)));
3541
3542 default:
3543 assert ("OR bad basictype" == NULL);
3544 /* Fall through. */
3545 case FFEINFO_basictypeANY:
3546 return error_mark_node;
3547 }
3548 break;
3549
3550 case FFEBLD_opXOR:
3551 case FFEBLD_opNEQV:
5ff904cd
JL
3552 switch (bt)
3553 {
3554 case FFEINFO_basictypeLOGICAL:
3555 item
3556 = ffecom_2 (NE_EXPR, integer_type_node,
3557 ffecom_expr (ffebld_left (expr)),
3558 ffecom_expr (ffebld_right (expr)));
3559 return convert (tree_type, ffecom_truth_value (item));
3560
3561 case FFEINFO_basictypeINTEGER:
3562 return ffecom_2 (BIT_XOR_EXPR, tree_type,
3563 ffecom_expr (ffebld_left (expr)),
3564 ffecom_expr (ffebld_right (expr)));
3565
3566 default:
3567 assert ("XOR/NEQV bad basictype" == NULL);
3568 /* Fall through. */
3569 case FFEINFO_basictypeANY:
3570 return error_mark_node;
3571 }
3572 break;
3573
3574 case FFEBLD_opEQV:
5ff904cd
JL
3575 switch (bt)
3576 {
3577 case FFEINFO_basictypeLOGICAL:
3578 item
3579 = ffecom_2 (EQ_EXPR, integer_type_node,
3580 ffecom_expr (ffebld_left (expr)),
3581 ffecom_expr (ffebld_right (expr)));
3582 return convert (tree_type, ffecom_truth_value (item));
3583
3584 case FFEINFO_basictypeINTEGER:
3585 return
3586 ffecom_1 (BIT_NOT_EXPR, tree_type,
3587 ffecom_2 (BIT_XOR_EXPR, tree_type,
3588 ffecom_expr (ffebld_left (expr)),
3589 ffecom_expr (ffebld_right (expr))));
3590
3591 default:
3592 assert ("EQV bad basictype" == NULL);
3593 /* Fall through. */
3594 case FFEINFO_basictypeANY:
3595 return error_mark_node;
3596 }
3597 break;
3598
3599 case FFEBLD_opCONVERT:
3600 if (ffebld_op (ffebld_left (expr)) == FFEBLD_opANY)
3601 return error_mark_node;
3602
5ff904cd
JL
3603 switch (bt)
3604 {
3605 case FFEINFO_basictypeLOGICAL:
3606 case FFEINFO_basictypeINTEGER:
3607 case FFEINFO_basictypeREAL:
3608 return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3609
3610 case FFEINFO_basictypeCOMPLEX:
3611 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3612 {
3613 case FFEINFO_basictypeINTEGER:
3614 case FFEINFO_basictypeLOGICAL:
3615 case FFEINFO_basictypeREAL:
3616 item = ffecom_expr (ffebld_left (expr));
3617 if (item == error_mark_node)
3618 return error_mark_node;
3619 /* convert() takes care of converting to the subtype first,
3620 at least in gcc-2.7.2. */
3621 item = convert (tree_type, item);
3622 return item;
3623
3624 case FFEINFO_basictypeCOMPLEX:
3625 return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3626
3627 default:
3628 assert ("CONVERT COMPLEX bad basictype" == NULL);
3629 /* Fall through. */
3630 case FFEINFO_basictypeANY:
3631 return error_mark_node;
3632 }
3633 break;
3634
3635 default:
3636 assert ("CONVERT bad basictype" == NULL);
3637 /* Fall through. */
3638 case FFEINFO_basictypeANY:
3639 return error_mark_node;
3640 }
3641 break;
3642
3643 case FFEBLD_opLT:
3644 code = LT_EXPR;
3645 goto relational; /* :::::::::::::::::::: */
3646
3647 case FFEBLD_opLE:
3648 code = LE_EXPR;
3649 goto relational; /* :::::::::::::::::::: */
3650
3651 case FFEBLD_opEQ:
3652 code = EQ_EXPR;
3653 goto relational; /* :::::::::::::::::::: */
3654
3655 case FFEBLD_opNE:
3656 code = NE_EXPR;
3657 goto relational; /* :::::::::::::::::::: */
3658
3659 case FFEBLD_opGT:
3660 code = GT_EXPR;
3661 goto relational; /* :::::::::::::::::::: */
3662
3663 case FFEBLD_opGE:
3664 code = GE_EXPR;
3665
3666 relational: /* :::::::::::::::::::: */
5ff904cd
JL
3667 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3668 {
3669 case FFEINFO_basictypeLOGICAL:
3670 case FFEINFO_basictypeINTEGER:
3671 case FFEINFO_basictypeREAL:
3672 item = ffecom_2 (code, integer_type_node,
3673 ffecom_expr (ffebld_left (expr)),
3674 ffecom_expr (ffebld_right (expr)));
3675 return convert (tree_type, item);
3676
3677 case FFEINFO_basictypeCOMPLEX:
3678 assert (code == EQ_EXPR || code == NE_EXPR);
3679 {
3680 tree real_type;
3681 tree arg1 = ffecom_expr (ffebld_left (expr));
3682 tree arg2 = ffecom_expr (ffebld_right (expr));
3683
3684 if (arg1 == error_mark_node || arg2 == error_mark_node)
3685 return error_mark_node;
3686
3687 arg1 = ffecom_save_tree (arg1);
3688 arg2 = ffecom_save_tree (arg2);
3689
3690 if (TREE_CODE (TREE_TYPE (arg1)) == COMPLEX_TYPE)
3691 {
3692 real_type = TREE_TYPE (TREE_TYPE (arg1));
3693 assert (real_type == TREE_TYPE (TREE_TYPE (arg2)));
3694 }
3695 else
3696 {
3697 real_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg1)));
3698 assert (real_type == TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg2))));
3699 }
3700
3701 item
3702 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3703 ffecom_2 (EQ_EXPR, integer_type_node,
3704 ffecom_1 (REALPART_EXPR, real_type, arg1),
3705 ffecom_1 (REALPART_EXPR, real_type, arg2)),
3706 ffecom_2 (EQ_EXPR, integer_type_node,
3707 ffecom_1 (IMAGPART_EXPR, real_type, arg1),
3708 ffecom_1 (IMAGPART_EXPR, real_type,
3709 arg2)));
3710 if (code == EQ_EXPR)
3711 item = ffecom_truth_value (item);
3712 else
3713 item = ffecom_truth_value_invert (item);
3714 return convert (tree_type, item);
3715 }
3716
3717 case FFEINFO_basictypeCHARACTER:
5ff904cd
JL
3718 {
3719 ffebld left = ffebld_left (expr);
3720 ffebld right = ffebld_right (expr);
3721 tree left_tree;
3722 tree right_tree;
3723 tree left_length;
3724 tree right_length;
3725
3726 /* f2c run-time functions do the implicit blank-padding for us,
3727 so we don't usually have to implement blank-padding ourselves.
3728 (The exception is when we pass an argument to a separately
3729 compiled statement function -- if we know the arg is not the
3730 same length as the dummy, we must truncate or extend it. If
3731 we "inline" statement functions, that necessity goes away as
3732 well.)
3733
3734 Strip off the CONVERT operators that blank-pad. (Truncation by
3735 CONVERT shouldn't happen here, but it can happen in
3736 assignments.) */
3737
3738 while (ffebld_op (left) == FFEBLD_opCONVERT)
3739 left = ffebld_left (left);
3740 while (ffebld_op (right) == FFEBLD_opCONVERT)
3741 right = ffebld_left (right);
3742
3743 left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
3744 right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
3745
3746 if (left_tree == error_mark_node || left_length == error_mark_node
3747 || right_tree == error_mark_node
3748 || right_length == error_mark_node)
c7e4ee3a 3749 return error_mark_node;
5ff904cd
JL
3750
3751 if ((ffebld_size_known (left) == 1)
3752 && (ffebld_size_known (right) == 1))
3753 {
3754 left_tree
3755 = ffecom_1 (INDIRECT_REF,
3756 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3757 left_tree);
3758 right_tree
3759 = ffecom_1 (INDIRECT_REF,
3760 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3761 right_tree);
3762
3763 item
3764 = ffecom_2 (code, integer_type_node,
3765 ffecom_2 (ARRAY_REF,
3766 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3767 left_tree,
3768 integer_one_node),
3769 ffecom_2 (ARRAY_REF,
3770 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3771 right_tree,
3772 integer_one_node));
3773 }
3774 else
3775 {
3776 item = build_tree_list (NULL_TREE, left_tree);
3777 TREE_CHAIN (item) = build_tree_list (NULL_TREE, right_tree);
3778 TREE_CHAIN (TREE_CHAIN (item)) = build_tree_list (NULL_TREE,
3779 left_length);
3780 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
3781 = build_tree_list (NULL_TREE, right_length);
c7e4ee3a 3782 item = ffecom_call_gfrt (FFECOM_gfrtCMP, item, NULL_TREE);
5ff904cd
JL
3783 item = ffecom_2 (code, integer_type_node,
3784 item,
3785 convert (TREE_TYPE (item),
3786 integer_zero_node));
3787 }
3788 item = convert (tree_type, item);
3789 }
3790
5ff904cd
JL
3791 return item;
3792
3793 default:
3794 assert ("relational bad basictype" == NULL);
3795 /* Fall through. */
3796 case FFEINFO_basictypeANY:
3797 return error_mark_node;
3798 }
3799 break;
3800
3801 case FFEBLD_opPERCENT_LOC:
5ff904cd
JL
3802 item = ffecom_arg_ptr_to_expr (ffebld_left (expr), &list);
3803 return convert (tree_type, item);
3804
3805 case FFEBLD_opITEM:
3806 case FFEBLD_opSTAR:
3807 case FFEBLD_opBOUNDS:
3808 case FFEBLD_opREPEAT:
3809 case FFEBLD_opLABTER:
3810 case FFEBLD_opLABTOK:
3811 case FFEBLD_opIMPDO:
3812 case FFEBLD_opCONCATENATE:
3813 case FFEBLD_opSUBSTR:
3814 default:
3815 assert ("bad op" == NULL);
3816 /* Fall through. */
3817 case FFEBLD_opANY:
3818 return error_mark_node;
3819 }
3820
3821#if 1
3822 assert ("didn't think anything got here anymore!!" == NULL);
3823#else
3824 switch (ffebld_arity (expr))
3825 {
3826 case 2:
3827 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3828 TREE_OPERAND (item, 1) = ffecom_expr (ffebld_right (expr));
3829 if (TREE_OPERAND (item, 0) == error_mark_node
3830 || TREE_OPERAND (item, 1) == error_mark_node)
3831 return error_mark_node;
3832 break;
3833
3834 case 1:
3835 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3836 if (TREE_OPERAND (item, 0) == error_mark_node)
3837 return error_mark_node;
3838 break;
3839
3840 default:
3841 break;
3842 }
3843
3844 return fold (item);
3845#endif
3846}
3847
3848#endif
3849/* Returns the tree that does the intrinsic invocation.
3850
3851 Note: this function applies only to intrinsics returning
3852 CHARACTER*1 or non-CHARACTER results, and to intrinsic
3853 subroutines. */
3854
3855#if FFECOM_targetCURRENT == FFECOM_targetGCC
3856static tree
3857ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
3858 ffebld dest, bool *dest_used)
3859{
3860 tree expr_tree;
3861 tree saved_expr1; /* For those who need it. */
3862 tree saved_expr2; /* For those who need it. */
3863 ffeinfoBasictype bt;
3864 ffeinfoKindtype kt;
3865 tree tree_type;
3866 tree arg1_type;
3867 tree real_type; /* REAL type corresponding to COMPLEX. */
3868 tree tempvar;
3869 ffebld list = ffebld_right (expr); /* List of (some) args. */
3870 ffebld arg1; /* For handy reference. */
3871 ffebld arg2;
3872 ffebld arg3;
3873 ffeintrinImp codegen_imp;
3874 ffecomGfrt gfrt;
3875
3876 assert (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER);
3877
3878 if (dest_used != NULL)
3879 *dest_used = FALSE;
3880
3881 bt = ffeinfo_basictype (ffebld_info (expr));
3882 kt = ffeinfo_kindtype (ffebld_info (expr));
3883 tree_type = ffecom_tree_type[bt][kt];
3884
3885 if (list != NULL)
3886 {
3887 arg1 = ffebld_head (list);
3888 if (arg1 != NULL && ffebld_op (arg1) == FFEBLD_opANY)
3889 return error_mark_node;
3890 if ((list = ffebld_trail (list)) != NULL)
3891 {
3892 arg2 = ffebld_head (list);
3893 if (arg2 != NULL && ffebld_op (arg2) == FFEBLD_opANY)
3894 return error_mark_node;
3895 if ((list = ffebld_trail (list)) != NULL)
3896 {
3897 arg3 = ffebld_head (list);
3898 if (arg3 != NULL && ffebld_op (arg3) == FFEBLD_opANY)
3899 return error_mark_node;
3900 }
3901 else
3902 arg3 = NULL;
3903 }
3904 else
3905 arg2 = arg3 = NULL;
3906 }
3907 else
3908 arg1 = arg2 = arg3 = NULL;
3909
3910 /* <list> ends up at the opITEM of the 3rd arg, or NULL if there are < 3
3911 args. This is used by the MAX/MIN expansions. */
3912
3913 if (arg1 != NULL)
3914 arg1_type = ffecom_tree_type
3915 [ffeinfo_basictype (ffebld_info (arg1))]
3916 [ffeinfo_kindtype (ffebld_info (arg1))];
3917 else
3918 arg1_type = NULL_TREE; /* Really not needed, but might catch bugs
3919 here. */
3920
3921 /* There are several ways for each of the cases in the following switch
3922 statements to exit (from simplest to use to most complicated):
3923
3924 break; (when expr_tree == NULL)
3925
3926 A standard call is made to the specific intrinsic just as if it had been
3927 passed in as a dummy procedure and called as any old procedure. This
3928 method can produce slower code but in some cases it's the easiest way for
3929 now. However, if a (presumably faster) direct call is available,
3930 that is used, so this is the easiest way in many more cases now.
3931
3932 gfrt = FFECOM_gfrtWHATEVER;
3933 break;
3934
3935 gfrt contains the gfrt index of a library function to call, passing the
3936 argument(s) by value rather than by reference. Used when a more
3937 careful choice of library function is needed than that provided
3938 by the vanilla `break;'.
3939
3940 return expr_tree;
3941
3942 The expr_tree has been completely set up and is ready to be returned
3943 as is. No further actions are taken. Use this when the tree is not
3944 in the simple form for one of the arity_n labels. */
3945
3946 /* For info on how the switch statement cases were written, see the files
3947 enclosed in comments below the switch statement. */
3948
3949 codegen_imp = ffebld_symter_implementation (ffebld_left (expr));
3950 gfrt = ffeintrin_gfrt_direct (codegen_imp);
3951 if (gfrt == FFECOM_gfrt)
3952 gfrt = ffeintrin_gfrt_indirect (codegen_imp);
3953
3954 switch (codegen_imp)
3955 {
3956 case FFEINTRIN_impABS:
3957 case FFEINTRIN_impCABS:
3958 case FFEINTRIN_impCDABS:
3959 case FFEINTRIN_impDABS:
3960 case FFEINTRIN_impIABS:
3961 if (ffeinfo_basictype (ffebld_info (arg1))
3962 == FFEINFO_basictypeCOMPLEX)
3963 {
3964 if (kt == FFEINFO_kindtypeREAL1)
3965 gfrt = FFECOM_gfrtCABS;
3966 else if (kt == FFEINFO_kindtypeREAL2)
3967 gfrt = FFECOM_gfrtCDABS;
3968 break;
3969 }
3970 return ffecom_1 (ABS_EXPR, tree_type,
3971 convert (tree_type, ffecom_expr (arg1)));
3972
3973 case FFEINTRIN_impACOS:
3974 case FFEINTRIN_impDACOS:
3975 break;
3976
3977 case FFEINTRIN_impAIMAG:
3978 case FFEINTRIN_impDIMAG:
3979 case FFEINTRIN_impIMAGPART:
3980 if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
3981 arg1_type = TREE_TYPE (arg1_type);
3982 else
3983 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
3984
3985 return
3986 convert (tree_type,
3987 ffecom_1 (IMAGPART_EXPR, arg1_type,
3988 ffecom_expr (arg1)));
3989
3990 case FFEINTRIN_impAINT:
3991 case FFEINTRIN_impDINT:
c7e4ee3a
CB
3992#if 0
3993 /* ~~Someday implement FIX_TRUNC_EXPR yielding same type as arg. */
5ff904cd
JL
3994 return ffecom_1 (FIX_TRUNC_EXPR, tree_type, ffecom_expr (arg1));
3995#else /* in the meantime, must use floor to avoid range problems with ints */
3996 /* r__1 = r1 >= 0 ? floor(r1) : -floor(-r1); */
3997 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
3998 return
3999 convert (tree_type,
4000 ffecom_3 (COND_EXPR, double_type_node,
4001 ffecom_truth_value
4002 (ffecom_2 (GE_EXPR, integer_type_node,
4003 saved_expr1,
4004 convert (arg1_type,
4005 ffecom_float_zero_))),
4006 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4007 build_tree_list (NULL_TREE,
4008 convert (double_type_node,
c7e4ee3a
CB
4009 saved_expr1)),
4010 NULL_TREE),
5ff904cd
JL
4011 ffecom_1 (NEGATE_EXPR, double_type_node,
4012 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4013 build_tree_list (NULL_TREE,
4014 convert (double_type_node,
4015 ffecom_1 (NEGATE_EXPR,
4016 arg1_type,
c7e4ee3a
CB
4017 saved_expr1))),
4018 NULL_TREE)
5ff904cd
JL
4019 ))
4020 );
4021#endif
4022
4023 case FFEINTRIN_impANINT:
4024 case FFEINTRIN_impDNINT:
4025#if 0 /* This way of doing it won't handle real
4026 numbers of large magnitudes. */
4027 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4028 expr_tree = convert (tree_type,
4029 convert (integer_type_node,
4030 ffecom_3 (COND_EXPR, tree_type,
4031 ffecom_truth_value
4032 (ffecom_2 (GE_EXPR,
4033 integer_type_node,
4034 saved_expr1,
4035 ffecom_float_zero_)),
4036 ffecom_2 (PLUS_EXPR,
4037 tree_type,
4038 saved_expr1,
4039 ffecom_float_half_),
4040 ffecom_2 (MINUS_EXPR,
4041 tree_type,
4042 saved_expr1,
4043 ffecom_float_half_))));
4044 return expr_tree;
4045#else /* So we instead call floor. */
4046 /* r__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1) */
4047 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4048 return
4049 convert (tree_type,
4050 ffecom_3 (COND_EXPR, double_type_node,
4051 ffecom_truth_value
4052 (ffecom_2 (GE_EXPR, integer_type_node,
4053 saved_expr1,
4054 convert (arg1_type,
4055 ffecom_float_zero_))),
4056 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4057 build_tree_list (NULL_TREE,
4058 convert (double_type_node,
4059 ffecom_2 (PLUS_EXPR,
4060 arg1_type,
4061 saved_expr1,
4062 convert (arg1_type,
c7e4ee3a
CB
4063 ffecom_float_half_)))),
4064 NULL_TREE),
5ff904cd
JL
4065 ffecom_1 (NEGATE_EXPR, double_type_node,
4066 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4067 build_tree_list (NULL_TREE,
4068 convert (double_type_node,
4069 ffecom_2 (MINUS_EXPR,
4070 arg1_type,
4071 convert (arg1_type,
4072 ffecom_float_half_),
c7e4ee3a
CB
4073 saved_expr1))),
4074 NULL_TREE))
5ff904cd
JL
4075 )
4076 );
4077#endif
4078
4079 case FFEINTRIN_impASIN:
4080 case FFEINTRIN_impDASIN:
4081 case FFEINTRIN_impATAN:
4082 case FFEINTRIN_impDATAN:
4083 case FFEINTRIN_impATAN2:
4084 case FFEINTRIN_impDATAN2:
4085 break;
4086
4087 case FFEINTRIN_impCHAR:
4088 case FFEINTRIN_impACHAR:
c7e4ee3a
CB
4089#ifdef HOHO
4090 tempvar = ffecom_make_tempvar (char_type_node, 1, -1);
4091#else
4092 tempvar = ffebld_nonter_hook (expr);
4093 assert (tempvar);
4094#endif
5ff904cd
JL
4095 {
4096 tree tmv = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (tempvar)));
4097
4098 expr_tree = ffecom_modify (tmv,
4099 ffecom_2 (ARRAY_REF, tmv, tempvar,
4100 integer_one_node),
4101 convert (tmv, ffecom_expr (arg1)));
4102 }
4103 expr_tree = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar),
4104 expr_tree,
4105 tempvar);
4106 expr_tree = ffecom_1 (ADDR_EXPR,
4107 build_pointer_type (TREE_TYPE (expr_tree)),
4108 expr_tree);
4109 return expr_tree;
4110
4111 case FFEINTRIN_impCMPLX:
4112 case FFEINTRIN_impDCMPLX:
4113 if (arg2 == NULL)
4114 return
4115 convert (tree_type, ffecom_expr (arg1));
4116
4117 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
4118 return
4119 ffecom_2 (COMPLEX_EXPR, tree_type,
4120 convert (real_type, ffecom_expr (arg1)),
4121 convert (real_type,
4122 ffecom_expr (arg2)));
4123
4124 case FFEINTRIN_impCOMPLEX:
4125 return
4126 ffecom_2 (COMPLEX_EXPR, tree_type,
4127 ffecom_expr (arg1),
4128 ffecom_expr (arg2));
4129
4130 case FFEINTRIN_impCONJG:
4131 case FFEINTRIN_impDCONJG:
4132 {
4133 tree arg1_tree;
4134
4135 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
4136 arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4137 return
4138 ffecom_2 (COMPLEX_EXPR, tree_type,
4139 ffecom_1 (REALPART_EXPR, real_type, arg1_tree),
4140 ffecom_1 (NEGATE_EXPR, real_type,
4141 ffecom_1 (IMAGPART_EXPR, real_type, arg1_tree)));
4142 }
4143
4144 case FFEINTRIN_impCOS:
4145 case FFEINTRIN_impCCOS:
4146 case FFEINTRIN_impCDCOS:
4147 case FFEINTRIN_impDCOS:
4148 if (bt == FFEINFO_basictypeCOMPLEX)
4149 {
4150 if (kt == FFEINFO_kindtypeREAL1)
4151 gfrt = FFECOM_gfrtCCOS; /* Overlapping result okay. */
4152 else if (kt == FFEINFO_kindtypeREAL2)
4153 gfrt = FFECOM_gfrtCDCOS; /* Overlapping result okay. */
4154 }
4155 break;
4156
4157 case FFEINTRIN_impCOSH:
4158 case FFEINTRIN_impDCOSH:
4159 break;
4160
4161 case FFEINTRIN_impDBLE:
4162 case FFEINTRIN_impDFLOAT:
4163 case FFEINTRIN_impDREAL:
4164 case FFEINTRIN_impFLOAT:
4165 case FFEINTRIN_impIDINT:
4166 case FFEINTRIN_impIFIX:
4167 case FFEINTRIN_impINT2:
4168 case FFEINTRIN_impINT8:
4169 case FFEINTRIN_impINT:
4170 case FFEINTRIN_impLONG:
4171 case FFEINTRIN_impREAL:
4172 case FFEINTRIN_impSHORT:
4173 case FFEINTRIN_impSNGL:
4174 return convert (tree_type, ffecom_expr (arg1));
4175
4176 case FFEINTRIN_impDIM:
4177 case FFEINTRIN_impDDIM:
4178 case FFEINTRIN_impIDIM:
4179 saved_expr1 = ffecom_save_tree (convert (tree_type,
4180 ffecom_expr (arg1)));
4181 saved_expr2 = ffecom_save_tree (convert (tree_type,
4182 ffecom_expr (arg2)));
4183 return
4184 ffecom_3 (COND_EXPR, tree_type,
4185 ffecom_truth_value
4186 (ffecom_2 (GT_EXPR, integer_type_node,
4187 saved_expr1,
4188 saved_expr2)),
4189 ffecom_2 (MINUS_EXPR, tree_type,
4190 saved_expr1,
4191 saved_expr2),
4192 convert (tree_type, ffecom_float_zero_));
4193
4194 case FFEINTRIN_impDPROD:
4195 return
4196 ffecom_2 (MULT_EXPR, tree_type,
4197 convert (tree_type, ffecom_expr (arg1)),
4198 convert (tree_type, ffecom_expr (arg2)));
4199
4200 case FFEINTRIN_impEXP:
4201 case FFEINTRIN_impCDEXP:
4202 case FFEINTRIN_impCEXP:
4203 case FFEINTRIN_impDEXP:
4204 if (bt == FFEINFO_basictypeCOMPLEX)
4205 {
4206 if (kt == FFEINFO_kindtypeREAL1)
4207 gfrt = FFECOM_gfrtCEXP; /* Overlapping result okay. */
4208 else if (kt == FFEINFO_kindtypeREAL2)
4209 gfrt = FFECOM_gfrtCDEXP; /* Overlapping result okay. */
4210 }
4211 break;
4212
4213 case FFEINTRIN_impICHAR:
4214 case FFEINTRIN_impIACHAR:
4215#if 0 /* The simple approach. */
4216 ffecom_char_args_ (&expr_tree, &saved_expr1 /* Ignored */ , arg1);
4217 expr_tree
4218 = ffecom_1 (INDIRECT_REF,
4219 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
4220 expr_tree);
4221 expr_tree
4222 = ffecom_2 (ARRAY_REF,
4223 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
4224 expr_tree,
4225 integer_one_node);
4226 return convert (tree_type, expr_tree);
4227#else /* The more interesting (and more optimal) approach. */
4228 expr_tree = ffecom_intrinsic_ichar_ (tree_type, arg1, &saved_expr1);
4229 expr_tree = ffecom_3 (COND_EXPR, tree_type,
4230 saved_expr1,
4231 expr_tree,
4232 convert (tree_type, integer_zero_node));
4233 return expr_tree;
4234#endif
4235
4236 case FFEINTRIN_impINDEX:
4237 break;
4238
4239 case FFEINTRIN_impLEN:
4240#if 0
4241 break; /* The simple approach. */
4242#else
4243 return ffecom_intrinsic_len_ (arg1); /* The more optimal approach. */
4244#endif
4245
4246 case FFEINTRIN_impLGE:
4247 case FFEINTRIN_impLGT:
4248 case FFEINTRIN_impLLE:
4249 case FFEINTRIN_impLLT:
4250 break;
4251
4252 case FFEINTRIN_impLOG:
4253 case FFEINTRIN_impALOG:
4254 case FFEINTRIN_impCDLOG:
4255 case FFEINTRIN_impCLOG:
4256 case FFEINTRIN_impDLOG:
4257 if (bt == FFEINFO_basictypeCOMPLEX)
4258 {
4259 if (kt == FFEINFO_kindtypeREAL1)
4260 gfrt = FFECOM_gfrtCLOG; /* Overlapping result okay. */
4261 else if (kt == FFEINFO_kindtypeREAL2)
4262 gfrt = FFECOM_gfrtCDLOG; /* Overlapping result okay. */
4263 }
4264 break;
4265
4266 case FFEINTRIN_impLOG10:
4267 case FFEINTRIN_impALOG10:
4268 case FFEINTRIN_impDLOG10:
4269 if (gfrt != FFECOM_gfrt)
4270 break; /* Already picked one, stick with it. */
4271
4272 if (kt == FFEINFO_kindtypeREAL1)
95eb4fd9
TM
4273 /* We used to call FFECOM_gfrtALOG10 here. */
4274 gfrt = FFECOM_gfrtL_LOG10;
5ff904cd 4275 else if (kt == FFEINFO_kindtypeREAL2)
95eb4fd9
TM
4276 /* We used to call FFECOM_gfrtDLOG10 here. */
4277 gfrt = FFECOM_gfrtL_LOG10;
5ff904cd
JL
4278 break;
4279
4280 case FFEINTRIN_impMAX:
4281 case FFEINTRIN_impAMAX0:
4282 case FFEINTRIN_impAMAX1:
4283 case FFEINTRIN_impDMAX1:
4284 case FFEINTRIN_impMAX0:
4285 case FFEINTRIN_impMAX1:
4286 if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4287 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4288 else
4289 arg1_type = tree_type;
4290 expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4291 convert (arg1_type, ffecom_expr (arg1)),
4292 convert (arg1_type, ffecom_expr (arg2)));
4293 for (; list != NULL; list = ffebld_trail (list))
4294 {
4295 if ((ffebld_head (list) == NULL)
4296 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4297 continue;
4298 expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4299 expr_tree,
4300 convert (arg1_type,
4301 ffecom_expr (ffebld_head (list))));
4302 }
4303 return convert (tree_type, expr_tree);
4304
4305 case FFEINTRIN_impMIN:
4306 case FFEINTRIN_impAMIN0:
4307 case FFEINTRIN_impAMIN1:
4308 case FFEINTRIN_impDMIN1:
4309 case FFEINTRIN_impMIN0:
4310 case FFEINTRIN_impMIN1:
4311 if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4312 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4313 else
4314 arg1_type = tree_type;
4315 expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4316 convert (arg1_type, ffecom_expr (arg1)),
4317 convert (arg1_type, ffecom_expr (arg2)));
4318 for (; list != NULL; list = ffebld_trail (list))
4319 {
4320 if ((ffebld_head (list) == NULL)
4321 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4322 continue;
4323 expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4324 expr_tree,
4325 convert (arg1_type,
4326 ffecom_expr (ffebld_head (list))));
4327 }
4328 return convert (tree_type, expr_tree);
4329
4330 case FFEINTRIN_impMOD:
4331 case FFEINTRIN_impAMOD:
4332 case FFEINTRIN_impDMOD:
4333 if (bt != FFEINFO_basictypeREAL)
4334 return ffecom_2 (TRUNC_MOD_EXPR, tree_type,
4335 convert (tree_type, ffecom_expr (arg1)),
4336 convert (tree_type, ffecom_expr (arg2)));
4337
4338 if (kt == FFEINFO_kindtypeREAL1)
95eb4fd9
TM
4339 /* We used to call FFECOM_gfrtAMOD here. */
4340 gfrt = FFECOM_gfrtL_FMOD;
5ff904cd 4341 else if (kt == FFEINFO_kindtypeREAL2)
95eb4fd9
TM
4342 /* We used to call FFECOM_gfrtDMOD here. */
4343 gfrt = FFECOM_gfrtL_FMOD;
5ff904cd
JL
4344 break;
4345
4346 case FFEINTRIN_impNINT:
4347 case FFEINTRIN_impIDNINT:
c7e4ee3a
CB
4348#if 0
4349 /* ~~Ideally FIX_ROUND_EXPR would be implemented, but it ain't yet. */
5ff904cd
JL
4350 return ffecom_1 (FIX_ROUND_EXPR, tree_type, ffecom_expr (arg1));
4351#else
4352 /* i__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1); */
4353 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4354 return
4355 convert (ffecom_integer_type_node,
4356 ffecom_3 (COND_EXPR, arg1_type,
4357 ffecom_truth_value
4358 (ffecom_2 (GE_EXPR, integer_type_node,
4359 saved_expr1,
4360 convert (arg1_type,
4361 ffecom_float_zero_))),
4362 ffecom_2 (PLUS_EXPR, arg1_type,
4363 saved_expr1,
4364 convert (arg1_type,
4365 ffecom_float_half_)),
4366 ffecom_2 (MINUS_EXPR, arg1_type,
4367 saved_expr1,
4368 convert (arg1_type,
4369 ffecom_float_half_))));
4370#endif
4371
4372 case FFEINTRIN_impSIGN:
4373 case FFEINTRIN_impDSIGN:
4374 case FFEINTRIN_impISIGN:
4375 {
4376 tree arg2_tree = ffecom_expr (arg2);
4377
4378 saved_expr1
4379 = ffecom_save_tree
4380 (ffecom_1 (ABS_EXPR, tree_type,
4381 convert (tree_type,
4382 ffecom_expr (arg1))));
4383 expr_tree
4384 = ffecom_3 (COND_EXPR, tree_type,
4385 ffecom_truth_value
4386 (ffecom_2 (GE_EXPR, integer_type_node,
4387 arg2_tree,
4388 convert (TREE_TYPE (arg2_tree),
4389 integer_zero_node))),
4390 saved_expr1,
4391 ffecom_1 (NEGATE_EXPR, tree_type, saved_expr1));
4392 /* Make sure SAVE_EXPRs get referenced early enough. */
4393 expr_tree
4394 = ffecom_2 (COMPOUND_EXPR, tree_type,
4395 convert (void_type_node, saved_expr1),
4396 expr_tree);
4397 }
4398 return expr_tree;
4399
4400 case FFEINTRIN_impSIN:
4401 case FFEINTRIN_impCDSIN:
4402 case FFEINTRIN_impCSIN:
4403 case FFEINTRIN_impDSIN:
4404 if (bt == FFEINFO_basictypeCOMPLEX)
4405 {
4406 if (kt == FFEINFO_kindtypeREAL1)
4407 gfrt = FFECOM_gfrtCSIN; /* Overlapping result okay. */
4408 else if (kt == FFEINFO_kindtypeREAL2)
4409 gfrt = FFECOM_gfrtCDSIN; /* Overlapping result okay. */
4410 }
4411 break;
4412
4413 case FFEINTRIN_impSINH:
4414 case FFEINTRIN_impDSINH:
4415 break;
4416
4417 case FFEINTRIN_impSQRT:
4418 case FFEINTRIN_impCDSQRT:
4419 case FFEINTRIN_impCSQRT:
4420 case FFEINTRIN_impDSQRT:
4421 if (bt == FFEINFO_basictypeCOMPLEX)
4422 {
4423 if (kt == FFEINFO_kindtypeREAL1)
4424 gfrt = FFECOM_gfrtCSQRT; /* Overlapping result okay. */
4425 else if (kt == FFEINFO_kindtypeREAL2)
4426 gfrt = FFECOM_gfrtCDSQRT; /* Overlapping result okay. */
4427 }
4428 break;
4429
4430 case FFEINTRIN_impTAN:
4431 case FFEINTRIN_impDTAN:
4432 case FFEINTRIN_impTANH:
4433 case FFEINTRIN_impDTANH:
4434 break;
4435
4436 case FFEINTRIN_impREALPART:
4437 if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
4438 arg1_type = TREE_TYPE (arg1_type);
4439 else
4440 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
4441
4442 return
4443 convert (tree_type,
4444 ffecom_1 (REALPART_EXPR, arg1_type,
4445 ffecom_expr (arg1)));
4446
4447 case FFEINTRIN_impIAND:
4448 case FFEINTRIN_impAND:
4449 return ffecom_2 (BIT_AND_EXPR, tree_type,
4450 convert (tree_type,
4451 ffecom_expr (arg1)),
4452 convert (tree_type,
4453 ffecom_expr (arg2)));
4454
4455 case FFEINTRIN_impIOR:
4456 case FFEINTRIN_impOR:
4457 return ffecom_2 (BIT_IOR_EXPR, tree_type,
4458 convert (tree_type,
4459 ffecom_expr (arg1)),
4460 convert (tree_type,
4461 ffecom_expr (arg2)));
4462
4463 case FFEINTRIN_impIEOR:
4464 case FFEINTRIN_impXOR:
4465 return ffecom_2 (BIT_XOR_EXPR, tree_type,
4466 convert (tree_type,
4467 ffecom_expr (arg1)),
4468 convert (tree_type,
4469 ffecom_expr (arg2)));
4470
4471 case FFEINTRIN_impLSHIFT:
4472 return ffecom_2 (LSHIFT_EXPR, tree_type,
4473 ffecom_expr (arg1),
4474 convert (integer_type_node,
4475 ffecom_expr (arg2)));
4476
4477 case FFEINTRIN_impRSHIFT:
4478 return ffecom_2 (RSHIFT_EXPR, tree_type,
4479 ffecom_expr (arg1),
4480 convert (integer_type_node,
4481 ffecom_expr (arg2)));
4482
4483 case FFEINTRIN_impNOT:
4484 return ffecom_1 (BIT_NOT_EXPR, tree_type, ffecom_expr (arg1));
4485
4486 case FFEINTRIN_impBIT_SIZE:
4487 return convert (tree_type, TYPE_SIZE (arg1_type));
4488
4489 case FFEINTRIN_impBTEST:
4490 {
d6edb99e
ZW
4491 ffetargetLogical1 target_true;
4492 ffetargetLogical1 target_false;
5ff904cd
JL
4493 tree true_tree;
4494 tree false_tree;
4495
d6edb99e
ZW
4496 ffetarget_logical1 (&target_true, TRUE);
4497 ffetarget_logical1 (&target_false, FALSE);
4498 if (target_true == 1)
5ff904cd
JL
4499 true_tree = convert (tree_type, integer_one_node);
4500 else
d6edb99e
ZW
4501 true_tree = convert (tree_type, build_int_2 (target_true, 0));
4502 if (target_false == 0)
5ff904cd
JL
4503 false_tree = convert (tree_type, integer_zero_node);
4504 else
d6edb99e 4505 false_tree = convert (tree_type, build_int_2 (target_false, 0));
5ff904cd
JL
4506
4507 return
4508 ffecom_3 (COND_EXPR, tree_type,
4509 ffecom_truth_value
4510 (ffecom_2 (EQ_EXPR, integer_type_node,
4511 ffecom_2 (BIT_AND_EXPR, arg1_type,
4512 ffecom_expr (arg1),
4513 ffecom_2 (LSHIFT_EXPR, arg1_type,
4514 convert (arg1_type,
4515 integer_one_node),
4516 convert (integer_type_node,
4517 ffecom_expr (arg2)))),
4518 convert (arg1_type,
4519 integer_zero_node))),
4520 false_tree,
4521 true_tree);
4522 }
4523
4524 case FFEINTRIN_impIBCLR:
4525 return
4526 ffecom_2 (BIT_AND_EXPR, tree_type,
4527 ffecom_expr (arg1),
4528 ffecom_1 (BIT_NOT_EXPR, tree_type,
4529 ffecom_2 (LSHIFT_EXPR, tree_type,
4530 convert (tree_type,
4531 integer_one_node),
4532 convert (integer_type_node,
4533 ffecom_expr (arg2)))));
4534
4535 case FFEINTRIN_impIBITS:
4536 {
4537 tree arg3_tree = ffecom_save_tree (convert (integer_type_node,
4538 ffecom_expr (arg3)));
4539 tree uns_type
4540 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4541
4542 expr_tree
4543 = ffecom_2 (BIT_AND_EXPR, tree_type,
4544 ffecom_2 (RSHIFT_EXPR, tree_type,
4545 ffecom_expr (arg1),
4546 convert (integer_type_node,
4547 ffecom_expr (arg2))),
4548 convert (tree_type,
4549 ffecom_2 (RSHIFT_EXPR, uns_type,
4550 ffecom_1 (BIT_NOT_EXPR,
4551 uns_type,
4552 convert (uns_type,
4553 integer_zero_node)),
4554 ffecom_2 (MINUS_EXPR,
4555 integer_type_node,
4556 TYPE_SIZE (uns_type),
4557 arg3_tree))));
eec9ac3d 4558 /* Fix up, because the RSHIFT_EXPR above can't shift over TYPE_SIZE. */
5ff904cd
JL
4559 expr_tree
4560 = ffecom_3 (COND_EXPR, tree_type,
4561 ffecom_truth_value
4562 (ffecom_2 (NE_EXPR, integer_type_node,
4563 arg3_tree,
4564 integer_zero_node)),
4565 expr_tree,
4566 convert (tree_type, integer_zero_node));
5ff904cd
JL
4567 }
4568 return expr_tree;
4569
4570 case FFEINTRIN_impIBSET:
4571 return
4572 ffecom_2 (BIT_IOR_EXPR, tree_type,
4573 ffecom_expr (arg1),
4574 ffecom_2 (LSHIFT_EXPR, tree_type,
4575 convert (tree_type, integer_one_node),
4576 convert (integer_type_node,
4577 ffecom_expr (arg2))));
4578
4579 case FFEINTRIN_impISHFT:
4580 {
4581 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4582 tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4583 ffecom_expr (arg2)));
4584 tree uns_type
4585 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4586
4587 expr_tree
4588 = ffecom_3 (COND_EXPR, tree_type,
4589 ffecom_truth_value
4590 (ffecom_2 (GE_EXPR, integer_type_node,
4591 arg2_tree,
4592 integer_zero_node)),
4593 ffecom_2 (LSHIFT_EXPR, tree_type,
4594 arg1_tree,
4595 arg2_tree),
4596 convert (tree_type,
4597 ffecom_2 (RSHIFT_EXPR, uns_type,
4598 convert (uns_type, arg1_tree),
4599 ffecom_1 (NEGATE_EXPR,
4600 integer_type_node,
4601 arg2_tree))));
eec9ac3d 4602 /* Fix up, because {L|R}SHIFT_EXPR don't go over TYPE_SIZE bounds. */
5ff904cd
JL
4603 expr_tree
4604 = ffecom_3 (COND_EXPR, tree_type,
4605 ffecom_truth_value
eec9ac3d 4606 (ffecom_2 (NE_EXPR, integer_type_node,
7d46d516
TM
4607 ffecom_1 (ABS_EXPR,
4608 integer_type_node,
4609 arg2_tree),
5ff904cd
JL
4610 TYPE_SIZE (uns_type))),
4611 expr_tree,
4612 convert (tree_type, integer_zero_node));
5ff904cd
JL
4613 /* Make sure SAVE_EXPRs get referenced early enough. */
4614 expr_tree
4615 = ffecom_2 (COMPOUND_EXPR, tree_type,
4616 convert (void_type_node, arg1_tree),
4617 ffecom_2 (COMPOUND_EXPR, tree_type,
4618 convert (void_type_node, arg2_tree),
4619 expr_tree));
4620 }
4621 return expr_tree;
4622
4623 case FFEINTRIN_impISHFTC:
4624 {
4625 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4626 tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4627 ffecom_expr (arg2)));
4628 tree arg3_tree = (arg3 == NULL) ? TYPE_SIZE (tree_type)
4629 : ffecom_save_tree (convert (integer_type_node, ffecom_expr (arg3)));
4630 tree shift_neg;
4631 tree shift_pos;
4632 tree mask_arg1;
4633 tree masked_arg1;
4634 tree uns_type
4635 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4636
4637 mask_arg1
4638 = ffecom_2 (LSHIFT_EXPR, tree_type,
4639 ffecom_1 (BIT_NOT_EXPR, tree_type,
4640 convert (tree_type, integer_zero_node)),
4641 arg3_tree);
eec9ac3d 4642 /* Fix up, because LSHIFT_EXPR above can't shift over TYPE_SIZE. */
5ff904cd
JL
4643 mask_arg1
4644 = ffecom_3 (COND_EXPR, tree_type,
4645 ffecom_truth_value
4646 (ffecom_2 (NE_EXPR, integer_type_node,
4647 arg3_tree,
4648 TYPE_SIZE (uns_type))),
4649 mask_arg1,
4650 convert (tree_type, integer_zero_node));
5ff904cd
JL
4651 mask_arg1 = ffecom_save_tree (mask_arg1);
4652 masked_arg1
4653 = ffecom_2 (BIT_AND_EXPR, tree_type,
4654 arg1_tree,
4655 ffecom_1 (BIT_NOT_EXPR, tree_type,
4656 mask_arg1));
4657 masked_arg1 = ffecom_save_tree (masked_arg1);
4658 shift_neg
4659 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4660 convert (tree_type,
4661 ffecom_2 (RSHIFT_EXPR, uns_type,
4662 convert (uns_type, masked_arg1),
4663 ffecom_1 (NEGATE_EXPR,
4664 integer_type_node,
4665 arg2_tree))),
4666 ffecom_2 (LSHIFT_EXPR, tree_type,
4667 arg1_tree,
4668 ffecom_2 (PLUS_EXPR, integer_type_node,
4669 arg2_tree,
4670 arg3_tree)));
4671 shift_pos
4672 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4673 ffecom_2 (LSHIFT_EXPR, tree_type,
4674 arg1_tree,
4675 arg2_tree),
4676 convert (tree_type,
4677 ffecom_2 (RSHIFT_EXPR, uns_type,
4678 convert (uns_type, masked_arg1),
4679 ffecom_2 (MINUS_EXPR,
4680 integer_type_node,
4681 arg3_tree,
4682 arg2_tree))));
4683 expr_tree
4684 = ffecom_3 (COND_EXPR, tree_type,
4685 ffecom_truth_value
4686 (ffecom_2 (LT_EXPR, integer_type_node,
4687 arg2_tree,
4688 integer_zero_node)),
4689 shift_neg,
4690 shift_pos);
4691 expr_tree
4692 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4693 ffecom_2 (BIT_AND_EXPR, tree_type,
4694 mask_arg1,
4695 arg1_tree),
4696 ffecom_2 (BIT_AND_EXPR, tree_type,
4697 ffecom_1 (BIT_NOT_EXPR, tree_type,
4698 mask_arg1),
4699 expr_tree));
4700 expr_tree
4701 = ffecom_3 (COND_EXPR, tree_type,
4702 ffecom_truth_value
4703 (ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
4704 ffecom_2 (EQ_EXPR, integer_type_node,
4705 ffecom_1 (ABS_EXPR,
4706 integer_type_node,
4707 arg2_tree),
4708 arg3_tree),
4709 ffecom_2 (EQ_EXPR, integer_type_node,
4710 arg2_tree,
4711 integer_zero_node))),
4712 arg1_tree,
4713 expr_tree);
4714 /* Make sure SAVE_EXPRs get referenced early enough. */
4715 expr_tree
4716 = ffecom_2 (COMPOUND_EXPR, tree_type,
4717 convert (void_type_node, arg1_tree),
4718 ffecom_2 (COMPOUND_EXPR, tree_type,
4719 convert (void_type_node, arg2_tree),
4720 ffecom_2 (COMPOUND_EXPR, tree_type,
4721 convert (void_type_node,
4722 mask_arg1),
4723 ffecom_2 (COMPOUND_EXPR, tree_type,
4724 convert (void_type_node,
4725 masked_arg1),
4726 expr_tree))));
4727 expr_tree
4728 = ffecom_2 (COMPOUND_EXPR, tree_type,
4729 convert (void_type_node,
4730 arg3_tree),
4731 expr_tree);
4732 }
4733 return expr_tree;
4734
4735 case FFEINTRIN_impLOC:
4736 {
4737 tree arg1_tree = ffecom_expr (arg1);
4738
4739 expr_tree
4740 = convert (tree_type,
4741 ffecom_1 (ADDR_EXPR,
4742 build_pointer_type (TREE_TYPE (arg1_tree)),
4743 arg1_tree));
4744 }
4745 return expr_tree;
4746
4747 case FFEINTRIN_impMVBITS:
4748 {
4749 tree arg1_tree;
4750 tree arg2_tree;
4751 tree arg3_tree;
4752 ffebld arg4 = ffebld_head (ffebld_trail (list));
4753 tree arg4_tree;
4754 tree arg4_type;
4755 ffebld arg5 = ffebld_head (ffebld_trail (ffebld_trail (list)));
4756 tree arg5_tree;
4757 tree prep_arg1;
4758 tree prep_arg4;
4759 tree arg5_plus_arg3;
4760
5ff904cd
JL
4761 arg2_tree = convert (integer_type_node,
4762 ffecom_expr (arg2));
4763 arg3_tree = ffecom_save_tree (convert (integer_type_node,
4764 ffecom_expr (arg3)));
c7e4ee3a 4765 arg4_tree = ffecom_expr_rw (NULL_TREE, arg4);
5ff904cd
JL
4766 arg4_type = TREE_TYPE (arg4_tree);
4767
4768 arg1_tree = ffecom_save_tree (convert (arg4_type,
4769 ffecom_expr (arg1)));
4770
4771 arg5_tree = ffecom_save_tree (convert (integer_type_node,
4772 ffecom_expr (arg5)));
4773
5ff904cd
JL
4774 prep_arg1
4775 = ffecom_2 (LSHIFT_EXPR, arg4_type,
4776 ffecom_2 (BIT_AND_EXPR, arg4_type,
4777 ffecom_2 (RSHIFT_EXPR, arg4_type,
4778 arg1_tree,
4779 arg2_tree),
4780 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4781 ffecom_2 (LSHIFT_EXPR, arg4_type,
4782 ffecom_1 (BIT_NOT_EXPR,
4783 arg4_type,
4784 convert
4785 (arg4_type,
4786 integer_zero_node)),
4787 arg3_tree))),
4788 arg5_tree);
4789 arg5_plus_arg3
4790 = ffecom_save_tree (ffecom_2 (PLUS_EXPR, arg4_type,
4791 arg5_tree,
4792 arg3_tree));
4793 prep_arg4
4794 = ffecom_2 (LSHIFT_EXPR, arg4_type,
4795 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4796 convert (arg4_type,
4797 integer_zero_node)),
4798 arg5_plus_arg3);
eec9ac3d 4799 /* Fix up, because LSHIFT_EXPR above can't shift over TYPE_SIZE. */
5ff904cd
JL
4800 prep_arg4
4801 = ffecom_3 (COND_EXPR, arg4_type,
4802 ffecom_truth_value
4803 (ffecom_2 (NE_EXPR, integer_type_node,
4804 arg5_plus_arg3,
4805 convert (TREE_TYPE (arg5_plus_arg3),
4806 TYPE_SIZE (arg4_type)))),
4807 prep_arg4,
4808 convert (arg4_type, integer_zero_node));
5ff904cd
JL
4809 prep_arg4
4810 = ffecom_2 (BIT_AND_EXPR, arg4_type,
4811 arg4_tree,
4812 ffecom_2 (BIT_IOR_EXPR, arg4_type,
4813 prep_arg4,
4814 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4815 ffecom_2 (LSHIFT_EXPR, arg4_type,
4816 ffecom_1 (BIT_NOT_EXPR,
4817 arg4_type,
4818 convert
4819 (arg4_type,
4820 integer_zero_node)),
4821 arg5_tree))));
4822 prep_arg1
4823 = ffecom_2 (BIT_IOR_EXPR, arg4_type,
4824 prep_arg1,
4825 prep_arg4);
eec9ac3d
TM
4826 /* Fix up (twice), because LSHIFT_EXPR above
4827 can't shift over TYPE_SIZE. */
5ff904cd
JL
4828 prep_arg1
4829 = ffecom_3 (COND_EXPR, arg4_type,
4830 ffecom_truth_value
4831 (ffecom_2 (NE_EXPR, integer_type_node,
4832 arg3_tree,
4833 convert (TREE_TYPE (arg3_tree),
4834 integer_zero_node))),
4835 prep_arg1,
4836 arg4_tree);
4837 prep_arg1
4838 = ffecom_3 (COND_EXPR, arg4_type,
4839 ffecom_truth_value
4840 (ffecom_2 (NE_EXPR, integer_type_node,
4841 arg3_tree,
4842 convert (TREE_TYPE (arg3_tree),
4843 TYPE_SIZE (arg4_type)))),
4844 prep_arg1,
4845 arg1_tree);
5ff904cd
JL
4846 expr_tree
4847 = ffecom_2s (MODIFY_EXPR, void_type_node,
4848 arg4_tree,
4849 prep_arg1);
4850 /* Make sure SAVE_EXPRs get referenced early enough. */
4851 expr_tree
4852 = ffecom_2 (COMPOUND_EXPR, void_type_node,
4853 arg1_tree,
4854 ffecom_2 (COMPOUND_EXPR, void_type_node,
4855 arg3_tree,
4856 ffecom_2 (COMPOUND_EXPR, void_type_node,
4857 arg5_tree,
4858 ffecom_2 (COMPOUND_EXPR, void_type_node,
4859 arg5_plus_arg3,
4860 expr_tree))));
4861 expr_tree
4862 = ffecom_2 (COMPOUND_EXPR, void_type_node,
4863 arg4_tree,
4864 expr_tree);
4865
4866 }
4867 return expr_tree;
4868
4869 case FFEINTRIN_impDERF:
4870 case FFEINTRIN_impERF:
4871 case FFEINTRIN_impDERFC:
4872 case FFEINTRIN_impERFC:
4873 break;
4874
4875 case FFEINTRIN_impIARGC:
4876 /* extern int xargc; i__1 = xargc - 1; */
4877 expr_tree = ffecom_2 (MINUS_EXPR, TREE_TYPE (ffecom_tree_xargc_),
4878 ffecom_tree_xargc_,
4879 convert (TREE_TYPE (ffecom_tree_xargc_),
4880 integer_one_node));
4881 return expr_tree;
4882
4883 case FFEINTRIN_impSIGNAL_func:
4884 case FFEINTRIN_impSIGNAL_subr:
4885 {
4886 tree arg1_tree;
4887 tree arg2_tree;
4888 tree arg3_tree;
4889
5ff904cd
JL
4890 arg1_tree = convert (ffecom_f2c_integer_type_node,
4891 ffecom_expr (arg1));
4892 arg1_tree = ffecom_1 (ADDR_EXPR,
4893 build_pointer_type (TREE_TYPE (arg1_tree)),
4894 arg1_tree);
4895
4896 /* Pass procedure as a pointer to it, anything else by value. */
4897 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
4898 arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
4899 else
4900 arg2_tree = ffecom_ptr_to_expr (arg2);
4901 arg2_tree = convert (TREE_TYPE (null_pointer_node),
4902 arg2_tree);
4903
4904 if (arg3 != NULL)
c7e4ee3a 4905 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
4906 else
4907 arg3_tree = NULL_TREE;
4908
5ff904cd
JL
4909 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4910 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4911 TREE_CHAIN (arg1_tree) = arg2_tree;
4912
4913 expr_tree
4914 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4915 ffecom_gfrt_kindtype (gfrt),
4916 FALSE,
4917 ((codegen_imp == FFEINTRIN_impSIGNAL_subr) ?
4918 NULL_TREE :
4919 tree_type),
4920 arg1_tree,
c7e4ee3a
CB
4921 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
4922 ffebld_nonter_hook (expr));
5ff904cd
JL
4923
4924 if (arg3_tree != NULL_TREE)
4925 expr_tree
4926 = ffecom_modify (NULL_TREE, arg3_tree,
4927 convert (TREE_TYPE (arg3_tree),
4928 expr_tree));
4929 }
4930 return expr_tree;
4931
4932 case FFEINTRIN_impALARM:
4933 {
4934 tree arg1_tree;
4935 tree arg2_tree;
4936 tree arg3_tree;
4937
5ff904cd
JL
4938 arg1_tree = convert (ffecom_f2c_integer_type_node,
4939 ffecom_expr (arg1));
4940 arg1_tree = ffecom_1 (ADDR_EXPR,
4941 build_pointer_type (TREE_TYPE (arg1_tree)),
4942 arg1_tree);
4943
4944 /* Pass procedure as a pointer to it, anything else by value. */
4945 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
4946 arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
4947 else
4948 arg2_tree = ffecom_ptr_to_expr (arg2);
4949 arg2_tree = convert (TREE_TYPE (null_pointer_node),
4950 arg2_tree);
4951
4952 if (arg3 != NULL)
c7e4ee3a 4953 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
4954 else
4955 arg3_tree = NULL_TREE;
4956
5ff904cd
JL
4957 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4958 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4959 TREE_CHAIN (arg1_tree) = arg2_tree;
4960
4961 expr_tree
4962 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4963 ffecom_gfrt_kindtype (gfrt),
4964 FALSE,
4965 NULL_TREE,
4966 arg1_tree,
c7e4ee3a
CB
4967 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
4968 ffebld_nonter_hook (expr));
5ff904cd
JL
4969
4970 if (arg3_tree != NULL_TREE)
4971 expr_tree
4972 = ffecom_modify (NULL_TREE, arg3_tree,
4973 convert (TREE_TYPE (arg3_tree),
4974 expr_tree));
4975 }
4976 return expr_tree;
4977
4978 case FFEINTRIN_impCHDIR_subr:
4979 case FFEINTRIN_impFDATE_subr:
4980 case FFEINTRIN_impFGET_subr:
4981 case FFEINTRIN_impFPUT_subr:
4982 case FFEINTRIN_impGETCWD_subr:
4983 case FFEINTRIN_impHOSTNM_subr:
4984 case FFEINTRIN_impSYSTEM_subr:
4985 case FFEINTRIN_impUNLINK_subr:
4986 {
4987 tree arg1_len = integer_zero_node;
4988 tree arg1_tree;
4989 tree arg2_tree;
4990
5ff904cd
JL
4991 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
4992
4993 if (arg2 != NULL)
c7e4ee3a 4994 arg2_tree = ffecom_expr_w (NULL_TREE, arg2);
5ff904cd
JL
4995 else
4996 arg2_tree = NULL_TREE;
4997
5ff904cd
JL
4998 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4999 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5000 TREE_CHAIN (arg1_tree) = arg1_len;
5001
5002 expr_tree
5003 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5004 ffecom_gfrt_kindtype (gfrt),
5005 FALSE,
5006 NULL_TREE,
5007 arg1_tree,
c7e4ee3a
CB
5008 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5009 ffebld_nonter_hook (expr));
5ff904cd
JL
5010
5011 if (arg2_tree != NULL_TREE)
5012 expr_tree
5013 = ffecom_modify (NULL_TREE, arg2_tree,
5014 convert (TREE_TYPE (arg2_tree),
5015 expr_tree));
5016 }
5017 return expr_tree;
5018
5019 case FFEINTRIN_impEXIT:
5020 if (arg1 != NULL)
5021 break;
5022
5023 expr_tree = build_tree_list (NULL_TREE,
5024 ffecom_1 (ADDR_EXPR,
5025 build_pointer_type
5026 (ffecom_integer_type_node),
5027 integer_zero_node));
5028
5029 return
5030 ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5031 ffecom_gfrt_kindtype (gfrt),
5032 FALSE,
5033 void_type_node,
5034 expr_tree,
c7e4ee3a
CB
5035 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5036 ffebld_nonter_hook (expr));
5ff904cd
JL
5037
5038 case FFEINTRIN_impFLUSH:
5039 if (arg1 == NULL)
5040 gfrt = FFECOM_gfrtFLUSH;
5041 else
5042 gfrt = FFECOM_gfrtFLUSH1;
5043 break;
5044
5045 case FFEINTRIN_impCHMOD_subr:
5046 case FFEINTRIN_impLINK_subr:
5047 case FFEINTRIN_impRENAME_subr:
5048 case FFEINTRIN_impSYMLNK_subr:
5049 {
5050 tree arg1_len = integer_zero_node;
5051 tree arg1_tree;
5052 tree arg2_len = integer_zero_node;
5053 tree arg2_tree;
5054 tree arg3_tree;
5055
5ff904cd
JL
5056 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5057 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
5058 if (arg3 != NULL)
c7e4ee3a 5059 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
5060 else
5061 arg3_tree = NULL_TREE;
5062
5ff904cd
JL
5063 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5064 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5065 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5066 arg2_len = build_tree_list (NULL_TREE, arg2_len);
5067 TREE_CHAIN (arg1_tree) = arg2_tree;
5068 TREE_CHAIN (arg2_tree) = arg1_len;
5069 TREE_CHAIN (arg1_len) = arg2_len;
5070 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5071 ffecom_gfrt_kindtype (gfrt),
5072 FALSE,
5073 NULL_TREE,
5074 arg1_tree,
c7e4ee3a
CB
5075 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5076 ffebld_nonter_hook (expr));
5ff904cd
JL
5077 if (arg3_tree != NULL_TREE)
5078 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5079 convert (TREE_TYPE (arg3_tree),
5080 expr_tree));
5081 }
5082 return expr_tree;
5083
5084 case FFEINTRIN_impLSTAT_subr:
5085 case FFEINTRIN_impSTAT_subr:
5086 {
5087 tree arg1_len = integer_zero_node;
5088 tree arg1_tree;
5089 tree arg2_tree;
5090 tree arg3_tree;
5091
5ff904cd
JL
5092 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5093
5094 arg2_tree = ffecom_ptr_to_expr (arg2);
5095
5096 if (arg3 != NULL)
c7e4ee3a 5097 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
5098 else
5099 arg3_tree = NULL_TREE;
5100
5ff904cd
JL
5101 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5102 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5103 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5104 TREE_CHAIN (arg1_tree) = arg2_tree;
5105 TREE_CHAIN (arg2_tree) = arg1_len;
5106 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5107 ffecom_gfrt_kindtype (gfrt),
5108 FALSE,
5109 NULL_TREE,
5110 arg1_tree,
c7e4ee3a
CB
5111 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5112 ffebld_nonter_hook (expr));
5ff904cd
JL
5113 if (arg3_tree != NULL_TREE)
5114 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5115 convert (TREE_TYPE (arg3_tree),
5116 expr_tree));
5117 }
5118 return expr_tree;
5119
5120 case FFEINTRIN_impFGETC_subr:
5121 case FFEINTRIN_impFPUTC_subr:
5122 {
5123 tree arg1_tree;
5124 tree arg2_tree;
5125 tree arg2_len = integer_zero_node;
5126 tree arg3_tree;
5127
5ff904cd
JL
5128 arg1_tree = convert (ffecom_f2c_integer_type_node,
5129 ffecom_expr (arg1));
5130 arg1_tree = ffecom_1 (ADDR_EXPR,
5131 build_pointer_type (TREE_TYPE (arg1_tree)),
5132 arg1_tree);
5133
5134 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
62b3b9db
TM
5135 if (arg3 != NULL)
5136 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5137 else
5138 arg3_tree = NULL_TREE;
5ff904cd
JL
5139
5140 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5141 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5142 arg2_len = build_tree_list (NULL_TREE, arg2_len);
5143 TREE_CHAIN (arg1_tree) = arg2_tree;
5144 TREE_CHAIN (arg2_tree) = arg2_len;
5145
5146 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5147 ffecom_gfrt_kindtype (gfrt),
5148 FALSE,
5149 NULL_TREE,
5150 arg1_tree,
c7e4ee3a
CB
5151 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5152 ffebld_nonter_hook (expr));
62b3b9db
TM
5153 if (arg3_tree != NULL_TREE)
5154 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5155 convert (TREE_TYPE (arg3_tree),
5156 expr_tree));
5ff904cd
JL
5157 }
5158 return expr_tree;
5159
5160 case FFEINTRIN_impFSTAT_subr:
5161 {
5162 tree arg1_tree;
5163 tree arg2_tree;
5164 tree arg3_tree;
5165
5ff904cd
JL
5166 arg1_tree = convert (ffecom_f2c_integer_type_node,
5167 ffecom_expr (arg1));
5168 arg1_tree = ffecom_1 (ADDR_EXPR,
5169 build_pointer_type (TREE_TYPE (arg1_tree)),
5170 arg1_tree);
5171
5172 arg2_tree = convert (ffecom_f2c_ptr_to_integer_type_node,
5173 ffecom_ptr_to_expr (arg2));
5174
5175 if (arg3 == NULL)
5176 arg3_tree = NULL_TREE;
5177 else
c7e4ee3a 5178 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
5179
5180 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5181 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5182 TREE_CHAIN (arg1_tree) = arg2_tree;
5183 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5184 ffecom_gfrt_kindtype (gfrt),
5185 FALSE,
5186 NULL_TREE,
5187 arg1_tree,
c7e4ee3a
CB
5188 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5189 ffebld_nonter_hook (expr));
5ff904cd
JL
5190 if (arg3_tree != NULL_TREE) {
5191 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5192 convert (TREE_TYPE (arg3_tree),
5193 expr_tree));
5194 }
5195 }
5196 return expr_tree;
5197
5198 case FFEINTRIN_impKILL_subr:
5199 {
5200 tree arg1_tree;
5201 tree arg2_tree;
5202 tree arg3_tree;
5203
5ff904cd
JL
5204 arg1_tree = convert (ffecom_f2c_integer_type_node,
5205 ffecom_expr (arg1));
5206 arg1_tree = ffecom_1 (ADDR_EXPR,
5207 build_pointer_type (TREE_TYPE (arg1_tree)),
5208 arg1_tree);
5209
5210 arg2_tree = convert (ffecom_f2c_integer_type_node,
5211 ffecom_expr (arg2));
5212 arg2_tree = ffecom_1 (ADDR_EXPR,
5213 build_pointer_type (TREE_TYPE (arg2_tree)),
5214 arg2_tree);
5215
5216 if (arg3 == NULL)
5217 arg3_tree = NULL_TREE;
5218 else
c7e4ee3a 5219 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
5220
5221 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5222 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5223 TREE_CHAIN (arg1_tree) = arg2_tree;
5224 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5225 ffecom_gfrt_kindtype (gfrt),
5226 FALSE,
5227 NULL_TREE,
5228 arg1_tree,
c7e4ee3a
CB
5229 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5230 ffebld_nonter_hook (expr));
5ff904cd
JL
5231 if (arg3_tree != NULL_TREE) {
5232 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5233 convert (TREE_TYPE (arg3_tree),
5234 expr_tree));
5235 }
5236 }
5237 return expr_tree;
5238
5239 case FFEINTRIN_impCTIME_subr:
5240 case FFEINTRIN_impTTYNAM_subr:
5241 {
5242 tree arg1_len = integer_zero_node;
5243 tree arg1_tree;
5244 tree arg2_tree;
5245
2b0bdd9a 5246 arg1_tree = ffecom_arg_ptr_to_expr (arg2, &arg1_len);
5ff904cd 5247
c56f65d6 5248 arg2_tree = convert (((codegen_imp == FFEINTRIN_impCTIME_subr) ?
5ff904cd
JL
5249 ffecom_f2c_longint_type_node :
5250 ffecom_f2c_integer_type_node),
2b0bdd9a 5251 ffecom_expr (arg1));
5ff904cd
JL
5252 arg2_tree = ffecom_1 (ADDR_EXPR,
5253 build_pointer_type (TREE_TYPE (arg2_tree)),
5254 arg2_tree);
5255
5ff904cd
JL
5256 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5257 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5258 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5259 TREE_CHAIN (arg1_len) = arg2_tree;
5260 TREE_CHAIN (arg1_tree) = arg1_len;
5261
5262 expr_tree
5263 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5264 ffecom_gfrt_kindtype (gfrt),
5265 FALSE,
5266 NULL_TREE,
5267 arg1_tree,
c7e4ee3a
CB
5268 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5269 ffebld_nonter_hook (expr));
2b0bdd9a 5270 TREE_SIDE_EFFECTS (expr_tree) = 1;
5ff904cd
JL
5271 }
5272 return expr_tree;
5273
5274 case FFEINTRIN_impIRAND:
5275 case FFEINTRIN_impRAND:
5276 /* Arg defaults to 0 (normal random case) */
5277 {
5278 tree arg1_tree;
5279
5280 if (arg1 == NULL)
5281 arg1_tree = ffecom_integer_zero_node;
5282 else
5283 arg1_tree = ffecom_expr (arg1);
5284 arg1_tree = convert (ffecom_f2c_integer_type_node,
5285 arg1_tree);
5286 arg1_tree = ffecom_1 (ADDR_EXPR,
5287 build_pointer_type (TREE_TYPE (arg1_tree)),
5288 arg1_tree);
5289 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5290
5291 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5292 ffecom_gfrt_kindtype (gfrt),
5293 FALSE,
5294 ((codegen_imp == FFEINTRIN_impIRAND) ?
5295 ffecom_f2c_integer_type_node :
de7f278a 5296 ffecom_f2c_real_type_node),
5ff904cd
JL
5297 arg1_tree,
5298 dest_tree, dest, dest_used,
c7e4ee3a
CB
5299 NULL_TREE, TRUE,
5300 ffebld_nonter_hook (expr));
5ff904cd
JL
5301 }
5302 return expr_tree;
5303
5304 case FFEINTRIN_impFTELL_subr:
5305 case FFEINTRIN_impUMASK_subr:
5306 {
5307 tree arg1_tree;
5308 tree arg2_tree;
5309
5ff904cd
JL
5310 arg1_tree = convert (ffecom_f2c_integer_type_node,
5311 ffecom_expr (arg1));
5312 arg1_tree = ffecom_1 (ADDR_EXPR,
5313 build_pointer_type (TREE_TYPE (arg1_tree)),
5314 arg1_tree);
5315
5316 if (arg2 == NULL)
5317 arg2_tree = NULL_TREE;
5318 else
c7e4ee3a 5319 arg2_tree = ffecom_expr_w (NULL_TREE, arg2);
5ff904cd
JL
5320
5321 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5322 ffecom_gfrt_kindtype (gfrt),
5323 FALSE,
5324 NULL_TREE,
5325 build_tree_list (NULL_TREE, arg1_tree),
5326 NULL_TREE, NULL, NULL, NULL_TREE,
c7e4ee3a
CB
5327 TRUE,
5328 ffebld_nonter_hook (expr));
5ff904cd
JL
5329 if (arg2_tree != NULL_TREE) {
5330 expr_tree = ffecom_modify (NULL_TREE, arg2_tree,
5331 convert (TREE_TYPE (arg2_tree),
5332 expr_tree));
5333 }
5334 }
5335 return expr_tree;
5336
5337 case FFEINTRIN_impCPU_TIME:
5338 case FFEINTRIN_impSECOND_subr:
5339 {
5340 tree arg1_tree;
5341
c7e4ee3a 5342 arg1_tree = ffecom_expr_w (NULL_TREE, arg1);
5ff904cd
JL
5343
5344 expr_tree
5345 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5346 ffecom_gfrt_kindtype (gfrt),
5347 FALSE,
5348 NULL_TREE,
5349 NULL_TREE,
c7e4ee3a
CB
5350 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5351 ffebld_nonter_hook (expr));
5ff904cd
JL
5352
5353 expr_tree
5354 = ffecom_modify (NULL_TREE, arg1_tree,
5355 convert (TREE_TYPE (arg1_tree),
5356 expr_tree));
5357 }
5358 return expr_tree;
5359
5360 case FFEINTRIN_impDTIME_subr:
5361 case FFEINTRIN_impETIME_subr:
5362 {
5363 tree arg1_tree;
2b0bdd9a 5364 tree result_tree;
5ff904cd 5365
2b0bdd9a 5366 result_tree = ffecom_expr_w (NULL_TREE, arg2);
5ff904cd 5367
2b0bdd9a 5368 arg1_tree = ffecom_ptr_to_expr (arg1);
5ff904cd 5369
5ff904cd
JL
5370 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5371 ffecom_gfrt_kindtype (gfrt),
5372 FALSE,
5373 NULL_TREE,
2b0bdd9a 5374 build_tree_list (NULL_TREE, arg1_tree),
5ff904cd 5375 NULL_TREE, NULL, NULL, NULL_TREE,
c7e4ee3a
CB
5376 TRUE,
5377 ffebld_nonter_hook (expr));
2b0bdd9a
CB
5378 expr_tree = ffecom_modify (NULL_TREE, result_tree,
5379 convert (TREE_TYPE (result_tree),
5ff904cd
JL
5380 expr_tree));
5381 }
5382 return expr_tree;
5383
c7e4ee3a 5384 /* Straightforward calls of libf2c routines: */
5ff904cd
JL
5385 case FFEINTRIN_impABORT:
5386 case FFEINTRIN_impACCESS:
5387 case FFEINTRIN_impBESJ0:
5388 case FFEINTRIN_impBESJ1:
5389 case FFEINTRIN_impBESJN:
5390 case FFEINTRIN_impBESY0:
5391 case FFEINTRIN_impBESY1:
5392 case FFEINTRIN_impBESYN:
5393 case FFEINTRIN_impCHDIR_func:
5394 case FFEINTRIN_impCHMOD_func:
5395 case FFEINTRIN_impDATE:
9e8e701d 5396 case FFEINTRIN_impDATE_AND_TIME:
5ff904cd
JL
5397 case FFEINTRIN_impDBESJ0:
5398 case FFEINTRIN_impDBESJ1:
5399 case FFEINTRIN_impDBESJN:
5400 case FFEINTRIN_impDBESY0:
5401 case FFEINTRIN_impDBESY1:
5402 case FFEINTRIN_impDBESYN:
5403 case FFEINTRIN_impDTIME_func:
5404 case FFEINTRIN_impETIME_func:
5405 case FFEINTRIN_impFGETC_func:
5406 case FFEINTRIN_impFGET_func:
5407 case FFEINTRIN_impFNUM:
5408 case FFEINTRIN_impFPUTC_func:
5409 case FFEINTRIN_impFPUT_func:
5410 case FFEINTRIN_impFSEEK:
5411 case FFEINTRIN_impFSTAT_func:
5412 case FFEINTRIN_impFTELL_func:
5413 case FFEINTRIN_impGERROR:
5414 case FFEINTRIN_impGETARG:
5415 case FFEINTRIN_impGETCWD_func:
5416 case FFEINTRIN_impGETENV:
5417 case FFEINTRIN_impGETGID:
5418 case FFEINTRIN_impGETLOG:
5419 case FFEINTRIN_impGETPID:
5420 case FFEINTRIN_impGETUID:
5421 case FFEINTRIN_impGMTIME:
5422 case FFEINTRIN_impHOSTNM_func:
5423 case FFEINTRIN_impIDATE_unix:
5424 case FFEINTRIN_impIDATE_vxt:
5425 case FFEINTRIN_impIERRNO:
5426 case FFEINTRIN_impISATTY:
5427 case FFEINTRIN_impITIME:
5428 case FFEINTRIN_impKILL_func:
5429 case FFEINTRIN_impLINK_func:
5430 case FFEINTRIN_impLNBLNK:
5431 case FFEINTRIN_impLSTAT_func:
5432 case FFEINTRIN_impLTIME:
5433 case FFEINTRIN_impMCLOCK8:
5434 case FFEINTRIN_impMCLOCK:
5435 case FFEINTRIN_impPERROR:
5436 case FFEINTRIN_impRENAME_func:
5437 case FFEINTRIN_impSECNDS:
5438 case FFEINTRIN_impSECOND_func:
5439 case FFEINTRIN_impSLEEP:
5440 case FFEINTRIN_impSRAND:
5441 case FFEINTRIN_impSTAT_func:
5442 case FFEINTRIN_impSYMLNK_func:
5443 case FFEINTRIN_impSYSTEM_CLOCK:
5444 case FFEINTRIN_impSYSTEM_func:
5445 case FFEINTRIN_impTIME8:
5446 case FFEINTRIN_impTIME_unix:
5447 case FFEINTRIN_impTIME_vxt:
5448 case FFEINTRIN_impUMASK_func:
5449 case FFEINTRIN_impUNLINK_func:
5450 break;
5451
5452 case FFEINTRIN_impCTIME_func: /* CHARACTER functions not handled here. */
5453 case FFEINTRIN_impFDATE_func: /* CHARACTER functions not handled here. */
5454 case FFEINTRIN_impTTYNAM_func: /* CHARACTER functions not handled here. */
5455 case FFEINTRIN_impNONE:
5456 case FFEINTRIN_imp: /* Hush up gcc warning. */
5457 fprintf (stderr, "No %s implementation.\n",
5458 ffeintrin_name_implementation (ffebld_symter_implementation (ffebld_left (expr))));
5459 assert ("unimplemented intrinsic" == NULL);
5460 return error_mark_node;
5461 }
5462
5463 assert (gfrt != FFECOM_gfrt); /* Must have an implementation! */
5464
5ff904cd
JL
5465 expr_tree = ffecom_arglist_expr_ (ffecom_gfrt_args_ (gfrt),
5466 ffebld_right (expr));
5ff904cd
JL
5467
5468 return ffecom_call_ (ffecom_gfrt_tree_ (gfrt), ffecom_gfrt_kindtype (gfrt),
5469 (ffe_is_f2c_library () && ffecom_gfrt_complex_[gfrt]),
5470 tree_type,
5471 expr_tree, dest_tree, dest, dest_used,
c7e4ee3a
CB
5472 NULL_TREE, TRUE,
5473 ffebld_nonter_hook (expr));
5ff904cd 5474
c7e4ee3a
CB
5475 /* See bottom of this file for f2c transforms used to determine
5476 many of the above implementations. The info seems to confuse
5477 Emacs's C mode indentation, which is why it's been moved to
5478 the bottom of this source file. */
5479}
5ff904cd 5480
c7e4ee3a
CB
5481#endif
5482/* For power (exponentiation) where right-hand operand is type INTEGER,
5483 generate in-line code to do it the fast way (which, if the operand
5484 is a constant, might just mean a series of multiplies). */
5ff904cd 5485
c7e4ee3a
CB
5486#if FFECOM_targetCURRENT == FFECOM_targetGCC
5487static tree
5488ffecom_expr_power_integer_ (ffebld expr)
5489{
5490 tree l = ffecom_expr (ffebld_left (expr));
5491 tree r = ffecom_expr (ffebld_right (expr));
5492 tree ltype = TREE_TYPE (l);
5493 tree rtype = TREE_TYPE (r);
5494 tree result = NULL_TREE;
5ff904cd 5495
c7e4ee3a
CB
5496 if (l == error_mark_node
5497 || r == error_mark_node)
5498 return error_mark_node;
5ff904cd 5499
c7e4ee3a
CB
5500 if (TREE_CODE (r) == INTEGER_CST)
5501 {
5502 int sgn = tree_int_cst_sgn (r);
5ff904cd 5503
c7e4ee3a
CB
5504 if (sgn == 0)
5505 return convert (ltype, integer_one_node);
5ff904cd 5506
c7e4ee3a
CB
5507 if ((TREE_CODE (ltype) == INTEGER_TYPE)
5508 && (sgn < 0))
5509 {
5510 /* Reciprocal of integer is either 0, -1, or 1, so after
5511 calculating that (which we leave to the back end to do
5512 or not do optimally), don't bother with any multiplying. */
5ff904cd 5513
c7e4ee3a
CB
5514 result = ffecom_tree_divide_ (ltype,
5515 convert (ltype, integer_one_node),
5516 l,
5517 NULL_TREE, NULL, NULL, NULL_TREE);
5518 r = ffecom_1 (NEGATE_EXPR,
5519 rtype,
5520 r);
5521 if ((TREE_INT_CST_LOW (r) & 1) == 0)
5522 result = ffecom_1 (ABS_EXPR, rtype,
5523 result);
5524 }
5ff904cd 5525
c7e4ee3a
CB
5526 /* Generate appropriate series of multiplies, preceded
5527 by divide if the exponent is negative. */
5ff904cd 5528
c7e4ee3a 5529 l = save_expr (l);
5ff904cd 5530
c7e4ee3a
CB
5531 if (sgn < 0)
5532 {
5533 l = ffecom_tree_divide_ (ltype,
5534 convert (ltype, integer_one_node),
5535 l,
5536 NULL_TREE, NULL, NULL,
5537 ffebld_nonter_hook (expr));
5538 r = ffecom_1 (NEGATE_EXPR, rtype, r);
5539 assert (TREE_CODE (r) == INTEGER_CST);
5ff904cd 5540
c7e4ee3a
CB
5541 if (tree_int_cst_sgn (r) < 0)
5542 { /* The "most negative" number. */
5543 r = ffecom_1 (NEGATE_EXPR, rtype,
5544 ffecom_2 (RSHIFT_EXPR, rtype,
5545 r,
5546 integer_one_node));
5547 l = save_expr (l);
5548 l = ffecom_2 (MULT_EXPR, ltype,
5549 l,
5550 l);
5551 }
5552 }
5ff904cd 5553
c7e4ee3a
CB
5554 for (;;)
5555 {
5556 if (TREE_INT_CST_LOW (r) & 1)
5557 {
5558 if (result == NULL_TREE)
5559 result = l;
5560 else
5561 result = ffecom_2 (MULT_EXPR, ltype,
5562 result,
5563 l);
5564 }
5ff904cd 5565
c7e4ee3a
CB
5566 r = ffecom_2 (RSHIFT_EXPR, rtype,
5567 r,
5568 integer_one_node);
5569 if (integer_zerop (r))
5570 break;
5571 assert (TREE_CODE (r) == INTEGER_CST);
5ff904cd 5572
c7e4ee3a
CB
5573 l = save_expr (l);
5574 l = ffecom_2 (MULT_EXPR, ltype,
5575 l,
5576 l);
5577 }
5578 return result;
5579 }
5ff904cd 5580
c7e4ee3a
CB
5581 /* Though rhs isn't a constant, in-line code cannot be expanded
5582 while transforming dummies
5583 because the back end cannot be easily convinced to generate
5584 stores (MODIFY_EXPR), handle temporaries, and so on before
5585 all the appropriate rtx's have been generated for things like
5586 dummy args referenced in rhs -- which doesn't happen until
5587 store_parm_decls() is called (expand_function_start, I believe,
5588 does the actual rtx-stuffing of PARM_DECLs).
5ff904cd 5589
c7e4ee3a
CB
5590 So, in this case, let the caller generate the call to the
5591 run-time-library function to evaluate the power for us. */
5ff904cd 5592
c7e4ee3a
CB
5593 if (ffecom_transform_only_dummies_)
5594 return NULL_TREE;
5ff904cd 5595
c7e4ee3a
CB
5596 /* Right-hand operand not a constant, expand in-line code to figure
5597 out how to do the multiplies, &c.
5ff904cd 5598
c7e4ee3a
CB
5599 The returned expression is expressed this way in GNU C, where l and
5600 r are the "inputs":
5ff904cd 5601
c7e4ee3a
CB
5602 ({ typeof (r) rtmp = r;
5603 typeof (l) ltmp = l;
5604 typeof (l) result;
5ff904cd 5605
c7e4ee3a
CB
5606 if (rtmp == 0)
5607 result = 1;
5608 else
5609 {
5610 if ((basetypeof (l) == basetypeof (int))
5611 && (rtmp < 0))
5612 {
5613 result = ((typeof (l)) 1) / ltmp;
5614 if ((ltmp < 0) && (((-rtmp) & 1) == 0))
5615 result = -result;
5616 }
5617 else
5618 {
5619 result = 1;
5620 if ((basetypeof (l) != basetypeof (int))
5621 && (rtmp < 0))
5622 {
5623 ltmp = ((typeof (l)) 1) / ltmp;
5624 rtmp = -rtmp;
5625 if (rtmp < 0)
5626 {
5627 rtmp = -(rtmp >> 1);
5628 ltmp *= ltmp;
5629 }
5630 }
5631 for (;;)
5632 {
5633 if (rtmp & 1)
5634 result *= ltmp;
5635 if ((rtmp >>= 1) == 0)
5636 break;
5637 ltmp *= ltmp;
5638 }
5639 }
5640 }
5641 result;
5642 })
5ff904cd 5643
c7e4ee3a
CB
5644 Note that some of the above is compile-time collapsable, such as
5645 the first part of the if statements that checks the base type of
5646 l against int. The if statements are phrased that way to suggest
5647 an easy way to generate the if/else constructs here, knowing that
5648 the back end should (and probably does) eliminate the resulting
5649 dead code (either the int case or the non-int case), something
5650 it couldn't do without the redundant phrasing, requiring explicit
5651 dead-code elimination here, which would be kind of difficult to
5652 read. */
5ff904cd 5653
c7e4ee3a
CB
5654 {
5655 tree rtmp;
5656 tree ltmp;
5657 tree divide;
5658 tree basetypeof_l_is_int;
5659 tree se;
5660 tree t;
5ff904cd 5661
c7e4ee3a
CB
5662 basetypeof_l_is_int
5663 = build_int_2 ((TREE_CODE (ltype) == INTEGER_TYPE), 0);
5ff904cd 5664
c7e4ee3a 5665 se = expand_start_stmt_expr ();
5ff904cd 5666
c7e4ee3a
CB
5667 ffecom_start_compstmt ();
5668
5669#ifndef HAHA
5670 rtmp = ffecom_make_tempvar ("power_r", rtype,
5671 FFETARGET_charactersizeNONE, -1);
5672 ltmp = ffecom_make_tempvar ("power_l", ltype,
5673 FFETARGET_charactersizeNONE, -1);
5674 result = ffecom_make_tempvar ("power_res", ltype,
5675 FFETARGET_charactersizeNONE, -1);
5676 if (TREE_CODE (ltype) == COMPLEX_TYPE
5677 || TREE_CODE (ltype) == RECORD_TYPE)
5678 divide = ffecom_make_tempvar ("power_div", ltype,
5679 FFETARGET_charactersizeNONE, -1);
5680 else
5681 divide = NULL_TREE;
5682#else /* HAHA */
5683 {
5684 tree hook;
5685
5686 hook = ffebld_nonter_hook (expr);
5687 assert (hook);
5688 assert (TREE_CODE (hook) == TREE_VEC);
5689 assert (TREE_VEC_LENGTH (hook) == 4);
5690 rtmp = TREE_VEC_ELT (hook, 0);
5691 ltmp = TREE_VEC_ELT (hook, 1);
5692 result = TREE_VEC_ELT (hook, 2);
5693 divide = TREE_VEC_ELT (hook, 3);
5694 if (TREE_CODE (ltype) == COMPLEX_TYPE
5695 || TREE_CODE (ltype) == RECORD_TYPE)
5696 assert (divide);
5697 else
5698 assert (! divide);
5699 }
5700#endif /* HAHA */
5ff904cd 5701
c7e4ee3a
CB
5702 expand_expr_stmt (ffecom_modify (void_type_node,
5703 rtmp,
5704 r));
5705 expand_expr_stmt (ffecom_modify (void_type_node,
5706 ltmp,
5707 l));
5708 expand_start_cond (ffecom_truth_value
5709 (ffecom_2 (EQ_EXPR, integer_type_node,
5710 rtmp,
5711 convert (rtype, integer_zero_node))),
5712 0);
5713 expand_expr_stmt (ffecom_modify (void_type_node,
5714 result,
5715 convert (ltype, integer_one_node)));
5716 expand_start_else ();
5717 if (! integer_zerop (basetypeof_l_is_int))
5718 {
5719 expand_start_cond (ffecom_2 (LT_EXPR, integer_type_node,
5720 rtmp,
5721 convert (rtype,
5722 integer_zero_node)),
5723 0);
5724 expand_expr_stmt (ffecom_modify (void_type_node,
5725 result,
5726 ffecom_tree_divide_
5727 (ltype,
5728 convert (ltype, integer_one_node),
5729 ltmp,
5730 NULL_TREE, NULL, NULL,
5731 divide)));
5732 expand_start_cond (ffecom_truth_value
5733 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
5734 ffecom_2 (LT_EXPR, integer_type_node,
5735 ltmp,
5736 convert (ltype,
5737 integer_zero_node)),
5738 ffecom_2 (EQ_EXPR, integer_type_node,
5739 ffecom_2 (BIT_AND_EXPR,
5740 rtype,
5741 ffecom_1 (NEGATE_EXPR,
5742 rtype,
5743 rtmp),
5744 convert (rtype,
5745 integer_one_node)),
5746 convert (rtype,
5747 integer_zero_node)))),
5748 0);
5749 expand_expr_stmt (ffecom_modify (void_type_node,
5750 result,
5751 ffecom_1 (NEGATE_EXPR,
5752 ltype,
5753 result)));
5754 expand_end_cond ();
5755 expand_start_else ();
5756 }
5757 expand_expr_stmt (ffecom_modify (void_type_node,
5758 result,
5759 convert (ltype, integer_one_node)));
5760 expand_start_cond (ffecom_truth_value
5761 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
5762 ffecom_truth_value_invert
5763 (basetypeof_l_is_int),
5764 ffecom_2 (LT_EXPR, integer_type_node,
5765 rtmp,
5766 convert (rtype,
5767 integer_zero_node)))),
5768 0);
5769 expand_expr_stmt (ffecom_modify (void_type_node,
5770 ltmp,
5771 ffecom_tree_divide_
5772 (ltype,
5773 convert (ltype, integer_one_node),
5774 ltmp,
5775 NULL_TREE, NULL, NULL,
5776 divide)));
5777 expand_expr_stmt (ffecom_modify (void_type_node,
5778 rtmp,
5779 ffecom_1 (NEGATE_EXPR, rtype,
5780 rtmp)));
5781 expand_start_cond (ffecom_truth_value
5782 (ffecom_2 (LT_EXPR, integer_type_node,
5783 rtmp,
5784 convert (rtype, integer_zero_node))),
5785 0);
5786 expand_expr_stmt (ffecom_modify (void_type_node,
5787 rtmp,
5788 ffecom_1 (NEGATE_EXPR, rtype,
5789 ffecom_2 (RSHIFT_EXPR,
5790 rtype,
5791 rtmp,
5792 integer_one_node))));
5793 expand_expr_stmt (ffecom_modify (void_type_node,
5794 ltmp,
5795 ffecom_2 (MULT_EXPR, ltype,
5796 ltmp,
5797 ltmp)));
5798 expand_end_cond ();
5799 expand_end_cond ();
5800 expand_start_loop (1);
5801 expand_start_cond (ffecom_truth_value
5802 (ffecom_2 (BIT_AND_EXPR, rtype,
5803 rtmp,
5804 convert (rtype, integer_one_node))),
5805 0);
5806 expand_expr_stmt (ffecom_modify (void_type_node,
5807 result,
5808 ffecom_2 (MULT_EXPR, ltype,
5809 result,
5810 ltmp)));
5811 expand_end_cond ();
5812 expand_exit_loop_if_false (NULL,
5813 ffecom_truth_value
5814 (ffecom_modify (rtype,
5815 rtmp,
5816 ffecom_2 (RSHIFT_EXPR,
5817 rtype,
5818 rtmp,
5819 integer_one_node))));
5820 expand_expr_stmt (ffecom_modify (void_type_node,
5821 ltmp,
5822 ffecom_2 (MULT_EXPR, ltype,
5823 ltmp,
5824 ltmp)));
5825 expand_end_loop ();
5826 expand_end_cond ();
5827 if (!integer_zerop (basetypeof_l_is_int))
5828 expand_end_cond ();
5829 expand_expr_stmt (result);
5ff904cd 5830
c7e4ee3a 5831 t = ffecom_end_compstmt ();
5ff904cd 5832
c7e4ee3a 5833 result = expand_end_stmt_expr (se);
5ff904cd 5834
c7e4ee3a 5835 /* This code comes from c-parse.in, after its expand_end_stmt_expr. */
5ff904cd 5836
c7e4ee3a
CB
5837 if (TREE_CODE (t) == BLOCK)
5838 {
5839 /* Make a BIND_EXPR for the BLOCK already made. */
5840 result = build (BIND_EXPR, TREE_TYPE (result),
5841 NULL_TREE, result, t);
5842 /* Remove the block from the tree at this point.
5843 It gets put back at the proper place
5844 when the BIND_EXPR is expanded. */
5845 delete_block (t);
5846 }
5847 else
5848 result = t;
5849 }
5ff904cd 5850
c7e4ee3a
CB
5851 return result;
5852}
5ff904cd 5853
c7e4ee3a
CB
5854#endif
5855/* ffecom_expr_transform_ -- Transform symbols in expr
5ff904cd 5856
c7e4ee3a
CB
5857 ffebld expr; // FFE expression.
5858 ffecom_expr_transform_ (expr);
5ff904cd 5859
c7e4ee3a 5860 Recursive descent on expr while transforming any untransformed SYMTERs. */
5ff904cd 5861
c7e4ee3a
CB
5862#if FFECOM_targetCURRENT == FFECOM_targetGCC
5863static void
5864ffecom_expr_transform_ (ffebld expr)
5865{
5866 tree t;
5867 ffesymbol s;
5ff904cd 5868
c7e4ee3a 5869tail_recurse: /* :::::::::::::::::::: */
5ff904cd 5870
c7e4ee3a
CB
5871 if (expr == NULL)
5872 return;
5ff904cd 5873
c7e4ee3a
CB
5874 switch (ffebld_op (expr))
5875 {
5876 case FFEBLD_opSYMTER:
5877 s = ffebld_symter (expr);
5878 t = ffesymbol_hook (s).decl_tree;
5879 if ((t == NULL_TREE)
5880 && ((ffesymbol_kind (s) != FFEINFO_kindNONE)
5881 || ((ffesymbol_where (s) != FFEINFO_whereNONE)
5882 && (ffesymbol_where (s) != FFEINFO_whereINTRINSIC))))
5883 {
5884 s = ffecom_sym_transform_ (s);
5885 t = ffesymbol_hook (s).decl_tree; /* Sfunc expr non-dummy,
5886 DIMENSION expr? */
5887 }
5888 break; /* Ok if (t == NULL) here. */
5ff904cd 5889
c7e4ee3a
CB
5890 case FFEBLD_opITEM:
5891 ffecom_expr_transform_ (ffebld_head (expr));
5892 expr = ffebld_trail (expr);
5893 goto tail_recurse; /* :::::::::::::::::::: */
5ff904cd 5894
c7e4ee3a
CB
5895 default:
5896 break;
5897 }
5ff904cd 5898
c7e4ee3a
CB
5899 switch (ffebld_arity (expr))
5900 {
5901 case 2:
5902 ffecom_expr_transform_ (ffebld_left (expr));
5903 expr = ffebld_right (expr);
5904 goto tail_recurse; /* :::::::::::::::::::: */
5ff904cd 5905
c7e4ee3a
CB
5906 case 1:
5907 expr = ffebld_left (expr);
5908 goto tail_recurse; /* :::::::::::::::::::: */
5ff904cd 5909
c7e4ee3a
CB
5910 default:
5911 break;
5912 }
5ff904cd 5913
c7e4ee3a
CB
5914 return;
5915}
5ff904cd 5916
c7e4ee3a
CB
5917#endif
5918/* Make a type based on info in live f2c.h file. */
5ff904cd 5919
c7e4ee3a
CB
5920#if FFECOM_targetCURRENT == FFECOM_targetGCC
5921static void
5922ffecom_f2c_make_type_ (tree *type, int tcode, const char *name)
5923{
5924 switch (tcode)
5925 {
5926 case FFECOM_f2ccodeCHAR:
5927 *type = make_signed_type (CHAR_TYPE_SIZE);
5928 break;
5ff904cd 5929
c7e4ee3a
CB
5930 case FFECOM_f2ccodeSHORT:
5931 *type = make_signed_type (SHORT_TYPE_SIZE);
5932 break;
5ff904cd 5933
c7e4ee3a
CB
5934 case FFECOM_f2ccodeINT:
5935 *type = make_signed_type (INT_TYPE_SIZE);
5936 break;
5ff904cd 5937
c7e4ee3a
CB
5938 case FFECOM_f2ccodeLONG:
5939 *type = make_signed_type (LONG_TYPE_SIZE);
5940 break;
5ff904cd 5941
c7e4ee3a
CB
5942 case FFECOM_f2ccodeLONGLONG:
5943 *type = make_signed_type (LONG_LONG_TYPE_SIZE);
5944 break;
5ff904cd 5945
c7e4ee3a
CB
5946 case FFECOM_f2ccodeCHARPTR:
5947 *type = build_pointer_type (DEFAULT_SIGNED_CHAR
5948 ? signed_char_type_node
5949 : unsigned_char_type_node);
5950 break;
5ff904cd 5951
c7e4ee3a
CB
5952 case FFECOM_f2ccodeFLOAT:
5953 *type = make_node (REAL_TYPE);
5954 TYPE_PRECISION (*type) = FLOAT_TYPE_SIZE;
5955 layout_type (*type);
5956 break;
5957
5958 case FFECOM_f2ccodeDOUBLE:
5959 *type = make_node (REAL_TYPE);
5960 TYPE_PRECISION (*type) = DOUBLE_TYPE_SIZE;
5961 layout_type (*type);
5962 break;
5963
5964 case FFECOM_f2ccodeLONGDOUBLE:
5965 *type = make_node (REAL_TYPE);
5966 TYPE_PRECISION (*type) = LONG_DOUBLE_TYPE_SIZE;
5967 layout_type (*type);
5968 break;
5ff904cd 5969
c7e4ee3a
CB
5970 case FFECOM_f2ccodeTWOREALS:
5971 *type = ffecom_make_complex_type_ (ffecom_f2c_real_type_node);
5972 break;
5ff904cd 5973
c7e4ee3a
CB
5974 case FFECOM_f2ccodeTWODOUBLEREALS:
5975 *type = ffecom_make_complex_type_ (ffecom_f2c_doublereal_type_node);
5976 break;
5ff904cd 5977
c7e4ee3a
CB
5978 default:
5979 assert ("unexpected FFECOM_f2ccodeXYZZY!" == NULL);
5980 *type = error_mark_node;
5981 return;
5982 }
5ff904cd 5983
c7e4ee3a 5984 pushdecl (build_decl (TYPE_DECL,
14657de8 5985 ffecom_get_invented_identifier ("__g77_f2c_%s", name),
c7e4ee3a
CB
5986 *type));
5987}
5ff904cd 5988
c7e4ee3a
CB
5989#endif
5990#if FFECOM_targetCURRENT == FFECOM_targetGCC
5991/* Set the f2c list-directed-I/O code for whatever (integral) type has the
5992 given size. */
5ff904cd 5993
c7e4ee3a
CB
5994static void
5995ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size,
5996 int code)
5997{
5998 int j;
5999 tree t;
5ff904cd 6000
c7e4ee3a 6001 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
05bccae2
RK
6002 if ((t = ffecom_tree_type[bt][j]) != NULL_TREE
6003 && compare_tree_int (TYPE_SIZE (t), size) == 0)
c7e4ee3a
CB
6004 {
6005 assert (code != -1);
6006 ffecom_f2c_typecode_[bt][j] = code;
6007 code = -1;
6008 }
6009}
5ff904cd 6010
c7e4ee3a
CB
6011#endif
6012/* Finish up globals after doing all program units in file
5ff904cd 6013
c7e4ee3a 6014 Need to handle only uninitialized COMMON areas. */
5ff904cd 6015
c7e4ee3a
CB
6016#if FFECOM_targetCURRENT == FFECOM_targetGCC
6017static ffeglobal
6018ffecom_finish_global_ (ffeglobal global)
6019{
6020 tree cbtype;
6021 tree cbt;
6022 tree size;
5ff904cd 6023
c7e4ee3a
CB
6024 if (ffeglobal_type (global) != FFEGLOBAL_typeCOMMON)
6025 return global;
5ff904cd 6026
c7e4ee3a
CB
6027 if (ffeglobal_common_init (global))
6028 return global;
5ff904cd 6029
c7e4ee3a
CB
6030 cbt = ffeglobal_hook (global);
6031 if ((cbt == NULL_TREE)
6032 || !ffeglobal_common_have_size (global))
6033 return global; /* No need to make common, never ref'd. */
5ff904cd 6034
c7e4ee3a 6035 DECL_EXTERNAL (cbt) = 0;
5ff904cd 6036
c7e4ee3a 6037 /* Give the array a size now. */
5ff904cd 6038
c7e4ee3a
CB
6039 size = build_int_2 ((ffeglobal_common_size (global)
6040 + ffeglobal_common_pad (global)) - 1,
6041 0);
5ff904cd 6042
c7e4ee3a
CB
6043 cbtype = TREE_TYPE (cbt);
6044 TYPE_DOMAIN (cbtype) = build_range_type (integer_type_node,
6045 integer_zero_node,
6046 size);
6047 if (!TREE_TYPE (size))
6048 TREE_TYPE (size) = TYPE_DOMAIN (cbtype);
6049 layout_type (cbtype);
5ff904cd 6050
c7e4ee3a
CB
6051 cbt = start_decl (cbt, FALSE);
6052 assert (cbt == ffeglobal_hook (global));
5ff904cd 6053
c7e4ee3a 6054 finish_decl (cbt, NULL_TREE, FALSE);
5ff904cd 6055
c7e4ee3a
CB
6056 return global;
6057}
5ff904cd 6058
c7e4ee3a
CB
6059#endif
6060/* Finish up any untransformed symbols. */
5ff904cd 6061
c7e4ee3a
CB
6062#if FFECOM_targetCURRENT == FFECOM_targetGCC
6063static ffesymbol
6064ffecom_finish_symbol_transform_ (ffesymbol s)
5ff904cd 6065{
c7e4ee3a
CB
6066 if ((s == NULL) || (TREE_CODE (current_function_decl) == ERROR_MARK))
6067 return s;
5ff904cd 6068
c7e4ee3a
CB
6069 /* It's easy to know to transform an untransformed symbol, to make sure
6070 we put out debugging info for it. But COMMON variables, unlike
6071 EQUIVALENCE ones, aren't given declarations in addition to the
6072 tree expressions that specify offsets, because COMMON variables
6073 can be referenced in the outer scope where only dummy arguments
6074 (PARM_DECLs) should really be seen. To be safe, just don't do any
6075 VAR_DECLs for COMMON variables when we transform them for real
6076 use, and therefore we do all the VAR_DECL creating here. */
5ff904cd 6077
c7e4ee3a
CB
6078 if (ffesymbol_hook (s).decl_tree == NULL_TREE)
6079 {
6080 if (ffesymbol_kind (s) != FFEINFO_kindNONE
6081 || (ffesymbol_where (s) != FFEINFO_whereNONE
6082 && ffesymbol_where (s) != FFEINFO_whereINTRINSIC
6083 && ffesymbol_where (s) != FFEINFO_whereDUMMY))
6084 /* Not transformed, and not CHARACTER*(*), and not a dummy
6085 argument, which can happen only if the entry point names
6086 it "rides in on" are all invalidated for other reasons. */
6087 s = ffecom_sym_transform_ (s);
6088 }
5ff904cd 6089
c7e4ee3a
CB
6090 if ((ffesymbol_where (s) == FFEINFO_whereCOMMON)
6091 && (ffesymbol_hook (s).decl_tree != error_mark_node))
6092 {
c7e4ee3a
CB
6093 /* This isn't working, at least for dbxout. The .s file looks
6094 okay to me (burley), but in gdb 4.9 at least, the variables
6095 appear to reside somewhere outside of the common area, so
6096 it doesn't make sense to mislead anyone by generating the info
6097 on those variables until this is fixed. NOTE: Same problem
6098 with EQUIVALENCE, sadly...see similar #if later. */
6099 ffecom_member_phase2_ (ffesymbol_storage (ffesymbol_common (s)),
6100 ffesymbol_storage (s));
5ff904cd
JL
6101 }
6102
c7e4ee3a
CB
6103 return s;
6104}
5ff904cd 6105
c7e4ee3a
CB
6106#endif
6107/* Append underscore(s) to name before calling get_identifier. "us"
6108 is nonzero if the name already contains an underscore and thus
6109 needs two underscores appended. */
5ff904cd 6110
c7e4ee3a
CB
6111#if FFECOM_targetCURRENT == FFECOM_targetGCC
6112static tree
6113ffecom_get_appended_identifier_ (char us, const char *name)
6114{
6115 int i;
6116 char *newname;
6117 tree id;
5ff904cd 6118
c7e4ee3a
CB
6119 newname = xmalloc ((i = strlen (name)) + 1
6120 + ffe_is_underscoring ()
6121 + us);
6122 memcpy (newname, name, i);
6123 newname[i] = '_';
6124 newname[i + us] = '_';
6125 newname[i + 1 + us] = '\0';
6126 id = get_identifier (newname);
5ff904cd 6127
c7e4ee3a 6128 free (newname);
5ff904cd 6129
c7e4ee3a
CB
6130 return id;
6131}
5ff904cd 6132
c7e4ee3a
CB
6133#endif
6134/* Decide whether to append underscore to name before calling
6135 get_identifier. */
5ff904cd 6136
c7e4ee3a
CB
6137#if FFECOM_targetCURRENT == FFECOM_targetGCC
6138static tree
6139ffecom_get_external_identifier_ (ffesymbol s)
6140{
6141 char us;
6142 const char *name = ffesymbol_text (s);
5ff904cd 6143
c7e4ee3a 6144 /* If name is a built-in name, just return it as is. */
5ff904cd 6145
c7e4ee3a
CB
6146 if (!ffe_is_underscoring ()
6147 || (strcmp (name, FFETARGET_nameBLANK_COMMON) == 0)
6148#if FFETARGET_isENFORCED_MAIN_NAME
6149 || (strcmp (name, FFETARGET_nameENFORCED_NAME) == 0)
6150#else
6151 || (strcmp (name, FFETARGET_nameUNNAMED_MAIN) == 0)
6152#endif
6153 || (strcmp (name, FFETARGET_nameUNNAMED_BLOCK_DATA) == 0))
6154 return get_identifier (name);
5ff904cd 6155
c7e4ee3a
CB
6156 us = ffe_is_second_underscore ()
6157 ? (strchr (name, '_') != NULL)
6158 : 0;
5ff904cd 6159
c7e4ee3a
CB
6160 return ffecom_get_appended_identifier_ (us, name);
6161}
5ff904cd 6162
c7e4ee3a
CB
6163#endif
6164/* Decide whether to append underscore to internal name before calling
6165 get_identifier.
6166
6167 This is for non-external, top-function-context names only. Transform
6168 identifier so it doesn't conflict with the transformed result
6169 of using a _different_ external name. E.g. if "CALL FOO" is
6170 transformed into "FOO_();", then the variable in "FOO_ = 3"
6171 must be transformed into something that does not conflict, since
6172 these two things should be independent.
5ff904cd 6173
c7e4ee3a
CB
6174 The transformation is as follows. If the name does not contain
6175 an underscore, there is no possible conflict, so just return.
6176 If the name does contain an underscore, then transform it just
6177 like we transform an external identifier. */
5ff904cd 6178
c7e4ee3a
CB
6179#if FFECOM_targetCURRENT == FFECOM_targetGCC
6180static tree
6181ffecom_get_identifier_ (const char *name)
6182{
6183 /* If name does not contain an underscore, just return it as is. */
6184
6185 if (!ffe_is_underscoring ()
6186 || (strchr (name, '_') == NULL))
6187 return get_identifier (name);
6188
6189 return ffecom_get_appended_identifier_ (ffe_is_second_underscore (),
6190 name);
5ff904cd
JL
6191}
6192
6193#endif
c7e4ee3a 6194/* ffecom_gen_sfuncdef_ -- Generate definition of statement function
5ff904cd 6195
c7e4ee3a
CB
6196 tree t;
6197 ffesymbol s; // kindFUNCTION, whereIMMEDIATE.
6198 t = ffecom_gen_sfuncdef_(s,ffesymbol_basictype(s),
6199 ffesymbol_kindtype(s));
5ff904cd 6200
c7e4ee3a
CB
6201 Call after setting up containing function and getting trees for all
6202 other symbols. */
5ff904cd
JL
6203
6204#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
6205static tree
6206ffecom_gen_sfuncdef_ (ffesymbol s, ffeinfoBasictype bt, ffeinfoKindtype kt)
5ff904cd 6207{
c7e4ee3a
CB
6208 ffebld expr = ffesymbol_sfexpr (s);
6209 tree type;
6210 tree func;
6211 tree result;
6212 bool charfunc = (bt == FFEINFO_basictypeCHARACTER);
6213 static bool recurse = FALSE;
c7e4ee3a 6214 int old_lineno = lineno;
3b304f5b 6215 const char *old_input_filename = input_filename;
5ff904cd 6216
c7e4ee3a 6217 ffecom_nested_entry_ = s;
5ff904cd 6218
c7e4ee3a
CB
6219 /* For now, we don't have a handy pointer to where the sfunc is actually
6220 defined, though that should be easy to add to an ffesymbol. (The
6221 token/where info available might well point to the place where the type
6222 of the sfunc is declared, especially if that precedes the place where
6223 the sfunc itself is defined, which is typically the case.) We should
6224 put out a null pointer rather than point somewhere wrong, but I want to
6225 see how it works at this point. */
5ff904cd 6226
c7e4ee3a
CB
6227 input_filename = ffesymbol_where_filename (s);
6228 lineno = ffesymbol_where_filelinenum (s);
5ff904cd 6229
c7e4ee3a
CB
6230 /* Pretransform the expression so any newly discovered things belong to the
6231 outer program unit, not to the statement function. */
5ff904cd 6232
c7e4ee3a 6233 ffecom_expr_transform_ (expr);
5ff904cd 6234
c7e4ee3a
CB
6235 /* Make sure no recursive invocation of this fn (a specific case of failing
6236 to pretransform an sfunc's expression, i.e. where its expression
6237 references another untransformed sfunc) happens. */
6238
6239 assert (!recurse);
6240 recurse = TRUE;
6241
c7e4ee3a
CB
6242 push_f_function_context ();
6243
6244 if (charfunc)
6245 type = void_type_node;
6246 else
5ff904cd 6247 {
c7e4ee3a
CB
6248 type = ffecom_tree_type[bt][kt];
6249 if (type == NULL_TREE)
6250 type = integer_type_node; /* _sym_exec_transition reports
6251 error. */
6252 }
5ff904cd 6253
c7e4ee3a
CB
6254 start_function (ffecom_get_identifier_ (ffesymbol_text (s)),
6255 build_function_type (type, NULL_TREE),
6256 1, /* nested/inline */
6257 0); /* TREE_PUBLIC */
5ff904cd 6258
c7e4ee3a
CB
6259 /* We don't worry about COMPLEX return values here, because this is
6260 entirely internal to our code, and gcc has the ability to return COMPLEX
6261 directly as a value. */
6262
c7e4ee3a
CB
6263 if (charfunc)
6264 { /* Prepend arg for where result goes. */
6265 tree type;
6266
6267 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
6268
14657de8 6269 result = ffecom_get_invented_identifier ("__g77_%s", "result");
c7e4ee3a
CB
6270
6271 ffecom_char_enhance_arg_ (&type, s); /* Ignore returned length. */
6272
6273 type = build_pointer_type (type);
6274 result = build_decl (PARM_DECL, result, type);
6275
6276 push_parm_decl (result);
5ff904cd 6277 }
c7e4ee3a
CB
6278 else
6279 result = NULL_TREE; /* Not ref'd if !charfunc. */
5ff904cd 6280
c7e4ee3a 6281 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (s), TRUE);
5ff904cd 6282
c7e4ee3a
CB
6283 store_parm_decls (0);
6284
6285 ffecom_start_compstmt ();
6286
6287 if (expr != NULL)
5ff904cd 6288 {
c7e4ee3a
CB
6289 if (charfunc)
6290 {
6291 ffetargetCharacterSize sz = ffesymbol_size (s);
6292 tree result_length;
5ff904cd 6293
c7e4ee3a
CB
6294 result_length = build_int_2 (sz, 0);
6295 TREE_TYPE (result_length) = ffecom_f2c_ftnlen_type_node;
5ff904cd 6296
c7e4ee3a 6297 ffecom_prepare_let_char_ (sz, expr);
5ff904cd 6298
c7e4ee3a 6299 ffecom_prepare_end ();
5ff904cd 6300
c7e4ee3a
CB
6301 ffecom_let_char_ (result, result_length, sz, expr);
6302 expand_null_return ();
6303 }
6304 else
6305 {
6306 ffecom_prepare_expr (expr);
5ff904cd 6307
c7e4ee3a 6308 ffecom_prepare_end ();
5ff904cd 6309
c7e4ee3a
CB
6310 expand_return (ffecom_modify (NULL_TREE,
6311 DECL_RESULT (current_function_decl),
6312 ffecom_expr (expr)));
6313 }
c7e4ee3a 6314 }
5ff904cd 6315
c7e4ee3a 6316 ffecom_end_compstmt ();
5ff904cd 6317
c7e4ee3a
CB
6318 func = current_function_decl;
6319 finish_function (1);
5ff904cd 6320
c7e4ee3a 6321 pop_f_function_context ();
5ff904cd 6322
c7e4ee3a
CB
6323 recurse = FALSE;
6324
6325 lineno = old_lineno;
6326 input_filename = old_input_filename;
6327
6328 ffecom_nested_entry_ = NULL;
6329
6330 return func;
5ff904cd
JL
6331}
6332
6333#endif
5ff904cd 6334
c7e4ee3a
CB
6335#if FFECOM_targetCURRENT == FFECOM_targetGCC
6336static const char *
6337ffecom_gfrt_args_ (ffecomGfrt ix)
5ff904cd 6338{
c7e4ee3a
CB
6339 return ffecom_gfrt_argstring_[ix];
6340}
5ff904cd 6341
c7e4ee3a
CB
6342#endif
6343#if FFECOM_targetCURRENT == FFECOM_targetGCC
6344static tree
6345ffecom_gfrt_tree_ (ffecomGfrt ix)
6346{
6347 if (ffecom_gfrt_[ix] == NULL_TREE)
6348 ffecom_make_gfrt_ (ix);
6349
6350 return ffecom_1 (ADDR_EXPR,
6351 build_pointer_type (TREE_TYPE (ffecom_gfrt_[ix])),
6352 ffecom_gfrt_[ix]);
5ff904cd
JL
6353}
6354
6355#endif
c7e4ee3a 6356/* Return initialize-to-zero expression for this VAR_DECL. */
5ff904cd
JL
6357
6358#if FFECOM_targetCURRENT == FFECOM_targetGCC
7189a4b0
GK
6359/* A somewhat evil way to prevent the garbage collector
6360 from collecting 'tree' structures. */
6361#define NUM_TRACKED_CHUNK 63
6362static struct tree_ggc_tracker
6363{
6364 struct tree_ggc_tracker *next;
6365 tree trees[NUM_TRACKED_CHUNK];
6366} *tracker_head = NULL;
6367
6368static void
54551044 6369mark_tracker_head (void *arg)
7189a4b0
GK
6370{
6371 struct tree_ggc_tracker *head;
6372 int i;
6373
6374 for (head = * (struct tree_ggc_tracker **) arg;
6375 head != NULL;
6376 head = head->next)
6377 {
6378 ggc_mark (head);
6379 for (i = 0; i < NUM_TRACKED_CHUNK; i++)
6380 ggc_mark_tree (head->trees[i]);
6381 }
6382}
6383
6384void
6385ffecom_save_tree_forever (tree t)
6386{
6387 int i;
6388 if (tracker_head != NULL)
6389 for (i = 0; i < NUM_TRACKED_CHUNK; i++)
6390 if (tracker_head->trees[i] == NULL)
6391 {
6392 tracker_head->trees[i] = t;
6393 return;
6394 }
6395
6396 {
6397 /* Need to allocate a new block. */
6398 struct tree_ggc_tracker *old_head = tracker_head;
6399
6400 tracker_head = ggc_alloc (sizeof (*tracker_head));
6401 tracker_head->next = old_head;
6402 tracker_head->trees[0] = t;
6403 for (i = 1; i < NUM_TRACKED_CHUNK; i++)
6404 tracker_head->trees[i] = NULL;
6405 }
6406}
6407
c7e4ee3a
CB
6408static tree
6409ffecom_init_zero_ (tree decl)
5ff904cd 6410{
c7e4ee3a
CB
6411 tree init;
6412 int incremental = TREE_STATIC (decl);
6413 tree type = TREE_TYPE (decl);
5ff904cd 6414
c7e4ee3a
CB
6415 if (incremental)
6416 {
6c418184 6417 make_decl_rtl (decl, NULL);
c7e4ee3a 6418 assemble_variable (decl, TREE_PUBLIC (decl) ? 1 : 0, 0, 1);
c7e4ee3a 6419 }
5ff904cd 6420
c7e4ee3a
CB
6421 if ((TREE_CODE (type) != ARRAY_TYPE)
6422 && (TREE_CODE (type) != RECORD_TYPE)
6423 && (TREE_CODE (type) != UNION_TYPE)
6424 && !incremental)
6425 init = convert (type, integer_zero_node);
6426 else if (!incremental)
6427 {
c7e4ee3a
CB
6428 init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
6429 TREE_CONSTANT (init) = 1;
6430 TREE_STATIC (init) = 1;
c7e4ee3a
CB
6431 }
6432 else
6433 {
c7e4ee3a
CB
6434 assemble_zeros (int_size_in_bytes (type));
6435 init = error_mark_node;
c7e4ee3a 6436 }
5ff904cd 6437
c7e4ee3a 6438 return init;
5ff904cd
JL
6439}
6440
6441#endif
5ff904cd 6442#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
6443static tree
6444ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg,
6445 tree *maybe_tree)
5ff904cd 6446{
c7e4ee3a
CB
6447 tree expr_tree;
6448 tree length_tree;
5ff904cd 6449
c7e4ee3a 6450 switch (ffebld_op (arg))
6829256f 6451 {
c7e4ee3a
CB
6452 case FFEBLD_opCONTER: /* For F90, check 0-length. */
6453 if (ffetarget_length_character1
6454 (ffebld_constant_character1
6455 (ffebld_conter (arg))) == 0)
6456 {
6457 *maybe_tree = integer_zero_node;
6458 return convert (tree_type, integer_zero_node);
6459 }
5ff904cd 6460
c7e4ee3a
CB
6461 *maybe_tree = integer_one_node;
6462 expr_tree = build_int_2 (*ffetarget_text_character1
6463 (ffebld_constant_character1
6464 (ffebld_conter (arg))),
6465 0);
6466 TREE_TYPE (expr_tree) = tree_type;
6467 return expr_tree;
5ff904cd 6468
c7e4ee3a
CB
6469 case FFEBLD_opSYMTER:
6470 case FFEBLD_opARRAYREF:
6471 case FFEBLD_opFUNCREF:
6472 case FFEBLD_opSUBSTR:
6473 ffecom_char_args_ (&expr_tree, &length_tree, arg);
5ff904cd 6474
c7e4ee3a
CB
6475 if ((expr_tree == error_mark_node)
6476 || (length_tree == error_mark_node))
6477 {
6478 *maybe_tree = error_mark_node;
6479 return error_mark_node;
6480 }
5ff904cd 6481
c7e4ee3a
CB
6482 if (integer_zerop (length_tree))
6483 {
6484 *maybe_tree = integer_zero_node;
6485 return convert (tree_type, integer_zero_node);
6486 }
6487
6488 expr_tree
6489 = ffecom_1 (INDIRECT_REF,
6490 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
6491 expr_tree);
6492 expr_tree
6493 = ffecom_2 (ARRAY_REF,
6494 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
6495 expr_tree,
6496 integer_one_node);
6497 expr_tree = convert (tree_type, expr_tree);
6498
6499 if (TREE_CODE (length_tree) == INTEGER_CST)
6500 *maybe_tree = integer_one_node;
6501 else /* Must check length at run time. */
6502 *maybe_tree
6503 = ffecom_truth_value
6504 (ffecom_2 (GT_EXPR, integer_type_node,
6505 length_tree,
6506 ffecom_f2c_ftnlen_zero_node));
6507 return expr_tree;
6508
6509 case FFEBLD_opPAREN:
6510 case FFEBLD_opCONVERT:
6511 if (ffeinfo_size (ffebld_info (arg)) == 0)
6512 {
6513 *maybe_tree = integer_zero_node;
6514 return convert (tree_type, integer_zero_node);
6515 }
6516 return ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
6517 maybe_tree);
6518
6519 case FFEBLD_opCONCATENATE:
6520 {
6521 tree maybe_left;
6522 tree maybe_right;
6523 tree expr_left;
6524 tree expr_right;
6525
6526 expr_left = ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
6527 &maybe_left);
6528 expr_right = ffecom_intrinsic_ichar_ (tree_type, ffebld_right (arg),
6529 &maybe_right);
6530 *maybe_tree = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
6531 maybe_left,
6532 maybe_right);
6533 expr_tree = ffecom_3 (COND_EXPR, tree_type,
6534 maybe_left,
6535 expr_left,
6536 expr_right);
6537 return expr_tree;
6538 }
6539
6540 default:
6541 assert ("bad op in ICHAR" == NULL);
6542 return error_mark_node;
6543 }
5ff904cd
JL
6544}
6545
6546#endif
c7e4ee3a
CB
6547/* ffecom_intrinsic_len_ -- Return length info for char arg (LEN())
6548
6549 tree length_arg;
6550 ffebld expr;
6551 length_arg = ffecom_intrinsic_len_ (expr);
6552
6553 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
6554 subexpressions by constructing the appropriate tree for the
6555 length-of-character-text argument in a calling sequence. */
5ff904cd
JL
6556
6557#if FFECOM_targetCURRENT == FFECOM_targetGCC
6558static tree
c7e4ee3a 6559ffecom_intrinsic_len_ (ffebld expr)
5ff904cd 6560{
c7e4ee3a
CB
6561 ffetargetCharacter1 val;
6562 tree length;
6563
6564 switch (ffebld_op (expr))
6565 {
6566 case FFEBLD_opCONTER:
6567 val = ffebld_constant_character1 (ffebld_conter (expr));
6568 length = build_int_2 (ffetarget_length_character1 (val), 0);
6569 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6570 break;
6571
6572 case FFEBLD_opSYMTER:
6573 {
6574 ffesymbol s = ffebld_symter (expr);
6575 tree item;
6576
6577 item = ffesymbol_hook (s).decl_tree;
6578 if (item == NULL_TREE)
6579 {
6580 s = ffecom_sym_transform_ (s);
6581 item = ffesymbol_hook (s).decl_tree;
6582 }
6583 if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
6584 {
6585 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
6586 length = ffesymbol_hook (s).length_tree;
6587 else
6588 {
6589 length = build_int_2 (ffesymbol_size (s), 0);
6590 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6591 }
6592 }
6593 else if (item == error_mark_node)
6594 length = error_mark_node;
6595 else /* FFEINFO_kindFUNCTION: */
6596 length = NULL_TREE;
6597 }
6598 break;
5ff904cd 6599
c7e4ee3a
CB
6600 case FFEBLD_opARRAYREF:
6601 length = ffecom_intrinsic_len_ (ffebld_left (expr));
6602 break;
5ff904cd 6603
c7e4ee3a
CB
6604 case FFEBLD_opSUBSTR:
6605 {
6606 ffebld start;
6607 ffebld end;
6608 ffebld thing = ffebld_right (expr);
6609 tree start_tree;
6610 tree end_tree;
5ff904cd 6611
c7e4ee3a
CB
6612 assert (ffebld_op (thing) == FFEBLD_opITEM);
6613 start = ffebld_head (thing);
6614 thing = ffebld_trail (thing);
6615 assert (ffebld_trail (thing) == NULL);
6616 end = ffebld_head (thing);
5ff904cd 6617
c7e4ee3a 6618 length = ffecom_intrinsic_len_ (ffebld_left (expr));
5ff904cd 6619
c7e4ee3a
CB
6620 if (length == error_mark_node)
6621 break;
5ff904cd 6622
c7e4ee3a
CB
6623 if (start == NULL)
6624 {
6625 if (end == NULL)
6626 ;
6627 else
6628 {
6629 length = convert (ffecom_f2c_ftnlen_type_node,
6630 ffecom_expr (end));
6631 }
6632 }
6633 else
6634 {
6635 start_tree = convert (ffecom_f2c_ftnlen_type_node,
6636 ffecom_expr (start));
5ff904cd 6637
c7e4ee3a
CB
6638 if (start_tree == error_mark_node)
6639 {
6640 length = error_mark_node;
6641 break;
6642 }
5ff904cd 6643
c7e4ee3a
CB
6644 if (end == NULL)
6645 {
6646 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6647 ffecom_f2c_ftnlen_one_node,
6648 ffecom_2 (MINUS_EXPR,
6649 ffecom_f2c_ftnlen_type_node,
6650 length,
6651 start_tree));
6652 }
6653 else
6654 {
6655 end_tree = convert (ffecom_f2c_ftnlen_type_node,
6656 ffecom_expr (end));
5ff904cd 6657
c7e4ee3a
CB
6658 if (end_tree == error_mark_node)
6659 {
6660 length = error_mark_node;
6661 break;
6662 }
5ff904cd 6663
c7e4ee3a
CB
6664 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6665 ffecom_f2c_ftnlen_one_node,
6666 ffecom_2 (MINUS_EXPR,
6667 ffecom_f2c_ftnlen_type_node,
6668 end_tree, start_tree));
6669 }
6670 }
6671 }
6672 break;
5ff904cd 6673
c7e4ee3a
CB
6674 case FFEBLD_opCONCATENATE:
6675 length
6676 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6677 ffecom_intrinsic_len_ (ffebld_left (expr)),
6678 ffecom_intrinsic_len_ (ffebld_right (expr)));
6679 break;
5ff904cd 6680
c7e4ee3a
CB
6681 case FFEBLD_opFUNCREF:
6682 case FFEBLD_opCONVERT:
6683 length = build_int_2 (ffebld_size (expr), 0);
6684 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6685 break;
5ff904cd 6686
c7e4ee3a
CB
6687 default:
6688 assert ("bad op for single char arg expr" == NULL);
6689 length = ffecom_f2c_ftnlen_zero_node;
6690 break;
6691 }
5ff904cd 6692
c7e4ee3a 6693 assert (length != NULL_TREE);
5ff904cd 6694
c7e4ee3a 6695 return length;
5ff904cd
JL
6696}
6697
6698#endif
c7e4ee3a 6699/* Handle CHARACTER assignments.
5ff904cd 6700
c7e4ee3a
CB
6701 Generates code to do the assignment. Used by ordinary assignment
6702 statement handler ffecom_let_stmt and by statement-function
6703 handler to generate code for a statement function. */
5ff904cd
JL
6704
6705#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
6706static void
6707ffecom_let_char_ (tree dest_tree, tree dest_length,
6708 ffetargetCharacterSize dest_size, ffebld source)
5ff904cd 6709{
c7e4ee3a
CB
6710 ffecomConcatList_ catlist;
6711 tree source_length;
6712 tree source_tree;
6713 tree expr_tree;
5ff904cd 6714
c7e4ee3a
CB
6715 if ((dest_tree == error_mark_node)
6716 || (dest_length == error_mark_node))
6717 return;
5ff904cd 6718
c7e4ee3a
CB
6719 assert (dest_tree != NULL_TREE);
6720 assert (dest_length != NULL_TREE);
5ff904cd 6721
c7e4ee3a
CB
6722 /* Source might be an opCONVERT, which just means it is a different size
6723 than the destination. Since the underlying implementation here handles
6724 that (directly or via the s_copy or s_cat run-time-library functions),
6725 we don't need the "convenience" of an opCONVERT that tells us to
6726 truncate or blank-pad, particularly since the resulting implementation
6727 would probably be slower than otherwise. */
5ff904cd 6728
c7e4ee3a
CB
6729 while (ffebld_op (source) == FFEBLD_opCONVERT)
6730 source = ffebld_left (source);
5ff904cd 6731
c7e4ee3a
CB
6732 catlist = ffecom_concat_list_new_ (source, dest_size);
6733 switch (ffecom_concat_list_count_ (catlist))
6734 {
6735 case 0: /* Shouldn't happen, but in case it does... */
6736 ffecom_concat_list_kill_ (catlist);
6737 source_tree = null_pointer_node;
6738 source_length = ffecom_f2c_ftnlen_zero_node;
6739 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6740 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
6741 TREE_CHAIN (TREE_CHAIN (expr_tree))
6742 = build_tree_list (NULL_TREE, dest_length);
6743 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6744 = build_tree_list (NULL_TREE, source_length);
5ff904cd 6745
c7e4ee3a
CB
6746 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree, NULL_TREE);
6747 TREE_SIDE_EFFECTS (expr_tree) = 1;
5ff904cd 6748
c7e4ee3a 6749 expand_expr_stmt (expr_tree);
5ff904cd 6750
c7e4ee3a 6751 return;
5ff904cd 6752
c7e4ee3a
CB
6753 case 1: /* The (fairly) easy case. */
6754 ffecom_char_args_ (&source_tree, &source_length,
6755 ffecom_concat_list_expr_ (catlist, 0));
6756 ffecom_concat_list_kill_ (catlist);
6757 assert (source_tree != NULL_TREE);
6758 assert (source_length != NULL_TREE);
6759
6760 if ((source_tree == error_mark_node)
6761 || (source_length == error_mark_node))
6762 return;
6763
6764 if (dest_size == 1)
6765 {
6766 dest_tree
6767 = ffecom_1 (INDIRECT_REF,
6768 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6769 (dest_tree))),
6770 dest_tree);
6771 dest_tree
6772 = ffecom_2 (ARRAY_REF,
6773 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6774 (dest_tree))),
6775 dest_tree,
6776 integer_one_node);
6777 source_tree
6778 = ffecom_1 (INDIRECT_REF,
6779 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6780 (source_tree))),
6781 source_tree);
6782 source_tree
6783 = ffecom_2 (ARRAY_REF,
6784 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6785 (source_tree))),
6786 source_tree,
6787 integer_one_node);
5ff904cd 6788
c7e4ee3a 6789 expr_tree = ffecom_modify (void_type_node, dest_tree, source_tree);
5ff904cd 6790
c7e4ee3a 6791 expand_expr_stmt (expr_tree);
5ff904cd 6792
c7e4ee3a
CB
6793 return;
6794 }
5ff904cd 6795
c7e4ee3a
CB
6796 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6797 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
6798 TREE_CHAIN (TREE_CHAIN (expr_tree))
6799 = build_tree_list (NULL_TREE, dest_length);
6800 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6801 = build_tree_list (NULL_TREE, source_length);
5ff904cd 6802
c7e4ee3a
CB
6803 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree, NULL_TREE);
6804 TREE_SIDE_EFFECTS (expr_tree) = 1;
5ff904cd 6805
c7e4ee3a 6806 expand_expr_stmt (expr_tree);
5ff904cd 6807
c7e4ee3a 6808 return;
5ff904cd 6809
c7e4ee3a
CB
6810 default: /* Must actually concatenate things. */
6811 break;
6812 }
5ff904cd 6813
c7e4ee3a 6814 /* Heavy-duty concatenation. */
5ff904cd 6815
c7e4ee3a
CB
6816 {
6817 int count = ffecom_concat_list_count_ (catlist);
6818 int i;
6819 tree lengths;
6820 tree items;
6821 tree length_array;
6822 tree item_array;
6823 tree citem;
6824 tree clength;
5ff904cd 6825
c7e4ee3a
CB
6826#ifdef HOHO
6827 length_array
6828 = lengths
6829 = ffecom_push_tempvar (ffecom_f2c_ftnlen_type_node,
6830 FFETARGET_charactersizeNONE, count, TRUE);
6831 item_array = items = ffecom_push_tempvar (ffecom_f2c_address_type_node,
6832 FFETARGET_charactersizeNONE,
6833 count, TRUE);
6834#else
6835 {
6836 tree hook;
6837
6838 hook = ffebld_nonter_hook (source);
6839 assert (hook);
6840 assert (TREE_CODE (hook) == TREE_VEC);
6841 assert (TREE_VEC_LENGTH (hook) == 2);
6842 length_array = lengths = TREE_VEC_ELT (hook, 0);
6843 item_array = items = TREE_VEC_ELT (hook, 1);
5ff904cd 6844 }
c7e4ee3a 6845#endif
5ff904cd 6846
c7e4ee3a
CB
6847 for (i = 0; i < count; ++i)
6848 {
6849 ffecom_char_args_ (&citem, &clength,
6850 ffecom_concat_list_expr_ (catlist, i));
6851 if ((citem == error_mark_node)
6852 || (clength == error_mark_node))
6853 {
6854 ffecom_concat_list_kill_ (catlist);
6855 return;
6856 }
5ff904cd 6857
c7e4ee3a
CB
6858 items
6859 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
6860 ffecom_modify (void_type_node,
6861 ffecom_2 (ARRAY_REF,
6862 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
6863 item_array,
6864 build_int_2 (i, 0)),
6865 citem),
6866 items);
6867 lengths
6868 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
6869 ffecom_modify (void_type_node,
6870 ffecom_2 (ARRAY_REF,
6871 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
6872 length_array,
6873 build_int_2 (i, 0)),
6874 clength),
6875 lengths);
6876 }
5ff904cd 6877
c7e4ee3a
CB
6878 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6879 TREE_CHAIN (expr_tree)
6880 = build_tree_list (NULL_TREE,
6881 ffecom_1 (ADDR_EXPR,
6882 build_pointer_type (TREE_TYPE (items)),
6883 items));
6884 TREE_CHAIN (TREE_CHAIN (expr_tree))
6885 = build_tree_list (NULL_TREE,
6886 ffecom_1 (ADDR_EXPR,
6887 build_pointer_type (TREE_TYPE (lengths)),
6888 lengths));
6889 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6890 = build_tree_list
6891 (NULL_TREE,
6892 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
6893 convert (ffecom_f2c_ftnlen_type_node,
6894 build_int_2 (count, 0))));
6895 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree))))
6896 = build_tree_list (NULL_TREE, dest_length);
5ff904cd 6897
c7e4ee3a
CB
6898 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCAT, expr_tree, NULL_TREE);
6899 TREE_SIDE_EFFECTS (expr_tree) = 1;
5ff904cd 6900
c7e4ee3a
CB
6901 expand_expr_stmt (expr_tree);
6902 }
5ff904cd 6903
c7e4ee3a
CB
6904 ffecom_concat_list_kill_ (catlist);
6905}
5ff904cd 6906
c7e4ee3a
CB
6907#endif
6908/* ffecom_make_gfrt_ -- Make initial info for run-time routine
5ff904cd 6909
c7e4ee3a
CB
6910 ffecomGfrt ix;
6911 ffecom_make_gfrt_(ix);
5ff904cd 6912
c7e4ee3a
CB
6913 Assumes gfrt_[ix] is NULL_TREE, and replaces it with the FUNCTION_DECL
6914 for the indicated run-time routine (ix). */
5ff904cd 6915
c7e4ee3a
CB
6916#if FFECOM_targetCURRENT == FFECOM_targetGCC
6917static void
6918ffecom_make_gfrt_ (ffecomGfrt ix)
6919{
6920 tree t;
6921 tree ttype;
5ff904cd 6922
c7e4ee3a
CB
6923 switch (ffecom_gfrt_type_[ix])
6924 {
6925 case FFECOM_rttypeVOID_:
6926 ttype = void_type_node;
6927 break;
5ff904cd 6928
c7e4ee3a
CB
6929 case FFECOM_rttypeVOIDSTAR_:
6930 ttype = TREE_TYPE (null_pointer_node); /* `void *'. */
6931 break;
5ff904cd 6932
c7e4ee3a
CB
6933 case FFECOM_rttypeFTNINT_:
6934 ttype = ffecom_f2c_ftnint_type_node;
6935 break;
5ff904cd 6936
c7e4ee3a
CB
6937 case FFECOM_rttypeINTEGER_:
6938 ttype = ffecom_f2c_integer_type_node;
6939 break;
5ff904cd 6940
c7e4ee3a
CB
6941 case FFECOM_rttypeLONGINT_:
6942 ttype = ffecom_f2c_longint_type_node;
6943 break;
5ff904cd 6944
c7e4ee3a
CB
6945 case FFECOM_rttypeLOGICAL_:
6946 ttype = ffecom_f2c_logical_type_node;
6947 break;
5ff904cd 6948
c7e4ee3a
CB
6949 case FFECOM_rttypeREAL_F2C_:
6950 ttype = double_type_node;
6951 break;
5ff904cd 6952
c7e4ee3a
CB
6953 case FFECOM_rttypeREAL_GNU_:
6954 ttype = float_type_node;
6955 break;
5ff904cd 6956
c7e4ee3a
CB
6957 case FFECOM_rttypeCOMPLEX_F2C_:
6958 ttype = void_type_node;
6959 break;
5ff904cd 6960
c7e4ee3a
CB
6961 case FFECOM_rttypeCOMPLEX_GNU_:
6962 ttype = ffecom_f2c_complex_type_node;
6963 break;
5ff904cd 6964
c7e4ee3a
CB
6965 case FFECOM_rttypeDOUBLE_:
6966 ttype = double_type_node;
6967 break;
5ff904cd 6968
c7e4ee3a
CB
6969 case FFECOM_rttypeDOUBLEREAL_:
6970 ttype = ffecom_f2c_doublereal_type_node;
6971 break;
5ff904cd 6972
c7e4ee3a
CB
6973 case FFECOM_rttypeDBLCMPLX_F2C_:
6974 ttype = void_type_node;
6975 break;
5ff904cd 6976
c7e4ee3a
CB
6977 case FFECOM_rttypeDBLCMPLX_GNU_:
6978 ttype = ffecom_f2c_doublecomplex_type_node;
6979 break;
5ff904cd 6980
c7e4ee3a
CB
6981 case FFECOM_rttypeCHARACTER_:
6982 ttype = void_type_node;
6983 break;
6984
6985 default:
6986 ttype = NULL;
6987 assert ("bad rttype" == NULL);
6988 break;
5ff904cd 6989 }
5ff904cd 6990
c7e4ee3a
CB
6991 ttype = build_function_type (ttype, NULL_TREE);
6992 t = build_decl (FUNCTION_DECL,
6993 get_identifier (ffecom_gfrt_name_[ix]),
6994 ttype);
6995 DECL_EXTERNAL (t) = 1;
95eb4fd9 6996 TREE_READONLY (t) = ffecom_gfrt_const_[ix] ? 1 : 0;
c7e4ee3a
CB
6997 TREE_PUBLIC (t) = 1;
6998 TREE_THIS_VOLATILE (t) = ffecom_gfrt_volatile_[ix] ? 1 : 0;
5ff904cd 6999
95eb4fd9
TM
7000 /* Sanity check: A function that's const cannot be volatile. */
7001
7002 assert (ffecom_gfrt_const_[ix] ? !ffecom_gfrt_volatile_[ix] : 1);
7003
7004 /* Sanity check: A function that's const cannot return complex. */
7005
7006 assert (ffecom_gfrt_const_[ix] ? !ffecom_gfrt_complex_[ix] : 1);
7007
c7e4ee3a 7008 t = start_decl (t, TRUE);
5ff904cd 7009
c7e4ee3a 7010 finish_decl (t, NULL_TREE, TRUE);
5ff904cd 7011
c7e4ee3a 7012 ffecom_gfrt_[ix] = t;
5ff904cd
JL
7013}
7014
7015#endif
c7e4ee3a
CB
7016/* Phase 1 pass over each member of a COMMON/EQUIVALENCE group. */
7017
5ff904cd 7018#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
7019static void
7020ffecom_member_phase1_ (ffestorag mst UNUSED, ffestorag st)
5ff904cd 7021{
c7e4ee3a 7022 ffesymbol s = ffestorag_symbol (st);
5ff904cd 7023
c7e4ee3a
CB
7024 if (ffesymbol_namelisted (s))
7025 ffecom_member_namelisted_ = TRUE;
7026}
5ff904cd 7027
c7e4ee3a
CB
7028#endif
7029/* Phase 2 pass over each member of a COMMON/EQUIVALENCE group. Declare
7030 the member so debugger will see it. Otherwise nobody should be
7031 referencing the member. */
5ff904cd 7032
c7e4ee3a 7033#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
7034static void
7035ffecom_member_phase2_ (ffestorag mst, ffestorag st)
7036{
7037 ffesymbol s;
7038 tree t;
7039 tree mt;
7040 tree type;
5ff904cd 7041
c7e4ee3a
CB
7042 if ((mst == NULL)
7043 || ((mt = ffestorag_hook (mst)) == NULL)
7044 || (mt == error_mark_node))
7045 return;
5ff904cd 7046
c7e4ee3a
CB
7047 if ((st == NULL)
7048 || ((s = ffestorag_symbol (st)) == NULL))
7049 return;
5ff904cd 7050
c7e4ee3a
CB
7051 type = ffecom_type_localvar_ (s,
7052 ffesymbol_basictype (s),
7053 ffesymbol_kindtype (s));
7054 if (type == error_mark_node)
7055 return;
5ff904cd 7056
c7e4ee3a
CB
7057 t = build_decl (VAR_DECL,
7058 ffecom_get_identifier_ (ffesymbol_text (s)),
7059 type);
5ff904cd 7060
c7e4ee3a
CB
7061 TREE_STATIC (t) = TREE_STATIC (mt);
7062 DECL_INITIAL (t) = NULL_TREE;
7063 TREE_ASM_WRITTEN (t) = 1;
045edebe 7064 TREE_USED (t) = 1;
5ff904cd 7065
19e7881c
MM
7066 SET_DECL_RTL (t,
7067 gen_rtx (MEM, TYPE_MODE (type),
7068 plus_constant (XEXP (DECL_RTL (mt), 0),
7069 ffestorag_modulo (mst)
7070 + ffestorag_offset (st)
7071 - ffestorag_offset (mst))));
5ff904cd 7072
c7e4ee3a 7073 t = start_decl (t, FALSE);
5ff904cd 7074
c7e4ee3a 7075 finish_decl (t, NULL_TREE, FALSE);
5ff904cd
JL
7076}
7077
c7e4ee3a
CB
7078#endif
7079/* Prepare source expression for assignment into a destination perhaps known
7080 to be of a specific size. */
5ff904cd 7081
c7e4ee3a
CB
7082static void
7083ffecom_prepare_let_char_ (ffetargetCharacterSize dest_size, ffebld source)
5ff904cd 7084{
c7e4ee3a
CB
7085 ffecomConcatList_ catlist;
7086 int count;
7087 int i;
7088 tree ltmp;
7089 tree itmp;
7090 tree tempvar = NULL_TREE;
5ff904cd 7091
c7e4ee3a
CB
7092 while (ffebld_op (source) == FFEBLD_opCONVERT)
7093 source = ffebld_left (source);
5ff904cd 7094
c7e4ee3a
CB
7095 catlist = ffecom_concat_list_new_ (source, dest_size);
7096 count = ffecom_concat_list_count_ (catlist);
5ff904cd 7097
c7e4ee3a
CB
7098 if (count >= 2)
7099 {
7100 ltmp
7101 = ffecom_make_tempvar ("let_char_len", ffecom_f2c_ftnlen_type_node,
7102 FFETARGET_charactersizeNONE, count);
7103 itmp
7104 = ffecom_make_tempvar ("let_char_item", ffecom_f2c_address_type_node,
7105 FFETARGET_charactersizeNONE, count);
7106
7107 tempvar = make_tree_vec (2);
7108 TREE_VEC_ELT (tempvar, 0) = ltmp;
7109 TREE_VEC_ELT (tempvar, 1) = itmp;
7110 }
5ff904cd 7111
c7e4ee3a
CB
7112 for (i = 0; i < count; ++i)
7113 ffecom_prepare_arg_ptr_to_expr (ffecom_concat_list_expr_ (catlist, i));
5ff904cd 7114
c7e4ee3a 7115 ffecom_concat_list_kill_ (catlist);
5ff904cd 7116
c7e4ee3a
CB
7117 if (tempvar)
7118 {
7119 ffebld_nonter_set_hook (source, tempvar);
7120 current_binding_level->prep_state = 1;
7121 }
7122}
5ff904cd 7123
c7e4ee3a 7124/* ffecom_push_dummy_decls_ -- Transform dummy args, push parm decls in order
5ff904cd 7125
c7e4ee3a
CB
7126 Ignores STAR (alternate-return) dummies. All other get exec-transitioned
7127 (which generates their trees) and then their trees get push_parm_decl'd.
5ff904cd 7128
c7e4ee3a
CB
7129 The second arg is TRUE if the dummies are for a statement function, in
7130 which case lengths are not pushed for character arguments (since they are
7131 always known by both the caller and the callee, though the code allows
7132 for someday permitting CHAR*(*) stmtfunc dummies). */
5ff904cd 7133
c7e4ee3a
CB
7134#if FFECOM_targetCURRENT == FFECOM_targetGCC
7135static void
7136ffecom_push_dummy_decls_ (ffebld dummy_list, bool stmtfunc)
7137{
7138 ffebld dummy;
7139 ffebld dumlist;
7140 ffesymbol s;
7141 tree parm;
5ff904cd 7142
c7e4ee3a 7143 ffecom_transform_only_dummies_ = TRUE;
5ff904cd 7144
c7e4ee3a 7145 /* First push the parms corresponding to actual dummy "contents". */
5ff904cd 7146
c7e4ee3a
CB
7147 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
7148 {
7149 dummy = ffebld_head (dumlist);
7150 switch (ffebld_op (dummy))
7151 {
7152 case FFEBLD_opSTAR:
7153 case FFEBLD_opANY:
7154 continue; /* Forget alternate returns. */
5ff904cd 7155
c7e4ee3a
CB
7156 default:
7157 break;
7158 }
7159 assert (ffebld_op (dummy) == FFEBLD_opSYMTER);
7160 s = ffebld_symter (dummy);
7161 parm = ffesymbol_hook (s).decl_tree;
7162 if (parm == NULL_TREE)
7163 {
7164 s = ffecom_sym_transform_ (s);
7165 parm = ffesymbol_hook (s).decl_tree;
7166 assert (parm != NULL_TREE);
7167 }
7168 if (parm != error_mark_node)
7169 push_parm_decl (parm);
5ff904cd
JL
7170 }
7171
c7e4ee3a 7172 /* Then, for CHARACTER dummies, push the parms giving their lengths. */
5ff904cd 7173
c7e4ee3a
CB
7174 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
7175 {
7176 dummy = ffebld_head (dumlist);
7177 switch (ffebld_op (dummy))
7178 {
7179 case FFEBLD_opSTAR:
7180 case FFEBLD_opANY:
7181 continue; /* Forget alternate returns, they mean
7182 NOTHING! */
7183
7184 default:
7185 break;
7186 }
7187 s = ffebld_symter (dummy);
7188 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
7189 continue; /* Only looking for CHARACTER arguments. */
7190 if (stmtfunc && (ffesymbol_size (s) != FFETARGET_charactersizeNONE))
7191 continue; /* Stmtfunc arg with known size needs no
7192 length param. */
7193 if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
7194 continue; /* Only looking for variables and arrays. */
7195 parm = ffesymbol_hook (s).length_tree;
7196 assert (parm != NULL_TREE);
7197 if (parm != error_mark_node)
7198 push_parm_decl (parm);
7199 }
7200
7201 ffecom_transform_only_dummies_ = FALSE;
5ff904cd
JL
7202}
7203
7204#endif
c7e4ee3a 7205/* ffecom_start_progunit_ -- Beginning of program unit
5ff904cd 7206
c7e4ee3a
CB
7207 Does GNU back end stuff necessary to teach it about the start of its
7208 equivalent of a Fortran program unit. */
5ff904cd
JL
7209
7210#if FFECOM_targetCURRENT == FFECOM_targetGCC
7211static void
c7e4ee3a 7212ffecom_start_progunit_ ()
5ff904cd 7213{
c7e4ee3a
CB
7214 ffesymbol fn = ffecom_primary_entry_;
7215 ffebld arglist;
7216 tree id; /* Identifier (name) of function. */
7217 tree type; /* Type of function. */
7218 tree result; /* Result of function. */
7219 ffeinfoBasictype bt;
7220 ffeinfoKindtype kt;
7221 ffeglobal g;
7222 ffeglobalType gt;
7223 ffeglobalType egt = FFEGLOBAL_type;
7224 bool charfunc;
7225 bool cmplxfunc;
7226 bool altentries = (ffecom_num_entrypoints_ != 0);
7227 bool multi
7228 = altentries
7229 && (ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
7230 && (ffecom_master_bt_ == FFEINFO_basictypeNONE);
7231 bool main_program = FALSE;
7232 int old_lineno = lineno;
3b304f5b 7233 const char *old_input_filename = input_filename;
5ff904cd 7234
c7e4ee3a
CB
7235 assert (fn != NULL);
7236 assert (ffesymbol_hook (fn).decl_tree == NULL_TREE);
5ff904cd 7237
c7e4ee3a
CB
7238 input_filename = ffesymbol_where_filename (fn);
7239 lineno = ffesymbol_where_filelinenum (fn);
5ff904cd 7240
c7e4ee3a
CB
7241 switch (ffecom_primary_entry_kind_)
7242 {
7243 case FFEINFO_kindPROGRAM:
7244 main_program = TRUE;
7245 gt = FFEGLOBAL_typeMAIN;
7246 bt = FFEINFO_basictypeNONE;
7247 kt = FFEINFO_kindtypeNONE;
7248 type = ffecom_tree_fun_type_void;
7249 charfunc = FALSE;
7250 cmplxfunc = FALSE;
7251 break;
7252
7253 case FFEINFO_kindBLOCKDATA:
7254 gt = FFEGLOBAL_typeBDATA;
7255 bt = FFEINFO_basictypeNONE;
7256 kt = FFEINFO_kindtypeNONE;
7257 type = ffecom_tree_fun_type_void;
7258 charfunc = FALSE;
7259 cmplxfunc = FALSE;
7260 break;
7261
7262 case FFEINFO_kindFUNCTION:
7263 gt = FFEGLOBAL_typeFUNC;
7264 egt = FFEGLOBAL_typeEXT;
7265 bt = ffesymbol_basictype (fn);
7266 kt = ffesymbol_kindtype (fn);
7267 if (bt == FFEINFO_basictypeNONE)
7268 {
7269 ffeimplic_establish_symbol (fn);
7270 if (ffesymbol_funcresult (fn) != NULL)
7271 ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
7272 bt = ffesymbol_basictype (fn);
7273 kt = ffesymbol_kindtype (fn);
7274 }
7275
7276 if (multi)
7277 charfunc = cmplxfunc = FALSE;
7278 else if (bt == FFEINFO_basictypeCHARACTER)
7279 charfunc = TRUE, cmplxfunc = FALSE;
7280 else if ((bt == FFEINFO_basictypeCOMPLEX)
7281 && ffesymbol_is_f2c (fn)
7282 && !altentries)
7283 charfunc = FALSE, cmplxfunc = TRUE;
7284 else
7285 charfunc = cmplxfunc = FALSE;
7286
7287 if (multi || charfunc)
7288 type = ffecom_tree_fun_type_void;
7289 else if (ffesymbol_is_f2c (fn) && !altentries)
7290 type = ffecom_tree_fun_type[bt][kt];
7291 else
7292 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
7293
7294 if ((type == NULL_TREE)
7295 || (TREE_TYPE (type) == NULL_TREE))
7296 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */
7297 break;
7298
7299 case FFEINFO_kindSUBROUTINE:
7300 gt = FFEGLOBAL_typeSUBR;
7301 egt = FFEGLOBAL_typeEXT;
7302 bt = FFEINFO_basictypeNONE;
7303 kt = FFEINFO_kindtypeNONE;
7304 if (ffecom_is_altreturning_)
7305 type = ffecom_tree_subr_type;
7306 else
7307 type = ffecom_tree_fun_type_void;
7308 charfunc = FALSE;
7309 cmplxfunc = FALSE;
7310 break;
5ff904cd 7311
c7e4ee3a
CB
7312 default:
7313 assert ("say what??" == NULL);
7314 /* Fall through. */
7315 case FFEINFO_kindANY:
7316 gt = FFEGLOBAL_typeANY;
7317 bt = FFEINFO_basictypeNONE;
7318 kt = FFEINFO_kindtypeNONE;
7319 type = error_mark_node;
7320 charfunc = FALSE;
7321 cmplxfunc = FALSE;
7322 break;
7323 }
5ff904cd 7324
c7e4ee3a 7325 if (altentries)
5ff904cd 7326 {
c7e4ee3a 7327 id = ffecom_get_invented_identifier ("__g77_masterfun_%s",
14657de8 7328 ffesymbol_text (fn));
c7e4ee3a
CB
7329 }
7330#if FFETARGET_isENFORCED_MAIN
7331 else if (main_program)
7332 id = get_identifier (FFETARGET_nameENFORCED_MAIN_NAME);
7333#endif
7334 else
7335 id = ffecom_get_external_identifier_ (fn);
5ff904cd 7336
c7e4ee3a
CB
7337 start_function (id,
7338 type,
7339 0, /* nested/inline */
7340 !altentries); /* TREE_PUBLIC */
5ff904cd 7341
c7e4ee3a 7342 TREE_USED (current_function_decl) = 1; /* Avoid spurious warning if altentries. */
5ff904cd 7343
c7e4ee3a
CB
7344 if (!altentries
7345 && ((g = ffesymbol_global (fn)) != NULL)
7346 && ((ffeglobal_type (g) == gt)
7347 || (ffeglobal_type (g) == egt)))
7348 {
7349 ffeglobal_set_hook (g, current_function_decl);
7350 }
5ff904cd 7351
c7e4ee3a
CB
7352 /* Arg handling needs exec-transitioned ffesymbols to work with. But
7353 exec-transitioning needs current_function_decl to be filled in. So we
7354 do these things in two phases. */
5ff904cd 7355
c7e4ee3a
CB
7356 if (altentries)
7357 { /* 1st arg identifies which entrypoint. */
7358 ffecom_which_entrypoint_decl_
7359 = build_decl (PARM_DECL,
7360 ffecom_get_invented_identifier ("__g77_%s",
14657de8 7361 "which_entrypoint"),
c7e4ee3a
CB
7362 integer_type_node);
7363 push_parm_decl (ffecom_which_entrypoint_decl_);
7364 }
5ff904cd 7365
c7e4ee3a
CB
7366 if (charfunc
7367 || cmplxfunc
7368 || multi)
7369 { /* Arg for result (return value). */
7370 tree type;
7371 tree length;
5ff904cd 7372
c7e4ee3a
CB
7373 if (charfunc)
7374 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
7375 else if (cmplxfunc)
7376 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
7377 else
7378 type = ffecom_multi_type_node_;
5ff904cd 7379
14657de8 7380 result = ffecom_get_invented_identifier ("__g77_%s", "result");
5ff904cd 7381
c7e4ee3a 7382 /* Make length arg _and_ enhance type info for CHAR arg itself. */
5ff904cd 7383
c7e4ee3a
CB
7384 if (charfunc)
7385 length = ffecom_char_enhance_arg_ (&type, fn);
7386 else
7387 length = NULL_TREE; /* Not ref'd if !charfunc. */
5ff904cd 7388
c7e4ee3a
CB
7389 type = build_pointer_type (type);
7390 result = build_decl (PARM_DECL, result, type);
5ff904cd 7391
c7e4ee3a
CB
7392 push_parm_decl (result);
7393 if (multi)
7394 ffecom_multi_retval_ = result;
7395 else
7396 ffecom_func_result_ = result;
5ff904cd 7397
c7e4ee3a
CB
7398 if (charfunc)
7399 {
7400 push_parm_decl (length);
7401 ffecom_func_length_ = length;
7402 }
5ff904cd
JL
7403 }
7404
c7e4ee3a
CB
7405 if (ffecom_primary_entry_is_proc_)
7406 {
7407 if (altentries)
7408 arglist = ffecom_master_arglist_;
7409 else
7410 arglist = ffesymbol_dummyargs (fn);
7411 ffecom_push_dummy_decls_ (arglist, FALSE);
7412 }
5ff904cd 7413
c7e4ee3a
CB
7414 if (TREE_CODE (current_function_decl) != ERROR_MARK)
7415 store_parm_decls (main_program ? 1 : 0);
5ff904cd 7416
c7e4ee3a
CB
7417 ffecom_start_compstmt ();
7418 /* Disallow temp vars at this level. */
7419 current_binding_level->prep_state = 2;
5ff904cd 7420
c7e4ee3a
CB
7421 lineno = old_lineno;
7422 input_filename = old_input_filename;
5ff904cd 7423
c7e4ee3a
CB
7424 /* This handles any symbols still untransformed, in case -g specified.
7425 This used to be done in ffecom_finish_progunit, but it turns out to
7426 be necessary to do it here so that statement functions are
7427 expanded before code. But don't bother for BLOCK DATA. */
5ff904cd 7428
c7e4ee3a
CB
7429 if (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
7430 ffesymbol_drive (ffecom_finish_symbol_transform_);
5ff904cd
JL
7431}
7432
7433#endif
c7e4ee3a 7434/* ffecom_sym_transform_ -- Transform FFE sym into backend sym
5ff904cd 7435
c7e4ee3a
CB
7436 ffesymbol s;
7437 ffecom_sym_transform_(s);
7438
7439 The ffesymbol_hook info for s is updated with appropriate backend info
7440 on the symbol. */
7441
7442#if FFECOM_targetCURRENT == FFECOM_targetGCC
7443static ffesymbol
7444ffecom_sym_transform_ (ffesymbol s)
7445{
7446 tree t; /* Transformed thingy. */
7447 tree tlen; /* Length if CHAR*(*). */
7448 bool addr; /* Is t the address of the thingy? */
7449 ffeinfoBasictype bt;
7450 ffeinfoKindtype kt;
7451 ffeglobal g;
c7e4ee3a 7452 int old_lineno = lineno;
3b304f5b 7453 const char *old_input_filename = input_filename;
5ff904cd 7454
c7e4ee3a
CB
7455 /* Must ensure special ASSIGN variables are declared at top of outermost
7456 block, else they'll end up in the innermost block when their first
7457 ASSIGN is seen, which leaves them out of scope when they're the
7458 subject of a GOTO or I/O statement.
5ff904cd 7459
c7e4ee3a
CB
7460 We make this variable even if -fugly-assign. Just let it go unused,
7461 in case it turns out there are cases where we really want to use this
7462 variable anyway (e.g. ASSIGN to INTEGER*2 variable). */
5ff904cd 7463
c7e4ee3a
CB
7464 if (! ffecom_transform_only_dummies_
7465 && ffesymbol_assigned (s)
7466 && ! ffesymbol_hook (s).assign_tree)
7467 s = ffecom_sym_transform_assign_ (s);
5ff904cd 7468
c7e4ee3a 7469 if (ffesymbol_sfdummyparent (s) == NULL)
5ff904cd 7470 {
c7e4ee3a
CB
7471 input_filename = ffesymbol_where_filename (s);
7472 lineno = ffesymbol_where_filelinenum (s);
7473 }
7474 else
7475 {
7476 ffesymbol sf = ffesymbol_sfdummyparent (s);
5ff904cd 7477
c7e4ee3a
CB
7478 input_filename = ffesymbol_where_filename (sf);
7479 lineno = ffesymbol_where_filelinenum (sf);
7480 }
6d433196 7481
c7e4ee3a
CB
7482 bt = ffeinfo_basictype (ffebld_info (s));
7483 kt = ffeinfo_kindtype (ffebld_info (s));
5ff904cd 7484
c7e4ee3a
CB
7485 t = NULL_TREE;
7486 tlen = NULL_TREE;
7487 addr = FALSE;
5ff904cd 7488
c7e4ee3a
CB
7489 switch (ffesymbol_kind (s))
7490 {
7491 case FFEINFO_kindNONE:
7492 switch (ffesymbol_where (s))
7493 {
7494 case FFEINFO_whereDUMMY: /* Subroutine or function. */
7495 assert (ffecom_transform_only_dummies_);
5ff904cd 7496
c7e4ee3a
CB
7497 /* Before 0.4, this could be ENTITY/DUMMY, but see
7498 ffestu_sym_end_transition -- no longer true (in particular, if
7499 it could be an ENTITY, it _will_ be made one, so that
7500 possibility won't come through here). So we never make length
7501 arg for CHARACTER type. */
5ff904cd 7502
c7e4ee3a
CB
7503 t = build_decl (PARM_DECL,
7504 ffecom_get_identifier_ (ffesymbol_text (s)),
7505 ffecom_tree_ptr_to_subr_type);
7506#if BUILT_FOR_270
7507 DECL_ARTIFICIAL (t) = 1;
7508#endif
7509 addr = TRUE;
7510 break;
5ff904cd 7511
c7e4ee3a
CB
7512 case FFEINFO_whereGLOBAL: /* Subroutine or function. */
7513 assert (!ffecom_transform_only_dummies_);
5ff904cd 7514
c7e4ee3a
CB
7515 if (((g = ffesymbol_global (s)) != NULL)
7516 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
7517 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
7518 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
7519 && (ffeglobal_hook (g) != NULL_TREE)
7520 && ffe_is_globals ())
7521 {
7522 t = ffeglobal_hook (g);
7523 break;
7524 }
5ff904cd 7525
c7e4ee3a
CB
7526 t = build_decl (FUNCTION_DECL,
7527 ffecom_get_external_identifier_ (s),
7528 ffecom_tree_subr_type); /* Assume subr. */
7529 DECL_EXTERNAL (t) = 1;
7530 TREE_PUBLIC (t) = 1;
5ff904cd 7531
c7e4ee3a
CB
7532 t = start_decl (t, FALSE);
7533 finish_decl (t, NULL_TREE, FALSE);
795232f7 7534
c7e4ee3a
CB
7535 if ((g != NULL)
7536 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
7537 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
7538 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
7539 ffeglobal_set_hook (g, t);
5ff904cd 7540
7189a4b0 7541 ffecom_save_tree_forever (t);
5ff904cd 7542
c7e4ee3a 7543 break;
5ff904cd 7544
c7e4ee3a
CB
7545 default:
7546 assert ("NONE where unexpected" == NULL);
7547 /* Fall through. */
7548 case FFEINFO_whereANY:
7549 break;
7550 }
5ff904cd 7551 break;
5ff904cd 7552
c7e4ee3a
CB
7553 case FFEINFO_kindENTITY:
7554 switch (ffeinfo_where (ffesymbol_info (s)))
7555 {
5ff904cd 7556
c7e4ee3a
CB
7557 case FFEINFO_whereCONSTANT:
7558 /* ~~Debugging info needed? */
7559 assert (!ffecom_transform_only_dummies_);
7560 t = error_mark_node; /* Shouldn't ever see this in expr. */
7561 break;
5ff904cd 7562
c7e4ee3a
CB
7563 case FFEINFO_whereLOCAL:
7564 assert (!ffecom_transform_only_dummies_);
5ff904cd 7565
c7e4ee3a
CB
7566 {
7567 ffestorag st = ffesymbol_storage (s);
7568 tree type;
5ff904cd 7569
c7e4ee3a
CB
7570 if ((st != NULL)
7571 && (ffestorag_size (st) == 0))
7572 {
7573 t = error_mark_node;
7574 break;
7575 }
5ff904cd 7576
c7e4ee3a 7577 type = ffecom_type_localvar_ (s, bt, kt);
5ff904cd 7578
c7e4ee3a
CB
7579 if (type == error_mark_node)
7580 {
7581 t = error_mark_node;
7582 break;
7583 }
5ff904cd 7584
c7e4ee3a
CB
7585 if ((st != NULL)
7586 && (ffestorag_parent (st) != NULL))
7587 { /* Child of EQUIVALENCE parent. */
7588 ffestorag est;
7589 tree et;
c7e4ee3a 7590 ffetargetOffset offset;
5ff904cd 7591
c7e4ee3a
CB
7592 est = ffestorag_parent (st);
7593 ffecom_transform_equiv_ (est);
5ff904cd 7594
c7e4ee3a
CB
7595 et = ffestorag_hook (est);
7596 assert (et != NULL_TREE);
5ff904cd 7597
c7e4ee3a
CB
7598 if (! TREE_STATIC (et))
7599 put_var_into_stack (et);
5ff904cd 7600
c7e4ee3a
CB
7601 offset = ffestorag_modulo (est)
7602 + ffestorag_offset (ffesymbol_storage (s))
7603 - ffestorag_offset (est);
5ff904cd 7604
c7e4ee3a 7605 ffecom_debug_kludge_ (et, "EQUIVALENCE", s, type, offset);
5ff904cd 7606
c7e4ee3a 7607 /* (t_type *) (((char *) &et) + offset) */
5ff904cd 7608
c7e4ee3a
CB
7609 t = convert (string_type_node, /* (char *) */
7610 ffecom_1 (ADDR_EXPR,
7611 build_pointer_type (TREE_TYPE (et)),
7612 et));
7613 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
7614 t,
7615 build_int_2 (offset, 0));
7616 t = convert (build_pointer_type (type),
7617 t);
d50108c7 7618 TREE_CONSTANT (t) = staticp (et);
5ff904cd 7619
c7e4ee3a 7620 addr = TRUE;
c7e4ee3a
CB
7621 }
7622 else
7623 {
7624 tree initexpr;
7625 bool init = ffesymbol_is_init (s);
5ff904cd 7626
c7e4ee3a
CB
7627 t = build_decl (VAR_DECL,
7628 ffecom_get_identifier_ (ffesymbol_text (s)),
7629 type);
5ff904cd 7630
c7e4ee3a
CB
7631 if (init
7632 || ffesymbol_namelisted (s)
7633#ifdef FFECOM_sizeMAXSTACKITEM
7634 || ((st != NULL)
7635 && (ffestorag_size (st) > FFECOM_sizeMAXSTACKITEM))
7636#endif
7637 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
7638 && (ffecom_primary_entry_kind_
7639 != FFEINFO_kindBLOCKDATA)
7640 && (ffesymbol_is_save (s) || ffe_is_saveall ())))
7641 TREE_STATIC (t) = !ffesymbol_attr (s, FFESYMBOL_attrADJUSTABLE);
7642 else
7643 TREE_STATIC (t) = 0; /* No need to make static. */
5ff904cd 7644
c7e4ee3a
CB
7645 if (init || ffe_is_init_local_zero ())
7646 DECL_INITIAL (t) = error_mark_node;
5ff904cd 7647
c7e4ee3a
CB
7648 /* Keep -Wunused from complaining about var if it
7649 is used as sfunc arg or DATA implied-DO. */
7650 if (ffesymbol_attrs (s) & FFESYMBOL_attrsSFARG)
7651 DECL_IN_SYSTEM_HEADER (t) = 1;
5ff904cd 7652
c7e4ee3a 7653 t = start_decl (t, FALSE);
5ff904cd 7654
c7e4ee3a
CB
7655 if (init)
7656 {
7657 if (ffesymbol_init (s) != NULL)
7658 initexpr = ffecom_expr (ffesymbol_init (s));
7659 else
7660 initexpr = ffecom_init_zero_ (t);
7661 }
7662 else if (ffe_is_init_local_zero ())
7663 initexpr = ffecom_init_zero_ (t);
7664 else
7665 initexpr = NULL_TREE; /* Not ref'd if !init. */
5ff904cd 7666
c7e4ee3a 7667 finish_decl (t, initexpr, FALSE);
5ff904cd 7668
06ceef4e 7669 if (st != NULL && DECL_SIZE (t) != error_mark_node)
c7e4ee3a 7670 {
06ceef4e 7671 assert (TREE_CODE (DECL_SIZE_UNIT (t)) == INTEGER_CST);
05bccae2
RK
7672 assert (0 == compare_tree_int (DECL_SIZE_UNIT (t),
7673 ffestorag_size (st)));
c7e4ee3a 7674 }
c7e4ee3a
CB
7675 }
7676 }
5ff904cd 7677 break;
5ff904cd 7678
c7e4ee3a
CB
7679 case FFEINFO_whereRESULT:
7680 assert (!ffecom_transform_only_dummies_);
5ff904cd 7681
c7e4ee3a
CB
7682 if (bt == FFEINFO_basictypeCHARACTER)
7683 { /* Result is already in list of dummies, use
7684 it (& length). */
7685 t = ffecom_func_result_;
7686 tlen = ffecom_func_length_;
7687 addr = TRUE;
7688 break;
7689 }
7690 if ((ffecom_num_entrypoints_ == 0)
7691 && (bt == FFEINFO_basictypeCOMPLEX)
7692 && (ffesymbol_is_f2c (ffecom_primary_entry_)))
7693 { /* Result is already in list of dummies, use
7694 it. */
7695 t = ffecom_func_result_;
7696 addr = TRUE;
7697 break;
7698 }
7699 if (ffecom_func_result_ != NULL_TREE)
7700 {
7701 t = ffecom_func_result_;
7702 break;
7703 }
7704 if ((ffecom_num_entrypoints_ != 0)
7705 && (ffecom_master_bt_ == FFEINFO_basictypeNONE))
7706 {
c7e4ee3a
CB
7707 assert (ffecom_multi_retval_ != NULL_TREE);
7708 t = ffecom_1 (INDIRECT_REF, ffecom_multi_type_node_,
7709 ffecom_multi_retval_);
7710 t = ffecom_2 (COMPONENT_REF, ffecom_tree_type[bt][kt],
7711 t, ffecom_multi_fields_[bt][kt]);
5ff904cd 7712
c7e4ee3a
CB
7713 break;
7714 }
5ff904cd 7715
c7e4ee3a
CB
7716 t = build_decl (VAR_DECL,
7717 ffecom_get_identifier_ (ffesymbol_text (s)),
7718 ffecom_tree_type[bt][kt]);
7719 TREE_STATIC (t) = 0; /* Put result on stack. */
7720 t = start_decl (t, FALSE);
7721 finish_decl (t, NULL_TREE, FALSE);
5ff904cd 7722
c7e4ee3a 7723 ffecom_func_result_ = t;
5ff904cd 7724
c7e4ee3a 7725 break;
5ff904cd 7726
c7e4ee3a
CB
7727 case FFEINFO_whereDUMMY:
7728 {
7729 tree type;
7730 ffebld dl;
7731 ffebld dim;
7732 tree low;
7733 tree high;
7734 tree old_sizes;
7735 bool adjustable = FALSE; /* Conditionally adjustable? */
5ff904cd 7736
c7e4ee3a
CB
7737 type = ffecom_tree_type[bt][kt];
7738 if (ffesymbol_sfdummyparent (s) != NULL)
7739 {
7740 if (current_function_decl == ffecom_outer_function_decl_)
7741 { /* Exec transition before sfunc
7742 context; get it later. */
7743 break;
7744 }
7745 t = ffecom_get_identifier_ (ffesymbol_text
7746 (ffesymbol_sfdummyparent (s)));
7747 }
7748 else
7749 t = ffecom_get_identifier_ (ffesymbol_text (s));
5ff904cd 7750
c7e4ee3a 7751 assert (ffecom_transform_only_dummies_);
5ff904cd 7752
c7e4ee3a
CB
7753 old_sizes = get_pending_sizes ();
7754 put_pending_sizes (old_sizes);
5ff904cd 7755
c7e4ee3a
CB
7756 if (bt == FFEINFO_basictypeCHARACTER)
7757 tlen = ffecom_char_enhance_arg_ (&type, s);
7758 type = ffecom_check_size_overflow_ (s, type, TRUE);
5ff904cd 7759
c7e4ee3a
CB
7760 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
7761 {
7762 if (type == error_mark_node)
7763 break;
5ff904cd 7764
c7e4ee3a
CB
7765 dim = ffebld_head (dl);
7766 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
7767 if ((ffebld_left (dim) == NULL) || ffecom_doing_entry_)
7768 low = ffecom_integer_one_node;
7769 else
7770 low = ffecom_expr (ffebld_left (dim));
7771 assert (ffebld_right (dim) != NULL);
7772 if ((ffebld_op (ffebld_right (dim)) == FFEBLD_opSTAR)
7773 || ffecom_doing_entry_)
7774 {
7775 /* Used to just do high=low. But for ffecom_tree_
7776 canonize_ref_, it probably is important to correctly
7777 assess the size. E.g. given COMPLEX C(*),CFUNC and
7778 C(2)=CFUNC(C), overlap can happen, while it can't
7779 for, say, C(1)=CFUNC(C(2)). */
7780 /* Even more recently used to set to INT_MAX, but that
7781 broke when some overflow checking went into the back
7782 end. Now we just leave the upper bound unspecified. */
7783 high = NULL;
7784 }
7785 else
7786 high = ffecom_expr (ffebld_right (dim));
5ff904cd 7787
c7e4ee3a
CB
7788 /* Determine whether array is conditionally adjustable,
7789 to decide whether back-end magic is needed.
5ff904cd 7790
c7e4ee3a
CB
7791 Normally the front end uses the back-end function
7792 variable_size to wrap SAVE_EXPR's around expressions
7793 affecting the size/shape of an array so that the
7794 size/shape info doesn't change during execution
7795 of the compiled code even though variables and
7796 functions referenced in those expressions might.
5ff904cd 7797
c7e4ee3a
CB
7798 variable_size also makes sure those saved expressions
7799 get evaluated immediately upon entry to the
7800 compiled procedure -- the front end normally doesn't
7801 have to worry about that.
3cf0cea4 7802
c7e4ee3a
CB
7803 However, there is a problem with this that affects
7804 g77's implementation of entry points, and that is
7805 that it is _not_ true that each invocation of the
7806 compiled procedure is permitted to evaluate
7807 array size/shape info -- because it is possible
7808 that, for some invocations, that info is invalid (in
7809 which case it is "promised" -- i.e. a violation of
7810 the Fortran standard -- that the compiled code
7811 won't reference the array or its size/shape
7812 during that particular invocation).
5ff904cd 7813
c7e4ee3a 7814 To phrase this in C terms, consider this gcc function:
5ff904cd 7815
c7e4ee3a
CB
7816 void foo (int *n, float (*a)[*n])
7817 {
7818 // a is "pointer to array ...", fyi.
7819 }
5ff904cd 7820
c7e4ee3a
CB
7821 Suppose that, for some invocations, it is permitted
7822 for a caller of foo to do this:
5ff904cd 7823
c7e4ee3a 7824 foo (NULL, NULL);
5ff904cd 7825
c7e4ee3a
CB
7826 Now the _written_ code for foo can take such a call
7827 into account by either testing explicitly for whether
7828 (a == NULL) || (n == NULL) -- presumably it is
7829 not permitted to reference *a in various fashions
7830 if (n == NULL) I suppose -- or it can avoid it by
7831 looking at other info (other arguments, static/global
7832 data, etc.).
5ff904cd 7833
c7e4ee3a
CB
7834 However, this won't work in gcc 2.5.8 because it'll
7835 automatically emit the code to save the "*n"
7836 expression, which'll yield a NULL dereference for
7837 the "foo (NULL, NULL)" call, something the code
7838 for foo cannot prevent.
5ff904cd 7839
c7e4ee3a
CB
7840 g77 definitely needs to avoid executing such
7841 code anytime the pointer to the adjustable array
7842 is NULL, because even if its bounds expressions
7843 don't have any references to possible "absent"
7844 variables like "*n" -- say all variable references
7845 are to COMMON variables, i.e. global (though in C,
7846 local static could actually make sense) -- the
7847 expressions could yield other run-time problems
7848 for allowably "dead" values in those variables.
5ff904cd 7849
c7e4ee3a
CB
7850 For example, let's consider a more complicated
7851 version of foo:
5ff904cd 7852
c7e4ee3a
CB
7853 extern int i;
7854 extern int j;
5ff904cd 7855
c7e4ee3a
CB
7856 void foo (float (*a)[i/j])
7857 {
7858 ...
7859 }
5ff904cd 7860
c7e4ee3a
CB
7861 The above is (essentially) quite valid for Fortran
7862 but, again, for a call like "foo (NULL);", it is
7863 permitted for i and j to be undefined when the
7864 call is made. If j happened to be zero, for
7865 example, emitting the code to evaluate "i/j"
7866 could result in a run-time error.
5ff904cd 7867
c7e4ee3a
CB
7868 Offhand, though I don't have my F77 or F90
7869 standards handy, it might even be valid for a
7870 bounds expression to contain a function reference,
7871 in which case I doubt it is permitted for an
7872 implementation to invoke that function in the
7873 Fortran case involved here (invocation of an
7874 alternate ENTRY point that doesn't have the adjustable
7875 array as one of its arguments).
5ff904cd 7876
c7e4ee3a
CB
7877 So, the code that the compiler would normally emit
7878 to preevaluate the size/shape info for an
7879 adjustable array _must not_ be executed at run time
7880 in certain cases. Specifically, for Fortran,
7881 the case is when the pointer to the adjustable
7882 array == NULL. (For gnu-ish C, it might be nice
7883 for the source code itself to specify an expression
7884 that, if TRUE, inhibits execution of the code. Or
7885 reverse the sense for elegance.)
5ff904cd 7886
c7e4ee3a
CB
7887 (Note that g77 could use a different test than NULL,
7888 actually, since it happens to always pass an
7889 integer to the called function that specifies which
7890 entry point is being invoked. Hmm, this might
7891 solve the next problem.)
7892
7893 One way a user could, I suppose, write "foo" so
7894 it works is to insert COND_EXPR's for the
7895 size/shape info so the dangerous stuff isn't
7896 actually done, as in:
7897
7898 void foo (int *n, float (*a)[(a == NULL) ? 0 : *n])
7899 {
7900 ...
7901 }
5ff904cd 7902
c7e4ee3a
CB
7903 The next problem is that the front end needs to
7904 be able to tell the back end about the array's
7905 decl _before_ it tells it about the conditional
7906 expression to inhibit evaluation of size/shape info,
7907 as shown above.
5ff904cd 7908
c7e4ee3a
CB
7909 To solve this, the front end needs to be able
7910 to give the back end the expression to inhibit
7911 generation of the preevaluation code _after_
7912 it makes the decl for the adjustable array.
5ff904cd 7913
c7e4ee3a
CB
7914 Until then, the above example using the COND_EXPR
7915 doesn't pass muster with gcc because the "(a == NULL)"
7916 part has a reference to "a", which is still
7917 undefined at that point.
5ff904cd 7918
c7e4ee3a
CB
7919 g77 will therefore use a different mechanism in the
7920 meantime. */
5ff904cd 7921
c7e4ee3a
CB
7922 if (!adjustable
7923 && ((TREE_CODE (low) != INTEGER_CST)
7924 || (high && TREE_CODE (high) != INTEGER_CST)))
7925 adjustable = TRUE;
5ff904cd 7926
c7e4ee3a
CB
7927#if 0 /* Old approach -- see below. */
7928 if (TREE_CODE (low) != INTEGER_CST)
7929 low = ffecom_3 (COND_EXPR, integer_type_node,
7930 ffecom_adjarray_passed_ (s),
7931 low,
7932 ffecom_integer_zero_node);
5ff904cd 7933
c7e4ee3a
CB
7934 if (high && TREE_CODE (high) != INTEGER_CST)
7935 high = ffecom_3 (COND_EXPR, integer_type_node,
7936 ffecom_adjarray_passed_ (s),
7937 high,
7938 ffecom_integer_zero_node);
7939#endif
5ff904cd 7940
c7e4ee3a
CB
7941 /* ~~~gcc/stor-layout.c (layout_type) should do this,
7942 probably. Fixes 950302-1.f. */
5ff904cd 7943
c7e4ee3a
CB
7944 if (TREE_CODE (low) != INTEGER_CST)
7945 low = variable_size (low);
5ff904cd 7946
c7e4ee3a
CB
7947 /* ~~~Similarly, this fixes dumb0.f. The C front end
7948 does this, which is why dumb0.c would work. */
5ff904cd 7949
c7e4ee3a
CB
7950 if (high && TREE_CODE (high) != INTEGER_CST)
7951 high = variable_size (high);
5ff904cd 7952
c7e4ee3a
CB
7953 type
7954 = build_array_type
7955 (type,
7956 build_range_type (ffecom_integer_type_node,
7957 low, high));
7958 type = ffecom_check_size_overflow_ (s, type, TRUE);
7959 }
5ff904cd 7960
c7e4ee3a
CB
7961 if (type == error_mark_node)
7962 {
7963 t = error_mark_node;
7964 break;
7965 }
5ff904cd 7966
c7e4ee3a
CB
7967 if ((ffesymbol_sfdummyparent (s) == NULL)
7968 || (ffesymbol_basictype (s) == FFEINFO_basictypeCHARACTER))
7969 {
7970 type = build_pointer_type (type);
7971 addr = TRUE;
7972 }
5ff904cd 7973
c7e4ee3a 7974 t = build_decl (PARM_DECL, t, type);
5ff904cd 7975#if BUILT_FOR_270
c7e4ee3a 7976 DECL_ARTIFICIAL (t) = 1;
5ff904cd 7977#endif
5ff904cd 7978
c7e4ee3a
CB
7979 /* If this arg is present in every entry point's list of
7980 dummy args, then we're done. */
5ff904cd 7981
c7e4ee3a
CB
7982 if (ffesymbol_numentries (s)
7983 == (ffecom_num_entrypoints_ + 1))
5ff904cd 7984 break;
5ff904cd 7985
c7e4ee3a 7986#if 1
5ff904cd 7987
c7e4ee3a
CB
7988 /* If variable_size in stor-layout has been called during
7989 the above, then get_pending_sizes should have the
7990 yet-to-be-evaluated saved expressions pending.
7991 Make the whole lot of them get emitted, conditionally
7992 on whether the array decl ("t" above) is not NULL. */
5ff904cd 7993
c7e4ee3a
CB
7994 {
7995 tree sizes = get_pending_sizes ();
7996 tree tem;
5ff904cd 7997
c7e4ee3a
CB
7998 for (tem = sizes;
7999 tem != old_sizes;
8000 tem = TREE_CHAIN (tem))
8001 {
8002 tree temv = TREE_VALUE (tem);
5ff904cd 8003
c7e4ee3a
CB
8004 if (sizes == tem)
8005 sizes = temv;
8006 else
8007 sizes
8008 = ffecom_2 (COMPOUND_EXPR,
8009 TREE_TYPE (sizes),
8010 temv,
8011 sizes);
8012 }
5ff904cd 8013
c7e4ee3a
CB
8014 if (sizes != tem)
8015 {
8016 sizes
8017 = ffecom_3 (COND_EXPR,
8018 TREE_TYPE (sizes),
8019 ffecom_2 (NE_EXPR,
8020 integer_type_node,
8021 t,
8022 null_pointer_node),
8023 sizes,
8024 convert (TREE_TYPE (sizes),
8025 integer_zero_node));
8026 sizes = ffecom_save_tree (sizes);
5ff904cd 8027
c7e4ee3a
CB
8028 sizes
8029 = tree_cons (NULL_TREE, sizes, tem);
8030 }
5ff904cd 8031
c7e4ee3a
CB
8032 if (sizes)
8033 put_pending_sizes (sizes);
8034 }
5ff904cd 8035
c7e4ee3a
CB
8036#else
8037#if 0
8038 if (adjustable
8039 && (ffesymbol_numentries (s)
8040 != ffecom_num_entrypoints_ + 1))
8041 DECL_SOMETHING (t)
8042 = ffecom_2 (NE_EXPR, integer_type_node,
8043 t,
8044 null_pointer_node);
8045#else
8046#if 0
8047 if (adjustable
8048 && (ffesymbol_numentries (s)
8049 != ffecom_num_entrypoints_ + 1))
8050 {
8051 ffebad_start (FFEBAD_MISSING_ADJARRAY_UNSUPPORTED);
8052 ffebad_here (0, ffesymbol_where_line (s),
8053 ffesymbol_where_column (s));
8054 ffebad_string (ffesymbol_text (s));
8055 ffebad_finish ();
8056 }
8057#endif
8058#endif
8059#endif
8060 }
5ff904cd
JL
8061 break;
8062
c7e4ee3a 8063 case FFEINFO_whereCOMMON:
5ff904cd 8064 {
c7e4ee3a
CB
8065 ffesymbol cs;
8066 ffeglobal cg;
8067 tree ct;
5ff904cd
JL
8068 ffestorag st = ffesymbol_storage (s);
8069 tree type;
8070
c7e4ee3a
CB
8071 cs = ffesymbol_common (s); /* The COMMON area itself. */
8072 if (st != NULL) /* Else not laid out. */
5ff904cd 8073 {
c7e4ee3a
CB
8074 ffecom_transform_common_ (cs);
8075 st = ffesymbol_storage (s);
5ff904cd
JL
8076 }
8077
c7e4ee3a 8078 type = ffecom_type_localvar_ (s, bt, kt);
5ff904cd 8079
c7e4ee3a
CB
8080 cg = ffesymbol_global (cs); /* The global COMMON info. */
8081 if ((cg == NULL)
8082 || (ffeglobal_type (cg) != FFEGLOBAL_typeCOMMON))
8083 ct = NULL_TREE;
8084 else
8085 ct = ffeglobal_hook (cg); /* The common area's tree. */
5ff904cd 8086
c7e4ee3a
CB
8087 if ((ct == NULL_TREE)
8088 || (st == NULL)
8089 || (type == error_mark_node))
8090 t = error_mark_node;
8091 else
8092 {
8093 ffetargetOffset offset;
8094 ffestorag cst;
5ff904cd 8095
c7e4ee3a
CB
8096 cst = ffestorag_parent (st);
8097 assert (cst == ffesymbol_storage (cs));
5ff904cd 8098
c7e4ee3a
CB
8099 offset = ffestorag_modulo (cst)
8100 + ffestorag_offset (st)
8101 - ffestorag_offset (cst);
5ff904cd 8102
c7e4ee3a 8103 ffecom_debug_kludge_ (ct, "COMMON", s, type, offset);
5ff904cd 8104
c7e4ee3a 8105 /* (t_type *) (((char *) &ct) + offset) */
5ff904cd
JL
8106
8107 t = convert (string_type_node, /* (char *) */
8108 ffecom_1 (ADDR_EXPR,
c7e4ee3a
CB
8109 build_pointer_type (TREE_TYPE (ct)),
8110 ct));
5ff904cd
JL
8111 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
8112 t,
8113 build_int_2 (offset, 0));
8114 t = convert (build_pointer_type (type),
8115 t);
d50108c7 8116 TREE_CONSTANT (t) = 1;
5ff904cd
JL
8117
8118 addr = TRUE;
5ff904cd 8119 }
c7e4ee3a
CB
8120 }
8121 break;
5ff904cd 8122
c7e4ee3a
CB
8123 case FFEINFO_whereIMMEDIATE:
8124 case FFEINFO_whereGLOBAL:
8125 case FFEINFO_whereFLEETING:
8126 case FFEINFO_whereFLEETING_CADDR:
8127 case FFEINFO_whereFLEETING_IADDR:
8128 case FFEINFO_whereINTRINSIC:
8129 case FFEINFO_whereCONSTANT_SUBOBJECT:
8130 default:
8131 assert ("ENTITY where unheard of" == NULL);
8132 /* Fall through. */
8133 case FFEINFO_whereANY:
8134 t = error_mark_node;
8135 break;
8136 }
8137 break;
5ff904cd 8138
c7e4ee3a
CB
8139 case FFEINFO_kindFUNCTION:
8140 switch (ffeinfo_where (ffesymbol_info (s)))
8141 {
8142 case FFEINFO_whereLOCAL: /* Me. */
8143 assert (!ffecom_transform_only_dummies_);
8144 t = current_function_decl;
5ff904cd
JL
8145 break;
8146
c7e4ee3a 8147 case FFEINFO_whereGLOBAL:
5ff904cd
JL
8148 assert (!ffecom_transform_only_dummies_);
8149
c7e4ee3a
CB
8150 if (((g = ffesymbol_global (s)) != NULL)
8151 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8152 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8153 && (ffeglobal_hook (g) != NULL_TREE)
8154 && ffe_is_globals ())
5ff904cd 8155 {
c7e4ee3a 8156 t = ffeglobal_hook (g);
5ff904cd
JL
8157 break;
8158 }
5ff904cd 8159
c7e4ee3a
CB
8160 if (ffesymbol_is_f2c (s)
8161 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
8162 t = ffecom_tree_fun_type[bt][kt];
8163 else
8164 t = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
5ff904cd 8165
c7e4ee3a
CB
8166 t = build_decl (FUNCTION_DECL,
8167 ffecom_get_external_identifier_ (s),
8168 t);
8169 DECL_EXTERNAL (t) = 1;
8170 TREE_PUBLIC (t) = 1;
5ff904cd 8171
5ff904cd
JL
8172 t = start_decl (t, FALSE);
8173 finish_decl (t, NULL_TREE, FALSE);
8174
c7e4ee3a
CB
8175 if ((g != NULL)
8176 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8177 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8178 ffeglobal_set_hook (g, t);
8179
7189a4b0 8180 ffecom_save_tree_forever (t);
5ff904cd 8181
5ff904cd
JL
8182 break;
8183
8184 case FFEINFO_whereDUMMY:
c7e4ee3a 8185 assert (ffecom_transform_only_dummies_);
5ff904cd 8186
c7e4ee3a
CB
8187 if (ffesymbol_is_f2c (s)
8188 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
8189 t = ffecom_tree_ptr_to_fun_type[bt][kt];
8190 else
8191 t = build_pointer_type
8192 (build_function_type (ffecom_tree_type[bt][kt], NULL_TREE));
8193
8194 t = build_decl (PARM_DECL,
8195 ffecom_get_identifier_ (ffesymbol_text (s)),
8196 t);
8197#if BUILT_FOR_270
8198 DECL_ARTIFICIAL (t) = 1;
8199#endif
8200 addr = TRUE;
8201 break;
8202
8203 case FFEINFO_whereCONSTANT: /* Statement function. */
8204 assert (!ffecom_transform_only_dummies_);
8205 t = ffecom_gen_sfuncdef_ (s, bt, kt);
8206 break;
8207
8208 case FFEINFO_whereINTRINSIC:
8209 assert (!ffecom_transform_only_dummies_);
8210 break; /* Let actual references generate their
8211 decls. */
8212
8213 default:
8214 assert ("FUNCTION where unheard of" == NULL);
8215 /* Fall through. */
8216 case FFEINFO_whereANY:
8217 t = error_mark_node;
8218 break;
8219 }
8220 break;
8221
8222 case FFEINFO_kindSUBROUTINE:
8223 switch (ffeinfo_where (ffesymbol_info (s)))
8224 {
8225 case FFEINFO_whereLOCAL: /* Me. */
8226 assert (!ffecom_transform_only_dummies_);
8227 t = current_function_decl;
8228 break;
5ff904cd 8229
c7e4ee3a
CB
8230 case FFEINFO_whereGLOBAL:
8231 assert (!ffecom_transform_only_dummies_);
5ff904cd 8232
c7e4ee3a
CB
8233 if (((g = ffesymbol_global (s)) != NULL)
8234 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8235 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8236 && (ffeglobal_hook (g) != NULL_TREE)
8237 && ffe_is_globals ())
8238 {
8239 t = ffeglobal_hook (g);
8240 break;
8241 }
5ff904cd 8242
c7e4ee3a
CB
8243 t = build_decl (FUNCTION_DECL,
8244 ffecom_get_external_identifier_ (s),
8245 ffecom_tree_subr_type);
8246 DECL_EXTERNAL (t) = 1;
8247 TREE_PUBLIC (t) = 1;
5ff904cd 8248
c7e4ee3a
CB
8249 t = start_decl (t, FALSE);
8250 finish_decl (t, NULL_TREE, FALSE);
5ff904cd 8251
c7e4ee3a
CB
8252 if ((g != NULL)
8253 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8254 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8255 ffeglobal_set_hook (g, t);
5ff904cd 8256
7189a4b0 8257 ffecom_save_tree_forever (t);
5ff904cd 8258
c7e4ee3a 8259 break;
5ff904cd 8260
c7e4ee3a
CB
8261 case FFEINFO_whereDUMMY:
8262 assert (ffecom_transform_only_dummies_);
5ff904cd 8263
c7e4ee3a
CB
8264 t = build_decl (PARM_DECL,
8265 ffecom_get_identifier_ (ffesymbol_text (s)),
8266 ffecom_tree_ptr_to_subr_type);
8267#if BUILT_FOR_270
8268 DECL_ARTIFICIAL (t) = 1;
8269#endif
8270 addr = TRUE;
8271 break;
5ff904cd 8272
c7e4ee3a
CB
8273 case FFEINFO_whereINTRINSIC:
8274 assert (!ffecom_transform_only_dummies_);
8275 break; /* Let actual references generate their
8276 decls. */
5ff904cd 8277
c7e4ee3a
CB
8278 default:
8279 assert ("SUBROUTINE where unheard of" == NULL);
8280 /* Fall through. */
8281 case FFEINFO_whereANY:
8282 t = error_mark_node;
8283 break;
8284 }
8285 break;
5ff904cd 8286
c7e4ee3a
CB
8287 case FFEINFO_kindPROGRAM:
8288 switch (ffeinfo_where (ffesymbol_info (s)))
8289 {
8290 case FFEINFO_whereLOCAL: /* Me. */
8291 assert (!ffecom_transform_only_dummies_);
8292 t = current_function_decl;
8293 break;
5ff904cd 8294
c7e4ee3a
CB
8295 case FFEINFO_whereCOMMON:
8296 case FFEINFO_whereDUMMY:
8297 case FFEINFO_whereGLOBAL:
8298 case FFEINFO_whereRESULT:
8299 case FFEINFO_whereFLEETING:
8300 case FFEINFO_whereFLEETING_CADDR:
8301 case FFEINFO_whereFLEETING_IADDR:
8302 case FFEINFO_whereIMMEDIATE:
8303 case FFEINFO_whereINTRINSIC:
8304 case FFEINFO_whereCONSTANT:
8305 case FFEINFO_whereCONSTANT_SUBOBJECT:
8306 default:
8307 assert ("PROGRAM where unheard of" == NULL);
8308 /* Fall through. */
8309 case FFEINFO_whereANY:
8310 t = error_mark_node;
8311 break;
8312 }
8313 break;
5ff904cd 8314
c7e4ee3a
CB
8315 case FFEINFO_kindBLOCKDATA:
8316 switch (ffeinfo_where (ffesymbol_info (s)))
8317 {
8318 case FFEINFO_whereLOCAL: /* Me. */
8319 assert (!ffecom_transform_only_dummies_);
8320 t = current_function_decl;
8321 break;
5ff904cd 8322
c7e4ee3a
CB
8323 case FFEINFO_whereGLOBAL:
8324 assert (!ffecom_transform_only_dummies_);
5ff904cd 8325
c7e4ee3a
CB
8326 t = build_decl (FUNCTION_DECL,
8327 ffecom_get_external_identifier_ (s),
8328 ffecom_tree_blockdata_type);
8329 DECL_EXTERNAL (t) = 1;
8330 TREE_PUBLIC (t) = 1;
5ff904cd 8331
c7e4ee3a
CB
8332 t = start_decl (t, FALSE);
8333 finish_decl (t, NULL_TREE, FALSE);
5ff904cd 8334
7189a4b0 8335 ffecom_save_tree_forever (t);
5ff904cd 8336
c7e4ee3a 8337 break;
5ff904cd 8338
c7e4ee3a
CB
8339 case FFEINFO_whereCOMMON:
8340 case FFEINFO_whereDUMMY:
8341 case FFEINFO_whereRESULT:
8342 case FFEINFO_whereFLEETING:
8343 case FFEINFO_whereFLEETING_CADDR:
8344 case FFEINFO_whereFLEETING_IADDR:
8345 case FFEINFO_whereIMMEDIATE:
8346 case FFEINFO_whereINTRINSIC:
8347 case FFEINFO_whereCONSTANT:
8348 case FFEINFO_whereCONSTANT_SUBOBJECT:
8349 default:
8350 assert ("BLOCKDATA where unheard of" == NULL);
8351 /* Fall through. */
8352 case FFEINFO_whereANY:
8353 t = error_mark_node;
8354 break;
8355 }
8356 break;
5ff904cd 8357
c7e4ee3a
CB
8358 case FFEINFO_kindCOMMON:
8359 switch (ffeinfo_where (ffesymbol_info (s)))
8360 {
8361 case FFEINFO_whereLOCAL:
8362 assert (!ffecom_transform_only_dummies_);
8363 ffecom_transform_common_ (s);
8364 break;
8365
8366 case FFEINFO_whereNONE:
8367 case FFEINFO_whereCOMMON:
8368 case FFEINFO_whereDUMMY:
8369 case FFEINFO_whereGLOBAL:
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:
8378 default:
8379 assert ("COMMON where unheard of" == NULL);
8380 /* Fall through. */
8381 case FFEINFO_whereANY:
8382 t = error_mark_node;
8383 break;
8384 }
8385 break;
5ff904cd 8386
c7e4ee3a
CB
8387 case FFEINFO_kindCONSTRUCT:
8388 switch (ffeinfo_where (ffesymbol_info (s)))
8389 {
8390 case FFEINFO_whereLOCAL:
8391 assert (!ffecom_transform_only_dummies_);
8392 break;
5ff904cd 8393
c7e4ee3a
CB
8394 case FFEINFO_whereNONE:
8395 case FFEINFO_whereCOMMON:
8396 case FFEINFO_whereDUMMY:
8397 case FFEINFO_whereGLOBAL:
8398 case FFEINFO_whereRESULT:
8399 case FFEINFO_whereFLEETING:
8400 case FFEINFO_whereFLEETING_CADDR:
8401 case FFEINFO_whereFLEETING_IADDR:
8402 case FFEINFO_whereIMMEDIATE:
8403 case FFEINFO_whereINTRINSIC:
8404 case FFEINFO_whereCONSTANT:
8405 case FFEINFO_whereCONSTANT_SUBOBJECT:
8406 default:
8407 assert ("CONSTRUCT where unheard of" == NULL);
8408 /* Fall through. */
8409 case FFEINFO_whereANY:
8410 t = error_mark_node;
8411 break;
8412 }
8413 break;
5ff904cd 8414
c7e4ee3a
CB
8415 case FFEINFO_kindNAMELIST:
8416 switch (ffeinfo_where (ffesymbol_info (s)))
8417 {
8418 case FFEINFO_whereLOCAL:
8419 assert (!ffecom_transform_only_dummies_);
8420 t = ffecom_transform_namelist_ (s);
8421 break;
5ff904cd 8422
c7e4ee3a
CB
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:
8435 default:
8436 assert ("NAMELIST where unheard of" == NULL);
8437 /* Fall through. */
8438 case FFEINFO_whereANY:
8439 t = error_mark_node;
8440 break;
8441 }
8442 break;
5ff904cd 8443
c7e4ee3a
CB
8444 default:
8445 assert ("kind unheard of" == NULL);
8446 /* Fall through. */
8447 case FFEINFO_kindANY:
8448 t = error_mark_node;
8449 break;
8450 }
5ff904cd 8451
c7e4ee3a
CB
8452 ffesymbol_hook (s).decl_tree = t;
8453 ffesymbol_hook (s).length_tree = tlen;
8454 ffesymbol_hook (s).addr = addr;
5ff904cd 8455
c7e4ee3a
CB
8456 lineno = old_lineno;
8457 input_filename = old_input_filename;
5ff904cd 8458
c7e4ee3a
CB
8459 return s;
8460}
5ff904cd 8461
5ff904cd 8462#endif
c7e4ee3a 8463/* Transform into ASSIGNable symbol.
5ff904cd 8464
c7e4ee3a
CB
8465 Symbol has already been transformed, but for whatever reason, the
8466 resulting decl_tree has been deemed not usable for an ASSIGN target.
8467 (E.g. it isn't wide enough to hold a pointer.) So, here we invent
8468 another local symbol of type void * and stuff that in the assign_tree
8469 argument. The F77/F90 standards allow this implementation. */
5ff904cd 8470
c7e4ee3a
CB
8471#if FFECOM_targetCURRENT == FFECOM_targetGCC
8472static ffesymbol
8473ffecom_sym_transform_assign_ (ffesymbol s)
8474{
8475 tree t; /* Transformed thingy. */
c7e4ee3a 8476 int old_lineno = lineno;
3b304f5b 8477 const char *old_input_filename = input_filename;
5ff904cd 8478
c7e4ee3a
CB
8479 if (ffesymbol_sfdummyparent (s) == NULL)
8480 {
8481 input_filename = ffesymbol_where_filename (s);
8482 lineno = ffesymbol_where_filelinenum (s);
8483 }
8484 else
8485 {
8486 ffesymbol sf = ffesymbol_sfdummyparent (s);
5ff904cd 8487
c7e4ee3a
CB
8488 input_filename = ffesymbol_where_filename (sf);
8489 lineno = ffesymbol_where_filelinenum (sf);
8490 }
5ff904cd 8491
c7e4ee3a 8492 assert (!ffecom_transform_only_dummies_);
5ff904cd 8493
c7e4ee3a
CB
8494 t = build_decl (VAR_DECL,
8495 ffecom_get_invented_identifier ("__g77_ASSIGN_%s",
14657de8 8496 ffesymbol_text (s)),
c7e4ee3a 8497 TREE_TYPE (null_pointer_node));
5ff904cd 8498
c7e4ee3a
CB
8499 switch (ffesymbol_where (s))
8500 {
8501 case FFEINFO_whereLOCAL:
8502 /* Unlike for regular vars, SAVE status is easy to determine for
8503 ASSIGNed vars, since there's no initialization, there's no
8504 effective storage association (so "SAVE J" does not apply to
8505 K even given "EQUIVALENCE (J,K)"), there's no size issue
8506 to worry about, etc. */
8507 if ((ffesymbol_is_save (s) || ffe_is_saveall ())
8508 && (ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
8509 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA))
8510 TREE_STATIC (t) = 1; /* SAVEd in proc, make static. */
8511 else
8512 TREE_STATIC (t) = 0; /* No need to make static. */
8513 break;
5ff904cd 8514
c7e4ee3a
CB
8515 case FFEINFO_whereCOMMON:
8516 TREE_STATIC (t) = 1; /* Assume COMMONs always SAVEd. */
8517 break;
5ff904cd 8518
c7e4ee3a
CB
8519 case FFEINFO_whereDUMMY:
8520 /* Note that twinning a DUMMY means the caller won't see
8521 the ASSIGNed value. But both F77 and F90 allow implementations
8522 to do this, i.e. disallow Fortran code that would try and
8523 take advantage of actually putting a label into a variable
8524 via a dummy argument (or any other storage association, for
8525 that matter). */
8526 TREE_STATIC (t) = 0;
8527 break;
5ff904cd 8528
c7e4ee3a
CB
8529 default:
8530 TREE_STATIC (t) = 0;
8531 break;
8532 }
5ff904cd 8533
c7e4ee3a
CB
8534 t = start_decl (t, FALSE);
8535 finish_decl (t, NULL_TREE, FALSE);
5ff904cd 8536
c7e4ee3a 8537 ffesymbol_hook (s).assign_tree = t;
5ff904cd 8538
c7e4ee3a
CB
8539 lineno = old_lineno;
8540 input_filename = old_input_filename;
5ff904cd 8541
c7e4ee3a
CB
8542 return s;
8543}
5ff904cd 8544
c7e4ee3a
CB
8545#endif
8546/* Implement COMMON area in back end.
5ff904cd 8547
c7e4ee3a
CB
8548 Because COMMON-based variables can be referenced in the dimension
8549 expressions of dummy (adjustable) arrays, and because dummies
8550 (in the gcc back end) need to be put in the outer binding level
8551 of a function (which has two binding levels, the outer holding
8552 the dummies and the inner holding the other vars), special care
8553 must be taken to handle COMMON areas.
5ff904cd 8554
c7e4ee3a
CB
8555 The current strategy is basically to always tell the back end about
8556 the COMMON area as a top-level external reference to just a block
8557 of storage of the master type of that area (e.g. integer, real,
8558 character, whatever -- not a structure). As a distinct action,
8559 if initial values are provided, tell the back end about the area
8560 as a top-level non-external (initialized) area and remember not to
8561 allow further initialization or expansion of the area. Meanwhile,
8562 if no initialization happens at all, tell the back end about
8563 the largest size we've seen declared so the space does get reserved.
8564 (This function doesn't handle all that stuff, but it does some
8565 of the important things.)
5ff904cd 8566
c7e4ee3a
CB
8567 Meanwhile, for COMMON variables themselves, just keep creating
8568 references like *((float *) (&common_area + offset)) each time
8569 we reference the variable. In other words, don't make a VAR_DECL
8570 or any kind of component reference (like we used to do before 0.4),
8571 though we might do that as well just for debugging purposes (and
8572 stuff the rtl with the appropriate offset expression). */
5ff904cd 8573
c7e4ee3a
CB
8574#if FFECOM_targetCURRENT == FFECOM_targetGCC
8575static void
8576ffecom_transform_common_ (ffesymbol s)
8577{
8578 ffestorag st = ffesymbol_storage (s);
8579 ffeglobal g = ffesymbol_global (s);
8580 tree cbt;
8581 tree cbtype;
8582 tree init;
8583 tree high;
8584 bool is_init = ffestorag_is_init (st);
5ff904cd 8585
c7e4ee3a 8586 assert (st != NULL);
5ff904cd 8587
c7e4ee3a
CB
8588 if ((g == NULL)
8589 || (ffeglobal_type (g) != FFEGLOBAL_typeCOMMON))
8590 return;
5ff904cd 8591
c7e4ee3a 8592 /* First update the size of the area in global terms. */
5ff904cd 8593
c7e4ee3a 8594 ffeglobal_size_common (s, ffestorag_size (st));
5ff904cd 8595
c7e4ee3a
CB
8596 if (!ffeglobal_common_init (g))
8597 is_init = FALSE; /* No explicit init, don't let erroneous joins init. */
5ff904cd 8598
c7e4ee3a 8599 cbt = ffeglobal_hook (g);
5ff904cd 8600
c7e4ee3a
CB
8601 /* If we already have declared this common block for a previous program
8602 unit, and either we already initialized it or we don't have new
8603 initialization for it, just return what we have without changing it. */
5ff904cd 8604
c7e4ee3a
CB
8605 if ((cbt != NULL_TREE)
8606 && (!is_init
8607 || !DECL_EXTERNAL (cbt)))
b7a80862
AV
8608 {
8609 if (st->hook == NULL) ffestorag_set_hook (st, cbt);
8610 return;
8611 }
5ff904cd 8612
c7e4ee3a 8613 /* Process inits. */
5ff904cd 8614
c7e4ee3a
CB
8615 if (is_init)
8616 {
8617 if (ffestorag_init (st) != NULL)
5ff904cd 8618 {
c7e4ee3a 8619 ffebld sexp;
5ff904cd 8620
c7e4ee3a
CB
8621 /* Set the padding for the expression, so ffecom_expr
8622 knows to insert that many zeros. */
8623 switch (ffebld_op (sexp = ffestorag_init (st)))
5ff904cd 8624 {
c7e4ee3a
CB
8625 case FFEBLD_opCONTER:
8626 ffebld_conter_set_pad (sexp, ffestorag_modulo (st));
5ff904cd 8627 break;
5ff904cd 8628
c7e4ee3a
CB
8629 case FFEBLD_opARRTER:
8630 ffebld_arrter_set_pad (sexp, ffestorag_modulo (st));
8631 break;
5ff904cd 8632
c7e4ee3a
CB
8633 case FFEBLD_opACCTER:
8634 ffebld_accter_set_pad (sexp, ffestorag_modulo (st));
8635 break;
5ff904cd 8636
c7e4ee3a
CB
8637 default:
8638 assert ("bad op for cmn init (pad)" == NULL);
8639 break;
8640 }
5ff904cd 8641
c7e4ee3a
CB
8642 init = ffecom_expr (sexp);
8643 if (init == error_mark_node)
8644 { /* Hopefully the back end complained! */
8645 init = NULL_TREE;
8646 if (cbt != NULL_TREE)
8647 return;
8648 }
8649 }
8650 else
8651 init = error_mark_node;
8652 }
8653 else
8654 init = NULL_TREE;
5ff904cd 8655
c7e4ee3a 8656 /* cbtype must be permanently allocated! */
5ff904cd 8657
c7e4ee3a
CB
8658 /* Allocate the MAX of the areas so far, seen filewide. */
8659 high = build_int_2 ((ffeglobal_common_size (g)
8660 + ffeglobal_common_pad (g)) - 1, 0);
8661 TREE_TYPE (high) = ffecom_integer_type_node;
5ff904cd 8662
c7e4ee3a
CB
8663 if (init)
8664 cbtype = build_array_type (char_type_node,
8665 build_range_type (integer_type_node,
8666 integer_zero_node,
8667 high));
8668 else
8669 cbtype = build_array_type (char_type_node, NULL_TREE);
5ff904cd 8670
c7e4ee3a
CB
8671 if (cbt == NULL_TREE)
8672 {
8673 cbt
8674 = build_decl (VAR_DECL,
8675 ffecom_get_external_identifier_ (s),
8676 cbtype);
8677 TREE_STATIC (cbt) = 1;
8678 TREE_PUBLIC (cbt) = 1;
8679 }
8680 else
8681 {
8682 assert (is_init);
8683 TREE_TYPE (cbt) = cbtype;
8684 }
8685 DECL_EXTERNAL (cbt) = init ? 0 : 1;
8686 DECL_INITIAL (cbt) = init ? error_mark_node : NULL_TREE;
5ff904cd 8687
c7e4ee3a
CB
8688 cbt = start_decl (cbt, TRUE);
8689 if (ffeglobal_hook (g) != NULL)
8690 assert (cbt == ffeglobal_hook (g));
5ff904cd 8691
c7e4ee3a 8692 assert (!init || !DECL_EXTERNAL (cbt));
5ff904cd 8693
c7e4ee3a
CB
8694 /* Make sure that any type can live in COMMON and be referenced
8695 without getting a bus error. We could pick the most restrictive
8696 alignment of all entities actually placed in the COMMON, but
8697 this seems easy enough. */
5ff904cd 8698
c7e4ee3a 8699 DECL_ALIGN (cbt) = BIGGEST_ALIGNMENT;
11cf4d18 8700 DECL_USER_ALIGN (cbt) = 0;
5ff904cd 8701
c7e4ee3a
CB
8702 if (is_init && (ffestorag_init (st) == NULL))
8703 init = ffecom_init_zero_ (cbt);
5ff904cd 8704
c7e4ee3a 8705 finish_decl (cbt, init, TRUE);
5ff904cd 8706
c7e4ee3a
CB
8707 if (is_init)
8708 ffestorag_set_init (st, ffebld_new_any ());
5ff904cd 8709
c7e4ee3a
CB
8710 if (init)
8711 {
06ceef4e
RK
8712 assert (DECL_SIZE_UNIT (cbt) != NULL_TREE);
8713 assert (TREE_CODE (DECL_SIZE_UNIT (cbt)) == INTEGER_CST);
05bccae2
RK
8714 assert (0 == compare_tree_int (DECL_SIZE_UNIT (cbt),
8715 (ffeglobal_common_size (g)
8716 + ffeglobal_common_pad (g))));
c7e4ee3a 8717 }
5ff904cd 8718
c7e4ee3a 8719 ffeglobal_set_hook (g, cbt);
5ff904cd 8720
c7e4ee3a 8721 ffestorag_set_hook (st, cbt);
5ff904cd 8722
7189a4b0 8723 ffecom_save_tree_forever (cbt);
c7e4ee3a 8724}
5ff904cd 8725
c7e4ee3a
CB
8726#endif
8727/* Make master area for local EQUIVALENCE. */
5ff904cd 8728
c7e4ee3a
CB
8729#if FFECOM_targetCURRENT == FFECOM_targetGCC
8730static void
8731ffecom_transform_equiv_ (ffestorag eqst)
8732{
8733 tree eqt;
8734 tree eqtype;
8735 tree init;
8736 tree high;
8737 bool is_init = ffestorag_is_init (eqst);
5ff904cd 8738
c7e4ee3a 8739 assert (eqst != NULL);
5ff904cd 8740
c7e4ee3a 8741 eqt = ffestorag_hook (eqst);
5ff904cd 8742
c7e4ee3a
CB
8743 if (eqt != NULL_TREE)
8744 return;
5ff904cd 8745
c7e4ee3a
CB
8746 /* Process inits. */
8747
8748 if (is_init)
8749 {
8750 if (ffestorag_init (eqst) != NULL)
5ff904cd 8751 {
c7e4ee3a 8752 ffebld sexp;
5ff904cd 8753
c7e4ee3a
CB
8754 /* Set the padding for the expression, so ffecom_expr
8755 knows to insert that many zeros. */
8756 switch (ffebld_op (sexp = ffestorag_init (eqst)))
8757 {
8758 case FFEBLD_opCONTER:
8759 ffebld_conter_set_pad (sexp, ffestorag_modulo (eqst));
8760 break;
5ff904cd 8761
c7e4ee3a
CB
8762 case FFEBLD_opARRTER:
8763 ffebld_arrter_set_pad (sexp, ffestorag_modulo (eqst));
8764 break;
5ff904cd 8765
c7e4ee3a
CB
8766 case FFEBLD_opACCTER:
8767 ffebld_accter_set_pad (sexp, ffestorag_modulo (eqst));
8768 break;
5ff904cd 8769
c7e4ee3a
CB
8770 default:
8771 assert ("bad op for eqv init (pad)" == NULL);
8772 break;
8773 }
5ff904cd 8774
c7e4ee3a
CB
8775 init = ffecom_expr (sexp);
8776 if (init == error_mark_node)
8777 init = NULL_TREE; /* Hopefully the back end complained! */
8778 }
8779 else
8780 init = error_mark_node;
8781 }
8782 else if (ffe_is_init_local_zero ())
8783 init = error_mark_node;
8784 else
8785 init = NULL_TREE;
5ff904cd 8786
c7e4ee3a
CB
8787 ffecom_member_namelisted_ = FALSE;
8788 ffestorag_drive (ffestorag_list_equivs (eqst),
8789 &ffecom_member_phase1_,
8790 eqst);
5ff904cd 8791
c7e4ee3a
CB
8792 high = build_int_2 ((ffestorag_size (eqst)
8793 + ffestorag_modulo (eqst)) - 1, 0);
8794 TREE_TYPE (high) = ffecom_integer_type_node;
5ff904cd 8795
c7e4ee3a
CB
8796 eqtype = build_array_type (char_type_node,
8797 build_range_type (ffecom_integer_type_node,
8798 ffecom_integer_zero_node,
8799 high));
8800
8801 eqt = build_decl (VAR_DECL,
8802 ffecom_get_invented_identifier ("__g77_equiv_%s",
8803 ffesymbol_text
14657de8 8804 (ffestorag_symbol (eqst))),
c7e4ee3a
CB
8805 eqtype);
8806 DECL_EXTERNAL (eqt) = 0;
8807 if (is_init
8808 || ffecom_member_namelisted_
8809#ifdef FFECOM_sizeMAXSTACKITEM
8810 || (ffestorag_size (eqst) > FFECOM_sizeMAXSTACKITEM)
8811#endif
8812 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
8813 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
8814 && (ffestorag_is_save (eqst) || ffe_is_saveall ())))
8815 TREE_STATIC (eqt) = 1;
8816 else
8817 TREE_STATIC (eqt) = 0;
8818 TREE_PUBLIC (eqt) = 0;
a8e2bb76 8819 TREE_ADDRESSABLE (eqt) = 1; /* Ensure non-register allocation */
c7e4ee3a
CB
8820 DECL_CONTEXT (eqt) = current_function_decl;
8821 if (init)
8822 DECL_INITIAL (eqt) = error_mark_node;
8823 else
8824 DECL_INITIAL (eqt) = NULL_TREE;
5ff904cd 8825
c7e4ee3a 8826 eqt = start_decl (eqt, FALSE);
5ff904cd 8827
c7e4ee3a
CB
8828 /* Make sure that any type can live in EQUIVALENCE and be referenced
8829 without getting a bus error. We could pick the most restrictive
8830 alignment of all entities actually placed in the EQUIVALENCE, but
8831 this seems easy enough. */
5ff904cd 8832
c7e4ee3a 8833 DECL_ALIGN (eqt) = BIGGEST_ALIGNMENT;
11cf4d18 8834 DECL_USER_ALIGN (eqt) = 0;
5ff904cd 8835
c7e4ee3a
CB
8836 if ((!is_init && ffe_is_init_local_zero ())
8837 || (is_init && (ffestorag_init (eqst) == NULL)))
8838 init = ffecom_init_zero_ (eqt);
5ff904cd 8839
c7e4ee3a 8840 finish_decl (eqt, init, FALSE);
5ff904cd 8841
c7e4ee3a
CB
8842 if (is_init)
8843 ffestorag_set_init (eqst, ffebld_new_any ());
5ff904cd 8844
c7e4ee3a 8845 {
06ceef4e 8846 assert (TREE_CODE (DECL_SIZE_UNIT (eqt)) == INTEGER_CST);
05bccae2
RK
8847 assert (0 == compare_tree_int (DECL_SIZE_UNIT (eqt),
8848 (ffestorag_size (eqst)
8849 + ffestorag_modulo (eqst))));
c7e4ee3a 8850 }
5ff904cd 8851
c7e4ee3a 8852 ffestorag_set_hook (eqst, eqt);
5ff904cd 8853
c7e4ee3a
CB
8854 ffestorag_drive (ffestorag_list_equivs (eqst),
8855 &ffecom_member_phase2_,
8856 eqst);
5ff904cd
JL
8857}
8858
8859#endif
c7e4ee3a 8860/* Implement NAMELIST in back end. See f2c/format.c for more info. */
5ff904cd
JL
8861
8862#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
8863static tree
8864ffecom_transform_namelist_ (ffesymbol s)
5ff904cd 8865{
c7e4ee3a
CB
8866 tree nmlt;
8867 tree nmltype = ffecom_type_namelist_ ();
8868 tree nmlinits;
8869 tree nameinit;
8870 tree varsinit;
8871 tree nvarsinit;
8872 tree field;
8873 tree high;
c7e4ee3a
CB
8874 int i;
8875 static int mynumber = 0;
5ff904cd 8876
c7e4ee3a
CB
8877 nmlt = build_decl (VAR_DECL,
8878 ffecom_get_invented_identifier ("__g77_namelist_%d",
14657de8 8879 mynumber++),
c7e4ee3a
CB
8880 nmltype);
8881 TREE_STATIC (nmlt) = 1;
8882 DECL_INITIAL (nmlt) = error_mark_node;
5ff904cd 8883
c7e4ee3a 8884 nmlt = start_decl (nmlt, FALSE);
5ff904cd 8885
c7e4ee3a 8886 /* Process inits. */
5ff904cd 8887
c7e4ee3a 8888 i = strlen (ffesymbol_text (s));
5ff904cd 8889
c7e4ee3a
CB
8890 high = build_int_2 (i, 0);
8891 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
8892
8893 nameinit = ffecom_build_f2c_string_ (i + 1,
8894 ffesymbol_text (s));
8895 TREE_TYPE (nameinit)
8896 = build_type_variant
8897 (build_array_type
8898 (char_type_node,
8899 build_range_type (ffecom_f2c_ftnlen_type_node,
8900 ffecom_f2c_ftnlen_one_node,
8901 high)),
8902 1, 0);
8903 TREE_CONSTANT (nameinit) = 1;
8904 TREE_STATIC (nameinit) = 1;
8905 nameinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (nameinit)),
8906 nameinit);
8907
8908 varsinit = ffecom_vardesc_array_ (s);
8909 varsinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (varsinit)),
8910 varsinit);
8911 TREE_CONSTANT (varsinit) = 1;
8912 TREE_STATIC (varsinit) = 1;
8913
8914 {
8915 ffebld b;
8916
8917 for (i = 0, b = ffesymbol_namelist (s); b != NULL; b = ffebld_trail (b))
8918 ++i;
8919 }
8920 nvarsinit = build_int_2 (i, 0);
8921 TREE_TYPE (nvarsinit) = integer_type_node;
8922 TREE_CONSTANT (nvarsinit) = 1;
8923 TREE_STATIC (nvarsinit) = 1;
8924
8925 nmlinits = build_tree_list ((field = TYPE_FIELDS (nmltype)), nameinit);
8926 TREE_CHAIN (nmlinits) = build_tree_list ((field = TREE_CHAIN (field)),
8927 varsinit);
8928 TREE_CHAIN (TREE_CHAIN (nmlinits))
8929 = build_tree_list ((field = TREE_CHAIN (field)), nvarsinit);
8930
8931 nmlinits = build (CONSTRUCTOR, nmltype, NULL_TREE, nmlinits);
8932 TREE_CONSTANT (nmlinits) = 1;
8933 TREE_STATIC (nmlinits) = 1;
8934
8935 finish_decl (nmlt, nmlinits, FALSE);
8936
8937 nmlt = ffecom_1 (ADDR_EXPR, build_pointer_type (nmltype), nmlt);
8938
c7e4ee3a
CB
8939 return nmlt;
8940}
8941
8942#endif
8943
8944/* A subroutine of ffecom_tree_canonize_ref_. The incoming tree is
8945 analyzed on the assumption it is calculating a pointer to be
8946 indirected through. It must return the proper decl and offset,
8947 taking into account different units of measurements for offsets. */
8948
8949#if FFECOM_targetCURRENT == FFECOM_targetGCC
8950static void
8951ffecom_tree_canonize_ptr_ (tree *decl, tree *offset,
8952 tree t)
8953{
8954 switch (TREE_CODE (t))
8955 {
8956 case NOP_EXPR:
8957 case CONVERT_EXPR:
8958 case NON_LVALUE_EXPR:
8959 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
5ff904cd
JL
8960 break;
8961
c7e4ee3a
CB
8962 case PLUS_EXPR:
8963 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
8964 if ((*decl == NULL_TREE)
8965 || (*decl == error_mark_node))
8966 break;
8967
8968 if (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST)
8969 {
8970 /* An offset into COMMON. */
fed3cef0
RK
8971 *offset = fold (build (PLUS_EXPR, TREE_TYPE (*offset),
8972 *offset, TREE_OPERAND (t, 1)));
c7e4ee3a
CB
8973 /* Convert offset (presumably in bytes) into canonical units
8974 (presumably bits). */
76fa6b3b
ZW
8975 *offset = size_binop (MULT_EXPR,
8976 convert (bitsizetype, *offset),
8977 TYPE_SIZE (TREE_TYPE (TREE_TYPE (t))));
c7e4ee3a
CB
8978 break;
8979 }
8980 /* Not a COMMON reference, so an unrecognized pattern. */
8981 *decl = error_mark_node;
5ff904cd
JL
8982 break;
8983
c7e4ee3a
CB
8984 case PARM_DECL:
8985 *decl = t;
770ae6cc 8986 *offset = bitsize_zero_node;
5ff904cd
JL
8987 break;
8988
c7e4ee3a
CB
8989 case ADDR_EXPR:
8990 if (TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL)
8991 {
8992 /* A reference to COMMON. */
8993 *decl = TREE_OPERAND (t, 0);
770ae6cc 8994 *offset = bitsize_zero_node;
c7e4ee3a
CB
8995 break;
8996 }
8997 /* Fall through. */
5ff904cd 8998 default:
c7e4ee3a
CB
8999 /* Not a COMMON reference, so an unrecognized pattern. */
9000 *decl = error_mark_node;
5ff904cd
JL
9001 break;
9002 }
c7e4ee3a
CB
9003}
9004#endif
5ff904cd 9005
c7e4ee3a
CB
9006/* Given a tree that is possibly intended for use as an lvalue, return
9007 information representing a canonical view of that tree as a decl, an
9008 offset into that decl, and a size for the lvalue.
5ff904cd 9009
c7e4ee3a
CB
9010 If there's no applicable decl, NULL_TREE is returned for the decl,
9011 and the other fields are left undefined.
5ff904cd 9012
c7e4ee3a
CB
9013 If the tree doesn't fit the recognizable forms, an ERROR_MARK node
9014 is returned for the decl, and the other fields are left undefined.
5ff904cd 9015
c7e4ee3a
CB
9016 Otherwise, the decl returned currently is either a VAR_DECL or a
9017 PARM_DECL.
5ff904cd 9018
c7e4ee3a
CB
9019 The offset returned is always valid, but of course not necessarily
9020 a constant, and not necessarily converted into the appropriate
9021 type, leaving that up to the caller (so as to avoid that overhead
9022 if the decls being looked at are different anyway).
5ff904cd 9023
c7e4ee3a
CB
9024 If the size cannot be determined (e.g. an adjustable array),
9025 an ERROR_MARK node is returned for the size. Otherwise, the
9026 size returned is valid, not necessarily a constant, and not
9027 necessarily converted into the appropriate type as with the
9028 offset.
5ff904cd 9029
c7e4ee3a
CB
9030 Note that the offset and size expressions are expressed in the
9031 base storage units (usually bits) rather than in the units of
9032 the type of the decl, because two decls with different types
9033 might overlap but with apparently non-overlapping array offsets,
9034 whereas converting the array offsets to consistant offsets will
9035 reveal the overlap. */
5ff904cd
JL
9036
9037#if FFECOM_targetCURRENT == FFECOM_targetGCC
9038static void
c7e4ee3a
CB
9039ffecom_tree_canonize_ref_ (tree *decl, tree *offset,
9040 tree *size, tree t)
5ff904cd 9041{
c7e4ee3a
CB
9042 /* The default path is to report a nonexistant decl. */
9043 *decl = NULL_TREE;
5ff904cd 9044
c7e4ee3a 9045 if (t == NULL_TREE)
5ff904cd
JL
9046 return;
9047
c7e4ee3a
CB
9048 switch (TREE_CODE (t))
9049 {
9050 case ERROR_MARK:
9051 case IDENTIFIER_NODE:
9052 case INTEGER_CST:
9053 case REAL_CST:
9054 case COMPLEX_CST:
9055 case STRING_CST:
9056 case CONST_DECL:
9057 case PLUS_EXPR:
9058 case MINUS_EXPR:
9059 case MULT_EXPR:
9060 case TRUNC_DIV_EXPR:
9061 case CEIL_DIV_EXPR:
9062 case FLOOR_DIV_EXPR:
9063 case ROUND_DIV_EXPR:
9064 case TRUNC_MOD_EXPR:
9065 case CEIL_MOD_EXPR:
9066 case FLOOR_MOD_EXPR:
9067 case ROUND_MOD_EXPR:
9068 case RDIV_EXPR:
9069 case EXACT_DIV_EXPR:
9070 case FIX_TRUNC_EXPR:
9071 case FIX_CEIL_EXPR:
9072 case FIX_FLOOR_EXPR:
9073 case FIX_ROUND_EXPR:
9074 case FLOAT_EXPR:
c7e4ee3a
CB
9075 case NEGATE_EXPR:
9076 case MIN_EXPR:
9077 case MAX_EXPR:
9078 case ABS_EXPR:
9079 case FFS_EXPR:
9080 case LSHIFT_EXPR:
9081 case RSHIFT_EXPR:
9082 case LROTATE_EXPR:
9083 case RROTATE_EXPR:
9084 case BIT_IOR_EXPR:
9085 case BIT_XOR_EXPR:
9086 case BIT_AND_EXPR:
9087 case BIT_ANDTC_EXPR:
9088 case BIT_NOT_EXPR:
9089 case TRUTH_ANDIF_EXPR:
9090 case TRUTH_ORIF_EXPR:
9091 case TRUTH_AND_EXPR:
9092 case TRUTH_OR_EXPR:
9093 case TRUTH_XOR_EXPR:
9094 case TRUTH_NOT_EXPR:
9095 case LT_EXPR:
9096 case LE_EXPR:
9097 case GT_EXPR:
9098 case GE_EXPR:
9099 case EQ_EXPR:
9100 case NE_EXPR:
9101 case COMPLEX_EXPR:
9102 case CONJ_EXPR:
9103 case REALPART_EXPR:
9104 case IMAGPART_EXPR:
9105 case LABEL_EXPR:
9106 case COMPONENT_REF:
9107 case COMPOUND_EXPR:
9108 case ADDR_EXPR:
9109 return;
5ff904cd 9110
c7e4ee3a
CB
9111 case VAR_DECL:
9112 case PARM_DECL:
9113 *decl = t;
770ae6cc 9114 *offset = bitsize_zero_node;
c7e4ee3a
CB
9115 *size = TYPE_SIZE (TREE_TYPE (t));
9116 return;
5ff904cd 9117
c7e4ee3a
CB
9118 case ARRAY_REF:
9119 {
9120 tree array = TREE_OPERAND (t, 0);
9121 tree element = TREE_OPERAND (t, 1);
9122 tree init_offset;
9123
9124 if ((array == NULL_TREE)
9125 || (element == NULL_TREE))
9126 {
9127 *decl = error_mark_node;
9128 return;
9129 }
9130
9131 ffecom_tree_canonize_ref_ (decl, &init_offset, size,
9132 array);
9133 if ((*decl == NULL_TREE)
9134 || (*decl == error_mark_node))
9135 return;
9136
76fa6b3b
ZW
9137 /* Calculate ((element - base) * NBBY) + init_offset. */
9138 *offset = fold (build (MINUS_EXPR, TREE_TYPE (element),
9139 element,
9140 TYPE_MIN_VALUE (TYPE_DOMAIN
9141 (TREE_TYPE (array)))));
9142
9143 *offset = size_binop (MULT_EXPR,
9144 convert (bitsizetype, *offset),
9145 TYPE_SIZE (TREE_TYPE (TREE_TYPE (array))));
9146
9147 *offset = size_binop (PLUS_EXPR, init_offset, *offset);
c7e4ee3a
CB
9148
9149 *size = TYPE_SIZE (TREE_TYPE (t));
9150 return;
9151 }
9152
9153 case INDIRECT_REF:
9154
9155 /* Most of this code is to handle references to COMMON. And so
9156 far that is useful only for calling library functions, since
9157 external (user) functions might reference common areas. But
9158 even calling an external function, it's worthwhile to decode
9159 COMMON references because if not storing into COMMON, we don't
9160 want COMMON-based arguments to gratuitously force use of a
9161 temporary. */
9162
9163 *size = TYPE_SIZE (TREE_TYPE (t));
5ff904cd 9164
c7e4ee3a
CB
9165 ffecom_tree_canonize_ptr_ (decl, offset,
9166 TREE_OPERAND (t, 0));
5ff904cd 9167
c7e4ee3a 9168 return;
5ff904cd 9169
c7e4ee3a
CB
9170 case CONVERT_EXPR:
9171 case NOP_EXPR:
9172 case MODIFY_EXPR:
9173 case NON_LVALUE_EXPR:
9174 case RESULT_DECL:
9175 case FIELD_DECL:
9176 case COND_EXPR: /* More cases than we can handle. */
9177 case SAVE_EXPR:
9178 case REFERENCE_EXPR:
9179 case PREDECREMENT_EXPR:
9180 case PREINCREMENT_EXPR:
9181 case POSTDECREMENT_EXPR:
9182 case POSTINCREMENT_EXPR:
9183 case CALL_EXPR:
9184 default:
9185 *decl = error_mark_node;
9186 return;
9187 }
9188}
9189#endif
5ff904cd 9190
c7e4ee3a 9191/* Do divide operation appropriate to type of operands. */
5ff904cd 9192
c7e4ee3a
CB
9193#if FFECOM_targetCURRENT == FFECOM_targetGCC
9194static tree
9195ffecom_tree_divide_ (tree tree_type, tree left, tree right,
9196 tree dest_tree, ffebld dest, bool *dest_used,
9197 tree hook)
9198{
9199 if ((left == error_mark_node)
9200 || (right == error_mark_node))
9201 return error_mark_node;
a6fa6420 9202
c7e4ee3a
CB
9203 switch (TREE_CODE (tree_type))
9204 {
9205 case INTEGER_TYPE:
9206 return ffecom_2 (TRUNC_DIV_EXPR, tree_type,
9207 left,
9208 right);
a6fa6420 9209
c7e4ee3a 9210 case COMPLEX_TYPE:
c64f913e
CB
9211 if (! optimize_size)
9212 return ffecom_2 (RDIV_EXPR, tree_type,
9213 left,
9214 right);
c7e4ee3a
CB
9215 {
9216 ffecomGfrt ix;
a6fa6420 9217
c7e4ee3a
CB
9218 if (TREE_TYPE (tree_type)
9219 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9220 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */
9221 else
9222 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */
a6fa6420 9223
c7e4ee3a
CB
9224 left = ffecom_1 (ADDR_EXPR,
9225 build_pointer_type (TREE_TYPE (left)),
9226 left);
9227 left = build_tree_list (NULL_TREE, left);
9228 right = ffecom_1 (ADDR_EXPR,
9229 build_pointer_type (TREE_TYPE (right)),
9230 right);
9231 right = build_tree_list (NULL_TREE, right);
9232 TREE_CHAIN (left) = right;
a6fa6420 9233
c7e4ee3a
CB
9234 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9235 ffecom_gfrt_kindtype (ix),
9236 ffe_is_f2c_library (),
9237 tree_type,
9238 left,
9239 dest_tree, dest, dest_used,
9240 NULL_TREE, TRUE, hook);
9241 }
9242 break;
5ff904cd 9243
c7e4ee3a
CB
9244 case RECORD_TYPE:
9245 {
9246 ffecomGfrt ix;
5ff904cd 9247
c7e4ee3a
CB
9248 if (TREE_TYPE (TYPE_FIELDS (tree_type))
9249 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9250 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */
9251 else
9252 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */
5ff904cd 9253
c7e4ee3a
CB
9254 left = ffecom_1 (ADDR_EXPR,
9255 build_pointer_type (TREE_TYPE (left)),
9256 left);
9257 left = build_tree_list (NULL_TREE, left);
9258 right = ffecom_1 (ADDR_EXPR,
9259 build_pointer_type (TREE_TYPE (right)),
9260 right);
9261 right = build_tree_list (NULL_TREE, right);
9262 TREE_CHAIN (left) = right;
a6fa6420 9263
c7e4ee3a
CB
9264 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9265 ffecom_gfrt_kindtype (ix),
9266 ffe_is_f2c_library (),
9267 tree_type,
9268 left,
9269 dest_tree, dest, dest_used,
9270 NULL_TREE, TRUE, hook);
9271 }
9272 break;
5ff904cd 9273
c7e4ee3a
CB
9274 default:
9275 return ffecom_2 (RDIV_EXPR, tree_type,
9276 left,
9277 right);
5ff904cd 9278 }
c7e4ee3a 9279}
5ff904cd 9280
c7e4ee3a
CB
9281#endif
9282/* Build type info for non-dummy variable. */
5ff904cd 9283
c7e4ee3a
CB
9284#if FFECOM_targetCURRENT == FFECOM_targetGCC
9285static tree
9286ffecom_type_localvar_ (ffesymbol s, ffeinfoBasictype bt,
9287 ffeinfoKindtype kt)
9288{
9289 tree type;
9290 ffebld dl;
9291 ffebld dim;
9292 tree lowt;
9293 tree hight;
5ff904cd 9294
c7e4ee3a
CB
9295 type = ffecom_tree_type[bt][kt];
9296 if (bt == FFEINFO_basictypeCHARACTER)
9297 {
9298 hight = build_int_2 (ffesymbol_size (s), 0);
9299 TREE_TYPE (hight) = ffecom_f2c_ftnlen_type_node;
5ff904cd 9300
c7e4ee3a
CB
9301 type
9302 = build_array_type
9303 (type,
9304 build_range_type (ffecom_f2c_ftnlen_type_node,
9305 ffecom_f2c_ftnlen_one_node,
9306 hight));
9307 type = ffecom_check_size_overflow_ (s, type, FALSE);
9308 }
5ff904cd 9309
c7e4ee3a
CB
9310 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
9311 {
9312 if (type == error_mark_node)
9313 break;
5ff904cd 9314
c7e4ee3a
CB
9315 dim = ffebld_head (dl);
9316 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
5ff904cd 9317
c7e4ee3a
CB
9318 if (ffebld_left (dim) == NULL)
9319 lowt = integer_one_node;
9320 else
9321 lowt = ffecom_expr (ffebld_left (dim));
5ff904cd 9322
c7e4ee3a
CB
9323 if (TREE_CODE (lowt) != INTEGER_CST)
9324 lowt = variable_size (lowt);
5ff904cd 9325
c7e4ee3a
CB
9326 assert (ffebld_right (dim) != NULL);
9327 hight = ffecom_expr (ffebld_right (dim));
5ff904cd 9328
c7e4ee3a
CB
9329 if (TREE_CODE (hight) != INTEGER_CST)
9330 hight = variable_size (hight);
5ff904cd 9331
c7e4ee3a
CB
9332 type = build_array_type (type,
9333 build_range_type (ffecom_integer_type_node,
9334 lowt, hight));
9335 type = ffecom_check_size_overflow_ (s, type, FALSE);
9336 }
5ff904cd 9337
c7e4ee3a 9338 return type;
5ff904cd
JL
9339}
9340
9341#endif
c7e4ee3a 9342/* Build Namelist type. */
5ff904cd 9343
c7e4ee3a
CB
9344#if FFECOM_targetCURRENT == FFECOM_targetGCC
9345static tree
9346ffecom_type_namelist_ ()
9347{
9348 static tree type = NULL_TREE;
5ff904cd 9349
c7e4ee3a
CB
9350 if (type == NULL_TREE)
9351 {
9352 static tree namefield, varsfield, nvarsfield;
9353 tree vardesctype;
5ff904cd 9354
c7e4ee3a 9355 vardesctype = ffecom_type_vardesc_ ();
5ff904cd 9356
c7e4ee3a 9357 type = make_node (RECORD_TYPE);
a6fa6420 9358
c7e4ee3a 9359 vardesctype = build_pointer_type (build_pointer_type (vardesctype));
a6fa6420 9360
c7e4ee3a
CB
9361 namefield = ffecom_decl_field (type, NULL_TREE, "name",
9362 string_type_node);
9363 varsfield = ffecom_decl_field (type, namefield, "vars", vardesctype);
9364 nvarsfield = ffecom_decl_field (type, varsfield, "nvars",
9365 integer_type_node);
a6fa6420 9366
c7e4ee3a
CB
9367 TYPE_FIELDS (type) = namefield;
9368 layout_type (type);
a6fa6420 9369
7189a4b0 9370 ggc_add_tree_root (&type, 1);
5ff904cd 9371 }
5ff904cd 9372
c7e4ee3a
CB
9373 return type;
9374}
5ff904cd 9375
c7e4ee3a 9376#endif
5ff904cd 9377
c7e4ee3a 9378/* Build Vardesc type. */
5ff904cd 9379
c7e4ee3a
CB
9380#if FFECOM_targetCURRENT == FFECOM_targetGCC
9381static tree
9382ffecom_type_vardesc_ ()
9383{
9384 static tree type = NULL_TREE;
9385 static tree namefield, addrfield, dimsfield, typefield;
5ff904cd 9386
c7e4ee3a
CB
9387 if (type == NULL_TREE)
9388 {
c7e4ee3a 9389 type = make_node (RECORD_TYPE);
5ff904cd 9390
c7e4ee3a
CB
9391 namefield = ffecom_decl_field (type, NULL_TREE, "name",
9392 string_type_node);
9393 addrfield = ffecom_decl_field (type, namefield, "addr",
9394 string_type_node);
9395 dimsfield = ffecom_decl_field (type, addrfield, "dims",
9396 ffecom_f2c_ptr_to_ftnlen_type_node);
9397 typefield = ffecom_decl_field (type, dimsfield, "type",
9398 integer_type_node);
5ff904cd 9399
c7e4ee3a
CB
9400 TYPE_FIELDS (type) = namefield;
9401 layout_type (type);
9402
7189a4b0 9403 ggc_add_tree_root (&type, 1);
c7e4ee3a
CB
9404 }
9405
9406 return type;
5ff904cd
JL
9407}
9408
9409#endif
5ff904cd
JL
9410
9411#if FFECOM_targetCURRENT == FFECOM_targetGCC
9412static tree
c7e4ee3a 9413ffecom_vardesc_ (ffebld expr)
5ff904cd 9414{
c7e4ee3a 9415 ffesymbol s;
5ff904cd 9416
c7e4ee3a
CB
9417 assert (ffebld_op (expr) == FFEBLD_opSYMTER);
9418 s = ffebld_symter (expr);
5ff904cd 9419
c7e4ee3a
CB
9420 if (ffesymbol_hook (s).vardesc_tree == NULL_TREE)
9421 {
9422 int i;
9423 tree vardesctype = ffecom_type_vardesc_ ();
9424 tree var;
9425 tree nameinit;
9426 tree dimsinit;
9427 tree addrinit;
9428 tree typeinit;
9429 tree field;
9430 tree varinits;
c7e4ee3a 9431 static int mynumber = 0;
5ff904cd 9432
c7e4ee3a
CB
9433 var = build_decl (VAR_DECL,
9434 ffecom_get_invented_identifier ("__g77_vardesc_%d",
14657de8 9435 mynumber++),
c7e4ee3a
CB
9436 vardesctype);
9437 TREE_STATIC (var) = 1;
9438 DECL_INITIAL (var) = error_mark_node;
5ff904cd 9439
c7e4ee3a 9440 var = start_decl (var, FALSE);
5ff904cd 9441
c7e4ee3a 9442 /* Process inits. */
5ff904cd 9443
c7e4ee3a
CB
9444 nameinit = ffecom_build_f2c_string_ ((i = strlen (ffesymbol_text (s)))
9445 + 1,
9446 ffesymbol_text (s));
9447 TREE_TYPE (nameinit)
9448 = build_type_variant
9449 (build_array_type
9450 (char_type_node,
9451 build_range_type (integer_type_node,
9452 integer_one_node,
9453 build_int_2 (i, 0))),
9454 1, 0);
9455 TREE_CONSTANT (nameinit) = 1;
9456 TREE_STATIC (nameinit) = 1;
9457 nameinit = ffecom_1 (ADDR_EXPR,
9458 build_pointer_type (TREE_TYPE (nameinit)),
9459 nameinit);
5ff904cd 9460
c7e4ee3a 9461 addrinit = ffecom_arg_ptr_to_expr (expr, &typeinit);
5ff904cd 9462
c7e4ee3a 9463 dimsinit = ffecom_vardesc_dims_ (s);
5ff904cd 9464
c7e4ee3a
CB
9465 if (typeinit == NULL_TREE)
9466 {
9467 ffeinfoBasictype bt = ffesymbol_basictype (s);
9468 ffeinfoKindtype kt = ffesymbol_kindtype (s);
9469 int tc = ffecom_f2c_typecode (bt, kt);
5ff904cd 9470
c7e4ee3a
CB
9471 assert (tc != -1);
9472 typeinit = build_int_2 (tc, (tc < 0) ? -1 : 0);
9473 }
9474 else
9475 typeinit = ffecom_1 (NEGATE_EXPR, TREE_TYPE (typeinit), typeinit);
5ff904cd 9476
c7e4ee3a
CB
9477 varinits = build_tree_list ((field = TYPE_FIELDS (vardesctype)),
9478 nameinit);
9479 TREE_CHAIN (varinits) = build_tree_list ((field = TREE_CHAIN (field)),
9480 addrinit);
9481 TREE_CHAIN (TREE_CHAIN (varinits))
9482 = build_tree_list ((field = TREE_CHAIN (field)), dimsinit);
9483 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (varinits)))
9484 = build_tree_list ((field = TREE_CHAIN (field)), typeinit);
5ff904cd 9485
c7e4ee3a
CB
9486 varinits = build (CONSTRUCTOR, vardesctype, NULL_TREE, varinits);
9487 TREE_CONSTANT (varinits) = 1;
9488 TREE_STATIC (varinits) = 1;
5ff904cd 9489
c7e4ee3a 9490 finish_decl (var, varinits, FALSE);
5ff904cd 9491
c7e4ee3a 9492 var = ffecom_1 (ADDR_EXPR, build_pointer_type (vardesctype), var);
5ff904cd 9493
c7e4ee3a
CB
9494 ffesymbol_hook (s).vardesc_tree = var;
9495 }
5ff904cd 9496
c7e4ee3a
CB
9497 return ffesymbol_hook (s).vardesc_tree;
9498}
5ff904cd 9499
c7e4ee3a 9500#endif
5ff904cd 9501#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
9502static tree
9503ffecom_vardesc_array_ (ffesymbol s)
5ff904cd 9504{
c7e4ee3a
CB
9505 ffebld b;
9506 tree list;
9507 tree item = NULL_TREE;
9508 tree var;
9509 int i;
c7e4ee3a 9510 static int mynumber = 0;
5ff904cd 9511
c7e4ee3a
CB
9512 for (i = 0, list = NULL_TREE, b = ffesymbol_namelist (s);
9513 b != NULL;
9514 b = ffebld_trail (b), ++i)
9515 {
9516 tree t;
5ff904cd 9517
c7e4ee3a 9518 t = ffecom_vardesc_ (ffebld_head (b));
5ff904cd 9519
c7e4ee3a
CB
9520 if (list == NULL_TREE)
9521 list = item = build_tree_list (NULL_TREE, t);
9522 else
5ff904cd 9523 {
c7e4ee3a
CB
9524 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
9525 item = TREE_CHAIN (item);
5ff904cd 9526 }
5ff904cd 9527 }
5ff904cd 9528
c7e4ee3a
CB
9529 item = build_array_type (build_pointer_type (ffecom_type_vardesc_ ()),
9530 build_range_type (integer_type_node,
9531 integer_one_node,
9532 build_int_2 (i, 0)));
9533 list = build (CONSTRUCTOR, item, NULL_TREE, list);
9534 TREE_CONSTANT (list) = 1;
9535 TREE_STATIC (list) = 1;
5ff904cd 9536
14657de8 9537 var = ffecom_get_invented_identifier ("__g77_vardesc_array_%d", mynumber++);
c7e4ee3a
CB
9538 var = build_decl (VAR_DECL, var, item);
9539 TREE_STATIC (var) = 1;
9540 DECL_INITIAL (var) = error_mark_node;
9541 var = start_decl (var, FALSE);
9542 finish_decl (var, list, FALSE);
5ff904cd 9543
c7e4ee3a
CB
9544 return var;
9545}
5ff904cd 9546
c7e4ee3a
CB
9547#endif
9548#if FFECOM_targetCURRENT == FFECOM_targetGCC
9549static tree
9550ffecom_vardesc_dims_ (ffesymbol s)
9551{
9552 if (ffesymbol_dims (s) == NULL)
9553 return convert (ffecom_f2c_ptr_to_ftnlen_type_node,
9554 integer_zero_node);
5ff904cd 9555
c7e4ee3a
CB
9556 {
9557 ffebld b;
9558 ffebld e;
9559 tree list;
9560 tree backlist;
9561 tree item = NULL_TREE;
9562 tree var;
c7e4ee3a
CB
9563 tree numdim;
9564 tree numelem;
9565 tree baseoff = NULL_TREE;
9566 static int mynumber = 0;
9567
9568 numdim = build_int_2 ((int) ffesymbol_rank (s), 0);
9569 TREE_TYPE (numdim) = ffecom_f2c_ftnlen_type_node;
9570
9571 numelem = ffecom_expr (ffesymbol_arraysize (s));
9572 TREE_TYPE (numelem) = ffecom_f2c_ftnlen_type_node;
9573
9574 list = NULL_TREE;
9575 backlist = NULL_TREE;
9576 for (b = ffesymbol_dims (s), e = ffesymbol_extents (s);
9577 b != NULL;
9578 b = ffebld_trail (b), e = ffebld_trail (e))
5ff904cd 9579 {
c7e4ee3a
CB
9580 tree t;
9581 tree low;
9582 tree back;
5ff904cd 9583
c7e4ee3a
CB
9584 if (ffebld_trail (b) == NULL)
9585 t = NULL_TREE;
9586 else
5ff904cd 9587 {
c7e4ee3a
CB
9588 t = convert (ffecom_f2c_ftnlen_type_node,
9589 ffecom_expr (ffebld_head (e)));
5ff904cd 9590
c7e4ee3a
CB
9591 if (list == NULL_TREE)
9592 list = item = build_tree_list (NULL_TREE, t);
9593 else
9594 {
9595 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
9596 item = TREE_CHAIN (item);
9597 }
9598 }
5ff904cd 9599
c7e4ee3a
CB
9600 if (ffebld_left (ffebld_head (b)) == NULL)
9601 low = ffecom_integer_one_node;
9602 else
9603 low = ffecom_expr (ffebld_left (ffebld_head (b)));
9604 low = convert (ffecom_f2c_ftnlen_type_node, low);
5ff904cd 9605
c7e4ee3a
CB
9606 back = build_tree_list (low, t);
9607 TREE_CHAIN (back) = backlist;
9608 backlist = back;
9609 }
5ff904cd 9610
c7e4ee3a
CB
9611 for (item = backlist; item != NULL_TREE; item = TREE_CHAIN (item))
9612 {
9613 if (TREE_VALUE (item) == NULL_TREE)
9614 baseoff = TREE_PURPOSE (item);
9615 else
9616 baseoff = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
9617 TREE_PURPOSE (item),
9618 ffecom_2 (MULT_EXPR,
9619 ffecom_f2c_ftnlen_type_node,
9620 TREE_VALUE (item),
9621 baseoff));
5ff904cd
JL
9622 }
9623
c7e4ee3a 9624 /* backlist now dead, along with all TREE_PURPOSEs on it. */
5ff904cd 9625
c7e4ee3a
CB
9626 baseoff = build_tree_list (NULL_TREE, baseoff);
9627 TREE_CHAIN (baseoff) = list;
5ff904cd 9628
c7e4ee3a
CB
9629 numelem = build_tree_list (NULL_TREE, numelem);
9630 TREE_CHAIN (numelem) = baseoff;
5ff904cd 9631
c7e4ee3a
CB
9632 numdim = build_tree_list (NULL_TREE, numdim);
9633 TREE_CHAIN (numdim) = numelem;
5ff904cd 9634
c7e4ee3a
CB
9635 item = build_array_type (ffecom_f2c_ftnlen_type_node,
9636 build_range_type (integer_type_node,
9637 integer_zero_node,
9638 build_int_2
9639 ((int) ffesymbol_rank (s)
9640 + 2, 0)));
9641 list = build (CONSTRUCTOR, item, NULL_TREE, numdim);
9642 TREE_CONSTANT (list) = 1;
9643 TREE_STATIC (list) = 1;
9644
14657de8 9645 var = ffecom_get_invented_identifier ("__g77_dims_%d", mynumber++);
c7e4ee3a
CB
9646 var = build_decl (VAR_DECL, var, item);
9647 TREE_STATIC (var) = 1;
9648 DECL_INITIAL (var) = error_mark_node;
9649 var = start_decl (var, FALSE);
9650 finish_decl (var, list, FALSE);
9651
9652 var = ffecom_1 (ADDR_EXPR, build_pointer_type (item), var);
9653
c7e4ee3a
CB
9654 return var;
9655 }
5ff904cd 9656}
c7e4ee3a 9657
5ff904cd 9658#endif
c7e4ee3a
CB
9659/* Essentially does a "fold (build1 (code, type, node))" while checking
9660 for certain housekeeping things.
5ff904cd 9661
c7e4ee3a
CB
9662 NOTE: for building an ADDR_EXPR around a FUNCTION_DECL, use
9663 ffecom_1_fn instead. */
5ff904cd
JL
9664
9665#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
9666tree
9667ffecom_1 (enum tree_code code, tree type, tree node)
5ff904cd 9668{
c7e4ee3a
CB
9669 tree item;
9670
9671 if ((node == error_mark_node)
9672 || (type == error_mark_node))
5ff904cd
JL
9673 return error_mark_node;
9674
c7e4ee3a 9675 if (code == ADDR_EXPR)
5ff904cd 9676 {
c7e4ee3a
CB
9677 if (!mark_addressable (node))
9678 assert ("can't mark_addressable this node!" == NULL);
9679 }
5ff904cd 9680
c7e4ee3a
CB
9681 switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
9682 {
9683 tree realtype;
5ff904cd 9684
c7e4ee3a
CB
9685 case REALPART_EXPR:
9686 item = build (COMPONENT_REF, type, node, TYPE_FIELDS (TREE_TYPE (node)));
5ff904cd
JL
9687 break;
9688
c7e4ee3a
CB
9689 case IMAGPART_EXPR:
9690 item = build (COMPONENT_REF, type, node, TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (node))));
9691 break;
5ff904cd 9692
5ff904cd 9693
c7e4ee3a
CB
9694 case NEGATE_EXPR:
9695 if (TREE_CODE (type) != RECORD_TYPE)
9696 {
9697 item = build1 (code, type, node);
9698 break;
9699 }
9700 node = ffecom_stabilize_aggregate_ (node);
9701 realtype = TREE_TYPE (TYPE_FIELDS (type));
9702 item =
9703 ffecom_2 (COMPLEX_EXPR, type,
9704 ffecom_1 (NEGATE_EXPR, realtype,
9705 ffecom_1 (REALPART_EXPR, realtype,
9706 node)),
9707 ffecom_1 (NEGATE_EXPR, realtype,
9708 ffecom_1 (IMAGPART_EXPR, realtype,
9709 node)));
5ff904cd
JL
9710 break;
9711
9712 default:
c7e4ee3a
CB
9713 item = build1 (code, type, node);
9714 break;
5ff904cd 9715 }
5ff904cd 9716
c7e4ee3a
CB
9717 if (TREE_SIDE_EFFECTS (node))
9718 TREE_SIDE_EFFECTS (item) = 1;
9719 if ((code == ADDR_EXPR) && staticp (node))
9720 TREE_CONSTANT (item) = 1;
9721 return fold (item);
9722}
5ff904cd 9723#endif
5ff904cd 9724
c7e4ee3a
CB
9725/* Like ffecom_1 (ADDR_EXPR, TREE_TYPE (node), node), except
9726 handles TREE_CODE (node) == FUNCTION_DECL. In particular,
9727 does not set TREE_ADDRESSABLE (because calling an inline
9728 function does not mean the function needs to be separately
9729 compiled). */
5ff904cd
JL
9730
9731#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
9732tree
9733ffecom_1_fn (tree node)
5ff904cd 9734{
c7e4ee3a 9735 tree item;
5ff904cd 9736 tree type;
5ff904cd 9737
c7e4ee3a
CB
9738 if (node == error_mark_node)
9739 return error_mark_node;
5ff904cd 9740
c7e4ee3a
CB
9741 type = build_type_variant (TREE_TYPE (node),
9742 TREE_READONLY (node),
9743 TREE_THIS_VOLATILE (node));
9744 item = build1 (ADDR_EXPR,
9745 build_pointer_type (type), node);
9746 if (TREE_SIDE_EFFECTS (node))
9747 TREE_SIDE_EFFECTS (item) = 1;
9748 if (staticp (node))
9749 TREE_CONSTANT (item) = 1;
9750 return fold (item);
5ff904cd 9751}
5ff904cd 9752#endif
c7e4ee3a
CB
9753
9754/* Essentially does a "fold (build (code, type, node1, node2))" while
9755 checking for certain housekeeping things. */
5ff904cd
JL
9756
9757#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
9758tree
9759ffecom_2 (enum tree_code code, tree type, tree node1,
9760 tree node2)
5ff904cd 9761{
c7e4ee3a 9762 tree item;
5ff904cd 9763
c7e4ee3a
CB
9764 if ((node1 == error_mark_node)
9765 || (node2 == error_mark_node)
9766 || (type == error_mark_node))
9767 return error_mark_node;
9768
9769 switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
5ff904cd 9770 {
c7e4ee3a 9771 tree a, b, c, d, realtype;
5ff904cd 9772
c7e4ee3a
CB
9773 case CONJ_EXPR:
9774 assert ("no CONJ_EXPR support yet" == NULL);
9775 return error_mark_node;
5ff904cd 9776
c7e4ee3a
CB
9777 case COMPLEX_EXPR:
9778 item = build_tree_list (TYPE_FIELDS (type), node1);
9779 TREE_CHAIN (item) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), node2);
9780 item = build (CONSTRUCTOR, type, NULL_TREE, item);
9781 break;
5ff904cd 9782
c7e4ee3a
CB
9783 case PLUS_EXPR:
9784 if (TREE_CODE (type) != RECORD_TYPE)
9785 {
9786 item = build (code, type, node1, node2);
9787 break;
9788 }
9789 node1 = ffecom_stabilize_aggregate_ (node1);
9790 node2 = ffecom_stabilize_aggregate_ (node2);
9791 realtype = TREE_TYPE (TYPE_FIELDS (type));
9792 item =
9793 ffecom_2 (COMPLEX_EXPR, type,
9794 ffecom_2 (PLUS_EXPR, realtype,
9795 ffecom_1 (REALPART_EXPR, realtype,
9796 node1),
9797 ffecom_1 (REALPART_EXPR, realtype,
9798 node2)),
9799 ffecom_2 (PLUS_EXPR, realtype,
9800 ffecom_1 (IMAGPART_EXPR, realtype,
9801 node1),
9802 ffecom_1 (IMAGPART_EXPR, realtype,
9803 node2)));
9804 break;
5ff904cd 9805
c7e4ee3a
CB
9806 case MINUS_EXPR:
9807 if (TREE_CODE (type) != RECORD_TYPE)
9808 {
9809 item = build (code, type, node1, node2);
9810 break;
9811 }
9812 node1 = ffecom_stabilize_aggregate_ (node1);
9813 node2 = ffecom_stabilize_aggregate_ (node2);
9814 realtype = TREE_TYPE (TYPE_FIELDS (type));
9815 item =
9816 ffecom_2 (COMPLEX_EXPR, type,
9817 ffecom_2 (MINUS_EXPR, realtype,
9818 ffecom_1 (REALPART_EXPR, realtype,
9819 node1),
9820 ffecom_1 (REALPART_EXPR, realtype,
9821 node2)),
9822 ffecom_2 (MINUS_EXPR, realtype,
9823 ffecom_1 (IMAGPART_EXPR, realtype,
9824 node1),
9825 ffecom_1 (IMAGPART_EXPR, realtype,
9826 node2)));
9827 break;
5ff904cd 9828
c7e4ee3a
CB
9829 case MULT_EXPR:
9830 if (TREE_CODE (type) != RECORD_TYPE)
9831 {
9832 item = build (code, type, node1, node2);
9833 break;
9834 }
9835 node1 = ffecom_stabilize_aggregate_ (node1);
9836 node2 = ffecom_stabilize_aggregate_ (node2);
9837 realtype = TREE_TYPE (TYPE_FIELDS (type));
9838 a = save_expr (ffecom_1 (REALPART_EXPR, realtype,
9839 node1));
9840 b = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
9841 node1));
9842 c = save_expr (ffecom_1 (REALPART_EXPR, realtype,
9843 node2));
9844 d = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
9845 node2));
9846 item =
9847 ffecom_2 (COMPLEX_EXPR, type,
9848 ffecom_2 (MINUS_EXPR, realtype,
9849 ffecom_2 (MULT_EXPR, realtype,
9850 a,
9851 c),
9852 ffecom_2 (MULT_EXPR, realtype,
9853 b,
9854 d)),
9855 ffecom_2 (PLUS_EXPR, realtype,
9856 ffecom_2 (MULT_EXPR, realtype,
9857 a,
9858 d),
9859 ffecom_2 (MULT_EXPR, realtype,
9860 c,
9861 b)));
9862 break;
5ff904cd 9863
c7e4ee3a
CB
9864 case EQ_EXPR:
9865 if ((TREE_CODE (node1) != RECORD_TYPE)
9866 && (TREE_CODE (node2) != RECORD_TYPE))
9867 {
9868 item = build (code, type, node1, node2);
9869 break;
9870 }
9871 assert (TREE_CODE (node1) == RECORD_TYPE);
9872 assert (TREE_CODE (node2) == RECORD_TYPE);
9873 node1 = ffecom_stabilize_aggregate_ (node1);
9874 node2 = ffecom_stabilize_aggregate_ (node2);
9875 realtype = TREE_TYPE (TYPE_FIELDS (type));
9876 item =
9877 ffecom_2 (TRUTH_ANDIF_EXPR, type,
9878 ffecom_2 (code, type,
9879 ffecom_1 (REALPART_EXPR, realtype,
9880 node1),
9881 ffecom_1 (REALPART_EXPR, realtype,
9882 node2)),
9883 ffecom_2 (code, type,
9884 ffecom_1 (IMAGPART_EXPR, realtype,
9885 node1),
9886 ffecom_1 (IMAGPART_EXPR, realtype,
9887 node2)));
9888 break;
9889
9890 case NE_EXPR:
9891 if ((TREE_CODE (node1) != RECORD_TYPE)
9892 && (TREE_CODE (node2) != RECORD_TYPE))
9893 {
9894 item = build (code, type, node1, node2);
9895 break;
9896 }
9897 assert (TREE_CODE (node1) == RECORD_TYPE);
9898 assert (TREE_CODE (node2) == RECORD_TYPE);
9899 node1 = ffecom_stabilize_aggregate_ (node1);
9900 node2 = ffecom_stabilize_aggregate_ (node2);
9901 realtype = TREE_TYPE (TYPE_FIELDS (type));
9902 item =
9903 ffecom_2 (TRUTH_ORIF_EXPR, type,
9904 ffecom_2 (code, type,
9905 ffecom_1 (REALPART_EXPR, realtype,
9906 node1),
9907 ffecom_1 (REALPART_EXPR, realtype,
9908 node2)),
9909 ffecom_2 (code, type,
9910 ffecom_1 (IMAGPART_EXPR, realtype,
9911 node1),
9912 ffecom_1 (IMAGPART_EXPR, realtype,
9913 node2)));
9914 break;
5ff904cd 9915
c7e4ee3a
CB
9916 default:
9917 item = build (code, type, node1, node2);
9918 break;
5ff904cd
JL
9919 }
9920
c7e4ee3a
CB
9921 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2))
9922 TREE_SIDE_EFFECTS (item) = 1;
9923 return fold (item);
5ff904cd
JL
9924}
9925
9926#endif
c7e4ee3a 9927/* ffecom_2pass_advise_entrypoint -- Advise that there's this entrypoint
5ff904cd 9928
c7e4ee3a
CB
9929 ffesymbol s; // the ENTRY point itself
9930 if (ffecom_2pass_advise_entrypoint(s))
9931 // the ENTRY point has been accepted
5ff904cd 9932
c7e4ee3a
CB
9933 Does whatever compiler needs to do when it learns about the entrypoint,
9934 like determine the return type of the master function, count the
9935 number of entrypoints, etc. Returns FALSE if the return type is
9936 not compatible with the return type(s) of other entrypoint(s).
5ff904cd 9937
c7e4ee3a
CB
9938 NOTE: for every call to this fn that returns TRUE, _do_entrypoint must
9939 later (after _finish_progunit) be called with the same entrypoint(s)
9940 as passed to this fn for which TRUE was returned.
5ff904cd 9941
c7e4ee3a
CB
9942 03-Jan-92 JCB 2.0
9943 Return FALSE if the return type conflicts with previous entrypoints. */
5ff904cd
JL
9944
9945#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
9946bool
9947ffecom_2pass_advise_entrypoint (ffesymbol entry)
5ff904cd 9948{
c7e4ee3a
CB
9949 ffebld list; /* opITEM. */
9950 ffebld mlist; /* opITEM. */
9951 ffebld plist; /* opITEM. */
9952 ffebld arg; /* ffebld_head(opITEM). */
9953 ffebld item; /* opITEM. */
9954 ffesymbol s; /* ffebld_symter(arg). */
9955 ffeinfoBasictype bt = ffesymbol_basictype (entry);
9956 ffeinfoKindtype kt = ffesymbol_kindtype (entry);
9957 ffetargetCharacterSize size = ffesymbol_size (entry);
9958 bool ok;
5ff904cd 9959
c7e4ee3a
CB
9960 if (ffecom_num_entrypoints_ == 0)
9961 { /* First entrypoint, make list of main
9962 arglist's dummies. */
9963 assert (ffecom_primary_entry_ != NULL);
5ff904cd 9964
c7e4ee3a
CB
9965 ffecom_master_bt_ = ffesymbol_basictype (ffecom_primary_entry_);
9966 ffecom_master_kt_ = ffesymbol_kindtype (ffecom_primary_entry_);
9967 ffecom_master_size_ = ffesymbol_size (ffecom_primary_entry_);
5ff904cd 9968
c7e4ee3a
CB
9969 for (plist = NULL, list = ffesymbol_dummyargs (ffecom_primary_entry_);
9970 list != NULL;
9971 list = ffebld_trail (list))
9972 {
9973 arg = ffebld_head (list);
9974 if (ffebld_op (arg) != FFEBLD_opSYMTER)
9975 continue; /* Alternate return or some such thing. */
9976 item = ffebld_new_item (arg, NULL);
9977 if (plist == NULL)
9978 ffecom_master_arglist_ = item;
9979 else
9980 ffebld_set_trail (plist, item);
9981 plist = item;
9982 }
5ff904cd
JL
9983 }
9984
c7e4ee3a
CB
9985 /* If necessary, scan entry arglist for alternate returns. Do this scan
9986 apparently redundantly (it's done below to UNIONize the arglists) so
9987 that we don't complain about RETURN 1 if an offending ENTRY is the only
9988 one with an alternate return. */
5ff904cd 9989
c7e4ee3a 9990 if (!ffecom_is_altreturning_)
5ff904cd 9991 {
c7e4ee3a
CB
9992 for (list = ffesymbol_dummyargs (entry);
9993 list != NULL;
9994 list = ffebld_trail (list))
9995 {
9996 arg = ffebld_head (list);
9997 if (ffebld_op (arg) == FFEBLD_opSTAR)
9998 {
9999 ffecom_is_altreturning_ = TRUE;
10000 break;
10001 }
10002 }
10003 }
5ff904cd 10004
c7e4ee3a 10005 /* Now check type compatibility. */
5ff904cd 10006
c7e4ee3a
CB
10007 switch (ffecom_master_bt_)
10008 {
10009 case FFEINFO_basictypeNONE:
10010 ok = (bt != FFEINFO_basictypeCHARACTER);
10011 break;
5ff904cd 10012
c7e4ee3a
CB
10013 case FFEINFO_basictypeCHARACTER:
10014 ok
10015 = (bt == FFEINFO_basictypeCHARACTER)
10016 && (kt == ffecom_master_kt_)
10017 && (size == ffecom_master_size_);
10018 break;
5ff904cd 10019
c7e4ee3a
CB
10020 case FFEINFO_basictypeANY:
10021 return FALSE; /* Just don't bother. */
5ff904cd 10022
c7e4ee3a
CB
10023 default:
10024 if (bt == FFEINFO_basictypeCHARACTER)
5ff904cd 10025 {
c7e4ee3a
CB
10026 ok = FALSE;
10027 break;
5ff904cd 10028 }
c7e4ee3a
CB
10029 ok = TRUE;
10030 if ((bt != ffecom_master_bt_) || (kt != ffecom_master_kt_))
10031 {
10032 ffecom_master_bt_ = FFEINFO_basictypeNONE;
10033 ffecom_master_kt_ = FFEINFO_kindtypeNONE;
10034 }
10035 break;
10036 }
5ff904cd 10037
c7e4ee3a
CB
10038 if (!ok)
10039 {
10040 ffebad_start (FFEBAD_ENTRY_CONFLICTS);
10041 ffest_ffebad_here_current_stmt (0);
10042 ffebad_finish ();
10043 return FALSE; /* Can't handle entrypoint. */
10044 }
5ff904cd 10045
c7e4ee3a 10046 /* Entrypoint type compatible with previous types. */
5ff904cd 10047
c7e4ee3a 10048 ++ffecom_num_entrypoints_;
5ff904cd 10049
c7e4ee3a
CB
10050 /* Master-arg-list = UNION(Master-arg-list,entry-arg-list). */
10051
10052 for (list = ffesymbol_dummyargs (entry);
10053 list != NULL;
10054 list = ffebld_trail (list))
10055 {
10056 arg = ffebld_head (list);
10057 if (ffebld_op (arg) != FFEBLD_opSYMTER)
10058 continue; /* Alternate return or some such thing. */
10059 s = ffebld_symter (arg);
10060 for (plist = NULL, mlist = ffecom_master_arglist_;
10061 mlist != NULL;
10062 plist = mlist, mlist = ffebld_trail (mlist))
10063 { /* plist points to previous item for easy
10064 appending of arg. */
10065 if (ffebld_symter (ffebld_head (mlist)) == s)
10066 break; /* Already have this arg in the master list. */
10067 }
10068 if (mlist != NULL)
10069 continue; /* Already have this arg in the master list. */
5ff904cd 10070
c7e4ee3a 10071 /* Append this arg to the master list. */
5ff904cd 10072
c7e4ee3a
CB
10073 item = ffebld_new_item (arg, NULL);
10074 if (plist == NULL)
10075 ffecom_master_arglist_ = item;
10076 else
10077 ffebld_set_trail (plist, item);
5ff904cd
JL
10078 }
10079
c7e4ee3a 10080 return TRUE;
5ff904cd
JL
10081}
10082
10083#endif
c7e4ee3a
CB
10084/* ffecom_2pass_do_entrypoint -- Do compilation of entrypoint
10085
10086 ffesymbol s; // the ENTRY point itself
10087 ffecom_2pass_do_entrypoint(s);
10088
10089 Does whatever compiler needs to do to make the entrypoint actually
10090 happen. Must be called for each entrypoint after
10091 ffecom_finish_progunit is called. */
10092
5ff904cd 10093#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
10094void
10095ffecom_2pass_do_entrypoint (ffesymbol entry)
5ff904cd 10096{
c7e4ee3a
CB
10097 static int mfn_num = 0;
10098 static int ent_num;
5ff904cd 10099
c7e4ee3a
CB
10100 if (mfn_num != ffecom_num_fns_)
10101 { /* First entrypoint for this program unit. */
10102 ent_num = 1;
10103 mfn_num = ffecom_num_fns_;
10104 ffecom_do_entry_ (ffecom_primary_entry_, 0);
10105 }
10106 else
10107 ++ent_num;
5ff904cd 10108
c7e4ee3a 10109 --ffecom_num_entrypoints_;
5ff904cd 10110
c7e4ee3a
CB
10111 ffecom_do_entry_ (entry, ent_num);
10112}
5ff904cd 10113
c7e4ee3a 10114#endif
5ff904cd 10115
c7e4ee3a
CB
10116/* Essentially does a "fold (build (code, type, node1, node2))" while
10117 checking for certain housekeeping things. Always sets
10118 TREE_SIDE_EFFECTS. */
5ff904cd 10119
c7e4ee3a
CB
10120#if FFECOM_targetCURRENT == FFECOM_targetGCC
10121tree
10122ffecom_2s (enum tree_code code, tree type, tree node1,
10123 tree node2)
10124{
10125 tree item;
5ff904cd 10126
c7e4ee3a
CB
10127 if ((node1 == error_mark_node)
10128 || (node2 == error_mark_node)
10129 || (type == error_mark_node))
10130 return error_mark_node;
5ff904cd 10131
c7e4ee3a
CB
10132 item = build (code, type, node1, node2);
10133 TREE_SIDE_EFFECTS (item) = 1;
10134 return fold (item);
5ff904cd
JL
10135}
10136
10137#endif
c7e4ee3a
CB
10138/* Essentially does a "fold (build (code, type, node1, node2, node3))" while
10139 checking for certain housekeeping things. */
10140
5ff904cd 10141#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
10142tree
10143ffecom_3 (enum tree_code code, tree type, tree node1,
10144 tree node2, tree node3)
5ff904cd 10145{
c7e4ee3a 10146 tree item;
5ff904cd 10147
c7e4ee3a
CB
10148 if ((node1 == error_mark_node)
10149 || (node2 == error_mark_node)
10150 || (node3 == error_mark_node)
10151 || (type == error_mark_node))
10152 return error_mark_node;
5ff904cd 10153
c7e4ee3a
CB
10154 item = build (code, type, node1, node2, node3);
10155 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2)
10156 || (node3 != NULL_TREE && TREE_SIDE_EFFECTS (node3)))
10157 TREE_SIDE_EFFECTS (item) = 1;
10158 return fold (item);
10159}
5ff904cd 10160
c7e4ee3a
CB
10161#endif
10162/* Essentially does a "fold (build (code, type, node1, node2, node3))" while
10163 checking for certain housekeeping things. Always sets
10164 TREE_SIDE_EFFECTS. */
5ff904cd 10165
c7e4ee3a
CB
10166#if FFECOM_targetCURRENT == FFECOM_targetGCC
10167tree
10168ffecom_3s (enum tree_code code, tree type, tree node1,
10169 tree node2, tree node3)
10170{
10171 tree item;
5ff904cd 10172
c7e4ee3a
CB
10173 if ((node1 == error_mark_node)
10174 || (node2 == error_mark_node)
10175 || (node3 == error_mark_node)
10176 || (type == error_mark_node))
10177 return error_mark_node;
5ff904cd 10178
c7e4ee3a
CB
10179 item = build (code, type, node1, node2, node3);
10180 TREE_SIDE_EFFECTS (item) = 1;
10181 return fold (item);
10182}
5ff904cd 10183
c7e4ee3a 10184#endif
5ff904cd 10185
c7e4ee3a 10186/* ffecom_arg_expr -- Transform argument expr into gcc tree
5ff904cd 10187
c7e4ee3a 10188 See use by ffecom_list_expr.
5ff904cd 10189
c7e4ee3a
CB
10190 If expression is NULL, returns an integer zero tree. If it is not
10191 a CHARACTER expression, returns whatever ffecom_expr
10192 returns and sets the length return value to NULL_TREE. Otherwise
10193 generates code to evaluate the character expression, returns the proper
10194 pointer to the result, but does NOT set the length return value to a tree
10195 that specifies the length of the result. (In other words, the length
10196 variable is always set to NULL_TREE, because a length is never passed.)
5ff904cd 10197
c7e4ee3a
CB
10198 21-Dec-91 JCB 1.1
10199 Don't set returned length, since nobody needs it (yet; someday if
10200 we allow CHARACTER*(*) dummies to statement functions, we'll need
10201 it). */
5ff904cd 10202
c7e4ee3a
CB
10203#if FFECOM_targetCURRENT == FFECOM_targetGCC
10204tree
10205ffecom_arg_expr (ffebld expr, tree *length)
10206{
10207 tree ign;
5ff904cd 10208
c7e4ee3a 10209 *length = NULL_TREE;
5ff904cd 10210
c7e4ee3a
CB
10211 if (expr == NULL)
10212 return integer_zero_node;
5ff904cd 10213
c7e4ee3a
CB
10214 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10215 return ffecom_expr (expr);
5ff904cd 10216
c7e4ee3a
CB
10217 return ffecom_arg_ptr_to_expr (expr, &ign);
10218}
10219
10220#endif
10221/* Transform expression into constant argument-pointer-to-expression tree.
10222
10223 If the expression can be transformed into a argument-pointer-to-expression
10224 tree that is constant, that is done, and the tree returned. Else
10225 NULL_TREE is returned.
5ff904cd 10226
c7e4ee3a
CB
10227 That way, a caller can attempt to provide compile-time initialization
10228 of a variable and, if that fails, *then* choose to start a new block
10229 and resort to using temporaries, as appropriate. */
5ff904cd 10230
c7e4ee3a
CB
10231tree
10232ffecom_arg_ptr_to_const_expr (ffebld expr, tree *length)
10233{
10234 if (! expr)
10235 return integer_zero_node;
5ff904cd 10236
c7e4ee3a
CB
10237 if (ffebld_op (expr) == FFEBLD_opANY)
10238 {
10239 if (length)
10240 *length = error_mark_node;
10241 return error_mark_node;
10242 }
10243
10244 if (ffebld_arity (expr) == 0
10245 && (ffebld_op (expr) != FFEBLD_opSYMTER
10246 || ffebld_where (expr) == FFEINFO_whereCOMMON
10247 || ffebld_where (expr) == FFEINFO_whereGLOBAL
10248 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
10249 {
10250 tree t;
10251
10252 t = ffecom_arg_ptr_to_expr (expr, length);
10253 assert (TREE_CONSTANT (t));
10254 assert (! length || TREE_CONSTANT (*length));
10255 return t;
10256 }
10257
10258 if (length
10259 && ffebld_size (expr) != FFETARGET_charactersizeNONE)
10260 *length = build_int_2 (ffebld_size (expr), 0);
10261 else if (length)
10262 *length = NULL_TREE;
10263 return NULL_TREE;
5ff904cd
JL
10264}
10265
c7e4ee3a 10266/* ffecom_arg_ptr_to_expr -- Transform argument expr into gcc tree
5ff904cd 10267
c7e4ee3a
CB
10268 See use by ffecom_list_ptr_to_expr.
10269
10270 If expression is NULL, returns an integer zero tree. If it is not
10271 a CHARACTER expression, returns whatever ffecom_ptr_to_expr
10272 returns and sets the length return value to NULL_TREE. Otherwise
10273 generates code to evaluate the character expression, returns the proper
10274 pointer to the result, AND sets the length return value to a tree that
10275 specifies the length of the result.
10276
10277 If the length argument is NULL, this is a slightly special
10278 case of building a FORMAT expression, that is, an expression that
10279 will be used at run time without regard to length. For the current
10280 implementation, which uses the libf2c library, this means it is nice
10281 to append a null byte to the end of the expression, where feasible,
10282 to make sure any diagnostic about the FORMAT string terminates at
10283 some useful point.
10284
10285 For now, treat %REF(char-expr) as the same as char-expr with a NULL
10286 length argument. This might even be seen as a feature, if a null
10287 byte can always be appended. */
5ff904cd
JL
10288
10289#if FFECOM_targetCURRENT == FFECOM_targetGCC
10290tree
c7e4ee3a 10291ffecom_arg_ptr_to_expr (ffebld expr, tree *length)
5ff904cd
JL
10292{
10293 tree item;
c7e4ee3a
CB
10294 tree ign_length;
10295 ffecomConcatList_ catlist;
5ff904cd 10296
c7e4ee3a
CB
10297 if (length != NULL)
10298 *length = NULL_TREE;
5ff904cd 10299
c7e4ee3a
CB
10300 if (expr == NULL)
10301 return integer_zero_node;
5ff904cd 10302
c7e4ee3a 10303 switch (ffebld_op (expr))
5ff904cd 10304 {
c7e4ee3a
CB
10305 case FFEBLD_opPERCENT_VAL:
10306 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10307 return ffecom_expr (ffebld_left (expr));
10308 {
10309 tree temp_exp;
10310 tree temp_length;
5ff904cd 10311
c7e4ee3a
CB
10312 temp_exp = ffecom_arg_ptr_to_expr (ffebld_left (expr), &temp_length);
10313 if (temp_exp == error_mark_node)
10314 return error_mark_node;
5ff904cd 10315
c7e4ee3a
CB
10316 return ffecom_1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (temp_exp)),
10317 temp_exp);
10318 }
5ff904cd 10319
c7e4ee3a
CB
10320 case FFEBLD_opPERCENT_REF:
10321 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10322 return ffecom_ptr_to_expr (ffebld_left (expr));
10323 if (length != NULL)
10324 {
10325 ign_length = NULL_TREE;
10326 length = &ign_length;
10327 }
10328 expr = ffebld_left (expr);
10329 break;
5ff904cd 10330
c7e4ee3a
CB
10331 case FFEBLD_opPERCENT_DESCR:
10332 switch (ffeinfo_basictype (ffebld_info (expr)))
5ff904cd 10333 {
c7e4ee3a
CB
10334#ifdef PASS_HOLLERITH_BY_DESCRIPTOR
10335 case FFEINFO_basictypeHOLLERITH:
10336#endif
10337 case FFEINFO_basictypeCHARACTER:
10338 break; /* Passed by descriptor anyway. */
10339
10340 default:
10341 item = ffecom_ptr_to_expr (expr);
10342 if (item != error_mark_node)
10343 *length = TYPE_SIZE (TREE_TYPE (TREE_TYPE (item)));
5ff904cd
JL
10344 break;
10345 }
5ff904cd
JL
10346 break;
10347
10348 default:
5ff904cd
JL
10349 break;
10350 }
10351
c7e4ee3a
CB
10352#ifdef PASS_HOLLERITH_BY_DESCRIPTOR
10353 if ((ffeinfo_basictype (ffebld_info (expr)) == FFEINFO_basictypeHOLLERITH)
10354 && (length != NULL))
10355 { /* Pass Hollerith by descriptor. */
10356 ffetargetHollerith h;
10357
10358 assert (ffebld_op (expr) == FFEBLD_opCONTER);
10359 h = ffebld_cu_val_hollerith (ffebld_constant_union
10360 (ffebld_conter (expr)));
10361 *length
10362 = build_int_2 (h.length, 0);
10363 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
10364 }
10365#endif
10366
10367 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10368 return ffecom_ptr_to_expr (expr);
10369
10370 assert (ffeinfo_kindtype (ffebld_info (expr))
10371 == FFEINFO_kindtypeCHARACTER1);
10372
47d98fa2
CB
10373 while (ffebld_op (expr) == FFEBLD_opPAREN)
10374 expr = ffebld_left (expr);
10375
c7e4ee3a
CB
10376 catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
10377 switch (ffecom_concat_list_count_ (catlist))
10378 {
10379 case 0: /* Shouldn't happen, but in case it does... */
10380 if (length != NULL)
10381 {
10382 *length = ffecom_f2c_ftnlen_zero_node;
10383 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
10384 }
10385 ffecom_concat_list_kill_ (catlist);
10386 return null_pointer_node;
10387
10388 case 1: /* The (fairly) easy case. */
10389 if (length == NULL)
10390 ffecom_char_args_with_null_ (&item, &ign_length,
10391 ffecom_concat_list_expr_ (catlist, 0));
10392 else
10393 ffecom_char_args_ (&item, length,
10394 ffecom_concat_list_expr_ (catlist, 0));
10395 ffecom_concat_list_kill_ (catlist);
10396 assert (item != NULL_TREE);
10397 return item;
10398
10399 default: /* Must actually concatenate things. */
10400 break;
10401 }
10402
10403 {
10404 int count = ffecom_concat_list_count_ (catlist);
10405 int i;
10406 tree lengths;
10407 tree items;
10408 tree length_array;
10409 tree item_array;
10410 tree citem;
10411 tree clength;
10412 tree temporary;
10413 tree num;
10414 tree known_length;
10415 ffetargetCharacterSize sz;
10416
10417 sz = ffecom_concat_list_maxlen_ (catlist);
10418 /* ~~Kludge! */
10419 assert (sz != FFETARGET_charactersizeNONE);
10420
10421#ifdef HOHO
10422 length_array
10423 = lengths
10424 = ffecom_push_tempvar (ffecom_f2c_ftnlen_type_node,
10425 FFETARGET_charactersizeNONE, count, TRUE);
10426 item_array
10427 = items
10428 = ffecom_push_tempvar (ffecom_f2c_address_type_node,
10429 FFETARGET_charactersizeNONE, count, TRUE);
10430 temporary = ffecom_push_tempvar (char_type_node,
10431 sz, -1, TRUE);
10432#else
10433 {
10434 tree hook;
10435
10436 hook = ffebld_nonter_hook (expr);
10437 assert (hook);
10438 assert (TREE_CODE (hook) == TREE_VEC);
10439 assert (TREE_VEC_LENGTH (hook) == 3);
10440 length_array = lengths = TREE_VEC_ELT (hook, 0);
10441 item_array = items = TREE_VEC_ELT (hook, 1);
10442 temporary = TREE_VEC_ELT (hook, 2);
10443 }
10444#endif
10445
10446 known_length = ffecom_f2c_ftnlen_zero_node;
10447
10448 for (i = 0; i < count; ++i)
10449 {
10450 if ((i == count)
10451 && (length == NULL))
10452 ffecom_char_args_with_null_ (&citem, &clength,
10453 ffecom_concat_list_expr_ (catlist, i));
10454 else
10455 ffecom_char_args_ (&citem, &clength,
10456 ffecom_concat_list_expr_ (catlist, i));
10457 if ((citem == error_mark_node)
10458 || (clength == error_mark_node))
10459 {
10460 ffecom_concat_list_kill_ (catlist);
10461 *length = error_mark_node;
10462 return error_mark_node;
10463 }
10464
10465 items
10466 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
10467 ffecom_modify (void_type_node,
10468 ffecom_2 (ARRAY_REF,
10469 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
10470 item_array,
10471 build_int_2 (i, 0)),
10472 citem),
10473 items);
10474 clength = ffecom_save_tree (clength);
10475 if (length != NULL)
10476 known_length
10477 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
10478 known_length,
10479 clength);
10480 lengths
10481 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
10482 ffecom_modify (void_type_node,
10483 ffecom_2 (ARRAY_REF,
10484 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
10485 length_array,
10486 build_int_2 (i, 0)),
10487 clength),
10488 lengths);
10489 }
10490
10491 temporary = ffecom_1 (ADDR_EXPR,
10492 build_pointer_type (TREE_TYPE (temporary)),
10493 temporary);
10494
10495 item = build_tree_list (NULL_TREE, temporary);
10496 TREE_CHAIN (item)
10497 = build_tree_list (NULL_TREE,
10498 ffecom_1 (ADDR_EXPR,
10499 build_pointer_type (TREE_TYPE (items)),
10500 items));
10501 TREE_CHAIN (TREE_CHAIN (item))
10502 = build_tree_list (NULL_TREE,
10503 ffecom_1 (ADDR_EXPR,
10504 build_pointer_type (TREE_TYPE (lengths)),
10505 lengths));
10506 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
10507 = build_tree_list
10508 (NULL_TREE,
10509 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
10510 convert (ffecom_f2c_ftnlen_type_node,
10511 build_int_2 (count, 0))));
10512 num = build_int_2 (sz, 0);
10513 TREE_TYPE (num) = ffecom_f2c_ftnlen_type_node;
10514 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item))))
10515 = build_tree_list (NULL_TREE, num);
10516
10517 item = ffecom_call_gfrt (FFECOM_gfrtCAT, item, NULL_TREE);
5ff904cd 10518 TREE_SIDE_EFFECTS (item) = 1;
c7e4ee3a
CB
10519 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (temporary),
10520 item,
10521 temporary);
10522
10523 if (length != NULL)
10524 *length = known_length;
10525 }
10526
10527 ffecom_concat_list_kill_ (catlist);
10528 assert (item != NULL_TREE);
10529 return item;
5ff904cd 10530}
c7e4ee3a 10531
5ff904cd 10532#endif
c7e4ee3a 10533/* Generate call to run-time function.
5ff904cd 10534
c7e4ee3a
CB
10535 The first arg is the GNU Fortran Run-Time function index, the second
10536 arg is the list of arguments to pass to it. Returned is the expression
10537 (WITHOUT TREE_SIDE_EFFECTS set!) that makes the call and returns the
10538 result (which may be void). */
5ff904cd
JL
10539
10540#if FFECOM_targetCURRENT == FFECOM_targetGCC
10541tree
c7e4ee3a 10542ffecom_call_gfrt (ffecomGfrt ix, tree args, tree hook)
5ff904cd 10543{
c7e4ee3a
CB
10544 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
10545 ffecom_gfrt_kindtype (ix),
10546 ffe_is_f2c_library () && ffecom_gfrt_complex_[ix],
10547 NULL_TREE, args, NULL_TREE, NULL,
10548 NULL, NULL_TREE, TRUE, hook);
5ff904cd
JL
10549}
10550#endif
10551
c7e4ee3a 10552/* Transform constant-union to tree. */
5ff904cd
JL
10553
10554#if FFECOM_targetCURRENT == FFECOM_targetGCC
10555tree
c7e4ee3a
CB
10556ffecom_constantunion (ffebldConstantUnion *cu, ffeinfoBasictype bt,
10557 ffeinfoKindtype kt, tree tree_type)
5ff904cd
JL
10558{
10559 tree item;
10560
c7e4ee3a 10561 switch (bt)
5ff904cd 10562 {
c7e4ee3a
CB
10563 case FFEINFO_basictypeINTEGER:
10564 {
10565 int val;
5ff904cd 10566
c7e4ee3a
CB
10567 switch (kt)
10568 {
10569#if FFETARGET_okINTEGER1
10570 case FFEINFO_kindtypeINTEGER1:
10571 val = ffebld_cu_val_integer1 (*cu);
10572 break;
10573#endif
5ff904cd 10574
c7e4ee3a
CB
10575#if FFETARGET_okINTEGER2
10576 case FFEINFO_kindtypeINTEGER2:
10577 val = ffebld_cu_val_integer2 (*cu);
10578 break;
10579#endif
5ff904cd 10580
c7e4ee3a
CB
10581#if FFETARGET_okINTEGER3
10582 case FFEINFO_kindtypeINTEGER3:
10583 val = ffebld_cu_val_integer3 (*cu);
10584 break;
10585#endif
5ff904cd 10586
c7e4ee3a
CB
10587#if FFETARGET_okINTEGER4
10588 case FFEINFO_kindtypeINTEGER4:
10589 val = ffebld_cu_val_integer4 (*cu);
10590 break;
10591#endif
5ff904cd 10592
c7e4ee3a
CB
10593 default:
10594 assert ("bad INTEGER constant kind type" == NULL);
10595 /* Fall through. */
10596 case FFEINFO_kindtypeANY:
10597 return error_mark_node;
10598 }
10599 item = build_int_2 (val, (val < 0) ? -1 : 0);
10600 TREE_TYPE (item) = tree_type;
10601 }
5ff904cd 10602 break;
5ff904cd 10603
c7e4ee3a
CB
10604 case FFEINFO_basictypeLOGICAL:
10605 {
10606 int val;
5ff904cd 10607
c7e4ee3a
CB
10608 switch (kt)
10609 {
10610#if FFETARGET_okLOGICAL1
10611 case FFEINFO_kindtypeLOGICAL1:
10612 val = ffebld_cu_val_logical1 (*cu);
10613 break;
5ff904cd 10614#endif
5ff904cd 10615
c7e4ee3a
CB
10616#if FFETARGET_okLOGICAL2
10617 case FFEINFO_kindtypeLOGICAL2:
10618 val = ffebld_cu_val_logical2 (*cu);
10619 break;
10620#endif
5ff904cd 10621
c7e4ee3a
CB
10622#if FFETARGET_okLOGICAL3
10623 case FFEINFO_kindtypeLOGICAL3:
10624 val = ffebld_cu_val_logical3 (*cu);
10625 break;
10626#endif
5ff904cd 10627
c7e4ee3a
CB
10628#if FFETARGET_okLOGICAL4
10629 case FFEINFO_kindtypeLOGICAL4:
10630 val = ffebld_cu_val_logical4 (*cu);
10631 break;
10632#endif
5ff904cd 10633
c7e4ee3a
CB
10634 default:
10635 assert ("bad LOGICAL constant kind type" == NULL);
10636 /* Fall through. */
10637 case FFEINFO_kindtypeANY:
10638 return error_mark_node;
10639 }
10640 item = build_int_2 (val, (val < 0) ? -1 : 0);
10641 TREE_TYPE (item) = tree_type;
10642 }
10643 break;
5ff904cd 10644
c7e4ee3a
CB
10645 case FFEINFO_basictypeREAL:
10646 {
10647 REAL_VALUE_TYPE val;
5ff904cd 10648
c7e4ee3a
CB
10649 switch (kt)
10650 {
10651#if FFETARGET_okREAL1
10652 case FFEINFO_kindtypeREAL1:
10653 val = ffetarget_value_real1 (ffebld_cu_val_real1 (*cu));
10654 break;
10655#endif
5ff904cd 10656
c7e4ee3a
CB
10657#if FFETARGET_okREAL2
10658 case FFEINFO_kindtypeREAL2:
10659 val = ffetarget_value_real2 (ffebld_cu_val_real2 (*cu));
10660 break;
10661#endif
5ff904cd 10662
c7e4ee3a
CB
10663#if FFETARGET_okREAL3
10664 case FFEINFO_kindtypeREAL3:
10665 val = ffetarget_value_real3 (ffebld_cu_val_real3 (*cu));
10666 break;
10667#endif
5ff904cd 10668
c7e4ee3a
CB
10669#if FFETARGET_okREAL4
10670 case FFEINFO_kindtypeREAL4:
10671 val = ffetarget_value_real4 (ffebld_cu_val_real4 (*cu));
10672 break;
10673#endif
5ff904cd 10674
c7e4ee3a
CB
10675 default:
10676 assert ("bad REAL constant kind type" == NULL);
10677 /* Fall through. */
10678 case FFEINFO_kindtypeANY:
10679 return error_mark_node;
10680 }
10681 item = build_real (tree_type, val);
10682 }
5ff904cd
JL
10683 break;
10684
c7e4ee3a
CB
10685 case FFEINFO_basictypeCOMPLEX:
10686 {
10687 REAL_VALUE_TYPE real;
10688 REAL_VALUE_TYPE imag;
10689 tree el_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
5ff904cd 10690
c7e4ee3a
CB
10691 switch (kt)
10692 {
10693#if FFETARGET_okCOMPLEX1
10694 case FFEINFO_kindtypeREAL1:
10695 real = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).real);
10696 imag = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).imaginary);
10697 break;
10698#endif
5ff904cd 10699
c7e4ee3a
CB
10700#if FFETARGET_okCOMPLEX2
10701 case FFEINFO_kindtypeREAL2:
10702 real = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).real);
10703 imag = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).imaginary);
10704 break;
10705#endif
5ff904cd 10706
c7e4ee3a
CB
10707#if FFETARGET_okCOMPLEX3
10708 case FFEINFO_kindtypeREAL3:
10709 real = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).real);
10710 imag = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).imaginary);
10711 break;
10712#endif
5ff904cd 10713
c7e4ee3a
CB
10714#if FFETARGET_okCOMPLEX4
10715 case FFEINFO_kindtypeREAL4:
10716 real = ffetarget_value_real4 (ffebld_cu_val_complex4 (*cu).real);
10717 imag = ffetarget_value_real4 (ffebld_cu_val_complex4 (*cu).imaginary);
10718 break;
10719#endif
5ff904cd 10720
c7e4ee3a
CB
10721 default:
10722 assert ("bad REAL constant kind type" == NULL);
10723 /* Fall through. */
10724 case FFEINFO_kindtypeANY:
10725 return error_mark_node;
10726 }
10727 item = ffecom_build_complex_constant_ (tree_type,
10728 build_real (el_type, real),
10729 build_real (el_type, imag));
10730 }
10731 break;
5ff904cd 10732
c7e4ee3a
CB
10733 case FFEINFO_basictypeCHARACTER:
10734 { /* Happens only in DATA and similar contexts. */
10735 ffetargetCharacter1 val;
5ff904cd 10736
c7e4ee3a
CB
10737 switch (kt)
10738 {
10739#if FFETARGET_okCHARACTER1
10740 case FFEINFO_kindtypeLOGICAL1:
10741 val = ffebld_cu_val_character1 (*cu);
10742 break;
10743#endif
10744
10745 default:
10746 assert ("bad CHARACTER constant kind type" == NULL);
10747 /* Fall through. */
10748 case FFEINFO_kindtypeANY:
10749 return error_mark_node;
10750 }
10751 item = build_string (ffetarget_length_character1 (val),
10752 ffetarget_text_character1 (val));
10753 TREE_TYPE (item)
10754 = build_type_variant (build_array_type (char_type_node,
10755 build_range_type
10756 (integer_type_node,
10757 integer_one_node,
10758 build_int_2
10759 (ffetarget_length_character1
10760 (val), 0))),
10761 1, 0);
10762 }
10763 break;
5ff904cd 10764
c7e4ee3a
CB
10765 case FFEINFO_basictypeHOLLERITH:
10766 {
10767 ffetargetHollerith h;
5ff904cd 10768
c7e4ee3a 10769 h = ffebld_cu_val_hollerith (*cu);
5ff904cd 10770
c7e4ee3a
CB
10771 /* If not at least as wide as default INTEGER, widen it. */
10772 if (h.length >= FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE)
10773 item = build_string (h.length, h.text);
10774 else
10775 {
10776 char str[FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE];
5ff904cd 10777
c7e4ee3a
CB
10778 memcpy (str, h.text, h.length);
10779 memset (&str[h.length], ' ',
10780 FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE
10781 - h.length);
10782 item = build_string (FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE,
10783 str);
10784 }
10785 TREE_TYPE (item)
10786 = build_type_variant (build_array_type (char_type_node,
10787 build_range_type
10788 (integer_type_node,
10789 integer_one_node,
10790 build_int_2
10791 (h.length, 0))),
10792 1, 0);
10793 }
10794 break;
5ff904cd 10795
c7e4ee3a
CB
10796 case FFEINFO_basictypeTYPELESS:
10797 {
10798 ffetargetInteger1 ival;
10799 ffetargetTypeless tless;
10800 ffebad error;
5ff904cd 10801
c7e4ee3a
CB
10802 tless = ffebld_cu_val_typeless (*cu);
10803 error = ffetarget_convert_integer1_typeless (&ival, tless);
10804 assert (error == FFEBAD);
5ff904cd 10805
c7e4ee3a
CB
10806 item = build_int_2 ((int) ival, 0);
10807 }
10808 break;
5ff904cd 10809
c7e4ee3a
CB
10810 default:
10811 assert ("not yet on constant type" == NULL);
10812 /* Fall through. */
10813 case FFEINFO_basictypeANY:
10814 return error_mark_node;
5ff904cd 10815 }
5ff904cd 10816
c7e4ee3a 10817 TREE_CONSTANT (item) = 1;
5ff904cd 10818
c7e4ee3a 10819 return item;
5ff904cd
JL
10820}
10821
10822#endif
10823
c7e4ee3a
CB
10824/* Transform expression into constant tree.
10825
10826 If the expression can be transformed into a tree that is constant,
10827 that is done, and the tree returned. Else NULL_TREE is returned.
10828
10829 That way, a caller can attempt to provide compile-time initialization
10830 of a variable and, if that fails, *then* choose to start a new block
10831 and resort to using temporaries, as appropriate. */
5ff904cd 10832
5ff904cd 10833tree
c7e4ee3a 10834ffecom_const_expr (ffebld expr)
5ff904cd 10835{
c7e4ee3a
CB
10836 if (! expr)
10837 return integer_zero_node;
5ff904cd 10838
c7e4ee3a 10839 if (ffebld_op (expr) == FFEBLD_opANY)
5ff904cd
JL
10840 return error_mark_node;
10841
c7e4ee3a
CB
10842 if (ffebld_arity (expr) == 0
10843 && (ffebld_op (expr) != FFEBLD_opSYMTER
10844#if NEWCOMMON
10845 /* ~~Enable once common/equivalence is handled properly? */
10846 || ffebld_where (expr) == FFEINFO_whereCOMMON
5ff904cd 10847#endif
c7e4ee3a
CB
10848 || ffebld_where (expr) == FFEINFO_whereGLOBAL
10849 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
10850 {
10851 tree t;
5ff904cd 10852
c7e4ee3a
CB
10853 t = ffecom_expr (expr);
10854 assert (TREE_CONSTANT (t));
10855 return t;
10856 }
5ff904cd 10857
c7e4ee3a 10858 return NULL_TREE;
5ff904cd
JL
10859}
10860
c7e4ee3a 10861/* Handy way to make a field in a struct/union. */
5ff904cd
JL
10862
10863#if FFECOM_targetCURRENT == FFECOM_targetGCC
10864tree
c7e4ee3a
CB
10865ffecom_decl_field (tree context, tree prevfield,
10866 const char *name, tree type)
5ff904cd 10867{
c7e4ee3a 10868 tree field;
5ff904cd 10869
c7e4ee3a
CB
10870 field = build_decl (FIELD_DECL, get_identifier (name), type);
10871 DECL_CONTEXT (field) = context;
8ba77681 10872 DECL_ALIGN (field) = 0;
11cf4d18 10873 DECL_USER_ALIGN (field) = 0;
c7e4ee3a
CB
10874 if (prevfield != NULL_TREE)
10875 TREE_CHAIN (prevfield) = field;
5ff904cd 10876
c7e4ee3a 10877 return field;
5ff904cd
JL
10878}
10879
10880#endif
5ff904cd 10881
c7e4ee3a
CB
10882void
10883ffecom_close_include (FILE *f)
10884{
10885#if FFECOM_GCC_INCLUDE
10886 ffecom_close_include_ (f);
10887#endif
10888}
5ff904cd 10889
c7e4ee3a
CB
10890int
10891ffecom_decode_include_option (char *spec)
10892{
10893#if FFECOM_GCC_INCLUDE
10894 return ffecom_decode_include_option_ (spec);
10895#else
10896 return 1;
10897#endif
10898}
5ff904cd 10899
c7e4ee3a 10900/* End a compound statement (block). */
5ff904cd
JL
10901
10902#if FFECOM_targetCURRENT == FFECOM_targetGCC
10903tree
c7e4ee3a 10904ffecom_end_compstmt (void)
5ff904cd 10905{
c7e4ee3a
CB
10906 return bison_rule_compstmt_ ();
10907}
10908#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
5ff904cd 10909
c7e4ee3a 10910/* ffecom_end_transition -- Perform end transition on all symbols
5ff904cd 10911
c7e4ee3a 10912 ffecom_end_transition();
5ff904cd 10913
c7e4ee3a 10914 Calls ffecom_sym_end_transition for each global and local symbol. */
5ff904cd 10915
c7e4ee3a
CB
10916void
10917ffecom_end_transition ()
10918{
10919#if FFECOM_targetCURRENT == FFECOM_targetGCC
10920 ffebld item;
5ff904cd 10921#endif
5ff904cd 10922
c7e4ee3a
CB
10923 if (ffe_is_ffedebug ())
10924 fprintf (dmpout, "; end_stmt_transition\n");
86fc7a6c 10925
c7e4ee3a
CB
10926#if FFECOM_targetCURRENT == FFECOM_targetGCC
10927 ffecom_list_blockdata_ = NULL;
10928 ffecom_list_common_ = NULL;
10929#endif
86fc7a6c 10930
c7e4ee3a
CB
10931 ffesymbol_drive (ffecom_sym_end_transition);
10932 if (ffe_is_ffedebug ())
10933 {
10934 ffestorag_report ();
10935#if FFECOM_targetCURRENT == FFECOM_targetFFE
10936 ffesymbol_report_all ();
10937#endif
10938 }
5ff904cd
JL
10939
10940#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
10941 ffecom_start_progunit_ ();
10942
10943 for (item = ffecom_list_blockdata_;
10944 item != NULL;
10945 item = ffebld_trail (item))
10946 {
10947 ffebld callee;
10948 ffesymbol s;
10949 tree dt;
10950 tree t;
10951 tree var;
c7e4ee3a
CB
10952 static int number = 0;
10953
10954 callee = ffebld_head (item);
10955 s = ffebld_symter (callee);
10956 t = ffesymbol_hook (s).decl_tree;
10957 if (t == NULL_TREE)
10958 {
10959 s = ffecom_sym_transform_ (s);
10960 t = ffesymbol_hook (s).decl_tree;
10961 }
5ff904cd 10962
c7e4ee3a 10963 dt = build_pointer_type (TREE_TYPE (t));
5ff904cd 10964
c7e4ee3a
CB
10965 var = build_decl (VAR_DECL,
10966 ffecom_get_invented_identifier ("__g77_forceload_%d",
14657de8 10967 number++),
c7e4ee3a
CB
10968 dt);
10969 DECL_EXTERNAL (var) = 0;
10970 TREE_STATIC (var) = 1;
10971 TREE_PUBLIC (var) = 0;
10972 DECL_INITIAL (var) = error_mark_node;
10973 TREE_USED (var) = 1;
5ff904cd 10974
c7e4ee3a 10975 var = start_decl (var, FALSE);
702edf1d 10976
c7e4ee3a 10977 t = ffecom_1 (ADDR_EXPR, dt, t);
5ff904cd 10978
c7e4ee3a 10979 finish_decl (var, t, FALSE);
c7e4ee3a
CB
10980 }
10981
10982 /* This handles any COMMON areas that weren't referenced but have, for
10983 example, important initial data. */
10984
10985 for (item = ffecom_list_common_;
10986 item != NULL;
10987 item = ffebld_trail (item))
10988 ffecom_transform_common_ (ffebld_symter (ffebld_head (item)));
10989
10990 ffecom_list_common_ = NULL;
5ff904cd 10991#endif
c7e4ee3a 10992}
5ff904cd 10993
c7e4ee3a 10994/* ffecom_exec_transition -- Perform exec transition on all symbols
5ff904cd 10995
c7e4ee3a 10996 ffecom_exec_transition();
5ff904cd 10997
c7e4ee3a
CB
10998 Calls ffecom_sym_exec_transition for each global and local symbol.
10999 Make sure error updating not inhibited. */
5ff904cd 11000
c7e4ee3a
CB
11001void
11002ffecom_exec_transition ()
11003{
11004 bool inhibited;
5ff904cd 11005
c7e4ee3a
CB
11006 if (ffe_is_ffedebug ())
11007 fprintf (dmpout, "; exec_stmt_transition\n");
5ff904cd 11008
c7e4ee3a
CB
11009 inhibited = ffebad_inhibit ();
11010 ffebad_set_inhibit (FALSE);
5ff904cd 11011
c7e4ee3a
CB
11012 ffesymbol_drive (ffecom_sym_exec_transition); /* Don't retract! */
11013 ffeequiv_exec_transition (); /* Handle all pending EQUIVALENCEs. */
11014 if (ffe_is_ffedebug ())
5ff904cd 11015 {
c7e4ee3a
CB
11016 ffestorag_report ();
11017#if FFECOM_targetCURRENT == FFECOM_targetFFE
11018 ffesymbol_report_all ();
11019#endif
11020 }
5ff904cd 11021
c7e4ee3a
CB
11022 if (inhibited)
11023 ffebad_set_inhibit (TRUE);
11024}
5ff904cd 11025
c7e4ee3a 11026/* Handle assignment statement.
5ff904cd 11027
c7e4ee3a
CB
11028 Convert dest and source using ffecom_expr, then join them
11029 with an ASSIGN op and pass the whole thing to expand_expr_stmt. */
5ff904cd 11030
c7e4ee3a
CB
11031#if FFECOM_targetCURRENT == FFECOM_targetGCC
11032void
11033ffecom_expand_let_stmt (ffebld dest, ffebld source)
11034{
11035 tree dest_tree;
11036 tree dest_length;
11037 tree source_tree;
11038 tree expr_tree;
5ff904cd 11039
c7e4ee3a
CB
11040 if (ffeinfo_basictype (ffebld_info (dest)) != FFEINFO_basictypeCHARACTER)
11041 {
11042 bool dest_used;
d6cd84e0 11043 tree assign_temp;
5ff904cd 11044
c7e4ee3a
CB
11045 /* This attempts to replicate the test below, but must not be
11046 true when the test below is false. (Always err on the side
11047 of creating unused temporaries, to avoid ICEs.) */
11048 if (ffebld_op (dest) != FFEBLD_opSYMTER
11049 || ((dest_tree = ffesymbol_hook (ffebld_symter (dest)).decl_tree)
11050 && (TREE_CODE (dest_tree) != VAR_DECL
11051 || TREE_ADDRESSABLE (dest_tree))))
11052 {
11053 ffecom_prepare_expr_ (source, dest);
11054 dest_used = TRUE;
11055 }
11056 else
11057 {
11058 ffecom_prepare_expr_ (source, NULL);
11059 dest_used = FALSE;
11060 }
5ff904cd 11061
c7e4ee3a 11062 ffecom_prepare_expr_w (NULL_TREE, dest);
5ff904cd 11063
d6cd84e0
CB
11064 /* For COMPLEX assignment like C1=C2, if partial overlap is possible,
11065 create a temporary through which the assignment is to take place,
11066 since MODIFY_EXPR doesn't handle partial overlap properly. */
11067 if (ffebld_basictype (dest) == FFEINFO_basictypeCOMPLEX
11068 && ffecom_possible_partial_overlap_ (dest, source))
11069 {
11070 assign_temp = ffecom_make_tempvar ("complex_let",
11071 ffecom_tree_type
11072 [ffebld_basictype (dest)]
11073 [ffebld_kindtype (dest)],
11074 FFETARGET_charactersizeNONE,
11075 -1);
11076 }
11077 else
11078 assign_temp = NULL_TREE;
11079
c7e4ee3a 11080 ffecom_prepare_end ();
5ff904cd 11081
c7e4ee3a
CB
11082 dest_tree = ffecom_expr_w (NULL_TREE, dest);
11083 if (dest_tree == error_mark_node)
11084 return;
5ff904cd 11085
c7e4ee3a
CB
11086 if ((TREE_CODE (dest_tree) != VAR_DECL)
11087 || TREE_ADDRESSABLE (dest_tree))
11088 source_tree = ffecom_expr_ (source, dest_tree, dest, &dest_used,
11089 FALSE, FALSE);
11090 else
11091 {
11092 assert (! dest_used);
11093 dest_used = FALSE;
11094 source_tree = ffecom_expr (source);
11095 }
11096 if (source_tree == error_mark_node)
11097 return;
5ff904cd 11098
c7e4ee3a
CB
11099 if (dest_used)
11100 expr_tree = source_tree;
d6cd84e0
CB
11101 else if (assign_temp)
11102 {
11103#ifdef MOVE_EXPR
11104 /* The back end understands a conceptual move (evaluate source;
11105 store into dest), so use that, in case it can determine
11106 that it is going to use, say, two registers as temporaries
11107 anyway. So don't use the temp (and someday avoid generating
11108 it, once this code starts triggering regularly). */
11109 expr_tree = ffecom_2s (MOVE_EXPR, void_type_node,
11110 dest_tree,
11111 source_tree);
11112#else
11113 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11114 assign_temp,
11115 source_tree);
11116 expand_expr_stmt (expr_tree);
11117 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11118 dest_tree,
11119 assign_temp);
11120#endif
11121 }
c7e4ee3a
CB
11122 else
11123 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11124 dest_tree,
11125 source_tree);
5ff904cd 11126
c7e4ee3a
CB
11127 expand_expr_stmt (expr_tree);
11128 return;
11129 }
5ff904cd 11130
c7e4ee3a
CB
11131 ffecom_prepare_let_char_ (ffebld_size_known (dest), source);
11132 ffecom_prepare_expr_w (NULL_TREE, dest);
11133
11134 ffecom_prepare_end ();
11135
11136 ffecom_char_args_ (&dest_tree, &dest_length, dest);
11137 ffecom_let_char_ (dest_tree, dest_length, ffebld_size_known (dest),
11138 source);
5ff904cd
JL
11139}
11140
11141#endif
c7e4ee3a 11142/* ffecom_expr -- Transform expr into gcc tree
5ff904cd 11143
c7e4ee3a
CB
11144 tree t;
11145 ffebld expr; // FFE expression.
11146 tree = ffecom_expr(expr);
5ff904cd 11147
c7e4ee3a
CB
11148 Recursive descent on expr while making corresponding tree nodes and
11149 attaching type info and such. */
5ff904cd
JL
11150
11151#if FFECOM_targetCURRENT == FFECOM_targetGCC
11152tree
c7e4ee3a 11153ffecom_expr (ffebld expr)
5ff904cd 11154{
c7e4ee3a 11155 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, FALSE, FALSE);
5ff904cd 11156}
c7e4ee3a 11157
5ff904cd 11158#endif
c7e4ee3a 11159/* Like ffecom_expr, but return tree usable for assigned GOTO or FORMAT. */
5ff904cd 11160
c7e4ee3a
CB
11161#if FFECOM_targetCURRENT == FFECOM_targetGCC
11162tree
11163ffecom_expr_assign (ffebld expr)
11164{
11165 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE);
11166}
5ff904cd 11167
c7e4ee3a
CB
11168#endif
11169/* Like ffecom_expr_rw, but return tree usable for ASSIGN. */
5ff904cd
JL
11170
11171#if FFECOM_targetCURRENT == FFECOM_targetGCC
11172tree
c7e4ee3a 11173ffecom_expr_assign_w (ffebld expr)
5ff904cd 11174{
c7e4ee3a
CB
11175 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE);
11176}
5ff904cd 11177
5ff904cd 11178#endif
c7e4ee3a
CB
11179/* Transform expr for use as into read/write tree and stabilize the
11180 reference. Not for use on CHARACTER expressions.
5ff904cd 11181
c7e4ee3a
CB
11182 Recursive descent on expr while making corresponding tree nodes and
11183 attaching type info and such. */
5ff904cd 11184
c7e4ee3a
CB
11185#if FFECOM_targetCURRENT == FFECOM_targetGCC
11186tree
11187ffecom_expr_rw (tree type, ffebld expr)
11188{
11189 assert (expr != NULL);
11190 /* Different target types not yet supported. */
11191 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
11192
11193 return stabilize_reference (ffecom_expr (expr));
11194}
5ff904cd 11195
5ff904cd 11196#endif
c7e4ee3a
CB
11197/* Transform expr for use as into write tree and stabilize the
11198 reference. Not for use on CHARACTER expressions.
5ff904cd 11199
c7e4ee3a
CB
11200 Recursive descent on expr while making corresponding tree nodes and
11201 attaching type info and such. */
5ff904cd 11202
c7e4ee3a
CB
11203#if FFECOM_targetCURRENT == FFECOM_targetGCC
11204tree
11205ffecom_expr_w (tree type, ffebld expr)
11206{
11207 assert (expr != NULL);
11208 /* Different target types not yet supported. */
11209 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
11210
11211 return stabilize_reference (ffecom_expr (expr));
11212}
5ff904cd 11213
5ff904cd 11214#endif
c7e4ee3a
CB
11215/* Do global stuff. */
11216
11217#if FFECOM_targetCURRENT == FFECOM_targetGCC
11218void
11219ffecom_finish_compile ()
11220{
11221 assert (ffecom_outer_function_decl_ == NULL_TREE);
11222 assert (current_function_decl == NULL_TREE);
11223
11224 ffeglobal_drive (ffecom_finish_global_);
11225}
5ff904cd 11226
5ff904cd 11227#endif
c7e4ee3a
CB
11228/* Public entry point for front end to access finish_decl. */
11229
11230#if FFECOM_targetCURRENT == FFECOM_targetGCC
11231void
11232ffecom_finish_decl (tree decl, tree init, bool is_top_level)
11233{
11234 assert (!is_top_level);
11235 finish_decl (decl, init, FALSE);
11236}
5ff904cd 11237
5ff904cd 11238#endif
c7e4ee3a
CB
11239/* Finish a program unit. */
11240
11241#if FFECOM_targetCURRENT == FFECOM_targetGCC
11242void
11243ffecom_finish_progunit ()
11244{
11245 ffecom_end_compstmt ();
11246
11247 ffecom_previous_function_decl_ = current_function_decl;
11248 ffecom_which_entrypoint_decl_ = NULL_TREE;
11249
11250 finish_function (0);
11251}
5ff904cd 11252
5ff904cd 11253#endif
14657de8
KG
11254
11255/* Wrapper for get_identifier. pattern is sprintf-like. */
c7e4ee3a
CB
11256
11257#if FFECOM_targetCURRENT == FFECOM_targetGCC
11258tree
14657de8 11259ffecom_get_invented_identifier (const char *pattern, ...)
c7e4ee3a
CB
11260{
11261 tree decl;
11262 char *nam;
14657de8 11263 va_list ap;
c7e4ee3a 11264
14657de8
KG
11265 va_start (ap, pattern);
11266 if (vasprintf (&nam, pattern, ap) == 0)
11267 abort ();
11268 va_end (ap);
c7e4ee3a 11269 decl = get_identifier (nam);
14657de8 11270 free (nam);
c7e4ee3a 11271 IDENTIFIER_INVENTED (decl) = 1;
c7e4ee3a
CB
11272 return decl;
11273}
11274
11275ffeinfoBasictype
11276ffecom_gfrt_basictype (ffecomGfrt gfrt)
11277{
11278 assert (gfrt < FFECOM_gfrt);
11279
11280 switch (ffecom_gfrt_type_[gfrt])
11281 {
11282 case FFECOM_rttypeVOID_:
11283 case FFECOM_rttypeVOIDSTAR_:
11284 return FFEINFO_basictypeNONE;
11285
11286 case FFECOM_rttypeFTNINT_:
11287 return FFEINFO_basictypeINTEGER;
11288
11289 case FFECOM_rttypeINTEGER_:
11290 return FFEINFO_basictypeINTEGER;
11291
11292 case FFECOM_rttypeLONGINT_:
11293 return FFEINFO_basictypeINTEGER;
11294
11295 case FFECOM_rttypeLOGICAL_:
11296 return FFEINFO_basictypeLOGICAL;
11297
11298 case FFECOM_rttypeREAL_F2C_:
11299 case FFECOM_rttypeREAL_GNU_:
11300 return FFEINFO_basictypeREAL;
11301
11302 case FFECOM_rttypeCOMPLEX_F2C_:
11303 case FFECOM_rttypeCOMPLEX_GNU_:
11304 return FFEINFO_basictypeCOMPLEX;
11305
11306 case FFECOM_rttypeDOUBLE_:
11307 case FFECOM_rttypeDOUBLEREAL_:
11308 return FFEINFO_basictypeREAL;
11309
11310 case FFECOM_rttypeDBLCMPLX_F2C_:
11311 case FFECOM_rttypeDBLCMPLX_GNU_:
11312 return FFEINFO_basictypeCOMPLEX;
11313
11314 case FFECOM_rttypeCHARACTER_:
11315 return FFEINFO_basictypeCHARACTER;
11316
11317 default:
11318 return FFEINFO_basictypeANY;
11319 }
11320}
11321
11322ffeinfoKindtype
11323ffecom_gfrt_kindtype (ffecomGfrt gfrt)
11324{
11325 assert (gfrt < FFECOM_gfrt);
11326
11327 switch (ffecom_gfrt_type_[gfrt])
11328 {
11329 case FFECOM_rttypeVOID_:
11330 case FFECOM_rttypeVOIDSTAR_:
11331 return FFEINFO_kindtypeNONE;
5ff904cd 11332
c7e4ee3a
CB
11333 case FFECOM_rttypeFTNINT_:
11334 return FFEINFO_kindtypeINTEGER1;
5ff904cd 11335
c7e4ee3a
CB
11336 case FFECOM_rttypeINTEGER_:
11337 return FFEINFO_kindtypeINTEGER1;
5ff904cd 11338
c7e4ee3a
CB
11339 case FFECOM_rttypeLONGINT_:
11340 return FFEINFO_kindtypeINTEGER4;
5ff904cd 11341
c7e4ee3a
CB
11342 case FFECOM_rttypeLOGICAL_:
11343 return FFEINFO_kindtypeLOGICAL1;
5ff904cd 11344
c7e4ee3a
CB
11345 case FFECOM_rttypeREAL_F2C_:
11346 case FFECOM_rttypeREAL_GNU_:
11347 return FFEINFO_kindtypeREAL1;
5ff904cd 11348
c7e4ee3a
CB
11349 case FFECOM_rttypeCOMPLEX_F2C_:
11350 case FFECOM_rttypeCOMPLEX_GNU_:
11351 return FFEINFO_kindtypeREAL1;
5ff904cd 11352
c7e4ee3a
CB
11353 case FFECOM_rttypeDOUBLE_:
11354 case FFECOM_rttypeDOUBLEREAL_:
11355 return FFEINFO_kindtypeREAL2;
5ff904cd 11356
c7e4ee3a
CB
11357 case FFECOM_rttypeDBLCMPLX_F2C_:
11358 case FFECOM_rttypeDBLCMPLX_GNU_:
11359 return FFEINFO_kindtypeREAL2;
5ff904cd 11360
c7e4ee3a
CB
11361 case FFECOM_rttypeCHARACTER_:
11362 return FFEINFO_kindtypeCHARACTER1;
5ff904cd 11363
c7e4ee3a
CB
11364 default:
11365 return FFEINFO_kindtypeANY;
11366 }
11367}
5ff904cd 11368
c7e4ee3a
CB
11369void
11370ffecom_init_0 ()
11371{
11372 tree endlink;
11373 int i;
11374 int j;
11375 tree t;
11376 tree field;
11377 ffetype type;
11378 ffetype base_type;
7189a4b0
GK
11379 tree double_ftype_double;
11380 tree float_ftype_float;
11381 tree ldouble_ftype_ldouble;
11382 tree ffecom_tree_ptr_to_fun_type_void;
5ff904cd 11383
c7e4ee3a
CB
11384 /* This block of code comes from the now-obsolete cktyps.c. It checks
11385 whether the compiler environment is buggy in known ways, some of which
11386 would, if not explicitly checked here, result in subtle bugs in g77. */
5ff904cd 11387
c7e4ee3a
CB
11388 if (ffe_is_do_internal_checks ())
11389 {
8b60264b 11390 static const char names[][12]
c7e4ee3a
CB
11391 =
11392 {"bar", "bletch", "foo", "foobar"};
8b60264b 11393 const char *name;
c7e4ee3a
CB
11394 unsigned long ul;
11395 double fl;
5ff904cd 11396
c7e4ee3a 11397 name = bsearch ("foo", &names[0], ARRAY_SIZE (names), sizeof (names[0]),
b0791fa9 11398 (int (*)(const void *, const void *)) strcmp);
8b60264b 11399 if (name != &names[0][2])
c7e4ee3a
CB
11400 {
11401 assert ("bsearch doesn't work, #define FFEPROJ_BSEARCH 0 in proj.h"
11402 == NULL);
11403 abort ();
11404 }
5ff904cd 11405
c7e4ee3a
CB
11406 ul = strtoul ("123456789", NULL, 10);
11407 if (ul != 123456789L)
11408 {
11409 assert ("strtoul doesn't have enough range, #define FFEPROJ_STRTOUL 0\
11410 in proj.h" == NULL);
11411 abort ();
11412 }
5ff904cd 11413
c7e4ee3a
CB
11414 fl = atof ("56.789");
11415 if ((fl < 56.788) || (fl > 56.79))
11416 {
11417 assert ("atof not type double, fix your #include <stdio.h>"
11418 == NULL);
11419 abort ();
11420 }
11421 }
5ff904cd 11422
c7e4ee3a
CB
11423#if FFECOM_GCC_INCLUDE
11424 ffecom_initialize_char_syntax_ ();
11425#endif
5ff904cd 11426
c7e4ee3a
CB
11427 ffecom_outer_function_decl_ = NULL_TREE;
11428 current_function_decl = NULL_TREE;
11429 named_labels = NULL_TREE;
11430 current_binding_level = NULL_BINDING_LEVEL;
11431 free_binding_level = NULL_BINDING_LEVEL;
11432 /* Make the binding_level structure for global names. */
11433 pushlevel (0);
11434 global_binding_level = current_binding_level;
11435 current_binding_level->prep_state = 2;
5ff904cd 11436
81b3411c 11437 build_common_tree_nodes (1);
5ff904cd 11438
81b3411c 11439 /* Define `int' and `char' first so that dbx will output them first. */
c7e4ee3a
CB
11440 pushdecl (build_decl (TYPE_DECL, get_identifier ("int"),
11441 integer_type_node));
a49bedaa
TM
11442 /* CHARACTER*1 is unsigned in ICHAR contexts. */
11443 char_type_node = make_unsigned_type (CHAR_TYPE_SIZE);
c7e4ee3a
CB
11444 pushdecl (build_decl (TYPE_DECL, get_identifier ("char"),
11445 char_type_node));
c7e4ee3a
CB
11446 pushdecl (build_decl (TYPE_DECL, get_identifier ("long int"),
11447 long_integer_type_node));
c7e4ee3a
CB
11448 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned int"),
11449 unsigned_type_node));
c7e4ee3a
CB
11450 pushdecl (build_decl (TYPE_DECL, get_identifier ("long unsigned int"),
11451 long_unsigned_type_node));
c7e4ee3a
CB
11452 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long int"),
11453 long_long_integer_type_node));
c7e4ee3a
CB
11454 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long unsigned int"),
11455 long_long_unsigned_type_node));
c7e4ee3a
CB
11456 pushdecl (build_decl (TYPE_DECL, get_identifier ("short int"),
11457 short_integer_type_node));
c7e4ee3a
CB
11458 pushdecl (build_decl (TYPE_DECL, get_identifier ("short unsigned int"),
11459 short_unsigned_type_node));
5ff904cd 11460
ff852b44
CB
11461 /* Set the sizetype before we make other types. This *should* be the
11462 first type we create. */
11463
11464 set_sizetype
11465 (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE))));
11466 ffecom_typesize_pointer_
11467 = TREE_INT_CST_LOW (TYPE_SIZE (sizetype)) / BITS_PER_UNIT;
11468
81b3411c 11469 build_common_tree_nodes_2 (0);
ff852b44 11470
c7e4ee3a 11471 /* Define both `signed char' and `unsigned char'. */
c7e4ee3a
CB
11472 pushdecl (build_decl (TYPE_DECL, get_identifier ("signed char"),
11473 signed_char_type_node));
5ff904cd 11474
c7e4ee3a
CB
11475 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned char"),
11476 unsigned_char_type_node));
5ff904cd 11477
c7e4ee3a
CB
11478 pushdecl (build_decl (TYPE_DECL, get_identifier ("float"),
11479 float_type_node));
c7e4ee3a
CB
11480 pushdecl (build_decl (TYPE_DECL, get_identifier ("double"),
11481 double_type_node));
c7e4ee3a
CB
11482 pushdecl (build_decl (TYPE_DECL, get_identifier ("long double"),
11483 long_double_type_node));
5ff904cd 11484
81b3411c 11485 /* For now, override what build_common_tree_nodes has done. */
c7e4ee3a 11486 complex_integer_type_node = ffecom_make_complex_type_ (integer_type_node);
81b3411c
BS
11487 complex_float_type_node = ffecom_make_complex_type_ (float_type_node);
11488 complex_double_type_node = ffecom_make_complex_type_ (double_type_node);
11489 complex_long_double_type_node
11490 = ffecom_make_complex_type_ (long_double_type_node);
11491
c7e4ee3a
CB
11492 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex int"),
11493 complex_integer_type_node));
c7e4ee3a
CB
11494 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex float"),
11495 complex_float_type_node));
c7e4ee3a
CB
11496 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex double"),
11497 complex_double_type_node));
c7e4ee3a
CB
11498 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex long double"),
11499 complex_long_double_type_node));
5ff904cd 11500
c7e4ee3a
CB
11501 pushdecl (build_decl (TYPE_DECL, get_identifier ("void"),
11502 void_type_node));
c7e4ee3a
CB
11503 /* We are not going to have real types in C with less than byte alignment,
11504 so we might as well not have any types that claim to have it. */
11505 TYPE_ALIGN (void_type_node) = BITS_PER_UNIT;
11cf4d18 11506 TYPE_USER_ALIGN (void_type_node) = 0;
5ff904cd 11507
c7e4ee3a 11508 string_type_node = build_pointer_type (char_type_node);
5ff904cd 11509
c7e4ee3a
CB
11510 ffecom_tree_fun_type_void
11511 = build_function_type (void_type_node, NULL_TREE);
5ff904cd 11512
c7e4ee3a
CB
11513 ffecom_tree_ptr_to_fun_type_void
11514 = build_pointer_type (ffecom_tree_fun_type_void);
5ff904cd 11515
c7e4ee3a 11516 endlink = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
5ff904cd 11517
c7e4ee3a
CB
11518 float_ftype_float
11519 = build_function_type (float_type_node,
11520 tree_cons (NULL_TREE, float_type_node, endlink));
5ff904cd 11521
c7e4ee3a
CB
11522 double_ftype_double
11523 = build_function_type (double_type_node,
11524 tree_cons (NULL_TREE, double_type_node, endlink));
5ff904cd 11525
c7e4ee3a
CB
11526 ldouble_ftype_ldouble
11527 = build_function_type (long_double_type_node,
11528 tree_cons (NULL_TREE, long_double_type_node,
11529 endlink));
5ff904cd 11530
c7e4ee3a
CB
11531 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11532 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11533 {
11534 ffecom_tree_type[i][j] = NULL_TREE;
11535 ffecom_tree_fun_type[i][j] = NULL_TREE;
11536 ffecom_tree_ptr_to_fun_type[i][j] = NULL_TREE;
11537 ffecom_f2c_typecode_[i][j] = -1;
11538 }
5ff904cd 11539
c7e4ee3a
CB
11540 /* Set up standard g77 types. Note that INTEGER and LOGICAL are set
11541 to size FLOAT_TYPE_SIZE because they have to be the same size as
11542 REAL, which also is FLOAT_TYPE_SIZE, according to the standard.
11543 Compiler options and other such stuff that change the ways these
11544 types are set should not affect this particular setup. */
5ff904cd 11545
c7e4ee3a
CB
11546 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1]
11547 = t = make_signed_type (FLOAT_TYPE_SIZE);
11548 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer"),
11549 t));
11550 type = ffetype_new ();
11551 base_type = type;
11552 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER1,
11553 type);
11554 ffetype_set_ams (type,
11555 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11556 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11557 ffetype_set_star (base_type,
11558 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11559 type);
11560 ffetype_set_kind (base_type, 1, type);
ff852b44 11561 ffecom_typesize_integer1_ = ffetype_size (type);
c7e4ee3a 11562 assert (ffetype_size (type) == sizeof (ffetargetInteger1));
5ff904cd 11563
c7e4ee3a
CB
11564 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER1]
11565 = t = make_unsigned_type (FLOAT_TYPE_SIZE); /* HOLLERITH means unsigned. */
11566 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned"),
11567 t));
5ff904cd 11568
c7e4ee3a
CB
11569 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER2]
11570 = t = make_signed_type (CHAR_TYPE_SIZE);
11571 pushdecl (build_decl (TYPE_DECL, get_identifier ("byte"),
11572 t));
11573 type = ffetype_new ();
11574 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER2,
11575 type);
11576 ffetype_set_ams (type,
11577 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11578 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11579 ffetype_set_star (base_type,
11580 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11581 type);
11582 ffetype_set_kind (base_type, 3, type);
11583 assert (ffetype_size (type) == sizeof (ffetargetInteger2));
5ff904cd 11584
c7e4ee3a
CB
11585 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER2]
11586 = t = make_unsigned_type (CHAR_TYPE_SIZE);
11587 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned byte"),
11588 t));
11589
11590 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER3]
11591 = t = make_signed_type (CHAR_TYPE_SIZE * 2);
11592 pushdecl (build_decl (TYPE_DECL, get_identifier ("word"),
11593 t));
11594 type = ffetype_new ();
11595 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER3,
11596 type);
11597 ffetype_set_ams (type,
11598 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11599 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11600 ffetype_set_star (base_type,
11601 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11602 type);
11603 ffetype_set_kind (base_type, 6, type);
11604 assert (ffetype_size (type) == sizeof (ffetargetInteger3));
5ff904cd 11605
c7e4ee3a
CB
11606 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER3]
11607 = t = make_unsigned_type (CHAR_TYPE_SIZE * 2);
11608 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned word"),
11609 t));
5ff904cd 11610
c7e4ee3a
CB
11611 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER4]
11612 = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
11613 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer4"),
11614 t));
11615 type = ffetype_new ();
11616 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER4,
11617 type);
11618 ffetype_set_ams (type,
11619 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11620 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11621 ffetype_set_star (base_type,
11622 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11623 type);
11624 ffetype_set_kind (base_type, 2, type);
11625 assert (ffetype_size (type) == sizeof (ffetargetInteger4));
5ff904cd 11626
c7e4ee3a
CB
11627 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER4]
11628 = t = make_unsigned_type (FLOAT_TYPE_SIZE * 2);
11629 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned4"),
11630 t));
5ff904cd 11631
c7e4ee3a
CB
11632#if 0
11633 if (ffe_is_do_internal_checks ()
11634 && LONG_TYPE_SIZE != FLOAT_TYPE_SIZE
11635 && LONG_TYPE_SIZE != CHAR_TYPE_SIZE
11636 && LONG_TYPE_SIZE != SHORT_TYPE_SIZE
11637 && LONG_TYPE_SIZE != LONG_LONG_TYPE_SIZE)
5ff904cd 11638 {
c7e4ee3a
CB
11639 fprintf (stderr, "Sorry, no g77 support for LONG_TYPE_SIZE (%d bits) yet.\n",
11640 LONG_TYPE_SIZE);
5ff904cd 11641 }
c7e4ee3a 11642#endif
5ff904cd 11643
c7e4ee3a
CB
11644 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL1]
11645 = t = make_signed_type (FLOAT_TYPE_SIZE);
11646 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical"),
11647 t));
11648 type = ffetype_new ();
11649 base_type = type;
11650 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL1,
11651 type);
11652 ffetype_set_ams (type,
11653 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11654 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11655 ffetype_set_star (base_type,
11656 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11657 type);
11658 ffetype_set_kind (base_type, 1, type);
11659 assert (ffetype_size (type) == sizeof (ffetargetLogical1));
5ff904cd 11660
c7e4ee3a
CB
11661 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL2]
11662 = t = make_signed_type (CHAR_TYPE_SIZE);
11663 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical2"),
11664 t));
11665 type = ffetype_new ();
11666 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL2,
11667 type);
11668 ffetype_set_ams (type,
11669 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11670 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11671 ffetype_set_star (base_type,
11672 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11673 type);
11674 ffetype_set_kind (base_type, 3, type);
11675 assert (ffetype_size (type) == sizeof (ffetargetLogical2));
5ff904cd 11676
c7e4ee3a
CB
11677 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL3]
11678 = t = make_signed_type (CHAR_TYPE_SIZE * 2);
11679 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical3"),
11680 t));
11681 type = ffetype_new ();
11682 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL3,
11683 type);
11684 ffetype_set_ams (type,
11685 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11686 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11687 ffetype_set_star (base_type,
11688 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11689 type);
11690 ffetype_set_kind (base_type, 6, type);
11691 assert (ffetype_size (type) == sizeof (ffetargetLogical3));
5ff904cd 11692
c7e4ee3a
CB
11693 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL4]
11694 = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
11695 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical4"),
11696 t));
11697 type = ffetype_new ();
11698 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL4,
11699 type);
11700 ffetype_set_ams (type,
11701 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11702 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11703 ffetype_set_star (base_type,
11704 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11705 type);
11706 ffetype_set_kind (base_type, 2, type);
11707 assert (ffetype_size (type) == sizeof (ffetargetLogical4));
5ff904cd 11708
c7e4ee3a
CB
11709 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
11710 = t = make_node (REAL_TYPE);
11711 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE;
11712 pushdecl (build_decl (TYPE_DECL, get_identifier ("real"),
11713 t));
11714 layout_type (t);
11715 type = ffetype_new ();
11716 base_type = type;
11717 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREAL1,
11718 type);
11719 ffetype_set_ams (type,
11720 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11721 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11722 ffetype_set_star (base_type,
11723 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11724 type);
11725 ffetype_set_kind (base_type, 1, type);
11726 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
11727 = FFETARGET_f2cTYREAL;
11728 assert (ffetype_size (type) == sizeof (ffetargetReal1));
5ff904cd 11729
c7e4ee3a
CB
11730 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREALDOUBLE]
11731 = t = make_node (REAL_TYPE);
11732 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE * 2; /* Always twice REAL. */
11733 pushdecl (build_decl (TYPE_DECL, get_identifier ("double precision"),
11734 t));
11735 layout_type (t);
11736 type = ffetype_new ();
11737 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREALDOUBLE,
11738 type);
11739 ffetype_set_ams (type,
11740 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11741 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11742 ffetype_set_star (base_type,
11743 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11744 type);
11745 ffetype_set_kind (base_type, 2, type);
11746 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]
11747 = FFETARGET_f2cTYDREAL;
11748 assert (ffetype_size (type) == sizeof (ffetargetReal2));
5ff904cd 11749
c7e4ee3a
CB
11750 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
11751 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]);
11752 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex"),
11753 t));
11754 type = ffetype_new ();
11755 base_type = type;
11756 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREAL1,
11757 type);
11758 ffetype_set_ams (type,
11759 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11760 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11761 ffetype_set_star (base_type,
11762 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11763 type);
11764 ffetype_set_kind (base_type, 1, type);
11765 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
11766 = FFETARGET_f2cTYCOMPLEX;
11767 assert (ffetype_size (type) == sizeof (ffetargetComplex1));
5ff904cd 11768
c7e4ee3a
CB
11769 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREALDOUBLE]
11770 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]);
11771 pushdecl (build_decl (TYPE_DECL, get_identifier ("double complex"),
11772 t));
11773 type = ffetype_new ();
11774 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREALDOUBLE,
11775 type);
11776 ffetype_set_ams (type,
11777 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11778 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11779 ffetype_set_star (base_type,
11780 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11781 type);
11782 ffetype_set_kind (base_type, 2,
11783 type);
11784 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL2]
11785 = FFETARGET_f2cTYDCOMPLEX;
11786 assert (ffetype_size (type) == sizeof (ffetargetComplex2));
5ff904cd 11787
c7e4ee3a 11788 /* Make function and ptr-to-function types for non-CHARACTER types. */
5ff904cd 11789
c7e4ee3a
CB
11790 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11791 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11792 {
11793 if ((t = ffecom_tree_type[i][j]) != NULL_TREE)
11794 {
11795 if (i == FFEINFO_basictypeINTEGER)
11796 {
11797 /* Figure out the smallest INTEGER type that can hold
11798 a pointer on this machine. */
11799 if (GET_MODE_SIZE (TYPE_MODE (t))
11800 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
11801 {
11802 if ((ffecom_pointer_kind_ == FFEINFO_kindtypeNONE)
11803 || (GET_MODE_SIZE (TYPE_MODE (ffecom_tree_type[i][ffecom_pointer_kind_]))
11804 > GET_MODE_SIZE (TYPE_MODE (t))))
11805 ffecom_pointer_kind_ = j;
11806 }
11807 }
11808 else if (i == FFEINFO_basictypeCOMPLEX)
11809 t = void_type_node;
11810 /* For f2c compatibility, REAL functions are really
11811 implemented as DOUBLE PRECISION. */
11812 else if ((i == FFEINFO_basictypeREAL)
11813 && (j == FFEINFO_kindtypeREAL1))
11814 t = ffecom_tree_type
11815 [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2];
5ff904cd 11816
c7e4ee3a
CB
11817 t = ffecom_tree_fun_type[i][j] = build_function_type (t,
11818 NULL_TREE);
11819 ffecom_tree_ptr_to_fun_type[i][j] = build_pointer_type (t);
11820 }
11821 }
5ff904cd 11822
c7e4ee3a 11823 /* Set up pointer types. */
5ff904cd 11824
c7e4ee3a 11825 if (ffecom_pointer_kind_ == FFEINFO_basictypeNONE)
400500c4 11826 fatal_error ("no INTEGER type can hold a pointer on this configuration");
c7e4ee3a
CB
11827 else if (0 && ffe_is_do_internal_checks ())
11828 fprintf (stderr, "Pointer type kt=%d\n", ffecom_pointer_kind_);
11829 ffetype_set_kind (ffeinfo_type (FFEINFO_basictypeINTEGER,
11830 FFEINFO_kindtypeINTEGERDEFAULT),
11831 7,
11832 ffeinfo_type (FFEINFO_basictypeINTEGER,
11833 ffecom_pointer_kind_));
5ff904cd 11834
c7e4ee3a
CB
11835 if (ffe_is_ugly_assign ())
11836 ffecom_label_kind_ = ffecom_pointer_kind_; /* Require ASSIGN etc to this. */
11837 else
11838 ffecom_label_kind_ = FFEINFO_kindtypeINTEGERDEFAULT;
11839 if (0 && ffe_is_do_internal_checks ())
11840 fprintf (stderr, "Label type kt=%d\n", ffecom_label_kind_);
5ff904cd 11841
c7e4ee3a
CB
11842 ffecom_integer_type_node
11843 = ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1];
11844 ffecom_integer_zero_node = convert (ffecom_integer_type_node,
11845 integer_zero_node);
11846 ffecom_integer_one_node = convert (ffecom_integer_type_node,
11847 integer_one_node);
5ff904cd 11848
c7e4ee3a
CB
11849 /* Yes, the "FLOAT_TYPE_SIZE" references below are intentional.
11850 Turns out that by TYLONG, runtime/libI77/lio.h really means
11851 "whatever size an ftnint is". For consistency and sanity,
11852 com.h and runtime/f2c.h.in agree that flag, ftnint, and ftlen
11853 all are INTEGER, which we also make out of whatever back-end
11854 integer type is FLOAT_TYPE_SIZE bits wide. This change, from
11855 LONG_TYPE_SIZE, for TYLONG and TYLOGICAL, was necessary to
11856 accommodate machines like the Alpha. Note that this suggests
11857 f2c and libf2c are missing a distinction perhaps needed on
11858 some machines between "int" and "long int". -- burley 0.5.5 950215 */
5ff904cd 11859
c7e4ee3a
CB
11860 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, FLOAT_TYPE_SIZE,
11861 FFETARGET_f2cTYLONG);
11862 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, SHORT_TYPE_SIZE,
11863 FFETARGET_f2cTYSHORT);
11864 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, CHAR_TYPE_SIZE,
11865 FFETARGET_f2cTYINT1);
11866 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, LONG_LONG_TYPE_SIZE,
11867 FFETARGET_f2cTYQUAD);
11868 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, FLOAT_TYPE_SIZE,
11869 FFETARGET_f2cTYLOGICAL);
11870 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, SHORT_TYPE_SIZE,
11871 FFETARGET_f2cTYLOGICAL2);
11872 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, CHAR_TYPE_SIZE,
11873 FFETARGET_f2cTYLOGICAL1);
11874 /* ~~~Not really such a type in libf2c, e.g. I/O support? */
11875 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, LONG_LONG_TYPE_SIZE,
11876 FFETARGET_f2cTYQUAD);
5ff904cd 11877
c7e4ee3a
CB
11878 /* CHARACTER stuff is all special-cased, so it is not handled in the above
11879 loop. CHARACTER items are built as arrays of unsigned char. */
5ff904cd 11880
c7e4ee3a
CB
11881 ffecom_tree_type[FFEINFO_basictypeCHARACTER]
11882 [FFEINFO_kindtypeCHARACTER1] = t = char_type_node;
11883 type = ffetype_new ();
11884 base_type = type;
11885 ffeinfo_set_type (FFEINFO_basictypeCHARACTER,
11886 FFEINFO_kindtypeCHARACTER1,
11887 type);
11888 ffetype_set_ams (type,
11889 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11890 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11891 ffetype_set_kind (base_type, 1, type);
11892 assert (ffetype_size (type)
11893 == sizeof (((ffetargetCharacter1) { 0, NULL }).text[0]));
5ff904cd 11894
c7e4ee3a
CB
11895 ffecom_tree_fun_type[FFEINFO_basictypeCHARACTER]
11896 [FFEINFO_kindtypeCHARACTER1] = ffecom_tree_fun_type_void;
11897 ffecom_tree_ptr_to_fun_type[FFEINFO_basictypeCHARACTER]
11898 [FFEINFO_kindtypeCHARACTER1]
11899 = ffecom_tree_ptr_to_fun_type_void;
11900 ffecom_f2c_typecode_[FFEINFO_basictypeCHARACTER][FFEINFO_kindtypeCHARACTER1]
11901 = FFETARGET_f2cTYCHAR;
5ff904cd 11902
c7e4ee3a
CB
11903 ffecom_f2c_typecode_[FFEINFO_basictypeANY][FFEINFO_kindtypeANY]
11904 = 0;
5ff904cd 11905
c7e4ee3a 11906 /* Make multi-return-value type and fields. */
5ff904cd 11907
c7e4ee3a 11908 ffecom_multi_type_node_ = make_node (UNION_TYPE);
5ff904cd 11909
c7e4ee3a 11910 field = NULL_TREE;
5ff904cd 11911
c7e4ee3a
CB
11912 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11913 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11914 {
11915 char name[30];
5ff904cd 11916
c7e4ee3a
CB
11917 if (ffecom_tree_type[i][j] == NULL_TREE)
11918 continue; /* Not supported. */
11919 sprintf (&name[0], "bt_%s_kt_%s",
11920 ffeinfo_basictype_string ((ffeinfoBasictype) i),
11921 ffeinfo_kindtype_string ((ffeinfoKindtype) j));
11922 ffecom_multi_fields_[i][j] = build_decl (FIELD_DECL,
11923 get_identifier (name),
11924 ffecom_tree_type[i][j]);
11925 DECL_CONTEXT (ffecom_multi_fields_[i][j])
11926 = ffecom_multi_type_node_;
8ba77681 11927 DECL_ALIGN (ffecom_multi_fields_[i][j]) = 0;
11cf4d18 11928 DECL_USER_ALIGN (ffecom_multi_fields_[i][j]) = 0;
c7e4ee3a
CB
11929 TREE_CHAIN (ffecom_multi_fields_[i][j]) = field;
11930 field = ffecom_multi_fields_[i][j];
11931 }
5ff904cd 11932
c7e4ee3a
CB
11933 TYPE_FIELDS (ffecom_multi_type_node_) = field;
11934 layout_type (ffecom_multi_type_node_);
5ff904cd 11935
c7e4ee3a
CB
11936 /* Subroutines usually return integer because they might have alternate
11937 returns. */
5ff904cd 11938
c7e4ee3a
CB
11939 ffecom_tree_subr_type
11940 = build_function_type (integer_type_node, NULL_TREE);
11941 ffecom_tree_ptr_to_subr_type
11942 = build_pointer_type (ffecom_tree_subr_type);
11943 ffecom_tree_blockdata_type
11944 = build_function_type (void_type_node, NULL_TREE);
5ff904cd 11945
c7e4ee3a 11946 builtin_function ("__builtin_sqrtf", float_ftype_float,
26db82d8 11947 BUILT_IN_FSQRT, BUILT_IN_NORMAL, "sqrtf");
c7e4ee3a 11948 builtin_function ("__builtin_fsqrt", double_ftype_double,
26db82d8 11949 BUILT_IN_FSQRT, BUILT_IN_NORMAL, "sqrt");
c7e4ee3a 11950 builtin_function ("__builtin_sqrtl", ldouble_ftype_ldouble,
26db82d8 11951 BUILT_IN_FSQRT, BUILT_IN_NORMAL, "sqrtl");
c7e4ee3a 11952 builtin_function ("__builtin_sinf", float_ftype_float,
26db82d8 11953 BUILT_IN_SIN, BUILT_IN_NORMAL, "sinf");
c7e4ee3a 11954 builtin_function ("__builtin_sin", double_ftype_double,
26db82d8 11955 BUILT_IN_SIN, BUILT_IN_NORMAL, "sin");
c7e4ee3a 11956 builtin_function ("__builtin_sinl", ldouble_ftype_ldouble,
26db82d8 11957 BUILT_IN_SIN, BUILT_IN_NORMAL, "sinl");
c7e4ee3a 11958 builtin_function ("__builtin_cosf", float_ftype_float,
26db82d8 11959 BUILT_IN_COS, BUILT_IN_NORMAL, "cosf");
c7e4ee3a 11960 builtin_function ("__builtin_cos", double_ftype_double,
26db82d8 11961 BUILT_IN_COS, BUILT_IN_NORMAL, "cos");
c7e4ee3a 11962 builtin_function ("__builtin_cosl", ldouble_ftype_ldouble,
26db82d8 11963 BUILT_IN_COS, BUILT_IN_NORMAL, "cosl");
5ff904cd 11964
c7e4ee3a
CB
11965#if BUILT_FOR_270
11966 pedantic_lvalues = FALSE;
5ff904cd 11967#endif
5ff904cd 11968
c7e4ee3a
CB
11969 ffecom_f2c_make_type_ (&ffecom_f2c_integer_type_node,
11970 FFECOM_f2cINTEGER,
11971 "integer");
11972 ffecom_f2c_make_type_ (&ffecom_f2c_address_type_node,
11973 FFECOM_f2cADDRESS,
11974 "address");
11975 ffecom_f2c_make_type_ (&ffecom_f2c_real_type_node,
11976 FFECOM_f2cREAL,
11977 "real");
11978 ffecom_f2c_make_type_ (&ffecom_f2c_doublereal_type_node,
11979 FFECOM_f2cDOUBLEREAL,
11980 "doublereal");
11981 ffecom_f2c_make_type_ (&ffecom_f2c_complex_type_node,
11982 FFECOM_f2cCOMPLEX,
11983 "complex");
11984 ffecom_f2c_make_type_ (&ffecom_f2c_doublecomplex_type_node,
11985 FFECOM_f2cDOUBLECOMPLEX,
11986 "doublecomplex");
11987 ffecom_f2c_make_type_ (&ffecom_f2c_longint_type_node,
11988 FFECOM_f2cLONGINT,
11989 "longint");
11990 ffecom_f2c_make_type_ (&ffecom_f2c_logical_type_node,
11991 FFECOM_f2cLOGICAL,
11992 "logical");
11993 ffecom_f2c_make_type_ (&ffecom_f2c_flag_type_node,
11994 FFECOM_f2cFLAG,
11995 "flag");
11996 ffecom_f2c_make_type_ (&ffecom_f2c_ftnlen_type_node,
11997 FFECOM_f2cFTNLEN,
11998 "ftnlen");
11999 ffecom_f2c_make_type_ (&ffecom_f2c_ftnint_type_node,
12000 FFECOM_f2cFTNINT,
12001 "ftnint");
5ff904cd 12002
c7e4ee3a
CB
12003 ffecom_f2c_ftnlen_zero_node
12004 = convert (ffecom_f2c_ftnlen_type_node, integer_zero_node);
5ff904cd 12005
c7e4ee3a
CB
12006 ffecom_f2c_ftnlen_one_node
12007 = convert (ffecom_f2c_ftnlen_type_node, integer_one_node);
5ff904cd 12008
c7e4ee3a
CB
12009 ffecom_f2c_ftnlen_two_node = build_int_2 (2, 0);
12010 TREE_TYPE (ffecom_f2c_ftnlen_two_node) = ffecom_integer_type_node;
5ff904cd 12011
c7e4ee3a
CB
12012 ffecom_f2c_ptr_to_ftnlen_type_node
12013 = build_pointer_type (ffecom_f2c_ftnlen_type_node);
5ff904cd 12014
c7e4ee3a
CB
12015 ffecom_f2c_ptr_to_ftnint_type_node
12016 = build_pointer_type (ffecom_f2c_ftnint_type_node);
5ff904cd 12017
c7e4ee3a
CB
12018 ffecom_f2c_ptr_to_integer_type_node
12019 = build_pointer_type (ffecom_f2c_integer_type_node);
5ff904cd 12020
c7e4ee3a
CB
12021 ffecom_f2c_ptr_to_real_type_node
12022 = build_pointer_type (ffecom_f2c_real_type_node);
5ff904cd 12023
c7e4ee3a
CB
12024 ffecom_float_zero_ = build_real (float_type_node, dconst0);
12025 ffecom_double_zero_ = build_real (double_type_node, dconst0);
12026 {
12027 REAL_VALUE_TYPE point_5;
5ff904cd 12028
c7e4ee3a
CB
12029#ifdef REAL_ARITHMETIC
12030 REAL_ARITHMETIC (point_5, RDIV_EXPR, dconst1, dconst2);
12031#else
12032 point_5 = .5;
12033#endif
12034 ffecom_float_half_ = build_real (float_type_node, point_5);
12035 ffecom_double_half_ = build_real (double_type_node, point_5);
12036 }
5ff904cd 12037
c7e4ee3a 12038 /* Do "extern int xargc;". */
5ff904cd 12039
c7e4ee3a
CB
12040 ffecom_tree_xargc_ = build_decl (VAR_DECL,
12041 get_identifier ("f__xargc"),
12042 integer_type_node);
12043 DECL_EXTERNAL (ffecom_tree_xargc_) = 1;
12044 TREE_STATIC (ffecom_tree_xargc_) = 1;
12045 TREE_PUBLIC (ffecom_tree_xargc_) = 1;
12046 ffecom_tree_xargc_ = start_decl (ffecom_tree_xargc_, FALSE);
12047 finish_decl (ffecom_tree_xargc_, NULL_TREE, FALSE);
5ff904cd 12048
c7e4ee3a
CB
12049#if 0 /* This is being fixed, and seems to be working now. */
12050 if ((FLOAT_TYPE_SIZE != 32)
12051 || (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))) != 32))
5ff904cd 12052 {
c7e4ee3a
CB
12053 warning ("configuration: REAL, INTEGER, and LOGICAL are %d bits wide,",
12054 (int) FLOAT_TYPE_SIZE);
12055 warning ("and pointers are %d bits wide, but g77 doesn't yet work",
12056 (int) TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))));
12057 warning ("properly unless they all are 32 bits wide.");
12058 warning ("Please keep this in mind before you report bugs. g77 should");
12059 warning ("support non-32-bit machines better as of version 0.6.");
12060 }
12061#endif
5ff904cd 12062
c7e4ee3a
CB
12063#if 0 /* Code in ste.c that would crash has been commented out. */
12064 if (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)
12065 < TYPE_PRECISION (string_type_node))
12066 /* I/O will probably crash. */
12067 warning ("configuration: char * holds %d bits, but ftnlen only %d",
12068 TYPE_PRECISION (string_type_node),
12069 TYPE_PRECISION (ffecom_f2c_ftnlen_type_node));
12070#endif
5ff904cd 12071
c7e4ee3a
CB
12072#if 0 /* ASSIGN-related stuff has been changed to accommodate this. */
12073 if (TYPE_PRECISION (ffecom_integer_type_node)
12074 < TYPE_PRECISION (string_type_node))
12075 /* ASSIGN 10 TO I will crash. */
12076 warning ("configuration: char * holds %d bits, but INTEGER only %d --\n\
12077 ASSIGN statement might fail",
12078 TYPE_PRECISION (string_type_node),
12079 TYPE_PRECISION (ffecom_integer_type_node));
12080#endif
12081}
5ff904cd 12082
c7e4ee3a
CB
12083#endif
12084/* ffecom_init_2 -- Initialize
5ff904cd 12085
c7e4ee3a 12086 ffecom_init_2(); */
5ff904cd 12087
c7e4ee3a
CB
12088#if FFECOM_targetCURRENT == FFECOM_targetGCC
12089void
12090ffecom_init_2 ()
12091{
12092 assert (ffecom_outer_function_decl_ == NULL_TREE);
12093 assert (current_function_decl == NULL_TREE);
12094 assert (ffecom_which_entrypoint_decl_ == NULL_TREE);
5ff904cd 12095
c7e4ee3a
CB
12096 ffecom_master_arglist_ = NULL;
12097 ++ffecom_num_fns_;
12098 ffecom_primary_entry_ = NULL;
12099 ffecom_is_altreturning_ = FALSE;
12100 ffecom_func_result_ = NULL_TREE;
12101 ffecom_multi_retval_ = NULL_TREE;
12102}
5ff904cd 12103
c7e4ee3a
CB
12104#endif
12105/* ffecom_list_expr -- Transform list of exprs into gcc tree
5ff904cd 12106
c7e4ee3a
CB
12107 tree t;
12108 ffebld expr; // FFE opITEM list.
12109 tree = ffecom_list_expr(expr);
5ff904cd 12110
c7e4ee3a 12111 List of actual args is transformed into corresponding gcc backend list. */
5ff904cd 12112
c7e4ee3a
CB
12113#if FFECOM_targetCURRENT == FFECOM_targetGCC
12114tree
12115ffecom_list_expr (ffebld expr)
5ff904cd 12116{
c7e4ee3a
CB
12117 tree list;
12118 tree *plist = &list;
12119 tree trail = NULL_TREE; /* Append char length args here. */
12120 tree *ptrail = &trail;
12121 tree length;
5ff904cd 12122
c7e4ee3a 12123 while (expr != NULL)
5ff904cd 12124 {
c7e4ee3a 12125 tree texpr = ffecom_arg_expr (ffebld_head (expr), &length);
5ff904cd 12126
c7e4ee3a
CB
12127 if (texpr == error_mark_node)
12128 return error_mark_node;
5ff904cd 12129
c7e4ee3a
CB
12130 *plist = build_tree_list (NULL_TREE, texpr);
12131 plist = &TREE_CHAIN (*plist);
12132 expr = ffebld_trail (expr);
12133 if (length != NULL_TREE)
5ff904cd 12134 {
c7e4ee3a
CB
12135 *ptrail = build_tree_list (NULL_TREE, length);
12136 ptrail = &TREE_CHAIN (*ptrail);
5ff904cd
JL
12137 }
12138 }
12139
c7e4ee3a 12140 *plist = trail;
5ff904cd 12141
c7e4ee3a
CB
12142 return list;
12143}
5ff904cd 12144
c7e4ee3a
CB
12145#endif
12146/* ffecom_list_ptr_to_expr -- Transform list of exprs into gcc tree
5ff904cd 12147
c7e4ee3a
CB
12148 tree t;
12149 ffebld expr; // FFE opITEM list.
12150 tree = ffecom_list_ptr_to_expr(expr);
5ff904cd 12151
c7e4ee3a
CB
12152 List of actual args is transformed into corresponding gcc backend list for
12153 use in calling an external procedure (vs. a statement function). */
5ff904cd 12154
c7e4ee3a
CB
12155#if FFECOM_targetCURRENT == FFECOM_targetGCC
12156tree
12157ffecom_list_ptr_to_expr (ffebld expr)
12158{
12159 tree list;
12160 tree *plist = &list;
12161 tree trail = NULL_TREE; /* Append char length args here. */
12162 tree *ptrail = &trail;
12163 tree length;
5ff904cd 12164
c7e4ee3a
CB
12165 while (expr != NULL)
12166 {
12167 tree texpr = ffecom_arg_ptr_to_expr (ffebld_head (expr), &length);
5ff904cd 12168
c7e4ee3a
CB
12169 if (texpr == error_mark_node)
12170 return error_mark_node;
5ff904cd 12171
c7e4ee3a
CB
12172 *plist = build_tree_list (NULL_TREE, texpr);
12173 plist = &TREE_CHAIN (*plist);
12174 expr = ffebld_trail (expr);
12175 if (length != NULL_TREE)
12176 {
12177 *ptrail = build_tree_list (NULL_TREE, length);
12178 ptrail = &TREE_CHAIN (*ptrail);
12179 }
12180 }
5ff904cd 12181
c7e4ee3a 12182 *plist = trail;
5ff904cd 12183
c7e4ee3a
CB
12184 return list;
12185}
5ff904cd 12186
c7e4ee3a
CB
12187#endif
12188/* Obtain gcc's LABEL_DECL tree for label. */
5ff904cd 12189
c7e4ee3a
CB
12190#if FFECOM_targetCURRENT == FFECOM_targetGCC
12191tree
12192ffecom_lookup_label (ffelab label)
12193{
12194 tree glabel;
5ff904cd 12195
c7e4ee3a
CB
12196 if (ffelab_hook (label) == NULL_TREE)
12197 {
12198 char labelname[16];
5ff904cd 12199
c7e4ee3a
CB
12200 switch (ffelab_type (label))
12201 {
12202 case FFELAB_typeLOOPEND:
12203 case FFELAB_typeNOTLOOP:
12204 case FFELAB_typeENDIF:
12205 sprintf (labelname, "%" ffelabValue_f "u", ffelab_value (label));
12206 glabel = build_decl (LABEL_DECL, get_identifier (labelname),
12207 void_type_node);
12208 DECL_CONTEXT (glabel) = current_function_decl;
12209 DECL_MODE (glabel) = VOIDmode;
12210 break;
5ff904cd 12211
c7e4ee3a 12212 case FFELAB_typeFORMAT:
c7e4ee3a
CB
12213 glabel = build_decl (VAR_DECL,
12214 ffecom_get_invented_identifier
14657de8 12215 ("__g77_format_%d", (int) ffelab_value (label)),
c7e4ee3a
CB
12216 build_type_variant (build_array_type
12217 (char_type_node,
12218 NULL_TREE),
12219 1, 0));
12220 TREE_CONSTANT (glabel) = 1;
12221 TREE_STATIC (glabel) = 1;
611081b2 12222 DECL_CONTEXT (glabel) = current_function_decl;
c7e4ee3a 12223 DECL_INITIAL (glabel) = NULL;
6c418184 12224 make_decl_rtl (glabel, NULL);
c7e4ee3a 12225 expand_decl (glabel);
5ff904cd 12226
7189a4b0 12227 ffecom_save_tree_forever (glabel);
5ff904cd 12228
c7e4ee3a 12229 break;
5ff904cd 12230
c7e4ee3a
CB
12231 case FFELAB_typeANY:
12232 glabel = error_mark_node;
12233 break;
5ff904cd 12234
c7e4ee3a
CB
12235 default:
12236 assert ("bad label type" == NULL);
12237 glabel = NULL;
12238 break;
12239 }
12240 ffelab_set_hook (label, glabel);
12241 }
12242 else
12243 {
12244 glabel = ffelab_hook (label);
12245 }
5ff904cd 12246
c7e4ee3a
CB
12247 return glabel;
12248}
5ff904cd 12249
c7e4ee3a
CB
12250#endif
12251/* Stabilizes the arguments. Don't use this if the lhs and rhs come from
12252 a single source specification (as in the fourth argument of MVBITS).
12253 If the type is NULL_TREE, the type of lhs is used to make the type of
12254 the MODIFY_EXPR. */
5ff904cd 12255
c7e4ee3a
CB
12256#if FFECOM_targetCURRENT == FFECOM_targetGCC
12257tree
12258ffecom_modify (tree newtype, tree lhs,
12259 tree rhs)
12260{
12261 if (lhs == error_mark_node || rhs == error_mark_node)
12262 return error_mark_node;
5ff904cd 12263
c7e4ee3a
CB
12264 if (newtype == NULL_TREE)
12265 newtype = TREE_TYPE (lhs);
5ff904cd 12266
c7e4ee3a
CB
12267 if (TREE_SIDE_EFFECTS (lhs))
12268 lhs = stabilize_reference (lhs);
5ff904cd 12269
c7e4ee3a
CB
12270 return ffecom_2s (MODIFY_EXPR, newtype, lhs, rhs);
12271}
5ff904cd 12272
c7e4ee3a 12273#endif
5ff904cd 12274
c7e4ee3a 12275/* Register source file name. */
5ff904cd 12276
c7e4ee3a 12277void
b0791fa9 12278ffecom_file (const char *name)
c7e4ee3a
CB
12279{
12280#if FFECOM_GCC_INCLUDE
12281 ffecom_file_ (name);
12282#endif
12283}
5ff904cd 12284
c7e4ee3a 12285/* ffecom_notify_init_storage -- An aggregate storage is now fully init'ed
5ff904cd 12286
c7e4ee3a
CB
12287 ffestorag st;
12288 ffecom_notify_init_storage(st);
5ff904cd 12289
c7e4ee3a
CB
12290 Gets called when all possible units in an aggregate storage area (a LOCAL
12291 with equivalences or a COMMON) have been initialized. The initialization
12292 info either is in ffestorag_init or, if that is NULL,
12293 ffestorag_accretion:
5ff904cd 12294
c7e4ee3a
CB
12295 ffestorag_init may contain an opCONTER or opARRTER. opCONTER may occur
12296 even for an array if the array is one element in length!
5ff904cd 12297
c7e4ee3a
CB
12298 ffestorag_accretion will contain an opACCTER. It is much like an
12299 opARRTER except it has an ffebit object in it instead of just a size.
12300 The back end can use the info in the ffebit object, if it wants, to
12301 reduce the amount of actual initialization, but in any case it should
12302 kill the ffebit object when done. Also, set accretion to NULL but
12303 init to a non-NULL value.
5ff904cd 12304
c7e4ee3a
CB
12305 After performing initialization, DO NOT set init to NULL, because that'll
12306 tell the front end it is ok for more initialization to happen. Instead,
12307 set init to an opANY expression or some such thing that you can use to
12308 tell that you've already initialized the object.
5ff904cd 12309
c7e4ee3a
CB
12310 27-Oct-91 JCB 1.1
12311 Support two-pass FFE. */
5ff904cd 12312
c7e4ee3a
CB
12313void
12314ffecom_notify_init_storage (ffestorag st)
12315{
12316 ffebld init; /* The initialization expression. */
12317#if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12318 ffetargetOffset size; /* The size of the entity. */
12319 ffetargetAlign pad; /* Its initial padding. */
12320#endif
12321
12322 if (ffestorag_init (st) == NULL)
5ff904cd 12323 {
c7e4ee3a
CB
12324 init = ffestorag_accretion (st);
12325 assert (init != NULL);
12326 ffestorag_set_accretion (st, NULL);
12327 ffestorag_set_accretes (st, 0);
12328
12329#if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12330 /* For GNU backend, just turn ACCTER into ARRTER and proceed. */
12331 size = ffebld_accter_size (init);
12332 pad = ffebld_accter_pad (init);
12333 ffebit_kill (ffebld_accter_bits (init));
12334 ffebld_set_op (init, FFEBLD_opARRTER);
12335 ffebld_set_arrter (init, ffebld_accter (init));
12336 ffebld_arrter_set_size (init, size);
12337 ffebld_arrter_set_pad (init, size);
12338#endif
12339
12340#if FFECOM_TWOPASS
12341 ffestorag_set_init (st, init);
12342#endif
5ff904cd 12343 }
c7e4ee3a
CB
12344#if FFECOM_ONEPASS
12345 else
12346 init = ffestorag_init (st);
5ff904cd
JL
12347#endif
12348
c7e4ee3a
CB
12349#if FFECOM_ONEPASS /* Process the inits, wipe 'em out. */
12350 ffestorag_set_init (st, ffebld_new_any ());
5ff904cd 12351
c7e4ee3a
CB
12352 if (ffebld_op (init) == FFEBLD_opANY)
12353 return; /* Oh, we already did this! */
5ff904cd 12354
c7e4ee3a
CB
12355#if FFECOM_targetCURRENT == FFECOM_targetFFE
12356 {
12357 ffesymbol s;
5ff904cd 12358
c7e4ee3a
CB
12359 if (ffestorag_symbol (st) != NULL)
12360 s = ffestorag_symbol (st);
12361 else
12362 s = ffestorag_typesymbol (st);
5ff904cd 12363
c7e4ee3a
CB
12364 fprintf (dmpout, "= initialize_storage \"%s\" ",
12365 (s != NULL) ? ffesymbol_text (s) : "(unnamed)");
12366 ffebld_dump (init);
12367 fputc ('\n', dmpout);
12368 }
12369#endif
5ff904cd 12370
c7e4ee3a
CB
12371#endif /* if FFECOM_ONEPASS */
12372}
5ff904cd 12373
c7e4ee3a 12374/* ffecom_notify_init_symbol -- A symbol is now fully init'ed
5ff904cd 12375
c7e4ee3a
CB
12376 ffesymbol s;
12377 ffecom_notify_init_symbol(s);
5ff904cd 12378
c7e4ee3a
CB
12379 Gets called when all possible units in a symbol (not placed in COMMON
12380 or involved in EQUIVALENCE, unless it as yet has no ffestorag object)
12381 have been initialized. The initialization info either is in
12382 ffesymbol_init or, if that is NULL, ffesymbol_accretion:
5ff904cd 12383
c7e4ee3a
CB
12384 ffesymbol_init may contain an opCONTER or opARRTER. opCONTER may occur
12385 even for an array if the array is one element in length!
5ff904cd 12386
c7e4ee3a
CB
12387 ffesymbol_accretion will contain an opACCTER. It is much like an
12388 opARRTER except it has an ffebit object in it instead of just a size.
12389 The back end can use the info in the ffebit object, if it wants, to
12390 reduce the amount of actual initialization, but in any case it should
12391 kill the ffebit object when done. Also, set accretion to NULL but
12392 init to a non-NULL value.
5ff904cd 12393
c7e4ee3a
CB
12394 After performing initialization, DO NOT set init to NULL, because that'll
12395 tell the front end it is ok for more initialization to happen. Instead,
12396 set init to an opANY expression or some such thing that you can use to
12397 tell that you've already initialized the object.
5ff904cd 12398
c7e4ee3a
CB
12399 27-Oct-91 JCB 1.1
12400 Support two-pass FFE. */
5ff904cd 12401
c7e4ee3a
CB
12402void
12403ffecom_notify_init_symbol (ffesymbol s)
12404{
12405 ffebld init; /* The initialization expression. */
12406#if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12407 ffetargetOffset size; /* The size of the entity. */
12408 ffetargetAlign pad; /* Its initial padding. */
12409#endif
5ff904cd 12410
c7e4ee3a
CB
12411 if (ffesymbol_storage (s) == NULL)
12412 return; /* Do nothing until COMMON/EQUIVALENCE
12413 possibilities checked. */
5ff904cd 12414
c7e4ee3a
CB
12415 if ((ffesymbol_init (s) == NULL)
12416 && ((init = ffesymbol_accretion (s)) != NULL))
12417 {
12418 ffesymbol_set_accretion (s, NULL);
12419 ffesymbol_set_accretes (s, 0);
5ff904cd 12420
c7e4ee3a
CB
12421#if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12422 /* For GNU backend, just turn ACCTER into ARRTER and proceed. */
12423 size = ffebld_accter_size (init);
12424 pad = ffebld_accter_pad (init);
12425 ffebit_kill (ffebld_accter_bits (init));
12426 ffebld_set_op (init, FFEBLD_opARRTER);
12427 ffebld_set_arrter (init, ffebld_accter (init));
12428 ffebld_arrter_set_size (init, size);
12429 ffebld_arrter_set_pad (init, size);
12430#endif
5ff904cd 12431
c7e4ee3a
CB
12432#if FFECOM_TWOPASS
12433 ffesymbol_set_init (s, init);
12434#endif
12435 }
12436#if FFECOM_ONEPASS
12437 else
12438 init = ffesymbol_init (s);
12439#endif
5ff904cd 12440
c7e4ee3a
CB
12441#if FFECOM_ONEPASS
12442 ffesymbol_set_init (s, ffebld_new_any ());
5ff904cd 12443
c7e4ee3a
CB
12444 if (ffebld_op (init) == FFEBLD_opANY)
12445 return; /* Oh, we already did this! */
5ff904cd 12446
c7e4ee3a
CB
12447#if FFECOM_targetCURRENT == FFECOM_targetFFE
12448 fprintf (dmpout, "= initialize_symbol \"%s\" ", ffesymbol_text (s));
12449 ffebld_dump (init);
12450 fputc ('\n', dmpout);
12451#endif
5ff904cd 12452
c7e4ee3a
CB
12453#endif /* if FFECOM_ONEPASS */
12454}
5ff904cd 12455
c7e4ee3a 12456/* ffecom_notify_primary_entry -- Learn which is the primary entry point
5ff904cd 12457
c7e4ee3a
CB
12458 ffesymbol s;
12459 ffecom_notify_primary_entry(s);
5ff904cd 12460
c7e4ee3a
CB
12461 Gets called when implicit or explicit PROGRAM statement seen or when
12462 FUNCTION, SUBROUTINE, or BLOCK DATA statement seen, with the primary
12463 global symbol that serves as the entry point. */
5ff904cd 12464
c7e4ee3a
CB
12465void
12466ffecom_notify_primary_entry (ffesymbol s)
12467{
12468 ffecom_primary_entry_ = s;
12469 ffecom_primary_entry_kind_ = ffesymbol_kind (s);
5ff904cd 12470
c7e4ee3a
CB
12471 if ((ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
12472 || (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE))
12473 ffecom_primary_entry_is_proc_ = TRUE;
12474 else
12475 ffecom_primary_entry_is_proc_ = FALSE;
5ff904cd 12476
c7e4ee3a
CB
12477 if (!ffe_is_silent ())
12478 {
12479 if (ffecom_primary_entry_kind_ == FFEINFO_kindPROGRAM)
12480 fprintf (stderr, "%s:\n", ffesymbol_text (s));
12481 else
12482 fprintf (stderr, " %s:\n", ffesymbol_text (s));
12483 }
5ff904cd 12484
c7e4ee3a
CB
12485#if FFECOM_targetCURRENT == FFECOM_targetGCC
12486 if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
12487 {
12488 ffebld list;
12489 ffebld arg;
5ff904cd 12490
c7e4ee3a
CB
12491 for (list = ffesymbol_dummyargs (s);
12492 list != NULL;
12493 list = ffebld_trail (list))
12494 {
12495 arg = ffebld_head (list);
12496 if (ffebld_op (arg) == FFEBLD_opSTAR)
12497 {
12498 ffecom_is_altreturning_ = TRUE;
12499 break;
12500 }
12501 }
12502 }
12503#endif
12504}
5ff904cd 12505
c7e4ee3a
CB
12506FILE *
12507ffecom_open_include (char *name, ffewhereLine l, ffewhereColumn c)
12508{
12509#if FFECOM_GCC_INCLUDE
12510 return ffecom_open_include_ (name, l, c);
12511#else
12512 return fopen (name, "r");
5ff904cd 12513#endif
c7e4ee3a 12514}
5ff904cd 12515
c7e4ee3a 12516/* ffecom_ptr_to_expr -- Transform expr into gcc tree with & in front
5ff904cd 12517
c7e4ee3a
CB
12518 tree t;
12519 ffebld expr; // FFE expression.
12520 tree = ffecom_ptr_to_expr(expr);
5ff904cd 12521
c7e4ee3a 12522 Like ffecom_expr, but sticks address-of in front of most things. */
5ff904cd 12523
c7e4ee3a
CB
12524#if FFECOM_targetCURRENT == FFECOM_targetGCC
12525tree
12526ffecom_ptr_to_expr (ffebld expr)
12527{
12528 tree item;
12529 ffeinfoBasictype bt;
12530 ffeinfoKindtype kt;
12531 ffesymbol s;
5ff904cd 12532
c7e4ee3a 12533 assert (expr != NULL);
5ff904cd 12534
c7e4ee3a
CB
12535 switch (ffebld_op (expr))
12536 {
12537 case FFEBLD_opSYMTER:
12538 s = ffebld_symter (expr);
12539 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
12540 {
12541 ffecomGfrt ix;
5ff904cd 12542
c7e4ee3a
CB
12543 ix = ffeintrin_gfrt_indirect (ffebld_symter_implementation (expr));
12544 assert (ix != FFECOM_gfrt);
12545 if ((item = ffecom_gfrt_[ix]) == NULL_TREE)
12546 {
12547 ffecom_make_gfrt_ (ix);
12548 item = ffecom_gfrt_[ix];
12549 }
12550 }
12551 else
12552 {
12553 item = ffesymbol_hook (s).decl_tree;
12554 if (item == NULL_TREE)
12555 {
12556 s = ffecom_sym_transform_ (s);
12557 item = ffesymbol_hook (s).decl_tree;
12558 }
12559 }
12560 assert (item != NULL);
12561 if (item == error_mark_node)
12562 return item;
12563 if (!ffesymbol_hook (s).addr)
12564 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12565 item);
12566 return item;
5ff904cd 12567
c7e4ee3a 12568 case FFEBLD_opARRAYREF:
ff852b44 12569 return ffecom_arrayref_ (NULL_TREE, expr, 1);
5ff904cd 12570
c7e4ee3a 12571 case FFEBLD_opCONTER:
5ff904cd 12572
c7e4ee3a
CB
12573 bt = ffeinfo_basictype (ffebld_info (expr));
12574 kt = ffeinfo_kindtype (ffebld_info (expr));
5ff904cd 12575
c7e4ee3a
CB
12576 item = ffecom_constantunion (&ffebld_constant_union
12577 (ffebld_conter (expr)), bt, kt,
12578 ffecom_tree_type[bt][kt]);
12579 if (item == error_mark_node)
12580 return error_mark_node;
12581 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12582 item);
12583 return item;
5ff904cd 12584
c7e4ee3a
CB
12585 case FFEBLD_opANY:
12586 return error_mark_node;
5ff904cd 12587
c7e4ee3a
CB
12588 default:
12589 bt = ffeinfo_basictype (ffebld_info (expr));
12590 kt = ffeinfo_kindtype (ffebld_info (expr));
12591
12592 item = ffecom_expr (expr);
12593 if (item == error_mark_node)
12594 return error_mark_node;
12595
12596 /* The back end currently optimizes a bit too zealously for us, in that
12597 we fail JCB001 if the following block of code is omitted. It checks
12598 to see if the transformed expression is a symbol or array reference,
12599 and encloses it in a SAVE_EXPR if that is the case. */
12600
12601 STRIP_NOPS (item);
12602 if ((TREE_CODE (item) == VAR_DECL)
12603 || (TREE_CODE (item) == PARM_DECL)
12604 || (TREE_CODE (item) == RESULT_DECL)
12605 || (TREE_CODE (item) == INDIRECT_REF)
12606 || (TREE_CODE (item) == ARRAY_REF)
12607 || (TREE_CODE (item) == COMPONENT_REF)
12608#ifdef OFFSET_REF
12609 || (TREE_CODE (item) == OFFSET_REF)
12610#endif
12611 || (TREE_CODE (item) == BUFFER_REF)
12612 || (TREE_CODE (item) == REALPART_EXPR)
12613 || (TREE_CODE (item) == IMAGPART_EXPR))
12614 {
12615 item = ffecom_save_tree (item);
12616 }
12617
12618 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12619 item);
12620 return item;
12621 }
12622
12623 assert ("fall-through error" == NULL);
12624 return error_mark_node;
5ff904cd
JL
12625}
12626
12627#endif
c7e4ee3a 12628/* Obtain a temp var with given data type.
5ff904cd 12629
c7e4ee3a
CB
12630 size is FFETARGET_charactersizeNONE for a non-CHARACTER type
12631 or >= 0 for a CHARACTER type.
5ff904cd 12632
c7e4ee3a 12633 elements is -1 for a scalar or > 0 for an array of type. */
5ff904cd
JL
12634
12635#if FFECOM_targetCURRENT == FFECOM_targetGCC
12636tree
c7e4ee3a
CB
12637ffecom_make_tempvar (const char *commentary, tree type,
12638 ffetargetCharacterSize size, int elements)
5ff904cd 12639{
c7e4ee3a
CB
12640 tree t;
12641 static int mynumber;
5ff904cd 12642
c7e4ee3a 12643 assert (current_binding_level->prep_state < 2);
702edf1d 12644
c7e4ee3a
CB
12645 if (type == error_mark_node)
12646 return error_mark_node;
702edf1d 12647
c7e4ee3a
CB
12648 if (size != FFETARGET_charactersizeNONE)
12649 type = build_array_type (type,
12650 build_range_type (ffecom_f2c_ftnlen_type_node,
12651 ffecom_f2c_ftnlen_one_node,
12652 build_int_2 (size, 0)));
12653 if (elements != -1)
12654 type = build_array_type (type,
12655 build_range_type (integer_type_node,
12656 integer_zero_node,
12657 build_int_2 (elements - 1,
12658 0)));
12659 t = build_decl (VAR_DECL,
12660 ffecom_get_invented_identifier ("__g77_%s_%d",
12661 commentary,
12662 mynumber++),
12663 type);
5ff904cd 12664
c7e4ee3a
CB
12665 t = start_decl (t, FALSE);
12666 finish_decl (t, NULL_TREE, FALSE);
12667
c7e4ee3a
CB
12668 return t;
12669}
5ff904cd 12670#endif
5ff904cd 12671
c7e4ee3a 12672/* Prepare argument pointer to expression.
5ff904cd 12673
c7e4ee3a
CB
12674 Like ffecom_prepare_expr, except for expressions to be evaluated
12675 via ffecom_arg_ptr_to_expr. */
5ff904cd 12676
c7e4ee3a
CB
12677void
12678ffecom_prepare_arg_ptr_to_expr (ffebld expr)
5ff904cd 12679{
c7e4ee3a
CB
12680 /* ~~For now, it seems to be the same thing. */
12681 ffecom_prepare_expr (expr);
12682 return;
12683}
702edf1d 12684
c7e4ee3a 12685/* End of preparations. */
702edf1d 12686
c7e4ee3a
CB
12687bool
12688ffecom_prepare_end (void)
12689{
12690 int prep_state = current_binding_level->prep_state;
5ff904cd 12691
c7e4ee3a
CB
12692 assert (prep_state < 2);
12693 current_binding_level->prep_state = 2;
5ff904cd 12694
c7e4ee3a 12695 return (prep_state == 1) ? TRUE : FALSE;
5ff904cd
JL
12696}
12697
c7e4ee3a 12698/* Prepare expression.
5ff904cd 12699
c7e4ee3a
CB
12700 This is called before any code is generated for the current block.
12701 It scans the expression, declares any temporaries that might be needed
12702 during evaluation of the expression, and stores those temporaries in
12703 the appropriate "hook" fields of the expression. `dest', if not NULL,
12704 specifies the destination that ffecom_expr_ will see, in case that
12705 helps avoid generating unused temporaries.
12706
12707 ~~Improve to avoid allocating unused temporaries by taking `dest'
12708 into account vis-a-vis aliasing requirements of complex/character
12709 functions. */
12710
12711void
12712ffecom_prepare_expr_ (ffebld expr, ffebld dest UNUSED)
5ff904cd 12713{
c7e4ee3a
CB
12714 ffeinfoBasictype bt;
12715 ffeinfoKindtype kt;
12716 ffetargetCharacterSize sz;
12717 tree tempvar = NULL_TREE;
5ff904cd 12718
c7e4ee3a
CB
12719 assert (current_binding_level->prep_state < 2);
12720
12721 if (! expr)
12722 return;
12723
12724 bt = ffeinfo_basictype (ffebld_info (expr));
12725 kt = ffeinfo_kindtype (ffebld_info (expr));
12726 sz = ffeinfo_size (ffebld_info (expr));
12727
12728 /* Generate whatever temporaries are needed to represent the result
12729 of the expression. */
12730
47d98fa2
CB
12731 if (bt == FFEINFO_basictypeCHARACTER)
12732 {
12733 while (ffebld_op (expr) == FFEBLD_opPAREN)
12734 expr = ffebld_left (expr);
12735 }
12736
c7e4ee3a 12737 switch (ffebld_op (expr))
5ff904cd 12738 {
c7e4ee3a
CB
12739 default:
12740 /* Don't make temps for SYMTER, CONTER, etc. */
12741 if (ffebld_arity (expr) == 0)
12742 break;
5ff904cd 12743
c7e4ee3a 12744 switch (bt)
5ff904cd 12745 {
c7e4ee3a
CB
12746 case FFEINFO_basictypeCOMPLEX:
12747 if (ffebld_op (expr) == FFEBLD_opFUNCREF)
12748 {
12749 ffesymbol s;
5ff904cd 12750
c7e4ee3a
CB
12751 if (ffebld_op (ffebld_left (expr)) != FFEBLD_opSYMTER)
12752 break;
5ff904cd 12753
c7e4ee3a
CB
12754 s = ffebld_symter (ffebld_left (expr));
12755 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT
68779408
CB
12756 || (ffesymbol_where (s) != FFEINFO_whereINTRINSIC
12757 && ! ffesymbol_is_f2c (s))
12758 || (ffesymbol_where (s) == FFEINFO_whereINTRINSIC
12759 && ! ffe_is_f2c_library ()))
c7e4ee3a
CB
12760 break;
12761 }
12762 else if (ffebld_op (expr) == FFEBLD_opPOWER)
12763 {
12764 /* Requires special treatment. There's no POW_CC function
12765 in libg2c, so POW_ZZ is used, which means we always
12766 need a double-complex temp, not a single-complex. */
12767 kt = FFEINFO_kindtypeREAL2;
12768 }
12769 else if (ffebld_op (expr) != FFEBLD_opDIVIDE)
12770 /* The other ops don't need temps for complex operands. */
12771 break;
5ff904cd 12772
c7e4ee3a
CB
12773 /* ~~~Avoid making temps for some intrinsics, such as AIMAG(C),
12774 REAL(C). See 19990325-0.f, routine `check', for cases. */
12775 tempvar = ffecom_make_tempvar ("complex",
12776 ffecom_tree_type
12777 [FFEINFO_basictypeCOMPLEX][kt],
12778 FFETARGET_charactersizeNONE,
12779 -1);
5ff904cd
JL
12780 break;
12781
c7e4ee3a
CB
12782 case FFEINFO_basictypeCHARACTER:
12783 if (ffebld_op (expr) != FFEBLD_opFUNCREF)
12784 break;
12785
12786 if (sz == FFETARGET_charactersizeNONE)
12787 /* ~~Kludge alert! This should someday be fixed. */
12788 sz = 24;
12789
12790 tempvar = ffecom_make_tempvar ("char", char_type_node, sz, -1);
5ff904cd
JL
12791 break;
12792
12793 default:
5ff904cd
JL
12794 break;
12795 }
c7e4ee3a 12796 break;
5ff904cd 12797
c7e4ee3a
CB
12798#ifdef HAHA
12799 case FFEBLD_opPOWER:
12800 {
12801 tree rtype, ltype;
12802 tree rtmp, ltmp, result;
5ff904cd 12803
c7e4ee3a
CB
12804 ltype = ffecom_type_expr (ffebld_left (expr));
12805 rtype = ffecom_type_expr (ffebld_right (expr));
5ff904cd 12806
c7e4ee3a
CB
12807 rtmp = ffecom_make_tempvar (rtype, FFETARGET_charactersizeNONE, -1);
12808 ltmp = ffecom_make_tempvar (ltype, FFETARGET_charactersizeNONE, -1);
12809 result = ffecom_make_tempvar (ltype, FFETARGET_charactersizeNONE, -1);
5ff904cd 12810
c7e4ee3a
CB
12811 tempvar = make_tree_vec (3);
12812 TREE_VEC_ELT (tempvar, 0) = rtmp;
12813 TREE_VEC_ELT (tempvar, 1) = ltmp;
12814 TREE_VEC_ELT (tempvar, 2) = result;
12815 }
12816 break;
12817#endif /* HAHA */
5ff904cd 12818
c7e4ee3a
CB
12819 case FFEBLD_opCONCATENATE:
12820 {
12821 /* This gets special handling, because only one set of temps
12822 is needed for a tree of these -- the tree is treated as
12823 a flattened list of concatenations when generating code. */
5ff904cd 12824
c7e4ee3a
CB
12825 ffecomConcatList_ catlist;
12826 tree ltmp, itmp, result;
12827 int count;
12828 int i;
5ff904cd 12829
c7e4ee3a
CB
12830 catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
12831 count = ffecom_concat_list_count_ (catlist);
5ff904cd 12832
c7e4ee3a
CB
12833 if (count >= 2)
12834 {
12835 ltmp
12836 = ffecom_make_tempvar ("concat_len",
12837 ffecom_f2c_ftnlen_type_node,
12838 FFETARGET_charactersizeNONE, count);
12839 itmp
12840 = ffecom_make_tempvar ("concat_item",
12841 ffecom_f2c_address_type_node,
12842 FFETARGET_charactersizeNONE, count);
12843 result
12844 = ffecom_make_tempvar ("concat_res",
12845 char_type_node,
12846 ffecom_concat_list_maxlen_ (catlist),
12847 -1);
12848
12849 tempvar = make_tree_vec (3);
12850 TREE_VEC_ELT (tempvar, 0) = ltmp;
12851 TREE_VEC_ELT (tempvar, 1) = itmp;
12852 TREE_VEC_ELT (tempvar, 2) = result;
12853 }
5ff904cd 12854
c7e4ee3a
CB
12855 for (i = 0; i < count; ++i)
12856 ffecom_prepare_arg_ptr_to_expr (ffecom_concat_list_expr_ (catlist,
12857 i));
5ff904cd 12858
c7e4ee3a 12859 ffecom_concat_list_kill_ (catlist);
5ff904cd 12860
c7e4ee3a
CB
12861 if (tempvar)
12862 {
12863 ffebld_nonter_set_hook (expr, tempvar);
12864 current_binding_level->prep_state = 1;
12865 }
12866 }
12867 return;
5ff904cd 12868
c7e4ee3a
CB
12869 case FFEBLD_opCONVERT:
12870 if (bt == FFEINFO_basictypeCHARACTER
12871 && ((ffebld_size_known (ffebld_left (expr))
12872 == FFETARGET_charactersizeNONE)
12873 || (ffebld_size_known (ffebld_left (expr)) >= sz)))
12874 tempvar = ffecom_make_tempvar ("convert", char_type_node, sz, -1);
12875 break;
12876 }
5ff904cd 12877
c7e4ee3a
CB
12878 if (tempvar)
12879 {
12880 ffebld_nonter_set_hook (expr, tempvar);
12881 current_binding_level->prep_state = 1;
12882 }
5ff904cd 12883
c7e4ee3a 12884 /* Prepare subexpressions for this expr. */
5ff904cd 12885
c7e4ee3a 12886 switch (ffebld_op (expr))
5ff904cd 12887 {
c7e4ee3a
CB
12888 case FFEBLD_opPERCENT_LOC:
12889 ffecom_prepare_ptr_to_expr (ffebld_left (expr));
12890 break;
5ff904cd 12891
c7e4ee3a
CB
12892 case FFEBLD_opPERCENT_VAL:
12893 case FFEBLD_opPERCENT_REF:
12894 ffecom_prepare_expr (ffebld_left (expr));
12895 break;
5ff904cd 12896
c7e4ee3a
CB
12897 case FFEBLD_opPERCENT_DESCR:
12898 ffecom_prepare_arg_ptr_to_expr (ffebld_left (expr));
12899 break;
5ff904cd 12900
c7e4ee3a
CB
12901 case FFEBLD_opITEM:
12902 {
12903 ffebld item;
5ff904cd 12904
c7e4ee3a
CB
12905 for (item = expr;
12906 item != NULL;
12907 item = ffebld_trail (item))
12908 if (ffebld_head (item) != NULL)
12909 ffecom_prepare_expr (ffebld_head (item));
12910 }
12911 break;
5ff904cd 12912
c7e4ee3a
CB
12913 default:
12914 /* Need to handle character conversion specially. */
12915 switch (ffebld_arity (expr))
12916 {
12917 case 2:
12918 ffecom_prepare_expr (ffebld_left (expr));
12919 ffecom_prepare_expr (ffebld_right (expr));
12920 break;
5ff904cd 12921
c7e4ee3a
CB
12922 case 1:
12923 ffecom_prepare_expr (ffebld_left (expr));
12924 break;
5ff904cd 12925
c7e4ee3a
CB
12926 default:
12927 break;
12928 }
12929 }
5ff904cd 12930
c7e4ee3a 12931 return;
5ff904cd
JL
12932}
12933
c7e4ee3a 12934/* Prepare expression for reading and writing.
5ff904cd 12935
c7e4ee3a
CB
12936 Like ffecom_prepare_expr, except for expressions to be evaluated
12937 via ffecom_expr_rw. */
5ff904cd 12938
c7e4ee3a
CB
12939void
12940ffecom_prepare_expr_rw (tree type, ffebld expr)
12941{
12942 /* This is all we support for now. */
12943 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
5ff904cd 12944
c7e4ee3a
CB
12945 /* ~~For now, it seems to be the same thing. */
12946 ffecom_prepare_expr (expr);
12947 return;
12948}
5ff904cd 12949
c7e4ee3a 12950/* Prepare expression for writing.
5ff904cd 12951
c7e4ee3a
CB
12952 Like ffecom_prepare_expr, except for expressions to be evaluated
12953 via ffecom_expr_w. */
5ff904cd
JL
12954
12955void
c7e4ee3a 12956ffecom_prepare_expr_w (tree type, ffebld expr)
5ff904cd 12957{
c7e4ee3a
CB
12958 /* This is all we support for now. */
12959 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
5ff904cd 12960
c7e4ee3a
CB
12961 /* ~~For now, it seems to be the same thing. */
12962 ffecom_prepare_expr (expr);
12963 return;
12964}
5ff904cd 12965
c7e4ee3a 12966/* Prepare expression for returning.
5ff904cd 12967
c7e4ee3a
CB
12968 Like ffecom_prepare_expr, except for expressions to be evaluated
12969 via ffecom_return_expr. */
5ff904cd 12970
c7e4ee3a
CB
12971void
12972ffecom_prepare_return_expr (ffebld expr)
12973{
12974 assert (current_binding_level->prep_state < 2);
5ff904cd 12975
c7e4ee3a
CB
12976 if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE
12977 && ffecom_is_altreturning_
12978 && expr != NULL)
12979 ffecom_prepare_expr (expr);
12980}
5ff904cd 12981
c7e4ee3a 12982/* Prepare pointer to expression.
5ff904cd 12983
c7e4ee3a
CB
12984 Like ffecom_prepare_expr, except for expressions to be evaluated
12985 via ffecom_ptr_to_expr. */
5ff904cd 12986
c7e4ee3a
CB
12987void
12988ffecom_prepare_ptr_to_expr (ffebld expr)
12989{
12990 /* ~~For now, it seems to be the same thing. */
12991 ffecom_prepare_expr (expr);
12992 return;
5ff904cd
JL
12993}
12994
c7e4ee3a 12995/* Transform expression into constant pointer-to-expression tree.
5ff904cd 12996
c7e4ee3a
CB
12997 If the expression can be transformed into a pointer-to-expression tree
12998 that is constant, that is done, and the tree returned. Else NULL_TREE
12999 is returned.
5ff904cd 13000
c7e4ee3a
CB
13001 That way, a caller can attempt to provide compile-time initialization
13002 of a variable and, if that fails, *then* choose to start a new block
13003 and resort to using temporaries, as appropriate. */
5ff904cd 13004
c7e4ee3a
CB
13005tree
13006ffecom_ptr_to_const_expr (ffebld expr)
5ff904cd 13007{
c7e4ee3a
CB
13008 if (! expr)
13009 return integer_zero_node;
5ff904cd 13010
c7e4ee3a
CB
13011 if (ffebld_op (expr) == FFEBLD_opANY)
13012 return error_mark_node;
5ff904cd 13013
c7e4ee3a
CB
13014 if (ffebld_arity (expr) == 0
13015 && (ffebld_op (expr) != FFEBLD_opSYMTER
13016 || ffebld_where (expr) == FFEINFO_whereCOMMON
13017 || ffebld_where (expr) == FFEINFO_whereGLOBAL
13018 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
5ff904cd 13019 {
c7e4ee3a
CB
13020 tree t;
13021
13022 t = ffecom_ptr_to_expr (expr);
13023 assert (TREE_CONSTANT (t));
13024 return t;
5ff904cd
JL
13025 }
13026
c7e4ee3a
CB
13027 return NULL_TREE;
13028}
13029
13030/* ffecom_return_expr -- Returns return-value expr given alt return expr
13031
13032 tree rtn; // NULL_TREE means use expand_null_return()
13033 ffebld expr; // NULL if no alt return expr to RETURN stmt
13034 rtn = ffecom_return_expr(expr);
13035
13036 Based on the program unit type and other info (like return function
13037 type, return master function type when alternate ENTRY points,
13038 whether subroutine has any alternate RETURN points, etc), returns the
13039 appropriate expression to be returned to the caller, or NULL_TREE
13040 meaning no return value or the caller expects it to be returned somewhere
13041 else (which is handled by other parts of this module). */
13042
5ff904cd 13043#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
13044tree
13045ffecom_return_expr (ffebld expr)
13046{
13047 tree rtn;
13048
13049 switch (ffecom_primary_entry_kind_)
5ff904cd 13050 {
c7e4ee3a
CB
13051 case FFEINFO_kindPROGRAM:
13052 case FFEINFO_kindBLOCKDATA:
13053 rtn = NULL_TREE;
13054 break;
5ff904cd 13055
c7e4ee3a
CB
13056 case FFEINFO_kindSUBROUTINE:
13057 if (!ffecom_is_altreturning_)
13058 rtn = NULL_TREE; /* No alt returns, never an expr. */
13059 else if (expr == NULL)
13060 rtn = integer_zero_node;
13061 else
13062 rtn = ffecom_expr (expr);
13063 break;
13064
13065 case FFEINFO_kindFUNCTION:
13066 if ((ffecom_multi_retval_ != NULL_TREE)
13067 || (ffesymbol_basictype (ffecom_primary_entry_)
13068 == FFEINFO_basictypeCHARACTER)
13069 || ((ffesymbol_basictype (ffecom_primary_entry_)
13070 == FFEINFO_basictypeCOMPLEX)
13071 && (ffecom_num_entrypoints_ == 0)
13072 && ffesymbol_is_f2c (ffecom_primary_entry_)))
13073 { /* Value is returned by direct assignment
13074 into (implicit) dummy. */
13075 rtn = NULL_TREE;
13076 break;
5ff904cd 13077 }
c7e4ee3a
CB
13078 rtn = ffecom_func_result_;
13079#if 0
13080 /* Spurious error if RETURN happens before first reference! So elide
13081 this code. In particular, for debugging registry, rtn should always
13082 be non-null after all, but TREE_USED won't be set until we encounter
13083 a reference in the code. Perfectly okay (but weird) code that,
13084 e.g., has "GOTO 20;10 RETURN;20 RTN=0;GOTO 10", would result in
13085 this diagnostic for no reason. Have people use -O -Wuninitialized
13086 and leave it to the back end to find obviously weird cases. */
5ff904cd 13087
c7e4ee3a
CB
13088 /* Used to "assert(rtn != NULL_TREE);" here, but it's kind of a valid
13089 situation; if the return value has never been referenced, it won't
13090 have a tree under 2pass mode. */
13091 if ((rtn == NULL_TREE)
13092 || !TREE_USED (rtn))
13093 {
13094 ffebad_start (FFEBAD_RETURN_VALUE_UNSET);
13095 ffebad_here (0, ffesymbol_where_line (ffecom_primary_entry_),
13096 ffesymbol_where_column (ffecom_primary_entry_));
13097 ffebad_string (ffesymbol_text (ffesymbol_funcresult
13098 (ffecom_primary_entry_)));
13099 ffebad_finish ();
13100 }
5ff904cd 13101#endif
c7e4ee3a 13102 break;
5ff904cd 13103
c7e4ee3a
CB
13104 default:
13105 assert ("bad unit kind" == NULL);
13106 case FFEINFO_kindANY:
13107 rtn = error_mark_node;
13108 break;
13109 }
5ff904cd 13110
c7e4ee3a
CB
13111 return rtn;
13112}
5ff904cd 13113
c7e4ee3a
CB
13114#endif
13115/* Do save_expr only if tree is not error_mark_node. */
5ff904cd
JL
13116
13117#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
13118tree
13119ffecom_save_tree (tree t)
5ff904cd 13120{
c7e4ee3a 13121 return save_expr (t);
5ff904cd 13122}
5ff904cd 13123#endif
c7e4ee3a
CB
13124
13125/* Start a compound statement (block). */
5ff904cd
JL
13126
13127#if FFECOM_targetCURRENT == FFECOM_targetGCC
13128void
c7e4ee3a 13129ffecom_start_compstmt (void)
5ff904cd 13130{
c7e4ee3a 13131 bison_rule_pushlevel_ ();
5ff904cd 13132}
c7e4ee3a 13133#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
5ff904cd 13134
c7e4ee3a 13135/* Public entry point for front end to access start_decl. */
5ff904cd
JL
13136
13137#if FFECOM_targetCURRENT == FFECOM_targetGCC
13138tree
c7e4ee3a 13139ffecom_start_decl (tree decl, bool is_initialized)
5ff904cd 13140{
c7e4ee3a
CB
13141 DECL_INITIAL (decl) = is_initialized ? error_mark_node : NULL_TREE;
13142 return start_decl (decl, FALSE);
13143}
5ff904cd 13144
c7e4ee3a
CB
13145#endif
13146/* ffecom_sym_commit -- Symbol's state being committed to reality
5ff904cd 13147
c7e4ee3a
CB
13148 ffesymbol s;
13149 ffecom_sym_commit(s);
5ff904cd 13150
c7e4ee3a
CB
13151 Does whatever the backend needs when a symbol is committed after having
13152 been backtrackable for a period of time. */
5ff904cd 13153
c7e4ee3a
CB
13154#if FFECOM_targetCURRENT == FFECOM_targetGCC
13155void
13156ffecom_sym_commit (ffesymbol s UNUSED)
13157{
13158 assert (!ffesymbol_retractable ());
13159}
5ff904cd 13160
c7e4ee3a
CB
13161#endif
13162/* ffecom_sym_end_transition -- Perform end transition on all symbols
5ff904cd 13163
c7e4ee3a 13164 ffecom_sym_end_transition();
5ff904cd 13165
c7e4ee3a
CB
13166 Does backend-specific stuff and also calls ffest_sym_end_transition
13167 to do the necessary FFE stuff.
5ff904cd 13168
c7e4ee3a
CB
13169 Backtracking is never enabled when this fn is called, so don't worry
13170 about it. */
5ff904cd 13171
c7e4ee3a
CB
13172ffesymbol
13173ffecom_sym_end_transition (ffesymbol s)
13174{
13175 ffestorag st;
5ff904cd 13176
c7e4ee3a 13177 assert (!ffesymbol_retractable ());
5ff904cd 13178
c7e4ee3a 13179 s = ffest_sym_end_transition (s);
5ff904cd 13180
c7e4ee3a
CB
13181#if FFECOM_targetCURRENT == FFECOM_targetGCC
13182 if ((ffesymbol_kind (s) == FFEINFO_kindBLOCKDATA)
13183 && (ffesymbol_where (s) == FFEINFO_whereGLOBAL))
13184 {
13185 ffecom_list_blockdata_
13186 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
13187 FFEINTRIN_specNONE,
13188 FFEINTRIN_impNONE),
13189 ffecom_list_blockdata_);
5ff904cd 13190 }
5ff904cd 13191#endif
5ff904cd 13192
c7e4ee3a
CB
13193 /* This is where we finally notice that a symbol has partial initialization
13194 and finalize it. */
5ff904cd 13195
c7e4ee3a
CB
13196 if (ffesymbol_accretion (s) != NULL)
13197 {
13198 assert (ffesymbol_init (s) == NULL);
13199 ffecom_notify_init_symbol (s);
13200 }
13201 else if (((st = ffesymbol_storage (s)) != NULL)
13202 && ((st = ffestorag_parent (st)) != NULL)
13203 && (ffestorag_accretion (st) != NULL))
13204 {
13205 assert (ffestorag_init (st) == NULL);
13206 ffecom_notify_init_storage (st);
13207 }
5ff904cd
JL
13208
13209#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
13210 if ((ffesymbol_kind (s) == FFEINFO_kindCOMMON)
13211 && (ffesymbol_where (s) == FFEINFO_whereLOCAL)
13212 && (ffesymbol_storage (s) != NULL))
13213 {
13214 ffecom_list_common_
13215 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
13216 FFEINTRIN_specNONE,
13217 FFEINTRIN_impNONE),
13218 ffecom_list_common_);
13219 }
13220#endif
5ff904cd 13221
c7e4ee3a
CB
13222 return s;
13223}
5ff904cd 13224
c7e4ee3a 13225/* ffecom_sym_exec_transition -- Perform exec transition on all symbols
5ff904cd 13226
c7e4ee3a 13227 ffecom_sym_exec_transition();
5ff904cd 13228
c7e4ee3a
CB
13229 Does backend-specific stuff and also calls ffest_sym_exec_transition
13230 to do the necessary FFE stuff.
5ff904cd 13231
c7e4ee3a
CB
13232 See the long-winded description in ffecom_sym_learned for info
13233 on handling the situation where backtracking is inhibited. */
5ff904cd 13234
c7e4ee3a
CB
13235ffesymbol
13236ffecom_sym_exec_transition (ffesymbol s)
13237{
13238 s = ffest_sym_exec_transition (s);
5ff904cd 13239
c7e4ee3a
CB
13240 return s;
13241}
5ff904cd 13242
c7e4ee3a 13243/* ffecom_sym_learned -- Initial or more info gained on symbol after exec
5ff904cd 13244
c7e4ee3a
CB
13245 ffesymbol s;
13246 s = ffecom_sym_learned(s);
5ff904cd 13247
c7e4ee3a
CB
13248 Called when a new symbol is seen after the exec transition or when more
13249 info (perhaps) is gained for an UNCERTAIN symbol. The symbol state when
13250 it arrives here is that all its latest info is updated already, so its
13251 state may be UNCERTAIN or UNDERSTOOD, it might already have the hook
13252 field filled in if its gone through here or exec_transition first, and
13253 so on.
5ff904cd 13254
c7e4ee3a
CB
13255 The backend probably wants to check ffesymbol_retractable() to see if
13256 backtracking is in effect. If so, the FFE's changes to the symbol may
13257 be retracted (undone) or committed (ratified), at which time the
13258 appropriate ffecom_sym_retract or _commit function will be called
13259 for that function.
5ff904cd 13260
c7e4ee3a
CB
13261 If the backend has its own backtracking mechanism, great, use it so that
13262 committal is a simple operation. Though it doesn't make much difference,
13263 I suppose: the reason for tentative symbol evolution in the FFE is to
13264 enable error detection in weird incorrect statements early and to disable
13265 incorrect error detection on a correct statement. The backend is not
13266 likely to introduce any information that'll get involved in these
13267 considerations, so it is probably just fine that the implementation
13268 model for this fn and for _exec_transition is to not do anything
13269 (besides the required FFE stuff) if ffesymbol_retractable() returns TRUE
13270 and instead wait until ffecom_sym_commit is called (which it never
13271 will be as long as we're using ambiguity-detecting statement analysis in
13272 the FFE, which we are initially to shake out the code, but don't depend
13273 on this), otherwise go ahead and do whatever is needed.
5ff904cd 13274
c7e4ee3a
CB
13275 In essence, then, when this fn and _exec_transition get called while
13276 backtracking is enabled, a general mechanism would be to flag which (or
13277 both) of these were called (and in what order? neat question as to what
13278 might happen that I'm too lame to think through right now) and then when
13279 _commit is called reproduce the original calling sequence, if any, for
13280 the two fns (at which point backtracking will, of course, be disabled). */
5ff904cd 13281
c7e4ee3a
CB
13282ffesymbol
13283ffecom_sym_learned (ffesymbol s)
13284{
13285 ffestorag_exec_layout (s);
5ff904cd 13286
c7e4ee3a 13287 return s;
5ff904cd
JL
13288}
13289
c7e4ee3a 13290/* ffecom_sym_retract -- Symbol's state being retracted from reality
5ff904cd 13291
c7e4ee3a
CB
13292 ffesymbol s;
13293 ffecom_sym_retract(s);
5ff904cd 13294
c7e4ee3a
CB
13295 Does whatever the backend needs when a symbol is retracted after having
13296 been backtrackable for a period of time. */
5ff904cd
JL
13297
13298#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
13299void
13300ffecom_sym_retract (ffesymbol s UNUSED)
5ff904cd 13301{
c7e4ee3a 13302 assert (!ffesymbol_retractable ());
5ff904cd 13303
c7e4ee3a
CB
13304#if 0 /* GCC doesn't commit any backtrackable sins,
13305 so nothing needed here. */
13306 switch (ffesymbol_hook (s).state)
5ff904cd 13307 {
c7e4ee3a 13308 case 0: /* nothing happened yet. */
5ff904cd
JL
13309 break;
13310
c7e4ee3a 13311 case 1: /* exec transition happened. */
5ff904cd
JL
13312 break;
13313
c7e4ee3a
CB
13314 case 2: /* learned happened. */
13315 break;
5ff904cd 13316
c7e4ee3a
CB
13317 case 3: /* learned then exec. */
13318 break;
13319
13320 case 4: /* exec then learned. */
5ff904cd
JL
13321 break;
13322
13323 default:
c7e4ee3a 13324 assert ("bad hook state" == NULL);
5ff904cd
JL
13325 break;
13326 }
c7e4ee3a
CB
13327#endif
13328}
5ff904cd 13329
c7e4ee3a
CB
13330#endif
13331/* Create temporary gcc label. */
13332
13333#if FFECOM_targetCURRENT == FFECOM_targetGCC
13334tree
13335ffecom_temp_label ()
13336{
13337 tree glabel;
13338 static int mynumber = 0;
13339
13340 glabel = build_decl (LABEL_DECL,
13341 ffecom_get_invented_identifier ("__g77_label_%d",
c7e4ee3a
CB
13342 mynumber++),
13343 void_type_node);
13344 DECL_CONTEXT (glabel) = current_function_decl;
13345 DECL_MODE (glabel) = VOIDmode;
13346
13347 return glabel;
5ff904cd
JL
13348}
13349
13350#endif
c7e4ee3a
CB
13351/* Return an expression that is usable as an arg in a conditional context
13352 (IF, DO WHILE, .NOT., and so on).
13353
13354 Use the one provided for the back end as of >2.6.0. */
5ff904cd
JL
13355
13356#if FFECOM_targetCURRENT == FFECOM_targetGCC
a2977d2d 13357tree
c7e4ee3a 13358ffecom_truth_value (tree expr)
5ff904cd 13359{
c7e4ee3a 13360 return truthvalue_conversion (expr);
5ff904cd 13361}
c7e4ee3a 13362
5ff904cd 13363#endif
c7e4ee3a
CB
13364/* Return the inversion of a truth value (the inversion of what
13365 ffecom_truth_value builds).
5ff904cd 13366
c7e4ee3a
CB
13367 Apparently invert_truthvalue, which is properly in the back end, is
13368 enough for now, so just use it. */
5ff904cd
JL
13369
13370#if FFECOM_targetCURRENT == FFECOM_targetGCC
13371tree
c7e4ee3a 13372ffecom_truth_value_invert (tree expr)
5ff904cd 13373{
c7e4ee3a 13374 return invert_truthvalue (ffecom_truth_value (expr));
5ff904cd
JL
13375}
13376
13377#endif
5ff904cd 13378
c7e4ee3a
CB
13379/* Return the tree that is the type of the expression, as would be
13380 returned in TREE_TYPE(ffecom_expr(expr)), without otherwise
13381 transforming the expression, generating temporaries, etc. */
5ff904cd 13382
c7e4ee3a
CB
13383tree
13384ffecom_type_expr (ffebld expr)
13385{
13386 ffeinfoBasictype bt;
13387 ffeinfoKindtype kt;
13388 tree tree_type;
13389
13390 assert (expr != NULL);
13391
13392 bt = ffeinfo_basictype (ffebld_info (expr));
13393 kt = ffeinfo_kindtype (ffebld_info (expr));
13394 tree_type = ffecom_tree_type[bt][kt];
13395
13396 switch (ffebld_op (expr))
13397 {
13398 case FFEBLD_opCONTER:
13399 case FFEBLD_opSYMTER:
13400 case FFEBLD_opARRAYREF:
13401 case FFEBLD_opUPLUS:
13402 case FFEBLD_opPAREN:
13403 case FFEBLD_opUMINUS:
13404 case FFEBLD_opADD:
13405 case FFEBLD_opSUBTRACT:
13406 case FFEBLD_opMULTIPLY:
13407 case FFEBLD_opDIVIDE:
13408 case FFEBLD_opPOWER:
13409 case FFEBLD_opNOT:
13410 case FFEBLD_opFUNCREF:
13411 case FFEBLD_opSUBRREF:
13412 case FFEBLD_opAND:
13413 case FFEBLD_opOR:
13414 case FFEBLD_opXOR:
13415 case FFEBLD_opNEQV:
13416 case FFEBLD_opEQV:
13417 case FFEBLD_opCONVERT:
13418 case FFEBLD_opLT:
13419 case FFEBLD_opLE:
13420 case FFEBLD_opEQ:
13421 case FFEBLD_opNE:
13422 case FFEBLD_opGT:
13423 case FFEBLD_opGE:
13424 case FFEBLD_opPERCENT_LOC:
13425 return tree_type;
13426
13427 case FFEBLD_opACCTER:
13428 case FFEBLD_opARRTER:
13429 case FFEBLD_opITEM:
13430 case FFEBLD_opSTAR:
13431 case FFEBLD_opBOUNDS:
13432 case FFEBLD_opREPEAT:
13433 case FFEBLD_opLABTER:
13434 case FFEBLD_opLABTOK:
13435 case FFEBLD_opIMPDO:
13436 case FFEBLD_opCONCATENATE:
13437 case FFEBLD_opSUBSTR:
13438 default:
13439 assert ("bad op for ffecom_type_expr" == NULL);
13440 /* Fall through. */
13441 case FFEBLD_opANY:
13442 return error_mark_node;
13443 }
13444}
13445
13446/* Return PARM_DECL for arg#1 of master fn containing alternate ENTRY points
13447
13448 If the PARM_DECL already exists, return it, else create it. It's an
13449 integer_type_node argument for the master function that implements a
13450 subroutine or function with more than one entrypoint and is bound at
13451 run time with the entrypoint number (0 for SUBROUTINE/FUNCTION, 1 for
13452 first ENTRY statement, and so on). */
5ff904cd
JL
13453
13454#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
13455tree
13456ffecom_which_entrypoint_decl ()
5ff904cd 13457{
c7e4ee3a
CB
13458 assert (ffecom_which_entrypoint_decl_ != NULL_TREE);
13459
13460 return ffecom_which_entrypoint_decl_;
5ff904cd
JL
13461}
13462
13463#endif
c7e4ee3a
CB
13464\f
13465/* The following sections consists of private and public functions
13466 that have the same names and perform roughly the same functions
13467 as counterparts in the C front end. Changes in the C front end
13468 might affect how things should be done here. Only functions
13469 needed by the back end should be public here; the rest should
13470 be private (static in the C sense). Functions needed by other
13471 g77 front-end modules should be accessed by them via public
13472 ffecom_* names, which should themselves call private versions
13473 in this section so the private versions are easy to recognize
13474 when upgrading to a new gcc and finding interesting changes
13475 in the front end.
5ff904cd 13476
c7e4ee3a
CB
13477 Functions named after rule "foo:" in c-parse.y are named
13478 "bison_rule_foo_" so they are easy to find. */
5ff904cd 13479
c7e4ee3a 13480#if FFECOM_targetCURRENT == FFECOM_targetGCC
5ff904cd 13481
c7e4ee3a
CB
13482static void
13483bison_rule_pushlevel_ ()
13484{
13485 emit_line_note (input_filename, lineno);
13486 pushlevel (0);
13487 clear_last_expr ();
c7e4ee3a
CB
13488 expand_start_bindings (0);
13489}
5ff904cd 13490
c7e4ee3a
CB
13491static tree
13492bison_rule_compstmt_ ()
5ff904cd 13493{
c7e4ee3a
CB
13494 tree t;
13495 int keep = kept_level_p ();
5ff904cd 13496
c7e4ee3a
CB
13497 /* Make the temps go away. */
13498 if (! keep)
13499 current_binding_level->names = NULL_TREE;
5ff904cd 13500
c7e4ee3a
CB
13501 emit_line_note (input_filename, lineno);
13502 expand_end_bindings (getdecls (), keep, 0);
13503 t = poplevel (keep, 1, 0);
5ff904cd 13504
c7e4ee3a
CB
13505 return t;
13506}
5ff904cd 13507
c7e4ee3a
CB
13508/* Return a definition for a builtin function named NAME and whose data type
13509 is TYPE. TYPE should be a function type with argument types.
13510 FUNCTION_CODE tells later passes how to compile calls to this function.
13511 See tree.h for its possible values.
5ff904cd 13512
c7e4ee3a
CB
13513 If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME,
13514 the name to be called if we can't opencode the function. */
5ff904cd 13515
26db82d8
BS
13516tree
13517builtin_function (const char *name, tree type, int function_code,
13518 enum built_in_class class,
c7e4ee3a
CB
13519 const char *library_name)
13520{
13521 tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
13522 DECL_EXTERNAL (decl) = 1;
13523 TREE_PUBLIC (decl) = 1;
13524 if (library_name)
92643fea 13525 SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name));
3e411c3f 13526 make_decl_rtl (decl, NULL);
c7e4ee3a 13527 pushdecl (decl);
26db82d8
BS
13528 DECL_BUILT_IN_CLASS (decl) = class;
13529 DECL_FUNCTION_CODE (decl) = function_code;
5ff904cd 13530
c7e4ee3a 13531 return decl;
5ff904cd
JL
13532}
13533
c7e4ee3a
CB
13534/* Handle when a new declaration NEWDECL
13535 has the same name as an old one OLDDECL
13536 in the same binding contour.
13537 Prints an error message if appropriate.
5ff904cd 13538
c7e4ee3a
CB
13539 If safely possible, alter OLDDECL to look like NEWDECL, and return 1.
13540 Otherwise, return 0. */
5ff904cd 13541
c7e4ee3a
CB
13542static int
13543duplicate_decls (tree newdecl, tree olddecl)
5ff904cd 13544{
c7e4ee3a
CB
13545 int types_match = 1;
13546 int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
13547 && DECL_INITIAL (newdecl) != 0);
13548 tree oldtype = TREE_TYPE (olddecl);
13549 tree newtype = TREE_TYPE (newdecl);
5ff904cd 13550
c7e4ee3a
CB
13551 if (olddecl == newdecl)
13552 return 1;
5ff904cd 13553
c7e4ee3a
CB
13554 if (TREE_CODE (newtype) == ERROR_MARK
13555 || TREE_CODE (oldtype) == ERROR_MARK)
13556 types_match = 0;
5ff904cd 13557
c7e4ee3a
CB
13558 /* New decl is completely inconsistent with the old one =>
13559 tell caller to replace the old one.
13560 This is always an error except in the case of shadowing a builtin. */
13561 if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
13562 return 0;
5ff904cd 13563
c7e4ee3a
CB
13564 /* For real parm decl following a forward decl,
13565 return 1 so old decl will be reused. */
13566 if (types_match && TREE_CODE (newdecl) == PARM_DECL
13567 && TREE_ASM_WRITTEN (olddecl) && ! TREE_ASM_WRITTEN (newdecl))
13568 return 1;
5ff904cd 13569
c7e4ee3a
CB
13570 /* The new declaration is the same kind of object as the old one.
13571 The declarations may partially match. Print warnings if they don't
13572 match enough. Ultimately, copy most of the information from the new
13573 decl to the old one, and keep using the old one. */
5ff904cd 13574
c7e4ee3a
CB
13575 if (TREE_CODE (olddecl) == FUNCTION_DECL
13576 && DECL_BUILT_IN (olddecl))
13577 {
13578 /* A function declaration for a built-in function. */
13579 if (!TREE_PUBLIC (newdecl))
13580 return 0;
13581 else if (!types_match)
13582 {
13583 /* Accept the return type of the new declaration if same modes. */
13584 tree oldreturntype = TREE_TYPE (TREE_TYPE (olddecl));
13585 tree newreturntype = TREE_TYPE (TREE_TYPE (newdecl));
5ff904cd 13586
c7e4ee3a
CB
13587 if (TYPE_MODE (oldreturntype) == TYPE_MODE (newreturntype))
13588 {
13589 /* Function types may be shared, so we can't just modify
13590 the return type of olddecl's function type. */
13591 tree newtype
13592 = build_function_type (newreturntype,
13593 TYPE_ARG_TYPES (TREE_TYPE (olddecl)));
5ff904cd 13594
c7e4ee3a
CB
13595 types_match = 1;
13596 if (types_match)
13597 TREE_TYPE (olddecl) = newtype;
13598 }
c7e4ee3a
CB
13599 }
13600 if (!types_match)
13601 return 0;
13602 }
13603 else if (TREE_CODE (olddecl) == FUNCTION_DECL
13604 && DECL_SOURCE_LINE (olddecl) == 0)
5ff904cd 13605 {
c7e4ee3a
CB
13606 /* A function declaration for a predeclared function
13607 that isn't actually built in. */
13608 if (!TREE_PUBLIC (newdecl))
13609 return 0;
13610 else if (!types_match)
13611 {
13612 /* If the types don't match, preserve volatility indication.
13613 Later on, we will discard everything else about the
13614 default declaration. */
13615 TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
13616 }
13617 }
5ff904cd 13618
c7e4ee3a
CB
13619 /* Copy all the DECL_... slots specified in the new decl
13620 except for any that we copy here from the old type.
5ff904cd 13621
c7e4ee3a
CB
13622 Past this point, we don't change OLDTYPE and NEWTYPE
13623 even if we change the types of NEWDECL and OLDDECL. */
5ff904cd 13624
c7e4ee3a
CB
13625 if (types_match)
13626 {
c7e4ee3a
CB
13627 /* Merge the data types specified in the two decls. */
13628 if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl))
13629 TREE_TYPE (newdecl)
13630 = TREE_TYPE (olddecl)
13631 = TREE_TYPE (newdecl);
5ff904cd 13632
c7e4ee3a
CB
13633 /* Lay the type out, unless already done. */
13634 if (oldtype != TREE_TYPE (newdecl))
13635 {
13636 if (TREE_TYPE (newdecl) != error_mark_node)
13637 layout_type (TREE_TYPE (newdecl));
13638 if (TREE_CODE (newdecl) != FUNCTION_DECL
13639 && TREE_CODE (newdecl) != TYPE_DECL
13640 && TREE_CODE (newdecl) != CONST_DECL)
13641 layout_decl (newdecl, 0);
13642 }
13643 else
13644 {
13645 /* Since the type is OLDDECL's, make OLDDECL's size go with. */
13646 DECL_SIZE (newdecl) = DECL_SIZE (olddecl);
06ceef4e 13647 DECL_SIZE_UNIT (newdecl) = DECL_SIZE_UNIT (olddecl);
c7e4ee3a
CB
13648 if (TREE_CODE (olddecl) != FUNCTION_DECL)
13649 if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
11cf4d18
JJ
13650 {
13651 DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
13652 DECL_USER_ALIGN (newdecl) |= DECL_USER_ALIGN (olddecl);
13653 }
c7e4ee3a 13654 }
5ff904cd 13655
c7e4ee3a 13656 /* Keep the old rtl since we can safely use it. */
fe01b88e 13657 COPY_DECL_RTL (olddecl, newdecl);
5ff904cd 13658
c7e4ee3a
CB
13659 /* Merge the type qualifiers. */
13660 if (DECL_BUILT_IN_NONANSI (olddecl) && TREE_THIS_VOLATILE (olddecl)
13661 && !TREE_THIS_VOLATILE (newdecl))
13662 TREE_THIS_VOLATILE (olddecl) = 0;
13663 if (TREE_READONLY (newdecl))
13664 TREE_READONLY (olddecl) = 1;
13665 if (TREE_THIS_VOLATILE (newdecl))
13666 {
13667 TREE_THIS_VOLATILE (olddecl) = 1;
13668 if (TREE_CODE (newdecl) == VAR_DECL)
13669 make_var_volatile (newdecl);
13670 }
5ff904cd 13671
c7e4ee3a
CB
13672 /* Keep source location of definition rather than declaration.
13673 Likewise, keep decl at outer scope. */
13674 if ((DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0)
13675 || (DECL_CONTEXT (newdecl) != 0 && DECL_CONTEXT (olddecl) == 0))
13676 {
13677 DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl);
13678 DECL_SOURCE_FILE (newdecl) = DECL_SOURCE_FILE (olddecl);
5ff904cd 13679
c7e4ee3a
CB
13680 if (DECL_CONTEXT (olddecl) == 0
13681 && TREE_CODE (newdecl) != FUNCTION_DECL)
13682 DECL_CONTEXT (newdecl) = 0;
13683 }
5ff904cd 13684
c7e4ee3a
CB
13685 /* Merge the unused-warning information. */
13686 if (DECL_IN_SYSTEM_HEADER (olddecl))
13687 DECL_IN_SYSTEM_HEADER (newdecl) = 1;
13688 else if (DECL_IN_SYSTEM_HEADER (newdecl))
13689 DECL_IN_SYSTEM_HEADER (olddecl) = 1;
5ff904cd 13690
c7e4ee3a
CB
13691 /* Merge the initialization information. */
13692 if (DECL_INITIAL (newdecl) == 0)
13693 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
5ff904cd 13694
c7e4ee3a
CB
13695 /* Merge the section attribute.
13696 We want to issue an error if the sections conflict but that must be
13697 done later in decl_attributes since we are called before attributes
13698 are assigned. */
13699 if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
13700 DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
5ff904cd 13701
c7e4ee3a
CB
13702#if BUILT_FOR_270
13703 if (TREE_CODE (newdecl) == FUNCTION_DECL)
13704 {
13705 DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
13706 DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
13707 }
5ff904cd 13708#endif
c7e4ee3a
CB
13709 }
13710 /* If cannot merge, then use the new type and qualifiers,
13711 and don't preserve the old rtl. */
13712 else
13713 {
13714 TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
13715 TREE_READONLY (olddecl) = TREE_READONLY (newdecl);
13716 TREE_THIS_VOLATILE (olddecl) = TREE_THIS_VOLATILE (newdecl);
13717 TREE_SIDE_EFFECTS (olddecl) = TREE_SIDE_EFFECTS (newdecl);
13718 }
5ff904cd 13719
c7e4ee3a
CB
13720 /* Merge the storage class information. */
13721 /* For functions, static overrides non-static. */
13722 if (TREE_CODE (newdecl) == FUNCTION_DECL)
13723 {
13724 TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl);
13725 /* This is since we don't automatically
13726 copy the attributes of NEWDECL into OLDDECL. */
13727 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
13728 /* If this clears `static', clear it in the identifier too. */
13729 if (! TREE_PUBLIC (olddecl))
13730 TREE_PUBLIC (DECL_NAME (olddecl)) = 0;
13731 }
13732 if (DECL_EXTERNAL (newdecl))
13733 {
13734 TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
13735 DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
13736 /* An extern decl does not override previous storage class. */
13737 TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
13738 }
13739 else
13740 {
13741 TREE_STATIC (olddecl) = TREE_STATIC (newdecl);
13742 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
13743 }
5ff904cd 13744
c7e4ee3a
CB
13745 /* If either decl says `inline', this fn is inline,
13746 unless its definition was passed already. */
13747 if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == 0)
13748 DECL_INLINE (olddecl) = 1;
13749 DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
5ff904cd 13750
c7e4ee3a
CB
13751 /* Get rid of any built-in function if new arg types don't match it
13752 or if we have a function definition. */
13753 if (TREE_CODE (newdecl) == FUNCTION_DECL
13754 && DECL_BUILT_IN (olddecl)
13755 && (!types_match || new_is_definition))
13756 {
13757 TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
26db82d8 13758 DECL_BUILT_IN_CLASS (olddecl) = NOT_BUILT_IN;
c7e4ee3a 13759 }
5ff904cd 13760
c7e4ee3a
CB
13761 /* If redeclaring a builtin function, and not a definition,
13762 it stays built in.
13763 Also preserve various other info from the definition. */
13764 if (TREE_CODE (newdecl) == FUNCTION_DECL && !new_is_definition)
13765 {
13766 if (DECL_BUILT_IN (olddecl))
13767 {
26db82d8 13768 DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
c7e4ee3a
CB
13769 DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
13770 }
5ff904cd 13771
c7e4ee3a
CB
13772 DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
13773 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
13774 DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
13775 DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
13776 }
5ff904cd 13777
c7e4ee3a
CB
13778 /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
13779 But preserve olddecl's DECL_UID. */
13780 {
13781 register unsigned olddecl_uid = DECL_UID (olddecl);
5ff904cd 13782
c7e4ee3a
CB
13783 memcpy ((char *) olddecl + sizeof (struct tree_common),
13784 (char *) newdecl + sizeof (struct tree_common),
13785 sizeof (struct tree_decl) - sizeof (struct tree_common));
13786 DECL_UID (olddecl) = olddecl_uid;
13787 }
5ff904cd 13788
c7e4ee3a 13789 return 1;
5ff904cd
JL
13790}
13791
c7e4ee3a
CB
13792/* Finish processing of a declaration;
13793 install its initial value.
13794 If the length of an array type is not known before,
13795 it must be determined now, from the initial value, or it is an error. */
13796
5ff904cd 13797static void
c7e4ee3a 13798finish_decl (tree decl, tree init, bool is_top_level)
5ff904cd 13799{
c7e4ee3a
CB
13800 register tree type = TREE_TYPE (decl);
13801 int was_incomplete = (DECL_SIZE (decl) == 0);
c7e4ee3a
CB
13802 bool at_top_level = (current_binding_level == global_binding_level);
13803 bool top_level = is_top_level || at_top_level;
5ff904cd 13804
c7e4ee3a
CB
13805 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
13806 level anyway. */
13807 assert (!is_top_level || !at_top_level);
5ff904cd 13808
c7e4ee3a
CB
13809 if (TREE_CODE (decl) == PARM_DECL)
13810 assert (init == NULL_TREE);
13811 /* Remember that PARM_DECL doesn't have a DECL_INITIAL field per se -- it
13812 overlaps DECL_ARG_TYPE. */
13813 else if (init == NULL_TREE)
13814 assert (DECL_INITIAL (decl) == NULL_TREE);
13815 else
13816 assert (DECL_INITIAL (decl) == error_mark_node);
5ff904cd 13817
c7e4ee3a 13818 if (init != NULL_TREE)
5ff904cd 13819 {
c7e4ee3a
CB
13820 if (TREE_CODE (decl) != TYPE_DECL)
13821 DECL_INITIAL (decl) = init;
13822 else
13823 {
13824 /* typedef foo = bar; store the type of bar as the type of foo. */
13825 TREE_TYPE (decl) = TREE_TYPE (init);
13826 DECL_INITIAL (decl) = init = 0;
13827 }
5ff904cd
JL
13828 }
13829
c7e4ee3a 13830 /* Deduce size of array from initialization, if not already known */
5ff904cd 13831
c7e4ee3a
CB
13832 if (TREE_CODE (type) == ARRAY_TYPE
13833 && TYPE_DOMAIN (type) == 0
13834 && TREE_CODE (decl) != TYPE_DECL)
13835 {
13836 assert (top_level);
13837 assert (was_incomplete);
5ff904cd 13838
c7e4ee3a
CB
13839 layout_decl (decl, 0);
13840 }
5ff904cd 13841
c7e4ee3a
CB
13842 if (TREE_CODE (decl) == VAR_DECL)
13843 {
13844 if (DECL_SIZE (decl) == NULL_TREE
13845 && TYPE_SIZE (TREE_TYPE (decl)) != NULL_TREE)
13846 layout_decl (decl, 0);
5ff904cd 13847
c7e4ee3a
CB
13848 if (DECL_SIZE (decl) == NULL_TREE
13849 && (TREE_STATIC (decl)
13850 ?
13851 /* A static variable with an incomplete type is an error if it is
13852 initialized. Also if it is not file scope. Otherwise, let it
13853 through, but if it is not `extern' then it may cause an error
13854 message later. */
13855 (DECL_INITIAL (decl) != 0 || DECL_CONTEXT (decl) != 0)
13856 :
13857 /* An automatic variable with an incomplete type is an error. */
13858 !DECL_EXTERNAL (decl)))
13859 {
13860 assert ("storage size not known" == NULL);
13861 abort ();
13862 }
5ff904cd 13863
c7e4ee3a
CB
13864 if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
13865 && (DECL_SIZE (decl) != 0)
13866 && (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST))
13867 {
13868 assert ("storage size not constant" == NULL);
13869 abort ();
13870 }
13871 }
5ff904cd 13872
c7e4ee3a
CB
13873 /* Output the assembler code and/or RTL code for variables and functions,
13874 unless the type is an undefined structure or union. If not, it will get
13875 done when the type is completed. */
5ff904cd 13876
c7e4ee3a 13877 if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
5ff904cd 13878 {
c7e4ee3a
CB
13879 rest_of_decl_compilation (decl, NULL,
13880 DECL_CONTEXT (decl) == 0,
13881 0);
5ff904cd 13882
c7e4ee3a
CB
13883 if (DECL_CONTEXT (decl) != 0)
13884 {
13885 /* Recompute the RTL of a local array now if it used to be an
13886 incomplete type. */
13887 if (was_incomplete
13888 && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
5ff904cd 13889 {
c7e4ee3a
CB
13890 /* If we used it already as memory, it must stay in memory. */
13891 TREE_ADDRESSABLE (decl) = TREE_USED (decl);
13892 /* If it's still incomplete now, no init will save it. */
13893 if (DECL_SIZE (decl) == 0)
13894 DECL_INITIAL (decl) = 0;
13895 expand_decl (decl);
5ff904cd 13896 }
c7e4ee3a
CB
13897 /* Compute and store the initial value. */
13898 if (TREE_CODE (decl) != FUNCTION_DECL)
13899 expand_decl_init (decl);
13900 }
13901 }
13902 else if (TREE_CODE (decl) == TYPE_DECL)
13903 {
3e411c3f 13904 rest_of_decl_compilation (decl, NULL,
c7e4ee3a
CB
13905 DECL_CONTEXT (decl) == 0,
13906 0);
13907 }
5ff904cd 13908
c7e4ee3a
CB
13909 /* At the end of a declaration, throw away any variable type sizes of types
13910 defined inside that declaration. There is no use computing them in the
13911 following function definition. */
13912 if (current_binding_level == global_binding_level)
13913 get_pending_sizes ();
13914}
5ff904cd 13915
c7e4ee3a
CB
13916/* Finish up a function declaration and compile that function
13917 all the way to assembler language output. The free the storage
13918 for the function definition.
5ff904cd 13919
c7e4ee3a 13920 This is called after parsing the body of the function definition.
5ff904cd 13921
c7e4ee3a
CB
13922 NESTED is nonzero if the function being finished is nested in another. */
13923
13924static void
13925finish_function (int nested)
13926{
13927 register tree fndecl = current_function_decl;
13928
13929 assert (fndecl != NULL_TREE);
13930 if (TREE_CODE (fndecl) != ERROR_MARK)
13931 {
13932 if (nested)
13933 assert (DECL_CONTEXT (fndecl) != NULL_TREE);
5ff904cd 13934 else
c7e4ee3a
CB
13935 assert (DECL_CONTEXT (fndecl) == NULL_TREE);
13936 }
5ff904cd 13937
c7e4ee3a
CB
13938/* TREE_READONLY (fndecl) = 1;
13939 This caused &foo to be of type ptr-to-const-function
13940 which then got a warning when stored in a ptr-to-function variable. */
5ff904cd 13941
c7e4ee3a 13942 poplevel (1, 0, 1);
5ff904cd 13943
c7e4ee3a
CB
13944 if (TREE_CODE (fndecl) != ERROR_MARK)
13945 {
13946 BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
5ff904cd 13947
c7e4ee3a 13948 /* Must mark the RESULT_DECL as being in this function. */
5ff904cd 13949
c7e4ee3a 13950 DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
5ff904cd 13951
c7e4ee3a
CB
13952 /* Obey `register' declarations if `setjmp' is called in this fn. */
13953 /* Generate rtl for function exit. */
13954 expand_function_end (input_filename, lineno, 0);
5ff904cd 13955
7189a4b0
GK
13956 /* If this is a nested function, protect the local variables in the stack
13957 above us from being collected while we're compiling this function. */
1f8f4a0b 13958 if (nested)
7189a4b0
GK
13959 ggc_push_context ();
13960
c7e4ee3a
CB
13961 /* Run the optimizers and output the assembler code for this function. */
13962 rest_of_compilation (fndecl);
7189a4b0
GK
13963
13964 /* Undo the GC context switch. */
1f8f4a0b 13965 if (nested)
7189a4b0 13966 ggc_pop_context ();
c7e4ee3a 13967 }
5ff904cd 13968
c7e4ee3a
CB
13969 if (TREE_CODE (fndecl) != ERROR_MARK
13970 && !nested
13971 && DECL_SAVED_INSNS (fndecl) == 0)
13972 {
13973 /* Stop pointing to the local nodes about to be freed. */
13974 /* But DECL_INITIAL must remain nonzero so we know this was an actual
13975 function definition. */
13976 /* For a nested function, this is done in pop_f_function_context. */
13977 /* If rest_of_compilation set this to 0, leave it 0. */
13978 if (DECL_INITIAL (fndecl) != 0)
13979 DECL_INITIAL (fndecl) = error_mark_node;
13980 DECL_ARGUMENTS (fndecl) = 0;
5ff904cd 13981 }
c7e4ee3a
CB
13982
13983 if (!nested)
5ff904cd 13984 {
c7e4ee3a
CB
13985 /* Let the error reporting routines know that we're outside a function.
13986 For a nested function, this value is used in pop_c_function_context
13987 and then reset via pop_function_context. */
13988 ffecom_outer_function_decl_ = current_function_decl = NULL;
5ff904cd 13989 }
c7e4ee3a 13990}
5ff904cd 13991
c7e4ee3a
CB
13992/* Plug-in replacement for identifying the name of a decl and, for a
13993 function, what we call it in diagnostics. For now, "program unit"
13994 should suffice, since it's a bit of a hassle to figure out which
13995 of several kinds of things it is. Note that it could conceivably
13996 be a statement function, which probably isn't really a program unit
13997 per se, but if that comes up, it should be easy to check (being a
13998 nested function and all). */
13999
4b731ffa 14000static const char *
c7e4ee3a
CB
14001lang_printable_name (tree decl, int v)
14002{
14003 /* Just to keep GCC quiet about the unused variable.
14004 In theory, differing values of V should produce different
14005 output. */
14006 switch (v)
5ff904cd 14007 {
c7e4ee3a
CB
14008 default:
14009 if (TREE_CODE (decl) == ERROR_MARK)
14010 return "erroneous code";
14011 return IDENTIFIER_POINTER (DECL_NAME (decl));
5ff904cd 14012 }
c7e4ee3a
CB
14013}
14014
14015/* g77's function to print out name of current function that caused
14016 an error. */
14017
14018#if BUILT_FOR_270
b0791fa9 14019static void
eae4bce3
TM
14020lang_print_error_function (diagnostic_context *context __attribute__((unused)),
14021 const char *file)
c7e4ee3a
CB
14022{
14023 static ffeglobal last_g = NULL;
14024 static ffesymbol last_s = NULL;
14025 ffeglobal g;
14026 ffesymbol s;
14027 const char *kind;
14028
14029 if ((ffecom_primary_entry_ == NULL)
14030 || (ffesymbol_global (ffecom_primary_entry_) == NULL))
5ff904cd 14031 {
c7e4ee3a
CB
14032 g = NULL;
14033 s = NULL;
14034 kind = NULL;
5ff904cd
JL
14035 }
14036 else
14037 {
c7e4ee3a
CB
14038 g = ffesymbol_global (ffecom_primary_entry_);
14039 if (ffecom_nested_entry_ == NULL)
14040 {
14041 s = ffecom_primary_entry_;
14042 switch (ffesymbol_kind (s))
14043 {
14044 case FFEINFO_kindFUNCTION:
14045 kind = "function";
14046 break;
5ff904cd 14047
c7e4ee3a
CB
14048 case FFEINFO_kindSUBROUTINE:
14049 kind = "subroutine";
14050 break;
5ff904cd 14051
c7e4ee3a
CB
14052 case FFEINFO_kindPROGRAM:
14053 kind = "program";
14054 break;
14055
14056 case FFEINFO_kindBLOCKDATA:
14057 kind = "block-data";
14058 break;
14059
14060 default:
14061 kind = ffeinfo_kind_message (ffesymbol_kind (s));
14062 break;
14063 }
14064 }
14065 else
14066 {
14067 s = ffecom_nested_entry_;
14068 kind = "statement function";
14069 }
5ff904cd
JL
14070 }
14071
c7e4ee3a 14072 if ((last_g != g) || (last_s != s))
5ff904cd 14073 {
c7e4ee3a
CB
14074 if (file)
14075 fprintf (stderr, "%s: ", file);
14076
14077 if (s == NULL)
14078 fprintf (stderr, "Outside of any program unit:\n");
14079 else
5ff904cd 14080 {
c7e4ee3a
CB
14081 const char *name = ffesymbol_text (s);
14082
14083 fprintf (stderr, "In %s `%s':\n", kind, name);
5ff904cd 14084 }
5ff904cd 14085
c7e4ee3a
CB
14086 last_g = g;
14087 last_s = s;
5ff904cd 14088 }
c7e4ee3a
CB
14089}
14090#endif
5ff904cd 14091
c7e4ee3a 14092/* Similar to `lookup_name' but look only at current binding level. */
5ff904cd 14093
c7e4ee3a
CB
14094static tree
14095lookup_name_current_level (tree name)
14096{
14097 register tree t;
5ff904cd 14098
c7e4ee3a
CB
14099 if (current_binding_level == global_binding_level)
14100 return IDENTIFIER_GLOBAL_VALUE (name);
14101
14102 if (IDENTIFIER_LOCAL_VALUE (name) == 0)
14103 return 0;
14104
14105 for (t = current_binding_level->names; t; t = TREE_CHAIN (t))
14106 if (DECL_NAME (t) == name)
14107 break;
14108
14109 return t;
5ff904cd
JL
14110}
14111
c7e4ee3a 14112/* Create a new `struct binding_level'. */
5ff904cd 14113
c7e4ee3a
CB
14114static struct binding_level *
14115make_binding_level ()
5ff904cd 14116{
c7e4ee3a
CB
14117 /* NOSTRICT */
14118 return (struct binding_level *) xmalloc (sizeof (struct binding_level));
14119}
5ff904cd 14120
c7e4ee3a
CB
14121/* Save and restore the variables in this file and elsewhere
14122 that keep track of the progress of compilation of the current function.
14123 Used for nested functions. */
5ff904cd 14124
c7e4ee3a
CB
14125struct f_function
14126{
14127 struct f_function *next;
14128 tree named_labels;
14129 tree shadowed_labels;
14130 struct binding_level *binding_level;
14131};
5ff904cd 14132
c7e4ee3a 14133struct f_function *f_function_chain;
5ff904cd 14134
c7e4ee3a 14135/* Restore the variables used during compilation of a C function. */
5ff904cd 14136
c7e4ee3a
CB
14137static void
14138pop_f_function_context ()
14139{
14140 struct f_function *p = f_function_chain;
14141 tree link;
5ff904cd 14142
c7e4ee3a
CB
14143 /* Bring back all the labels that were shadowed. */
14144 for (link = shadowed_labels; link; link = TREE_CHAIN (link))
14145 if (DECL_NAME (TREE_VALUE (link)) != 0)
14146 IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)))
14147 = TREE_VALUE (link);
5ff904cd 14148
c7e4ee3a
CB
14149 if (current_function_decl != error_mark_node
14150 && DECL_SAVED_INSNS (current_function_decl) == 0)
14151 {
14152 /* Stop pointing to the local nodes about to be freed. */
14153 /* But DECL_INITIAL must remain nonzero so we know this was an actual
14154 function definition. */
14155 DECL_INITIAL (current_function_decl) = error_mark_node;
14156 DECL_ARGUMENTS (current_function_decl) = 0;
5ff904cd
JL
14157 }
14158
c7e4ee3a 14159 pop_function_context ();
5ff904cd 14160
c7e4ee3a 14161 f_function_chain = p->next;
5ff904cd 14162
c7e4ee3a
CB
14163 named_labels = p->named_labels;
14164 shadowed_labels = p->shadowed_labels;
14165 current_binding_level = p->binding_level;
5ff904cd 14166
c7e4ee3a
CB
14167 free (p);
14168}
5ff904cd 14169
c7e4ee3a
CB
14170/* Save and reinitialize the variables
14171 used during compilation of a C function. */
5ff904cd 14172
c7e4ee3a
CB
14173static void
14174push_f_function_context ()
14175{
14176 struct f_function *p
14177 = (struct f_function *) xmalloc (sizeof (struct f_function));
5ff904cd 14178
c7e4ee3a
CB
14179 push_function_context ();
14180
14181 p->next = f_function_chain;
14182 f_function_chain = p;
14183
14184 p->named_labels = named_labels;
14185 p->shadowed_labels = shadowed_labels;
14186 p->binding_level = current_binding_level;
14187}
5ff904cd 14188
c7e4ee3a
CB
14189static void
14190push_parm_decl (tree parm)
14191{
14192 int old_immediate_size_expand = immediate_size_expand;
5ff904cd 14193
c7e4ee3a 14194 /* Don't try computing parm sizes now -- wait till fn is called. */
5ff904cd 14195
c7e4ee3a 14196 immediate_size_expand = 0;
5ff904cd 14197
c7e4ee3a 14198 /* Fill in arg stuff. */
5ff904cd 14199
c7e4ee3a
CB
14200 DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
14201 DECL_ARG_TYPE_AS_WRITTEN (parm) = TREE_TYPE (parm);
14202 TREE_READONLY (parm) = 1; /* All implementation args are read-only. */
5ff904cd 14203
c7e4ee3a
CB
14204 parm = pushdecl (parm);
14205
14206 immediate_size_expand = old_immediate_size_expand;
14207
14208 finish_decl (parm, NULL_TREE, FALSE);
5ff904cd
JL
14209}
14210
c7e4ee3a 14211/* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL, if appropriate. */
5ff904cd 14212
c7e4ee3a
CB
14213static tree
14214pushdecl_top_level (x)
14215 tree x;
14216{
14217 register tree t;
14218 register struct binding_level *b = current_binding_level;
14219 register tree f = current_function_decl;
5ff904cd 14220
c7e4ee3a
CB
14221 current_binding_level = global_binding_level;
14222 current_function_decl = NULL_TREE;
14223 t = pushdecl (x);
14224 current_binding_level = b;
14225 current_function_decl = f;
14226 return t;
14227}
14228
14229/* Store the list of declarations of the current level.
14230 This is done for the parameter declarations of a function being defined,
14231 after they are modified in the light of any missing parameters. */
14232
14233static tree
14234storedecls (decls)
14235 tree decls;
14236{
14237 return current_binding_level->names = decls;
14238}
14239
14240/* Store the parameter declarations into the current function declaration.
14241 This is called after parsing the parameter declarations, before
14242 digesting the body of the function.
14243
14244 For an old-style definition, modify the function's type
14245 to specify at least the number of arguments. */
5ff904cd
JL
14246
14247static void
c7e4ee3a 14248store_parm_decls (int is_main_program UNUSED)
5ff904cd
JL
14249{
14250 register tree fndecl = current_function_decl;
14251
c7e4ee3a
CB
14252 if (fndecl == error_mark_node)
14253 return;
5ff904cd 14254
c7e4ee3a
CB
14255 /* This is a chain of PARM_DECLs from old-style parm declarations. */
14256 DECL_ARGUMENTS (fndecl) = storedecls (nreverse (getdecls ()));
5ff904cd 14257
c7e4ee3a 14258 /* Initialize the RTL code for the function. */
5ff904cd 14259
c7e4ee3a 14260 init_function_start (fndecl, input_filename, lineno);
56a0044b 14261
c7e4ee3a 14262 /* Set up parameters and prepare for return, for the function. */
5ff904cd 14263
c7e4ee3a
CB
14264 expand_function_start (fndecl, 0);
14265}
5ff904cd 14266
c7e4ee3a
CB
14267static tree
14268start_decl (tree decl, bool is_top_level)
14269{
14270 register tree tem;
14271 bool at_top_level = (current_binding_level == global_binding_level);
14272 bool top_level = is_top_level || at_top_level;
5ff904cd 14273
c7e4ee3a
CB
14274 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
14275 level anyway. */
14276 assert (!is_top_level || !at_top_level);
5ff904cd 14277
c7e4ee3a
CB
14278 if (DECL_INITIAL (decl) != NULL_TREE)
14279 {
14280 assert (DECL_INITIAL (decl) == error_mark_node);
14281 assert (!DECL_EXTERNAL (decl));
56a0044b 14282 }
c7e4ee3a
CB
14283 else if (top_level)
14284 assert ((TREE_STATIC (decl) == 1) || DECL_EXTERNAL (decl) == 1);
5ff904cd 14285
c7e4ee3a
CB
14286 /* For Fortran, we by default put things in .common when possible. */
14287 DECL_COMMON (decl) = 1;
5ff904cd 14288
c7e4ee3a
CB
14289 /* Add this decl to the current binding level. TEM may equal DECL or it may
14290 be a previous decl of the same name. */
14291 if (is_top_level)
14292 tem = pushdecl_top_level (decl);
14293 else
14294 tem = pushdecl (decl);
14295
14296 /* For a local variable, define the RTL now. */
14297 if (!top_level
14298 /* But not if this is a duplicate decl and we preserved the rtl from the
14299 previous one (which may or may not happen). */
19e7881c 14300 && !DECL_RTL_SET_P (tem))
5ff904cd 14301 {
c7e4ee3a
CB
14302 if (TYPE_SIZE (TREE_TYPE (tem)) != 0)
14303 expand_decl (tem);
14304 else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
14305 && DECL_INITIAL (tem) != 0)
14306 expand_decl (tem);
5ff904cd
JL
14307 }
14308
c7e4ee3a 14309 return tem;
5ff904cd
JL
14310}
14311
c7e4ee3a
CB
14312/* Create the FUNCTION_DECL for a function definition.
14313 DECLSPECS and DECLARATOR are the parts of the declaration;
14314 they describe the function's name and the type it returns,
14315 but twisted together in a fashion that parallels the syntax of C.
5ff904cd 14316
c7e4ee3a
CB
14317 This function creates a binding context for the function body
14318 as well as setting up the FUNCTION_DECL in current_function_decl.
5ff904cd 14319
c7e4ee3a
CB
14320 Returns 1 on success. If the DECLARATOR is not suitable for a function
14321 (it defines a datum instead), we return 0, which tells
14322 yyparse to report a parse error.
5ff904cd 14323
c7e4ee3a
CB
14324 NESTED is nonzero for a function nested within another function. */
14325
14326static void
14327start_function (tree name, tree type, int nested, int public)
5ff904cd 14328{
c7e4ee3a
CB
14329 tree decl1;
14330 tree restype;
14331 int old_immediate_size_expand = immediate_size_expand;
5ff904cd 14332
c7e4ee3a
CB
14333 named_labels = 0;
14334 shadowed_labels = 0;
14335
14336 /* Don't expand any sizes in the return type of the function. */
14337 immediate_size_expand = 0;
14338
14339 if (nested)
5ff904cd 14340 {
c7e4ee3a
CB
14341 assert (!public);
14342 assert (current_function_decl != NULL_TREE);
14343 assert (DECL_CONTEXT (current_function_decl) == NULL_TREE);
14344 }
14345 else
14346 {
14347 assert (current_function_decl == NULL_TREE);
5ff904cd 14348 }
c7e4ee3a
CB
14349
14350 if (TREE_CODE (type) == ERROR_MARK)
14351 decl1 = current_function_decl = error_mark_node;
56a0044b 14352 else
5ff904cd 14353 {
c7e4ee3a
CB
14354 decl1 = build_decl (FUNCTION_DECL,
14355 name,
14356 type);
14357 TREE_PUBLIC (decl1) = public ? 1 : 0;
14358 if (nested)
14359 DECL_INLINE (decl1) = 1;
14360 TREE_STATIC (decl1) = 1;
14361 DECL_EXTERNAL (decl1) = 0;
5ff904cd 14362
c7e4ee3a 14363 announce_function (decl1);
5ff904cd 14364
c7e4ee3a
CB
14365 /* Make the init_value nonzero so pushdecl knows this is not tentative.
14366 error_mark_node is replaced below (in poplevel) with the BLOCK. */
14367 DECL_INITIAL (decl1) = error_mark_node;
5ff904cd 14368
c7e4ee3a
CB
14369 /* Record the decl so that the function name is defined. If we already have
14370 a decl for this name, and it is a FUNCTION_DECL, use the old decl. */
5ff904cd 14371
c7e4ee3a 14372 current_function_decl = pushdecl (decl1);
5ff904cd
JL
14373 }
14374
c7e4ee3a
CB
14375 if (!nested)
14376 ffecom_outer_function_decl_ = current_function_decl;
5ff904cd 14377
c7e4ee3a
CB
14378 pushlevel (0);
14379 current_binding_level->prep_state = 2;
5ff904cd 14380
c7e4ee3a
CB
14381 if (TREE_CODE (current_function_decl) != ERROR_MARK)
14382 {
6c418184 14383 make_decl_rtl (current_function_decl, NULL);
5ff904cd 14384
c7e4ee3a
CB
14385 restype = TREE_TYPE (TREE_TYPE (current_function_decl));
14386 DECL_RESULT (current_function_decl)
14387 = build_decl (RESULT_DECL, NULL_TREE, restype);
5ff904cd 14388 }
5ff904cd 14389
c7e4ee3a
CB
14390 if (!nested && (TREE_CODE (current_function_decl) != ERROR_MARK))
14391 TREE_ADDRESSABLE (current_function_decl) = 1;
14392
14393 immediate_size_expand = old_immediate_size_expand;
14394}
14395\f
14396/* Here are the public functions the GNU back end needs. */
14397
14398tree
14399convert (type, expr)
14400 tree type, expr;
5ff904cd 14401{
c7e4ee3a
CB
14402 register tree e = expr;
14403 register enum tree_code code = TREE_CODE (type);
5ff904cd 14404
c7e4ee3a
CB
14405 if (type == TREE_TYPE (e)
14406 || TREE_CODE (e) == ERROR_MARK)
14407 return e;
14408 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
14409 return fold (build1 (NOP_EXPR, type, e));
14410 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
14411 || code == ERROR_MARK)
14412 return error_mark_node;
14413 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
14414 {
14415 assert ("void value not ignored as it ought to be" == NULL);
14416 return error_mark_node;
14417 }
14418 if (code == VOID_TYPE)
14419 return build1 (CONVERT_EXPR, type, e);
14420 if ((code != RECORD_TYPE)
14421 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
14422 e = ffecom_1 (REALPART_EXPR, TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e))),
14423 e);
14424 if (code == INTEGER_TYPE || code == ENUMERAL_TYPE)
14425 return fold (convert_to_integer (type, e));
14426 if (code == POINTER_TYPE)
14427 return fold (convert_to_pointer (type, e));
14428 if (code == REAL_TYPE)
14429 return fold (convert_to_real (type, e));
14430 if (code == COMPLEX_TYPE)
14431 return fold (convert_to_complex (type, e));
14432 if (code == RECORD_TYPE)
14433 return fold (ffecom_convert_to_complex_ (type, e));
5ff904cd 14434
c7e4ee3a
CB
14435 assert ("conversion to non-scalar type requested" == NULL);
14436 return error_mark_node;
14437}
5ff904cd 14438
c7e4ee3a
CB
14439/* integrate_decl_tree calls this function, but since we don't use the
14440 DECL_LANG_SPECIFIC field, this is a no-op. */
5ff904cd 14441
c7e4ee3a
CB
14442void
14443copy_lang_decl (node)
14444 tree node UNUSED;
14445{
5ff904cd
JL
14446}
14447
c7e4ee3a
CB
14448/* Return the list of declarations of the current level.
14449 Note that this list is in reverse order unless/until
14450 you nreverse it; and when you do nreverse it, you must
14451 store the result back using `storedecls' or you will lose. */
5ff904cd 14452
c7e4ee3a
CB
14453tree
14454getdecls ()
5ff904cd 14455{
c7e4ee3a 14456 return current_binding_level->names;
5ff904cd
JL
14457}
14458
c7e4ee3a 14459/* Nonzero if we are currently in the global binding level. */
5ff904cd 14460
c7e4ee3a
CB
14461int
14462global_bindings_p ()
5ff904cd 14463{
c7e4ee3a
CB
14464 return current_binding_level == global_binding_level;
14465}
5ff904cd 14466
c7e4ee3a
CB
14467/* Print an error message for invalid use of an incomplete type.
14468 VALUE is the expression that was used (or 0 if that isn't known)
14469 and TYPE is the type that was invalid. */
5ff904cd 14470
c7e4ee3a
CB
14471void
14472incomplete_type_error (value, type)
14473 tree value UNUSED;
14474 tree type;
14475{
14476 if (TREE_CODE (type) == ERROR_MARK)
14477 return;
5ff904cd 14478
c7e4ee3a
CB
14479 assert ("incomplete type?!?" == NULL);
14480}
14481
7189a4b0
GK
14482/* Mark ARG for GC. */
14483static void
54551044 14484mark_binding_level (void *arg)
7189a4b0
GK
14485{
14486 struct binding_level *level = *(struct binding_level **) arg;
14487
14488 while (level)
14489 {
14490 ggc_mark_tree (level->names);
14491 ggc_mark_tree (level->blocks);
14492 ggc_mark_tree (level->this_block);
14493 level = level->level_chain;
14494 }
14495}
14496
c7e4ee3a
CB
14497void
14498init_decl_processing ()
5ff904cd 14499{
7189a4b0
GK
14500 static tree *const tree_roots[] = {
14501 &current_function_decl,
14502 &string_type_node,
14503 &ffecom_tree_fun_type_void,
14504 &ffecom_integer_zero_node,
14505 &ffecom_integer_one_node,
14506 &ffecom_tree_subr_type,
14507 &ffecom_tree_ptr_to_subr_type,
14508 &ffecom_tree_blockdata_type,
14509 &ffecom_tree_xargc_,
14510 &ffecom_f2c_integer_type_node,
14511 &ffecom_f2c_ptr_to_integer_type_node,
14512 &ffecom_f2c_address_type_node,
14513 &ffecom_f2c_real_type_node,
14514 &ffecom_f2c_ptr_to_real_type_node,
14515 &ffecom_f2c_doublereal_type_node,
14516 &ffecom_f2c_complex_type_node,
14517 &ffecom_f2c_doublecomplex_type_node,
14518 &ffecom_f2c_longint_type_node,
14519 &ffecom_f2c_logical_type_node,
14520 &ffecom_f2c_flag_type_node,
14521 &ffecom_f2c_ftnlen_type_node,
14522 &ffecom_f2c_ftnlen_zero_node,
14523 &ffecom_f2c_ftnlen_one_node,
14524 &ffecom_f2c_ftnlen_two_node,
14525 &ffecom_f2c_ptr_to_ftnlen_type_node,
14526 &ffecom_f2c_ftnint_type_node,
14527 &ffecom_f2c_ptr_to_ftnint_type_node,
14528 &ffecom_outer_function_decl_,
14529 &ffecom_previous_function_decl_,
14530 &ffecom_which_entrypoint_decl_,
14531 &ffecom_float_zero_,
14532 &ffecom_float_half_,
14533 &ffecom_double_zero_,
14534 &ffecom_double_half_,
14535 &ffecom_func_result_,
14536 &ffecom_func_length_,
14537 &ffecom_multi_type_node_,
14538 &ffecom_multi_retval_,
14539 &named_labels,
14540 &shadowed_labels
14541 };
14542 size_t i;
14543
c7e4ee3a 14544 malloc_init ();
7189a4b0
GK
14545
14546 /* Record our roots. */
75ff2ca7 14547 for (i = 0; i < ARRAY_SIZE (tree_roots); i++)
7189a4b0
GK
14548 ggc_add_tree_root (tree_roots[i], 1);
14549 ggc_add_tree_root (&ffecom_tree_type[0][0],
14550 FFEINFO_basictype*FFEINFO_kindtype);
14551 ggc_add_tree_root (&ffecom_tree_fun_type[0][0],
14552 FFEINFO_basictype*FFEINFO_kindtype);
14553 ggc_add_tree_root (&ffecom_tree_ptr_to_fun_type[0][0],
14554 FFEINFO_basictype*FFEINFO_kindtype);
14555 ggc_add_tree_root (ffecom_gfrt_, FFECOM_gfrt);
14556 ggc_add_root (&current_binding_level, 1, sizeof current_binding_level,
14557 mark_binding_level);
14558 ggc_add_root (&free_binding_level, 1, sizeof current_binding_level,
14559 mark_binding_level);
14560 ggc_add_root (&tracker_head, 1, sizeof tracker_head, mark_tracker_head);
14561
c7e4ee3a
CB
14562 ffe_init_0 ();
14563}
5ff904cd 14564
3b304f5b 14565const char *
c7e4ee3a 14566init_parse (filename)
3b304f5b 14567 const char *filename;
c7e4ee3a 14568{
c7e4ee3a
CB
14569 /* Open input file. */
14570 if (filename == 0 || !strcmp (filename, "-"))
5ff904cd 14571 {
c7e4ee3a
CB
14572 finput = stdin;
14573 filename = "stdin";
5ff904cd 14574 }
c7e4ee3a
CB
14575 else
14576 finput = fopen (filename, "r");
14577 if (finput == 0)
400500c4 14578 fatal_io_error ("can't open %s", filename);
5ff904cd 14579
c7e4ee3a
CB
14580#ifdef IO_BUFFER_SIZE
14581 setvbuf (finput, (char *) xmalloc (IO_BUFFER_SIZE), _IOFBF, IO_BUFFER_SIZE);
14582#endif
5ff904cd 14583
c7e4ee3a
CB
14584 /* Make identifier nodes long enough for the language-specific slots. */
14585 set_identifier_size (sizeof (struct lang_identifier));
14586 decl_printable_name = lang_printable_name;
14587#if BUILT_FOR_270
14588 print_error_function = lang_print_error_function;
14589#endif
5ff904cd 14590
c7e4ee3a
CB
14591 return filename;
14592}
5ff904cd 14593
c7e4ee3a
CB
14594void
14595finish_parse ()
14596{
14597 fclose (finput);
14598}
14599
14600/* Delete the node BLOCK from the current binding level.
14601 This is used for the block inside a stmt expr ({...})
14602 so that the block can be reinserted where appropriate. */
14603
14604static void
14605delete_block (block)
14606 tree block;
14607{
14608 tree t;
14609 if (current_binding_level->blocks == block)
14610 current_binding_level->blocks = TREE_CHAIN (block);
14611 for (t = current_binding_level->blocks; t;)
14612 {
14613 if (TREE_CHAIN (t) == block)
14614 TREE_CHAIN (t) = TREE_CHAIN (block);
14615 else
14616 t = TREE_CHAIN (t);
14617 }
14618 TREE_CHAIN (block) = NULL;
14619 /* Clear TREE_USED which is always set by poplevel.
14620 The flag is set again if insert_block is called. */
14621 TREE_USED (block) = 0;
14622}
14623
14624void
14625insert_block (block)
14626 tree block;
14627{
14628 TREE_USED (block) = 1;
14629 current_binding_level->blocks
14630 = chainon (current_binding_level->blocks, block);
14631}
14632
cd2a3ba2 14633/* Each front end provides its own. */
ee811cfd
NB
14634static void ffe_init PARAMS ((void));
14635static void ffe_finish PARAMS ((void));
14636static void ffe_init_options PARAMS ((void));
14637
17ed6335
RH
14638#undef LANG_HOOKS_INIT
14639#define LANG_HOOKS_INIT ffe_init
14640#undef LANG_HOOKS_FINISH
14641#define LANG_HOOKS_FINISH ffe_finish
14642#undef LANG_HOOKS_INIT_OPTIONS
14643#define LANG_HOOKS_INIT_OPTIONS ffe_init_options
14644#undef LANG_HOOKS_DECODE_OPTION
14645#define LANG_HOOKS_DECODE_OPTION ffe_decode_option
14646
14647struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
cd2a3ba2 14648
c7e4ee3a 14649/* used by print-tree.c */
5ff904cd 14650
c7e4ee3a
CB
14651void
14652lang_print_xnode (file, node, indent)
14653 FILE *file UNUSED;
14654 tree node UNUSED;
14655 int indent UNUSED;
5ff904cd 14656{
c7e4ee3a 14657}
5ff904cd 14658
13c61421 14659static void
ee811cfd 14660ffe_finish ()
c7e4ee3a
CB
14661{
14662 ffe_terminate_0 ();
5ff904cd 14663
c7e4ee3a
CB
14664 if (ffe_is_ffedebug ())
14665 malloc_pool_display (malloc_pool_image ());
5ff904cd
JL
14666}
14667
dafbd854 14668const char *
c7e4ee3a 14669lang_identify ()
5ff904cd 14670{
c7e4ee3a
CB
14671 return "f77";
14672}
5ff904cd 14673
2e761e49
RH
14674/* Return the typed-based alias set for T, which may be an expression
14675 or a type. Return -1 if we don't do anything special. */
14676
14677HOST_WIDE_INT
14678lang_get_alias_set (t)
5ac9118e 14679 tree t ATTRIBUTE_UNUSED;
2e761e49
RH
14680{
14681 /* We do not wish to use alias-set based aliasing at all. Used in the
14682 extreme (every object with its own set, with equivalences recorded)
14683 it might be helpful, but there are problems when it comes to inlining.
14684 We get on ok with flag_argument_noalias, and alias-set aliasing does
14685 currently limit how stack slots can be reused, which is a lose. */
14686 return 0;
14687}
14688
ee811cfd
NB
14689static void
14690ffe_init_options ()
c7e4ee3a
CB
14691{
14692 /* Set default options for Fortran. */
14693 flag_move_all_movables = 1;
14694 flag_reduce_all_givs = 1;
14695 flag_argument_noalias = 2;
201556f0 14696 flag_merge_constants = 2;
41af162c 14697 flag_errno_math = 0;
c64f913e 14698 flag_complex_divide_method = 1;
c7e4ee3a 14699}
5ff904cd 14700
13c61421 14701static void
ee811cfd 14702ffe_init ()
c7e4ee3a
CB
14703{
14704 /* If the file is output from cpp, it should contain a first line
14705 `# 1 "real-filename"', and the current design of gcc (toplev.c
14706 in particular and the way it sets up information relied on by
14707 INCLUDE) requires that we read this now, and store the
14708 "real-filename" info in master_input_filename. Ask the lexer
14709 to try doing this. */
14710 ffelex_hash_kludge (finput);
14711}
5ff904cd 14712
c7e4ee3a
CB
14713int
14714mark_addressable (exp)
14715 tree exp;
14716{
14717 register tree x = exp;
14718 while (1)
14719 switch (TREE_CODE (x))
14720 {
14721 case ADDR_EXPR:
14722 case COMPONENT_REF:
14723 case ARRAY_REF:
14724 x = TREE_OPERAND (x, 0);
14725 break;
5ff904cd 14726
c7e4ee3a
CB
14727 case CONSTRUCTOR:
14728 TREE_ADDRESSABLE (x) = 1;
14729 return 1;
5ff904cd 14730
c7e4ee3a
CB
14731 case VAR_DECL:
14732 case CONST_DECL:
14733 case PARM_DECL:
14734 case RESULT_DECL:
14735 if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x)
14736 && DECL_NONLOCAL (x))
14737 {
14738 if (TREE_PUBLIC (x))
14739 {
14740 assert ("address of global register var requested" == NULL);
14741 return 0;
14742 }
14743 assert ("address of register variable requested" == NULL);
14744 }
14745 else if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x))
14746 {
14747 if (TREE_PUBLIC (x))
14748 {
14749 assert ("address of global register var requested" == NULL);
14750 return 0;
14751 }
14752 assert ("address of register var requested" == NULL);
14753 }
14754 put_var_into_stack (x);
5ff904cd 14755
c7e4ee3a
CB
14756 /* drops in */
14757 case FUNCTION_DECL:
14758 TREE_ADDRESSABLE (x) = 1;
14759#if 0 /* poplevel deals with this now. */
14760 if (DECL_CONTEXT (x) == 0)
14761 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;
14762#endif
5ff904cd 14763
c7e4ee3a
CB
14764 default:
14765 return 1;
14766 }
5ff904cd
JL
14767}
14768
c7e4ee3a
CB
14769/* If DECL has a cleanup, build and return that cleanup here.
14770 This is a callback called by expand_expr. */
5ff904cd 14771
c7e4ee3a
CB
14772tree
14773maybe_build_cleanup (decl)
14774 tree decl UNUSED;
5ff904cd 14775{
c7e4ee3a
CB
14776 /* There are no cleanups in Fortran. */
14777 return NULL_TREE;
5ff904cd
JL
14778}
14779
c7e4ee3a
CB
14780/* Exit a binding level.
14781 Pop the level off, and restore the state of the identifier-decl mappings
14782 that were in effect when this level was entered.
5ff904cd 14783
c7e4ee3a
CB
14784 If KEEP is nonzero, this level had explicit declarations, so
14785 and create a "block" (a BLOCK node) for the level
14786 to record its declarations and subblocks for symbol table output.
5ff904cd 14787
c7e4ee3a
CB
14788 If FUNCTIONBODY is nonzero, this level is the body of a function,
14789 so create a block as if KEEP were set and also clear out all
14790 label names.
5ff904cd 14791
c7e4ee3a
CB
14792 If REVERSE is nonzero, reverse the order of decls before putting
14793 them into the BLOCK. */
5ff904cd 14794
c7e4ee3a
CB
14795tree
14796poplevel (keep, reverse, functionbody)
14797 int keep;
14798 int reverse;
14799 int functionbody;
5ff904cd 14800{
c7e4ee3a
CB
14801 register tree link;
14802 /* The chain of decls was accumulated in reverse order.
14803 Put it into forward order, just for cleanliness. */
14804 tree decls;
14805 tree subblocks = current_binding_level->blocks;
14806 tree block = 0;
14807 tree decl;
14808 int block_previously_created;
5ff904cd 14809
c7e4ee3a
CB
14810 /* Get the decls in the order they were written.
14811 Usually current_binding_level->names is in reverse order.
14812 But parameter decls were previously put in forward order. */
702edf1d 14813
c7e4ee3a
CB
14814 if (reverse)
14815 current_binding_level->names
14816 = decls = nreverse (current_binding_level->names);
14817 else
14818 decls = current_binding_level->names;
5ff904cd 14819
c7e4ee3a
CB
14820 /* Output any nested inline functions within this block
14821 if they weren't already output. */
5ff904cd 14822
c7e4ee3a
CB
14823 for (decl = decls; decl; decl = TREE_CHAIN (decl))
14824 if (TREE_CODE (decl) == FUNCTION_DECL
14825 && ! TREE_ASM_WRITTEN (decl)
14826 && DECL_INITIAL (decl) != 0
14827 && TREE_ADDRESSABLE (decl))
14828 {
14829 /* If this decl was copied from a file-scope decl
14830 on account of a block-scope extern decl,
14831 propagate TREE_ADDRESSABLE to the file-scope decl.
14832
14833 DECL_ABSTRACT_ORIGIN can be set to itself if warn_return_type is
14834 true, since then the decl goes through save_for_inline_copying. */
14835 if (DECL_ABSTRACT_ORIGIN (decl) != 0
14836 && DECL_ABSTRACT_ORIGIN (decl) != decl)
14837 TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
14838 else if (DECL_SAVED_INSNS (decl) != 0)
14839 {
14840 push_function_context ();
14841 output_inline_function (decl);
14842 pop_function_context ();
14843 }
14844 }
5ff904cd 14845
c7e4ee3a
CB
14846 /* If there were any declarations or structure tags in that level,
14847 or if this level is a function body,
14848 create a BLOCK to record them for the life of this function. */
5ff904cd 14849
c7e4ee3a
CB
14850 block = 0;
14851 block_previously_created = (current_binding_level->this_block != 0);
14852 if (block_previously_created)
14853 block = current_binding_level->this_block;
14854 else if (keep || functionbody)
14855 block = make_node (BLOCK);
14856 if (block != 0)
14857 {
14858 BLOCK_VARS (block) = decls;
14859 BLOCK_SUBBLOCKS (block) = subblocks;
c7e4ee3a 14860 }
5ff904cd 14861
c7e4ee3a 14862 /* In each subblock, record that this is its superior. */
5ff904cd 14863
c7e4ee3a
CB
14864 for (link = subblocks; link; link = TREE_CHAIN (link))
14865 BLOCK_SUPERCONTEXT (link) = block;
5ff904cd 14866
c7e4ee3a 14867 /* Clear out the meanings of the local variables of this level. */
5ff904cd 14868
c7e4ee3a 14869 for (link = decls; link; link = TREE_CHAIN (link))
5ff904cd 14870 {
c7e4ee3a
CB
14871 if (DECL_NAME (link) != 0)
14872 {
14873 /* If the ident. was used or addressed via a local extern decl,
14874 don't forget that fact. */
14875 if (DECL_EXTERNAL (link))
14876 {
14877 if (TREE_USED (link))
14878 TREE_USED (DECL_NAME (link)) = 1;
14879 if (TREE_ADDRESSABLE (link))
14880 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1;
14881 }
14882 IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = 0;
14883 }
5ff904cd 14884 }
5ff904cd 14885
c7e4ee3a
CB
14886 /* If the level being exited is the top level of a function,
14887 check over all the labels, and clear out the current
14888 (function local) meanings of their names. */
5ff904cd 14889
c7e4ee3a 14890 if (functionbody)
5ff904cd 14891 {
c7e4ee3a
CB
14892 /* If this is the top level block of a function,
14893 the vars are the function's parameters.
14894 Don't leave them in the BLOCK because they are
14895 found in the FUNCTION_DECL instead. */
14896
14897 BLOCK_VARS (block) = 0;
5ff904cd
JL
14898 }
14899
c7e4ee3a
CB
14900 /* Pop the current level, and free the structure for reuse. */
14901
14902 {
14903 register struct binding_level *level = current_binding_level;
14904 current_binding_level = current_binding_level->level_chain;
14905
14906 level->level_chain = free_binding_level;
14907 free_binding_level = level;
14908 }
14909
14910 /* Dispose of the block that we just made inside some higher level. */
14911 if (functionbody
14912 && current_function_decl != error_mark_node)
14913 DECL_INITIAL (current_function_decl) = block;
14914 else if (block)
5ff904cd 14915 {
c7e4ee3a
CB
14916 if (!block_previously_created)
14917 current_binding_level->blocks
14918 = chainon (current_binding_level->blocks, block);
5ff904cd 14919 }
c7e4ee3a
CB
14920 /* If we did not make a block for the level just exited,
14921 any blocks made for inner levels
14922 (since they cannot be recorded as subblocks in that level)
14923 must be carried forward so they will later become subblocks
14924 of something else. */
14925 else if (subblocks)
14926 current_binding_level->blocks
14927 = chainon (current_binding_level->blocks, subblocks);
5ff904cd 14928
c7e4ee3a
CB
14929 if (block)
14930 TREE_USED (block) = 1;
14931 return block;
5ff904cd
JL
14932}
14933
c7e4ee3a
CB
14934void
14935print_lang_decl (file, node, indent)
14936 FILE *file UNUSED;
14937 tree node UNUSED;
14938 int indent UNUSED;
14939{
14940}
5ff904cd 14941
c7e4ee3a
CB
14942void
14943print_lang_identifier (file, node, indent)
14944 FILE *file;
14945 tree node;
14946 int indent;
14947{
14948 print_node (file, "global", IDENTIFIER_GLOBAL_VALUE (node), indent + 4);
14949 print_node (file, "local", IDENTIFIER_LOCAL_VALUE (node), indent + 4);
14950}
5ff904cd 14951
c7e4ee3a
CB
14952void
14953print_lang_statistics ()
14954{
14955}
5ff904cd 14956
c7e4ee3a
CB
14957void
14958print_lang_type (file, node, indent)
14959 FILE *file UNUSED;
14960 tree node UNUSED;
14961 int indent UNUSED;
5ff904cd 14962{
c7e4ee3a 14963}
5ff904cd 14964
c7e4ee3a
CB
14965/* Record a decl-node X as belonging to the current lexical scope.
14966 Check for errors (such as an incompatible declaration for the same
14967 name already seen in the same scope).
5ff904cd 14968
c7e4ee3a
CB
14969 Returns either X or an old decl for the same name.
14970 If an old decl is returned, it may have been smashed
14971 to agree with what X says. */
5ff904cd 14972
c7e4ee3a
CB
14973tree
14974pushdecl (x)
14975 tree x;
14976{
14977 register tree t;
14978 register tree name = DECL_NAME (x);
14979 register struct binding_level *b = current_binding_level;
5ff904cd 14980
c7e4ee3a
CB
14981 if ((TREE_CODE (x) == FUNCTION_DECL)
14982 && (DECL_INITIAL (x) == 0)
14983 && DECL_EXTERNAL (x))
14984 DECL_CONTEXT (x) = NULL_TREE;
56a0044b 14985 else
c7e4ee3a
CB
14986 DECL_CONTEXT (x) = current_function_decl;
14987
14988 if (name)
56a0044b 14989 {
c7e4ee3a
CB
14990 if (IDENTIFIER_INVENTED (name))
14991 {
14992#if BUILT_FOR_270
14993 DECL_ARTIFICIAL (x) = 1;
14994#endif
14995 DECL_IN_SYSTEM_HEADER (x) = 1;
14996 }
5ff904cd 14997
c7e4ee3a 14998 t = lookup_name_current_level (name);
5ff904cd 14999
c7e4ee3a 15000 assert ((t == NULL_TREE) || (DECL_CONTEXT (x) == NULL_TREE));
5ff904cd 15001
c7e4ee3a
CB
15002 /* Don't push non-parms onto list for parms until we understand
15003 why we're doing this and whether it works. */
56a0044b 15004
c7e4ee3a
CB
15005 assert ((b == global_binding_level)
15006 || !ffecom_transform_only_dummies_
15007 || TREE_CODE (x) == PARM_DECL);
5ff904cd 15008
c7e4ee3a
CB
15009 if ((t != NULL_TREE) && duplicate_decls (x, t))
15010 return t;
5ff904cd 15011
c7e4ee3a
CB
15012 /* If we are processing a typedef statement, generate a whole new
15013 ..._TYPE node (which will be just an variant of the existing
15014 ..._TYPE node with identical properties) and then install the
15015 TYPE_DECL node generated to represent the typedef name as the
15016 TYPE_NAME of this brand new (duplicate) ..._TYPE node.
5ff904cd 15017
c7e4ee3a
CB
15018 The whole point here is to end up with a situation where each and every
15019 ..._TYPE node the compiler creates will be uniquely associated with
15020 AT MOST one node representing a typedef name. This way, even though
15021 the compiler substitutes corresponding ..._TYPE nodes for TYPE_DECL
15022 (i.e. "typedef name") nodes very early on, later parts of the
15023 compiler can always do the reverse translation and get back the
15024 corresponding typedef name. For example, given:
5ff904cd 15025
c7e4ee3a 15026 typedef struct S MY_TYPE; MY_TYPE object;
5ff904cd 15027
c7e4ee3a
CB
15028 Later parts of the compiler might only know that `object' was of type
15029 `struct S' if it were not for code just below. With this code
15030 however, later parts of the compiler see something like:
5ff904cd 15031
c7e4ee3a 15032 struct S' == struct S typedef struct S' MY_TYPE; struct S' object;
5ff904cd 15033
c7e4ee3a
CB
15034 And they can then deduce (from the node for type struct S') that the
15035 original object declaration was:
5ff904cd 15036
c7e4ee3a 15037 MY_TYPE object;
5ff904cd 15038
c7e4ee3a
CB
15039 Being able to do this is important for proper support of protoize, and
15040 also for generating precise symbolic debugging information which
15041 takes full account of the programmer's (typedef) vocabulary.
5ff904cd 15042
c7e4ee3a
CB
15043 Obviously, we don't want to generate a duplicate ..._TYPE node if the
15044 TYPE_DECL node that we are now processing really represents a
15045 standard built-in type.
5ff904cd 15046
c7e4ee3a
CB
15047 Since all standard types are effectively declared at line zero in the
15048 source file, we can easily check to see if we are working on a
15049 standard type by checking the current value of lineno. */
15050
15051 if (TREE_CODE (x) == TYPE_DECL)
15052 {
15053 if (DECL_SOURCE_LINE (x) == 0)
15054 {
15055 if (TYPE_NAME (TREE_TYPE (x)) == 0)
15056 TYPE_NAME (TREE_TYPE (x)) = x;
15057 }
15058 else if (TREE_TYPE (x) != error_mark_node)
15059 {
15060 tree tt = TREE_TYPE (x);
15061
15062 tt = build_type_copy (tt);
15063 TYPE_NAME (tt) = x;
15064 TREE_TYPE (x) = tt;
15065 }
15066 }
5ff904cd 15067
c7e4ee3a
CB
15068 /* This name is new in its binding level. Install the new declaration
15069 and return it. */
15070 if (b == global_binding_level)
15071 IDENTIFIER_GLOBAL_VALUE (name) = x;
15072 else
15073 IDENTIFIER_LOCAL_VALUE (name) = x;
15074 }
5ff904cd 15075
c7e4ee3a
CB
15076 /* Put decls on list in reverse order. We will reverse them later if
15077 necessary. */
15078 TREE_CHAIN (x) = b->names;
15079 b->names = x;
5ff904cd 15080
c7e4ee3a 15081 return x;
5ff904cd
JL
15082}
15083
c7e4ee3a 15084/* Nonzero if the current level needs to have a BLOCK made. */
5ff904cd 15085
c7e4ee3a
CB
15086static int
15087kept_level_p ()
5ff904cd 15088{
c7e4ee3a
CB
15089 tree decl;
15090
15091 for (decl = current_binding_level->names;
15092 decl;
15093 decl = TREE_CHAIN (decl))
15094 {
15095 if (TREE_USED (decl) || TREE_CODE (decl) != VAR_DECL
15096 || (DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl)))
15097 /* Currently, there aren't supposed to be non-artificial names
15098 at other than the top block for a function -- they're
15099 believed to always be temps. But it's wise to check anyway. */
15100 return 1;
15101 }
15102 return 0;
5ff904cd
JL
15103}
15104
c7e4ee3a
CB
15105/* Enter a new binding level.
15106 If TAG_TRANSPARENT is nonzero, do so only for the name space of variables,
15107 not for that of tags. */
5ff904cd
JL
15108
15109void
c7e4ee3a
CB
15110pushlevel (tag_transparent)
15111 int tag_transparent;
5ff904cd 15112{
c7e4ee3a 15113 register struct binding_level *newlevel = NULL_BINDING_LEVEL;
5ff904cd 15114
c7e4ee3a 15115 assert (! tag_transparent);
5ff904cd 15116
c7e4ee3a
CB
15117 if (current_binding_level == global_binding_level)
15118 {
15119 named_labels = 0;
15120 }
5ff904cd 15121
c7e4ee3a 15122 /* Reuse or create a struct for this binding level. */
5ff904cd 15123
c7e4ee3a 15124 if (free_binding_level)
77f77701 15125 {
c7e4ee3a
CB
15126 newlevel = free_binding_level;
15127 free_binding_level = free_binding_level->level_chain;
77f77701
DB
15128 }
15129 else
c7e4ee3a
CB
15130 {
15131 newlevel = make_binding_level ();
15132 }
77f77701 15133
c7e4ee3a
CB
15134 /* Add this level to the front of the chain (stack) of levels that
15135 are active. */
71b5e532 15136
c7e4ee3a
CB
15137 *newlevel = clear_binding_level;
15138 newlevel->level_chain = current_binding_level;
15139 current_binding_level = newlevel;
5ff904cd
JL
15140}
15141
c7e4ee3a
CB
15142/* Set the BLOCK node for the innermost scope
15143 (the one we are currently in). */
77f77701 15144
5ff904cd 15145void
c7e4ee3a
CB
15146set_block (block)
15147 register tree block;
5ff904cd 15148{
c7e4ee3a 15149 current_binding_level->this_block = block;
9b58f739
RK
15150 current_binding_level->names = chainon (current_binding_level->names,
15151 BLOCK_VARS (block));
15152 current_binding_level->blocks = chainon (current_binding_level->blocks,
15153 BLOCK_SUBBLOCKS (block));
5ff904cd
JL
15154}
15155
c7e4ee3a 15156/* ~~gcc/tree.h *should* declare this, because toplev.c references it. */
5ff904cd 15157
c7e4ee3a 15158/* Can't 'yydebug' a front end not generated by yacc/bison! */
bc289659
ML
15159
15160void
c7e4ee3a
CB
15161set_yydebug (value)
15162 int value;
bc289659 15163{
c7e4ee3a
CB
15164 if (value)
15165 fprintf (stderr, "warning: no yacc/bison-generated output to debug!\n");
bc289659
ML
15166}
15167
c7e4ee3a
CB
15168tree
15169signed_or_unsigned_type (unsignedp, type)
15170 int unsignedp;
15171 tree type;
5ff904cd 15172{
c7e4ee3a 15173 tree type2;
5ff904cd 15174
c7e4ee3a
CB
15175 if (! INTEGRAL_TYPE_P (type))
15176 return type;
15177 if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node))
15178 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15179 if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
15180 return unsignedp ? unsigned_type_node : integer_type_node;
15181 if (TYPE_PRECISION (type) == TYPE_PRECISION (short_integer_type_node))
15182 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15183 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_integer_type_node))
15184 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15185 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_long_integer_type_node))
15186 return (unsignedp ? long_long_unsigned_type_node
15187 : long_long_integer_type_node);
5ff904cd 15188
c7e4ee3a
CB
15189 type2 = type_for_size (TYPE_PRECISION (type), unsignedp);
15190 if (type2 == NULL_TREE)
15191 return type;
f84639ba 15192
c7e4ee3a 15193 return type2;
5ff904cd
JL
15194}
15195
c7e4ee3a
CB
15196tree
15197signed_type (type)
15198 tree type;
5ff904cd 15199{
c7e4ee3a
CB
15200 tree type1 = TYPE_MAIN_VARIANT (type);
15201 ffeinfoKindtype kt;
15202 tree type2;
5ff904cd 15203
c7e4ee3a
CB
15204 if (type1 == unsigned_char_type_node || type1 == char_type_node)
15205 return signed_char_type_node;
15206 if (type1 == unsigned_type_node)
15207 return integer_type_node;
15208 if (type1 == short_unsigned_type_node)
15209 return short_integer_type_node;
15210 if (type1 == long_unsigned_type_node)
15211 return long_integer_type_node;
15212 if (type1 == long_long_unsigned_type_node)
15213 return long_long_integer_type_node;
15214#if 0 /* gcc/c-* files only */
15215 if (type1 == unsigned_intDI_type_node)
15216 return intDI_type_node;
15217 if (type1 == unsigned_intSI_type_node)
15218 return intSI_type_node;
15219 if (type1 == unsigned_intHI_type_node)
15220 return intHI_type_node;
15221 if (type1 == unsigned_intQI_type_node)
15222 return intQI_type_node;
15223#endif
5ff904cd 15224
c7e4ee3a
CB
15225 type2 = type_for_size (TYPE_PRECISION (type1), 0);
15226 if (type2 != NULL_TREE)
15227 return type2;
5ff904cd 15228
c7e4ee3a
CB
15229 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15230 {
15231 type2 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
5ff904cd 15232
c7e4ee3a
CB
15233 if (type1 == type2)
15234 return ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15235 }
15236
15237 return type;
5ff904cd
JL
15238}
15239
c7e4ee3a
CB
15240/* Prepare expr to be an argument of a TRUTH_NOT_EXPR,
15241 or validate its data type for an `if' or `while' statement or ?..: exp.
15242
15243 This preparation consists of taking the ordinary
15244 representation of an expression expr and producing a valid tree
15245 boolean expression describing whether expr is nonzero. We could
15246 simply always do build_binary_op (NE_EXPR, expr, integer_zero_node, 1),
15247 but we optimize comparisons, &&, ||, and !.
15248
15249 The resulting type should always be `integer_type_node'. */
5ff904cd
JL
15250
15251tree
c7e4ee3a
CB
15252truthvalue_conversion (expr)
15253 tree expr;
5ff904cd 15254{
c7e4ee3a
CB
15255 if (TREE_CODE (expr) == ERROR_MARK)
15256 return expr;
5ff904cd 15257
c7e4ee3a
CB
15258#if 0 /* This appears to be wrong for C++. */
15259 /* These really should return error_mark_node after 2.4 is stable.
15260 But not all callers handle ERROR_MARK properly. */
15261 switch (TREE_CODE (TREE_TYPE (expr)))
15262 {
15263 case RECORD_TYPE:
15264 error ("struct type value used where scalar is required");
15265 return integer_zero_node;
5ff904cd 15266
c7e4ee3a
CB
15267 case UNION_TYPE:
15268 error ("union type value used where scalar is required");
15269 return integer_zero_node;
5ff904cd 15270
c7e4ee3a
CB
15271 case ARRAY_TYPE:
15272 error ("array type value used where scalar is required");
15273 return integer_zero_node;
5ff904cd 15274
c7e4ee3a
CB
15275 default:
15276 break;
15277 }
15278#endif /* 0 */
5ff904cd 15279
c7e4ee3a
CB
15280 switch (TREE_CODE (expr))
15281 {
15282 /* It is simpler and generates better code to have only TRUTH_*_EXPR
15283 or comparison expressions as truth values at this level. */
15284#if 0
15285 case COMPONENT_REF:
15286 /* A one-bit unsigned bit-field is already acceptable. */
15287 if (1 == TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (expr, 1)))
15288 && TREE_UNSIGNED (TREE_OPERAND (expr, 1)))
15289 return expr;
15290 break;
15291#endif
15292
15293 case EQ_EXPR:
15294 /* It is simpler and generates better code to have only TRUTH_*_EXPR
15295 or comparison expressions as truth values at this level. */
15296#if 0
15297 if (integer_zerop (TREE_OPERAND (expr, 1)))
15298 return build_unary_op (TRUTH_NOT_EXPR, TREE_OPERAND (expr, 0), 0);
15299#endif
15300 case NE_EXPR: case LE_EXPR: case GE_EXPR: case LT_EXPR: case GT_EXPR:
15301 case TRUTH_ANDIF_EXPR:
15302 case TRUTH_ORIF_EXPR:
15303 case TRUTH_AND_EXPR:
15304 case TRUTH_OR_EXPR:
15305 case TRUTH_XOR_EXPR:
15306 TREE_TYPE (expr) = integer_type_node;
15307 return expr;
5ff904cd 15308
c7e4ee3a
CB
15309 case ERROR_MARK:
15310 return expr;
5ff904cd 15311
c7e4ee3a
CB
15312 case INTEGER_CST:
15313 return integer_zerop (expr) ? integer_zero_node : integer_one_node;
5ff904cd 15314
c7e4ee3a
CB
15315 case REAL_CST:
15316 return real_zerop (expr) ? integer_zero_node : integer_one_node;
5ff904cd 15317
c7e4ee3a
CB
15318 case ADDR_EXPR:
15319 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 0)))
15320 return build (COMPOUND_EXPR, integer_type_node,
15321 TREE_OPERAND (expr, 0), integer_one_node);
15322 else
15323 return integer_one_node;
5ff904cd 15324
c7e4ee3a
CB
15325 case COMPLEX_EXPR:
15326 return ffecom_2 ((TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
15327 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
15328 integer_type_node,
15329 truthvalue_conversion (TREE_OPERAND (expr, 0)),
15330 truthvalue_conversion (TREE_OPERAND (expr, 1)));
5ff904cd 15331
c7e4ee3a
CB
15332 case NEGATE_EXPR:
15333 case ABS_EXPR:
15334 case FLOAT_EXPR:
15335 case FFS_EXPR:
15336 /* These don't change whether an object is non-zero or zero. */
15337 return truthvalue_conversion (TREE_OPERAND (expr, 0));
5ff904cd 15338
c7e4ee3a
CB
15339 case LROTATE_EXPR:
15340 case RROTATE_EXPR:
15341 /* These don't change whether an object is zero or non-zero, but
15342 we can't ignore them if their second arg has side-effects. */
15343 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
15344 return build (COMPOUND_EXPR, integer_type_node, TREE_OPERAND (expr, 1),
15345 truthvalue_conversion (TREE_OPERAND (expr, 0)));
15346 else
15347 return truthvalue_conversion (TREE_OPERAND (expr, 0));
5ff904cd 15348
c7e4ee3a
CB
15349 case COND_EXPR:
15350 /* Distribute the conversion into the arms of a COND_EXPR. */
15351 return fold (build (COND_EXPR, integer_type_node, TREE_OPERAND (expr, 0),
15352 truthvalue_conversion (TREE_OPERAND (expr, 1)),
15353 truthvalue_conversion (TREE_OPERAND (expr, 2))));
5ff904cd 15354
c7e4ee3a
CB
15355 case CONVERT_EXPR:
15356 /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
15357 since that affects how `default_conversion' will behave. */
15358 if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE
15359 || TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE)
15360 break;
15361 /* fall through... */
15362 case NOP_EXPR:
15363 /* If this is widening the argument, we can ignore it. */
15364 if (TYPE_PRECISION (TREE_TYPE (expr))
15365 >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))
15366 return truthvalue_conversion (TREE_OPERAND (expr, 0));
15367 break;
5ff904cd 15368
c7e4ee3a
CB
15369 case MINUS_EXPR:
15370 /* With IEEE arithmetic, x - x may not equal 0, so we can't optimize
15371 this case. */
15372 if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
15373 && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE)
15374 break;
15375 /* fall through... */
15376 case BIT_XOR_EXPR:
15377 /* This and MINUS_EXPR can be changed into a comparison of the
15378 two objects. */
15379 if (TREE_TYPE (TREE_OPERAND (expr, 0))
15380 == TREE_TYPE (TREE_OPERAND (expr, 1)))
15381 return ffecom_2 (NE_EXPR, integer_type_node,
15382 TREE_OPERAND (expr, 0),
15383 TREE_OPERAND (expr, 1));
15384 return ffecom_2 (NE_EXPR, integer_type_node,
15385 TREE_OPERAND (expr, 0),
15386 fold (build1 (NOP_EXPR,
15387 TREE_TYPE (TREE_OPERAND (expr, 0)),
15388 TREE_OPERAND (expr, 1))));
15389
15390 case BIT_AND_EXPR:
15391 if (integer_onep (TREE_OPERAND (expr, 1)))
15392 return expr;
15393 break;
15394
15395 case MODIFY_EXPR:
15396#if 0 /* No such thing in Fortran. */
15397 if (warn_parentheses && C_EXP_ORIGINAL_CODE (expr) == MODIFY_EXPR)
15398 warning ("suggest parentheses around assignment used as truth value");
15399#endif
15400 break;
15401
15402 default:
15403 break;
5ff904cd
JL
15404 }
15405
c7e4ee3a
CB
15406 if (TREE_CODE (TREE_TYPE (expr)) == COMPLEX_TYPE)
15407 return (ffecom_2
15408 ((TREE_SIDE_EFFECTS (expr)
15409 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
15410 integer_type_node,
15411 truthvalue_conversion (ffecom_1 (REALPART_EXPR,
15412 TREE_TYPE (TREE_TYPE (expr)),
15413 expr)),
15414 truthvalue_conversion (ffecom_1 (IMAGPART_EXPR,
15415 TREE_TYPE (TREE_TYPE (expr)),
15416 expr))));
15417
15418 return ffecom_2 (NE_EXPR, integer_type_node,
15419 expr,
15420 convert (TREE_TYPE (expr), integer_zero_node));
15421}
15422
15423tree
15424type_for_mode (mode, unsignedp)
15425 enum machine_mode mode;
15426 int unsignedp;
15427{
15428 int i;
15429 int j;
15430 tree t;
5ff904cd 15431
c7e4ee3a
CB
15432 if (mode == TYPE_MODE (integer_type_node))
15433 return unsignedp ? unsigned_type_node : integer_type_node;
5ff904cd 15434
c7e4ee3a
CB
15435 if (mode == TYPE_MODE (signed_char_type_node))
15436 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
5ff904cd 15437
c7e4ee3a
CB
15438 if (mode == TYPE_MODE (short_integer_type_node))
15439 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
5ff904cd 15440
c7e4ee3a
CB
15441 if (mode == TYPE_MODE (long_integer_type_node))
15442 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
5ff904cd 15443
c7e4ee3a
CB
15444 if (mode == TYPE_MODE (long_long_integer_type_node))
15445 return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
5ff904cd 15446
fed3cef0
RK
15447#if HOST_BITS_PER_WIDE_INT >= 64
15448 if (mode == TYPE_MODE (intTI_type_node))
15449 return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
15450#endif
15451
c7e4ee3a
CB
15452 if (mode == TYPE_MODE (float_type_node))
15453 return float_type_node;
5ff904cd 15454
c7e4ee3a
CB
15455 if (mode == TYPE_MODE (double_type_node))
15456 return double_type_node;
5ff904cd 15457
c7e4ee3a
CB
15458 if (mode == TYPE_MODE (build_pointer_type (char_type_node)))
15459 return build_pointer_type (char_type_node);
5ff904cd 15460
c7e4ee3a
CB
15461 if (mode == TYPE_MODE (build_pointer_type (integer_type_node)))
15462 return build_pointer_type (integer_type_node);
5ff904cd 15463
c7e4ee3a
CB
15464 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
15465 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
15466 {
15467 if (((t = ffecom_tree_type[i][j]) != NULL_TREE)
15468 && (mode == TYPE_MODE (t)))
15469 {
15470 if ((i == FFEINFO_basictypeINTEGER) && unsignedp)
15471 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][j];
15472 else
15473 return t;
15474 }
15475 }
5ff904cd 15476
c7e4ee3a 15477 return 0;
5ff904cd
JL
15478}
15479
c7e4ee3a
CB
15480tree
15481type_for_size (bits, unsignedp)
15482 unsigned bits;
15483 int unsignedp;
5ff904cd 15484{
c7e4ee3a
CB
15485 ffeinfoKindtype kt;
15486 tree type_node;
5ff904cd 15487
c7e4ee3a
CB
15488 if (bits == TYPE_PRECISION (integer_type_node))
15489 return unsignedp ? unsigned_type_node : integer_type_node;
5ff904cd 15490
c7e4ee3a
CB
15491 if (bits == TYPE_PRECISION (signed_char_type_node))
15492 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
5ff904cd 15493
c7e4ee3a
CB
15494 if (bits == TYPE_PRECISION (short_integer_type_node))
15495 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
5ff904cd 15496
c7e4ee3a
CB
15497 if (bits == TYPE_PRECISION (long_integer_type_node))
15498 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
5ff904cd 15499
c7e4ee3a
CB
15500 if (bits == TYPE_PRECISION (long_long_integer_type_node))
15501 return (unsignedp ? long_long_unsigned_type_node
15502 : long_long_integer_type_node);
5ff904cd 15503
c7e4ee3a 15504 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
5ff904cd 15505 {
c7e4ee3a 15506 type_node = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
5ff904cd 15507
c7e4ee3a
CB
15508 if ((type_node != NULL_TREE) && (bits == TYPE_PRECISION (type_node)))
15509 return unsignedp ? ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt]
15510 : type_node;
15511 }
5ff904cd 15512
c7e4ee3a
CB
15513 return 0;
15514}
5ff904cd 15515
c7e4ee3a
CB
15516tree
15517unsigned_type (type)
15518 tree type;
15519{
15520 tree type1 = TYPE_MAIN_VARIANT (type);
15521 ffeinfoKindtype kt;
15522 tree type2;
5ff904cd 15523
c7e4ee3a
CB
15524 if (type1 == signed_char_type_node || type1 == char_type_node)
15525 return unsigned_char_type_node;
15526 if (type1 == integer_type_node)
15527 return unsigned_type_node;
15528 if (type1 == short_integer_type_node)
15529 return short_unsigned_type_node;
15530 if (type1 == long_integer_type_node)
15531 return long_unsigned_type_node;
15532 if (type1 == long_long_integer_type_node)
15533 return long_long_unsigned_type_node;
15534#if 0 /* gcc/c-* files only */
15535 if (type1 == intDI_type_node)
15536 return unsigned_intDI_type_node;
15537 if (type1 == intSI_type_node)
15538 return unsigned_intSI_type_node;
15539 if (type1 == intHI_type_node)
15540 return unsigned_intHI_type_node;
15541 if (type1 == intQI_type_node)
15542 return unsigned_intQI_type_node;
15543#endif
5ff904cd 15544
c7e4ee3a
CB
15545 type2 = type_for_size (TYPE_PRECISION (type1), 1);
15546 if (type2 != NULL_TREE)
15547 return type2;
5ff904cd 15548
c7e4ee3a
CB
15549 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15550 {
15551 type2 = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
5ff904cd 15552
c7e4ee3a
CB
15553 if (type1 == type2)
15554 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
15555 }
5ff904cd 15556
c7e4ee3a
CB
15557 return type;
15558}
5ff904cd 15559
7189a4b0
GK
15560void
15561lang_mark_tree (t)
15562 union tree_node *t ATTRIBUTE_UNUSED;
15563{
15564 if (TREE_CODE (t) == IDENTIFIER_NODE)
15565 {
15566 struct lang_identifier *i = (struct lang_identifier *) t;
15567 ggc_mark_tree (IDENTIFIER_GLOBAL_VALUE (i));
15568 ggc_mark_tree (IDENTIFIER_LOCAL_VALUE (i));
15569 ggc_mark_tree (IDENTIFIER_LABEL_VALUE (i));
15570 }
15571 else if (TYPE_P (t) && TYPE_LANG_SPECIFIC (t))
15572 ggc_mark (TYPE_LANG_SPECIFIC (t));
15573}
15574
c7e4ee3a
CB
15575#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
15576\f
15577#if FFECOM_GCC_INCLUDE
5ff904cd 15578
c7e4ee3a 15579/* From gcc/cccp.c, the code to handle -I. */
5ff904cd 15580
c7e4ee3a
CB
15581/* Skip leading "./" from a directory name.
15582 This may yield the empty string, which represents the current directory. */
5ff904cd 15583
c7e4ee3a
CB
15584static const char *
15585skip_redundant_dir_prefix (const char *dir)
15586{
15587 while (dir[0] == '.' && dir[1] == '/')
15588 for (dir += 2; *dir == '/'; dir++)
15589 continue;
15590 if (dir[0] == '.' && !dir[1])
15591 dir++;
15592 return dir;
15593}
5ff904cd 15594
c7e4ee3a
CB
15595/* The file_name_map structure holds a mapping of file names for a
15596 particular directory. This mapping is read from the file named
15597 FILE_NAME_MAP_FILE in that directory. Such a file can be used to
15598 map filenames on a file system with severe filename restrictions,
15599 such as DOS. The format of the file name map file is just a series
15600 of lines with two tokens on each line. The first token is the name
15601 to map, and the second token is the actual name to use. */
5ff904cd 15602
c7e4ee3a
CB
15603struct file_name_map
15604{
15605 struct file_name_map *map_next;
15606 char *map_from;
15607 char *map_to;
15608};
5ff904cd 15609
c7e4ee3a 15610#define FILE_NAME_MAP_FILE "header.gcc"
5ff904cd 15611
c7e4ee3a
CB
15612/* Current maximum length of directory names in the search path
15613 for include files. (Altered as we get more of them.) */
5ff904cd 15614
c7e4ee3a 15615static int max_include_len = 0;
5ff904cd 15616
c7e4ee3a
CB
15617struct file_name_list
15618 {
15619 struct file_name_list *next;
15620 char *fname;
15621 /* Mapping of file names for this directory. */
15622 struct file_name_map *name_map;
15623 /* Non-zero if name_map is valid. */
15624 int got_name_map;
15625 };
5ff904cd 15626
c7e4ee3a
CB
15627static struct file_name_list *include = NULL; /* First dir to search */
15628static struct file_name_list *last_include = NULL; /* Last in chain */
5ff904cd 15629
c7e4ee3a
CB
15630/* I/O buffer structure.
15631 The `fname' field is nonzero for source files and #include files
15632 and for the dummy text used for -D and -U.
15633 It is zero for rescanning results of macro expansion
15634 and for expanding macro arguments. */
15635#define INPUT_STACK_MAX 400
15636static struct file_buf {
b0791fa9 15637 const char *fname;
c7e4ee3a 15638 /* Filename specified with #line command. */
b0791fa9 15639 const char *nominal_fname;
c7e4ee3a
CB
15640 /* Record where in the search path this file was found.
15641 For #include_next. */
15642 struct file_name_list *dir;
15643 ffewhereLine line;
15644 ffewhereColumn column;
15645} instack[INPUT_STACK_MAX];
5ff904cd 15646
c7e4ee3a
CB
15647static int last_error_tick = 0; /* Incremented each time we print it. */
15648static int input_file_stack_tick = 0; /* Incremented when status changes. */
5ff904cd 15649
c7e4ee3a
CB
15650/* Current nesting level of input sources.
15651 `instack[indepth]' is the level currently being read. */
15652static int indepth = -1;
5ff904cd 15653
c7e4ee3a 15654typedef struct file_buf FILE_BUF;
5ff904cd 15655
c7e4ee3a 15656typedef unsigned char U_CHAR;
5ff904cd 15657
c7e4ee3a
CB
15658/* table to tell if char can be part of a C identifier. */
15659U_CHAR is_idchar[256];
15660/* table to tell if char can be first char of a c identifier. */
15661U_CHAR is_idstart[256];
15662/* table to tell if c is horizontal space. */
15663U_CHAR is_hor_space[256];
15664/* table to tell if c is horizontal or vertical space. */
15665static U_CHAR is_space[256];
5ff904cd 15666
c7e4ee3a
CB
15667#define SKIP_WHITE_SPACE(p) do { while (is_hor_space[*p]) p++; } while (0)
15668#define SKIP_ALL_WHITE_SPACE(p) do { while (is_space[*p]) p++; } while (0)
5ff904cd 15669
c7e4ee3a
CB
15670/* Nonzero means -I- has been seen,
15671 so don't look for #include "foo" the source-file directory. */
15672static int ignore_srcdir;
5ff904cd 15673
c7e4ee3a
CB
15674#ifndef INCLUDE_LEN_FUDGE
15675#define INCLUDE_LEN_FUDGE 0
15676#endif
5ff904cd 15677
c7e4ee3a
CB
15678static void append_include_chain (struct file_name_list *first,
15679 struct file_name_list *last);
15680static FILE *open_include_file (char *filename,
15681 struct file_name_list *searchptr);
15682static void print_containing_files (ffebadSeverity sev);
c7e4ee3a
CB
15683static char *read_filename_string (int ch, FILE *f);
15684static struct file_name_map *read_name_map (const char *dirname);
5ff904cd 15685
c7e4ee3a
CB
15686/* Append a chain of `struct file_name_list's
15687 to the end of the main include chain.
15688 FIRST is the beginning of the chain to append, and LAST is the end. */
5ff904cd 15689
c7e4ee3a
CB
15690static void
15691append_include_chain (first, last)
15692 struct file_name_list *first, *last;
5ff904cd 15693{
c7e4ee3a 15694 struct file_name_list *dir;
5ff904cd 15695
c7e4ee3a
CB
15696 if (!first || !last)
15697 return;
5ff904cd 15698
c7e4ee3a
CB
15699 if (include == 0)
15700 include = first;
15701 else
15702 last_include->next = first;
5ff904cd 15703
c7e4ee3a
CB
15704 for (dir = first; ; dir = dir->next) {
15705 int len = strlen (dir->fname) + INCLUDE_LEN_FUDGE;
15706 if (len > max_include_len)
15707 max_include_len = len;
15708 if (dir == last)
15709 break;
15710 }
15711
15712 last->next = NULL;
15713 last_include = last;
5ff904cd
JL
15714}
15715
c7e4ee3a
CB
15716/* Try to open include file FILENAME. SEARCHPTR is the directory
15717 being tried from the include file search path. This function maps
15718 filenames on file systems based on information read by
15719 read_name_map. */
15720
15721static FILE *
15722open_include_file (filename, searchptr)
15723 char *filename;
15724 struct file_name_list *searchptr;
5ff904cd 15725{
c7e4ee3a
CB
15726 register struct file_name_map *map;
15727 register char *from;
15728 char *p, *dir;
5ff904cd 15729
c7e4ee3a
CB
15730 if (searchptr && ! searchptr->got_name_map)
15731 {
15732 searchptr->name_map = read_name_map (searchptr->fname
15733 ? searchptr->fname : ".");
15734 searchptr->got_name_map = 1;
15735 }
5ff904cd 15736
c7e4ee3a
CB
15737 /* First check the mapping for the directory we are using. */
15738 if (searchptr && searchptr->name_map)
15739 {
15740 from = filename;
15741 if (searchptr->fname)
15742 from += strlen (searchptr->fname) + 1;
15743 for (map = searchptr->name_map; map; map = map->map_next)
15744 {
15745 if (! strcmp (map->map_from, from))
15746 {
15747 /* Found a match. */
15748 return fopen (map->map_to, "r");
15749 }
15750 }
15751 }
5ff904cd 15752
c7e4ee3a
CB
15753 /* Try to find a mapping file for the particular directory we are
15754 looking in. Thus #include <sys/types.h> will look up sys/types.h
15755 in /usr/include/header.gcc and look up types.h in
15756 /usr/include/sys/header.gcc. */
9473c522 15757 p = strrchr (filename, '/');
c7e4ee3a 15758#ifdef DIR_SEPARATOR
9473c522 15759 if (! p) p = strrchr (filename, DIR_SEPARATOR);
c7e4ee3a 15760 else {
9473c522 15761 char *tmp = strrchr (filename, DIR_SEPARATOR);
c7e4ee3a
CB
15762 if (tmp != NULL && tmp > p) p = tmp;
15763 }
15764#endif
15765 if (! p)
15766 p = filename;
15767 if (searchptr
15768 && searchptr->fname
15769 && strlen (searchptr->fname) == (size_t) (p - filename)
15770 && ! strncmp (searchptr->fname, filename, (int) (p - filename)))
15771 {
15772 /* FILENAME is in SEARCHPTR, which we've already checked. */
15773 return fopen (filename, "r");
15774 }
15775
15776 if (p == filename)
15777 {
15778 from = filename;
15779 map = read_name_map (".");
15780 }
15781 else
5ff904cd 15782 {
c7e4ee3a
CB
15783 dir = (char *) xmalloc (p - filename + 1);
15784 memcpy (dir, filename, p - filename);
15785 dir[p - filename] = '\0';
15786 from = p + 1;
15787 map = read_name_map (dir);
15788 free (dir);
5ff904cd 15789 }
c7e4ee3a
CB
15790 for (; map; map = map->map_next)
15791 if (! strcmp (map->map_from, from))
15792 return fopen (map->map_to, "r");
5ff904cd 15793
c7e4ee3a 15794 return fopen (filename, "r");
5ff904cd
JL
15795}
15796
c7e4ee3a
CB
15797/* Print the file names and line numbers of the #include
15798 commands which led to the current file. */
5ff904cd 15799
c7e4ee3a
CB
15800static void
15801print_containing_files (ffebadSeverity sev)
15802{
15803 FILE_BUF *ip = NULL;
15804 int i;
15805 int first = 1;
15806 const char *str1;
15807 const char *str2;
5ff904cd 15808
c7e4ee3a
CB
15809 /* If stack of files hasn't changed since we last printed
15810 this info, don't repeat it. */
15811 if (last_error_tick == input_file_stack_tick)
15812 return;
5ff904cd 15813
c7e4ee3a
CB
15814 for (i = indepth; i >= 0; i--)
15815 if (instack[i].fname != NULL) {
15816 ip = &instack[i];
15817 break;
15818 }
5ff904cd 15819
c7e4ee3a
CB
15820 /* Give up if we don't find a source file. */
15821 if (ip == NULL)
15822 return;
5ff904cd 15823
c7e4ee3a
CB
15824 /* Find the other, outer source files. */
15825 for (i--; i >= 0; i--)
15826 if (instack[i].fname != NULL)
15827 {
15828 ip = &instack[i];
15829 if (first)
15830 {
15831 first = 0;
15832 str1 = "In file included";
15833 }
15834 else
15835 {
15836 str1 = "... ...";
15837 }
5ff904cd 15838
c7e4ee3a
CB
15839 if (i == 1)
15840 str2 = ":";
15841 else
15842 str2 = "";
5ff904cd 15843
c7e4ee3a
CB
15844 ffebad_start_msg ("%A from %B at %0%C", sev);
15845 ffebad_here (0, ip->line, ip->column);
15846 ffebad_string (str1);
15847 ffebad_string (ip->nominal_fname);
15848 ffebad_string (str2);
15849 ffebad_finish ();
15850 }
5ff904cd 15851
c7e4ee3a
CB
15852 /* Record we have printed the status as of this time. */
15853 last_error_tick = input_file_stack_tick;
15854}
5ff904cd 15855
c7e4ee3a
CB
15856/* Read a space delimited string of unlimited length from a stdio
15857 file. */
5ff904cd 15858
c7e4ee3a
CB
15859static char *
15860read_filename_string (ch, f)
15861 int ch;
15862 FILE *f;
15863{
15864 char *alloc, *set;
15865 int len;
5ff904cd 15866
c7e4ee3a
CB
15867 len = 20;
15868 set = alloc = xmalloc (len + 1);
15869 if (! is_space[ch])
15870 {
15871 *set++ = ch;
15872 while ((ch = getc (f)) != EOF && ! is_space[ch])
15873 {
15874 if (set - alloc == len)
15875 {
15876 len *= 2;
15877 alloc = xrealloc (alloc, len + 1);
15878 set = alloc + len / 2;
15879 }
15880 *set++ = ch;
15881 }
15882 }
15883 *set = '\0';
15884 ungetc (ch, f);
15885 return alloc;
15886}
5ff904cd 15887
c7e4ee3a 15888/* Read the file name map file for DIRNAME. */
5ff904cd 15889
c7e4ee3a
CB
15890static struct file_name_map *
15891read_name_map (dirname)
15892 const char *dirname;
15893{
15894 /* This structure holds a linked list of file name maps, one per
15895 directory. */
15896 struct file_name_map_list
15897 {
15898 struct file_name_map_list *map_list_next;
15899 char *map_list_name;
15900 struct file_name_map *map_list_map;
15901 };
15902 static struct file_name_map_list *map_list;
15903 register struct file_name_map_list *map_list_ptr;
15904 char *name;
15905 FILE *f;
15906 size_t dirlen;
15907 int separator_needed;
5ff904cd 15908
c7e4ee3a 15909 dirname = skip_redundant_dir_prefix (dirname);
5ff904cd 15910
c7e4ee3a
CB
15911 for (map_list_ptr = map_list; map_list_ptr;
15912 map_list_ptr = map_list_ptr->map_list_next)
15913 if (! strcmp (map_list_ptr->map_list_name, dirname))
15914 return map_list_ptr->map_list_map;
5ff904cd 15915
c7e4ee3a
CB
15916 map_list_ptr = ((struct file_name_map_list *)
15917 xmalloc (sizeof (struct file_name_map_list)));
15918 map_list_ptr->map_list_name = xstrdup (dirname);
15919 map_list_ptr->map_list_map = NULL;
5ff904cd 15920
c7e4ee3a
CB
15921 dirlen = strlen (dirname);
15922 separator_needed = dirlen != 0 && dirname[dirlen - 1] != '/';
15923 name = (char *) xmalloc (dirlen + strlen (FILE_NAME_MAP_FILE) + 2);
15924 strcpy (name, dirname);
15925 name[dirlen] = '/';
15926 strcpy (name + dirlen + separator_needed, FILE_NAME_MAP_FILE);
15927 f = fopen (name, "r");
15928 free (name);
15929 if (!f)
15930 map_list_ptr->map_list_map = NULL;
15931 else
15932 {
15933 int ch;
5ff904cd 15934
c7e4ee3a
CB
15935 while ((ch = getc (f)) != EOF)
15936 {
15937 char *from, *to;
15938 struct file_name_map *ptr;
15939
15940 if (is_space[ch])
15941 continue;
15942 from = read_filename_string (ch, f);
15943 while ((ch = getc (f)) != EOF && is_hor_space[ch])
15944 ;
15945 to = read_filename_string (ch, f);
5ff904cd 15946
c7e4ee3a
CB
15947 ptr = ((struct file_name_map *)
15948 xmalloc (sizeof (struct file_name_map)));
15949 ptr->map_from = from;
5ff904cd 15950
c7e4ee3a
CB
15951 /* Make the real filename absolute. */
15952 if (*to == '/')
15953 ptr->map_to = to;
15954 else
15955 {
15956 ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
15957 strcpy (ptr->map_to, dirname);
15958 ptr->map_to[dirlen] = '/';
15959 strcpy (ptr->map_to + dirlen + separator_needed, to);
15960 free (to);
15961 }
5ff904cd 15962
c7e4ee3a
CB
15963 ptr->map_next = map_list_ptr->map_list_map;
15964 map_list_ptr->map_list_map = ptr;
5ff904cd 15965
c7e4ee3a
CB
15966 while ((ch = getc (f)) != '\n')
15967 if (ch == EOF)
15968 break;
15969 }
15970 fclose (f);
5ff904cd
JL
15971 }
15972
c7e4ee3a
CB
15973 map_list_ptr->map_list_next = map_list;
15974 map_list = map_list_ptr;
5ff904cd 15975
c7e4ee3a 15976 return map_list_ptr->map_list_map;
5ff904cd
JL
15977}
15978
c7e4ee3a 15979static void
b0791fa9 15980ffecom_file_ (const char *name)
5ff904cd 15981{
c7e4ee3a 15982 FILE_BUF *fp;
5ff904cd 15983
c7e4ee3a
CB
15984 /* Do partial setup of input buffer for the sake of generating
15985 early #line directives (when -g is in effect). */
5ff904cd 15986
c7e4ee3a
CB
15987 fp = &instack[++indepth];
15988 memset ((char *) fp, 0, sizeof (FILE_BUF));
15989 if (name == NULL)
15990 name = "";
15991 fp->nominal_fname = fp->fname = name;
15992}
5ff904cd 15993
c7e4ee3a 15994/* Initialize syntactic classifications of characters. */
5ff904cd 15995
c7e4ee3a
CB
15996static void
15997ffecom_initialize_char_syntax_ ()
15998{
15999 register int i;
5ff904cd 16000
c7e4ee3a
CB
16001 /*
16002 * Set up is_idchar and is_idstart tables. These should be
16003 * faster than saying (is_alpha (c) || c == '_'), etc.
16004 * Set up these things before calling any routines tthat
16005 * refer to them.
16006 */
16007 for (i = 'a'; i <= 'z'; i++) {
16008 is_idchar[i - 'a' + 'A'] = 1;
16009 is_idchar[i] = 1;
16010 is_idstart[i - 'a' + 'A'] = 1;
16011 is_idstart[i] = 1;
16012 }
16013 for (i = '0'; i <= '9'; i++)
16014 is_idchar[i] = 1;
16015 is_idchar['_'] = 1;
16016 is_idstart['_'] = 1;
5ff904cd 16017
c7e4ee3a
CB
16018 /* horizontal space table */
16019 is_hor_space[' '] = 1;
16020 is_hor_space['\t'] = 1;
16021 is_hor_space['\v'] = 1;
16022 is_hor_space['\f'] = 1;
16023 is_hor_space['\r'] = 1;
5ff904cd 16024
c7e4ee3a
CB
16025 is_space[' '] = 1;
16026 is_space['\t'] = 1;
16027 is_space['\v'] = 1;
16028 is_space['\f'] = 1;
16029 is_space['\n'] = 1;
16030 is_space['\r'] = 1;
16031}
5ff904cd 16032
c7e4ee3a
CB
16033static void
16034ffecom_close_include_ (FILE *f)
16035{
16036 fclose (f);
5ff904cd 16037
c7e4ee3a
CB
16038 indepth--;
16039 input_file_stack_tick++;
5ff904cd 16040
c7e4ee3a
CB
16041 ffewhere_line_kill (instack[indepth].line);
16042 ffewhere_column_kill (instack[indepth].column);
16043}
5ff904cd 16044
c7e4ee3a
CB
16045static int
16046ffecom_decode_include_option_ (char *spec)
16047{
16048 struct file_name_list *dirtmp;
16049
16050 if (! ignore_srcdir && !strcmp (spec, "-"))
16051 ignore_srcdir = 1;
16052 else
16053 {
16054 dirtmp = (struct file_name_list *)
16055 xmalloc (sizeof (struct file_name_list));
16056 dirtmp->next = 0; /* New one goes on the end */
400500c4 16057 dirtmp->fname = spec;
c7e4ee3a 16058 dirtmp->got_name_map = 0;
400500c4
RK
16059 if (spec[0] == 0)
16060 error ("Directory name must immediately follow -I");
16061 else
16062 append_include_chain (dirtmp, dirtmp);
c7e4ee3a
CB
16063 }
16064 return 1;
5ff904cd
JL
16065}
16066
c7e4ee3a
CB
16067/* Open INCLUDEd file. */
16068
16069static FILE *
16070ffecom_open_include_ (char *name, ffewhereLine l, ffewhereColumn c)
5ff904cd 16071{
c7e4ee3a
CB
16072 char *fbeg = name;
16073 size_t flen = strlen (fbeg);
16074 struct file_name_list *search_start = include; /* Chain of dirs to search */
16075 struct file_name_list dsp[1]; /* First in chain, if #include "..." */
16076 struct file_name_list *searchptr = 0;
16077 char *fname; /* Dynamically allocated fname buffer */
16078 FILE *f;
16079 FILE_BUF *fp;
5ff904cd 16080
c7e4ee3a
CB
16081 if (flen == 0)
16082 return NULL;
5ff904cd 16083
c7e4ee3a 16084 dsp[0].fname = NULL;
5ff904cd 16085
c7e4ee3a
CB
16086 /* If -I- was specified, don't search current dir, only spec'd ones. */
16087 if (!ignore_srcdir)
16088 {
16089 for (fp = &instack[indepth]; fp >= instack; fp--)
16090 {
16091 int n;
16092 char *ep;
b0791fa9 16093 const char *nam;
5ff904cd 16094
c7e4ee3a
CB
16095 if ((nam = fp->nominal_fname) != NULL)
16096 {
16097 /* Found a named file. Figure out dir of the file,
16098 and put it in front of the search list. */
16099 dsp[0].next = search_start;
16100 search_start = dsp;
16101#ifndef VMS
9473c522 16102 ep = strrchr (nam, '/');
c7e4ee3a 16103#ifdef DIR_SEPARATOR
9473c522 16104 if (ep == NULL) ep = strrchr (nam, DIR_SEPARATOR);
c7e4ee3a 16105 else {
9473c522 16106 char *tmp = strrchr (nam, DIR_SEPARATOR);
c7e4ee3a
CB
16107 if (tmp != NULL && tmp > ep) ep = tmp;
16108 }
16109#endif
16110#else /* VMS */
9473c522
JM
16111 ep = strrchr (nam, ']');
16112 if (ep == NULL) ep = strrchr (nam, '>');
16113 if (ep == NULL) ep = strrchr (nam, ':');
c7e4ee3a
CB
16114 if (ep != NULL) ep++;
16115#endif /* VMS */
16116 if (ep != NULL)
16117 {
16118 n = ep - nam;
16119 dsp[0].fname = (char *) xmalloc (n + 1);
16120 strncpy (dsp[0].fname, nam, n);
16121 dsp[0].fname[n] = '\0';
16122 if (n + INCLUDE_LEN_FUDGE > max_include_len)
16123 max_include_len = n + INCLUDE_LEN_FUDGE;
16124 }
16125 else
16126 dsp[0].fname = NULL; /* Current directory */
16127 dsp[0].got_name_map = 0;
16128 break;
16129 }
16130 }
16131 }
5ff904cd 16132
c7e4ee3a
CB
16133 /* Allocate this permanently, because it gets stored in the definitions
16134 of macros. */
16135 fname = xmalloc (max_include_len + flen + 4);
16136 /* + 2 above for slash and terminating null. */
16137 /* + 2 added for '.h' on VMS (to support '#include filename') (NOT USED
16138 for g77 yet). */
5ff904cd 16139
c7e4ee3a 16140 /* If specified file name is absolute, just open it. */
5ff904cd 16141
c7e4ee3a
CB
16142 if (*fbeg == '/'
16143#ifdef DIR_SEPARATOR
16144 || *fbeg == DIR_SEPARATOR
16145#endif
16146 )
16147 {
16148 strncpy (fname, (char *) fbeg, flen);
16149 fname[flen] = 0;
3e411c3f 16150 f = open_include_file (fname, NULL);
5ff904cd 16151 }
c7e4ee3a
CB
16152 else
16153 {
16154 f = NULL;
5ff904cd 16155
c7e4ee3a
CB
16156 /* Search directory path, trying to open the file.
16157 Copy each filename tried into FNAME. */
5ff904cd 16158
c7e4ee3a
CB
16159 for (searchptr = search_start; searchptr; searchptr = searchptr->next)
16160 {
16161 if (searchptr->fname)
16162 {
16163 /* The empty string in a search path is ignored.
16164 This makes it possible to turn off entirely
16165 a standard piece of the list. */
16166 if (searchptr->fname[0] == 0)
16167 continue;
16168 strcpy (fname, skip_redundant_dir_prefix (searchptr->fname));
16169 if (fname[0] && fname[strlen (fname) - 1] != '/')
16170 strcat (fname, "/");
16171 fname[strlen (fname) + flen] = 0;
16172 }
16173 else
16174 fname[0] = 0;
5ff904cd 16175
c7e4ee3a
CB
16176 strncat (fname, fbeg, flen);
16177#ifdef VMS
16178 /* Change this 1/2 Unix 1/2 VMS file specification into a
16179 full VMS file specification */
16180 if (searchptr->fname && (searchptr->fname[0] != 0))
16181 {
16182 /* Fix up the filename */
16183 hack_vms_include_specification (fname);
16184 }
16185 else
16186 {
16187 /* This is a normal VMS filespec, so use it unchanged. */
16188 strncpy (fname, (char *) fbeg, flen);
16189 fname[flen] = 0;
16190#if 0 /* Not for g77. */
16191 /* if it's '#include filename', add the missing .h */
9473c522 16192 if (strchr (fname, '.') == NULL)
c7e4ee3a 16193 strcat (fname, ".h");
5ff904cd 16194#endif
c7e4ee3a
CB
16195 }
16196#endif /* VMS */
16197 f = open_include_file (fname, searchptr);
16198#ifdef EACCES
16199 if (f == NULL && errno == EACCES)
16200 {
16201 print_containing_files (FFEBAD_severityWARNING);
16202 ffebad_start_msg ("At %0, INCLUDE file %A exists, but is not readable",
16203 FFEBAD_severityWARNING);
16204 ffebad_string (fname);
16205 ffebad_here (0, l, c);
16206 ffebad_finish ();
16207 }
16208#endif
16209 if (f != NULL)
16210 break;
16211 }
16212 }
5ff904cd 16213
c7e4ee3a 16214 if (f == NULL)
5ff904cd 16215 {
c7e4ee3a 16216 /* A file that was not found. */
5ff904cd 16217
c7e4ee3a
CB
16218 strncpy (fname, (char *) fbeg, flen);
16219 fname[flen] = 0;
16220 print_containing_files (ffebad_severity (FFEBAD_OPEN_INCLUDE));
16221 ffebad_start (FFEBAD_OPEN_INCLUDE);
16222 ffebad_here (0, l, c);
16223 ffebad_string (fname);
16224 ffebad_finish ();
5ff904cd
JL
16225 }
16226
c7e4ee3a
CB
16227 if (dsp[0].fname != NULL)
16228 free (dsp[0].fname);
5ff904cd 16229
c7e4ee3a
CB
16230 if (f == NULL)
16231 return NULL;
5ff904cd 16232
c7e4ee3a
CB
16233 if (indepth >= (INPUT_STACK_MAX - 1))
16234 {
16235 print_containing_files (FFEBAD_severityFATAL);
16236 ffebad_start_msg ("At %0, INCLUDE nesting too deep",
16237 FFEBAD_severityFATAL);
16238 ffebad_string (fname);
16239 ffebad_here (0, l, c);
16240 ffebad_finish ();
16241 return NULL;
16242 }
5ff904cd 16243
c7e4ee3a
CB
16244 instack[indepth].line = ffewhere_line_use (l);
16245 instack[indepth].column = ffewhere_column_use (c);
5ff904cd 16246
c7e4ee3a
CB
16247 fp = &instack[indepth + 1];
16248 memset ((char *) fp, 0, sizeof (FILE_BUF));
16249 fp->nominal_fname = fp->fname = fname;
16250 fp->dir = searchptr;
5ff904cd 16251
c7e4ee3a
CB
16252 indepth++;
16253 input_file_stack_tick++;
5ff904cd 16254
c7e4ee3a
CB
16255 return f;
16256}
16257#endif /* FFECOM_GCC_INCLUDE */
5ff904cd 16258
c7e4ee3a
CB
16259/**INDENT* (Do not reformat this comment even with -fca option.)
16260 Data-gathering files: Given the source file listed below, compiled with
16261 f2c I obtained the output file listed after that, and from the output
16262 file I derived the above code.
5ff904cd 16263
c7e4ee3a
CB
16264-------- (begin input file to f2c)
16265 implicit none
16266 character*10 A1,A2
16267 complex C1,C2
16268 integer I1,I2
16269 real R1,R2
16270 double precision D1,D2
16271C
16272 call getem(A1,A2,C1,C2,I1,I2,R1,R2,D1,D2)
16273c /
16274 call fooI(I1/I2)
16275 call fooR(R1/I1)
16276 call fooD(D1/I1)
16277 call fooC(C1/I1)
16278 call fooR(R1/R2)
16279 call fooD(R1/D1)
16280 call fooD(D1/D2)
16281 call fooD(D1/R1)
16282 call fooC(C1/C2)
16283 call fooC(C1/R1)
16284 call fooZ(C1/D1)
16285c **
16286 call fooI(I1**I2)
16287 call fooR(R1**I1)
16288 call fooD(D1**I1)
16289 call fooC(C1**I1)
16290 call fooR(R1**R2)
16291 call fooD(R1**D1)
16292 call fooD(D1**D2)
16293 call fooD(D1**R1)
16294 call fooC(C1**C2)
16295 call fooC(C1**R1)
16296 call fooZ(C1**D1)
16297c FFEINTRIN_impABS
16298 call fooR(ABS(R1))
16299c FFEINTRIN_impACOS
16300 call fooR(ACOS(R1))
16301c FFEINTRIN_impAIMAG
16302 call fooR(AIMAG(C1))
16303c FFEINTRIN_impAINT
16304 call fooR(AINT(R1))
16305c FFEINTRIN_impALOG
16306 call fooR(ALOG(R1))
16307c FFEINTRIN_impALOG10
16308 call fooR(ALOG10(R1))
16309c FFEINTRIN_impAMAX0
16310 call fooR(AMAX0(I1,I2))
16311c FFEINTRIN_impAMAX1
16312 call fooR(AMAX1(R1,R2))
16313c FFEINTRIN_impAMIN0
16314 call fooR(AMIN0(I1,I2))
16315c FFEINTRIN_impAMIN1
16316 call fooR(AMIN1(R1,R2))
16317c FFEINTRIN_impAMOD
16318 call fooR(AMOD(R1,R2))
16319c FFEINTRIN_impANINT
16320 call fooR(ANINT(R1))
16321c FFEINTRIN_impASIN
16322 call fooR(ASIN(R1))
16323c FFEINTRIN_impATAN
16324 call fooR(ATAN(R1))
16325c FFEINTRIN_impATAN2
16326 call fooR(ATAN2(R1,R2))
16327c FFEINTRIN_impCABS
16328 call fooR(CABS(C1))
16329c FFEINTRIN_impCCOS
16330 call fooC(CCOS(C1))
16331c FFEINTRIN_impCEXP
16332 call fooC(CEXP(C1))
16333c FFEINTRIN_impCHAR
16334 call fooA(CHAR(I1))
16335c FFEINTRIN_impCLOG
16336 call fooC(CLOG(C1))
16337c FFEINTRIN_impCONJG
16338 call fooC(CONJG(C1))
16339c FFEINTRIN_impCOS
16340 call fooR(COS(R1))
16341c FFEINTRIN_impCOSH
16342 call fooR(COSH(R1))
16343c FFEINTRIN_impCSIN
16344 call fooC(CSIN(C1))
16345c FFEINTRIN_impCSQRT
16346 call fooC(CSQRT(C1))
16347c FFEINTRIN_impDABS
16348 call fooD(DABS(D1))
16349c FFEINTRIN_impDACOS
16350 call fooD(DACOS(D1))
16351c FFEINTRIN_impDASIN
16352 call fooD(DASIN(D1))
16353c FFEINTRIN_impDATAN
16354 call fooD(DATAN(D1))
16355c FFEINTRIN_impDATAN2
16356 call fooD(DATAN2(D1,D2))
16357c FFEINTRIN_impDCOS
16358 call fooD(DCOS(D1))
16359c FFEINTRIN_impDCOSH
16360 call fooD(DCOSH(D1))
16361c FFEINTRIN_impDDIM
16362 call fooD(DDIM(D1,D2))
16363c FFEINTRIN_impDEXP
16364 call fooD(DEXP(D1))
16365c FFEINTRIN_impDIM
16366 call fooR(DIM(R1,R2))
16367c FFEINTRIN_impDINT
16368 call fooD(DINT(D1))
16369c FFEINTRIN_impDLOG
16370 call fooD(DLOG(D1))
16371c FFEINTRIN_impDLOG10
16372 call fooD(DLOG10(D1))
16373c FFEINTRIN_impDMAX1
16374 call fooD(DMAX1(D1,D2))
16375c FFEINTRIN_impDMIN1
16376 call fooD(DMIN1(D1,D2))
16377c FFEINTRIN_impDMOD
16378 call fooD(DMOD(D1,D2))
16379c FFEINTRIN_impDNINT
16380 call fooD(DNINT(D1))
16381c FFEINTRIN_impDPROD
16382 call fooD(DPROD(R1,R2))
16383c FFEINTRIN_impDSIGN
16384 call fooD(DSIGN(D1,D2))
16385c FFEINTRIN_impDSIN
16386 call fooD(DSIN(D1))
16387c FFEINTRIN_impDSINH
16388 call fooD(DSINH(D1))
16389c FFEINTRIN_impDSQRT
16390 call fooD(DSQRT(D1))
16391c FFEINTRIN_impDTAN
16392 call fooD(DTAN(D1))
16393c FFEINTRIN_impDTANH
16394 call fooD(DTANH(D1))
16395c FFEINTRIN_impEXP
16396 call fooR(EXP(R1))
16397c FFEINTRIN_impIABS
16398 call fooI(IABS(I1))
16399c FFEINTRIN_impICHAR
16400 call fooI(ICHAR(A1))
16401c FFEINTRIN_impIDIM
16402 call fooI(IDIM(I1,I2))
16403c FFEINTRIN_impIDNINT
16404 call fooI(IDNINT(D1))
16405c FFEINTRIN_impINDEX
16406 call fooI(INDEX(A1,A2))
16407c FFEINTRIN_impISIGN
16408 call fooI(ISIGN(I1,I2))
16409c FFEINTRIN_impLEN
16410 call fooI(LEN(A1))
16411c FFEINTRIN_impLGE
16412 call fooL(LGE(A1,A2))
16413c FFEINTRIN_impLGT
16414 call fooL(LGT(A1,A2))
16415c FFEINTRIN_impLLE
16416 call fooL(LLE(A1,A2))
16417c FFEINTRIN_impLLT
16418 call fooL(LLT(A1,A2))
16419c FFEINTRIN_impMAX0
16420 call fooI(MAX0(I1,I2))
16421c FFEINTRIN_impMAX1
16422 call fooI(MAX1(R1,R2))
16423c FFEINTRIN_impMIN0
16424 call fooI(MIN0(I1,I2))
16425c FFEINTRIN_impMIN1
16426 call fooI(MIN1(R1,R2))
16427c FFEINTRIN_impMOD
16428 call fooI(MOD(I1,I2))
16429c FFEINTRIN_impNINT
16430 call fooI(NINT(R1))
16431c FFEINTRIN_impSIGN
16432 call fooR(SIGN(R1,R2))
16433c FFEINTRIN_impSIN
16434 call fooR(SIN(R1))
16435c FFEINTRIN_impSINH
16436 call fooR(SINH(R1))
16437c FFEINTRIN_impSQRT
16438 call fooR(SQRT(R1))
16439c FFEINTRIN_impTAN
16440 call fooR(TAN(R1))
16441c FFEINTRIN_impTANH
16442 call fooR(TANH(R1))
16443c FFEINTRIN_imp_CMPLX_C
16444 call fooC(cmplx(C1,C2))
16445c FFEINTRIN_imp_CMPLX_D
16446 call fooZ(cmplx(D1,D2))
16447c FFEINTRIN_imp_CMPLX_I
16448 call fooC(cmplx(I1,I2))
16449c FFEINTRIN_imp_CMPLX_R
16450 call fooC(cmplx(R1,R2))
16451c FFEINTRIN_imp_DBLE_C
16452 call fooD(dble(C1))
16453c FFEINTRIN_imp_DBLE_D
16454 call fooD(dble(D1))
16455c FFEINTRIN_imp_DBLE_I
16456 call fooD(dble(I1))
16457c FFEINTRIN_imp_DBLE_R
16458 call fooD(dble(R1))
16459c FFEINTRIN_imp_INT_C
16460 call fooI(int(C1))
16461c FFEINTRIN_imp_INT_D
16462 call fooI(int(D1))
16463c FFEINTRIN_imp_INT_I
16464 call fooI(int(I1))
16465c FFEINTRIN_imp_INT_R
16466 call fooI(int(R1))
16467c FFEINTRIN_imp_REAL_C
16468 call fooR(real(C1))
16469c FFEINTRIN_imp_REAL_D
16470 call fooR(real(D1))
16471c FFEINTRIN_imp_REAL_I
16472 call fooR(real(I1))
16473c FFEINTRIN_imp_REAL_R
16474 call fooR(real(R1))
16475c
16476c FFEINTRIN_imp_INT_D:
16477c
16478c FFEINTRIN_specIDINT
16479 call fooI(IDINT(D1))
16480c
16481c FFEINTRIN_imp_INT_R:
16482c
16483c FFEINTRIN_specIFIX
16484 call fooI(IFIX(R1))
16485c FFEINTRIN_specINT
16486 call fooI(INT(R1))
16487c
16488c FFEINTRIN_imp_REAL_D:
16489c
16490c FFEINTRIN_specSNGL
16491 call fooR(SNGL(D1))
16492c
16493c FFEINTRIN_imp_REAL_I:
16494c
16495c FFEINTRIN_specFLOAT
16496 call fooR(FLOAT(I1))
16497c FFEINTRIN_specREAL
16498 call fooR(REAL(I1))
16499c
16500 end
16501-------- (end input file to f2c)
5ff904cd 16502
c7e4ee3a
CB
16503-------- (begin output from providing above input file as input to:
16504-------- `f2c | gcc -E -C - | sed -e "s:/[*]*://:g" -e "s:[*]*[/]://:g" \
16505-------- -e "s:^#.*$::g"')
5ff904cd 16506
c7e4ee3a
CB
16507// -- translated by f2c (version 19950223).
16508 You must link the resulting object file with the libraries:
16509 -lf2c -lm (in that order)
16510//
5ff904cd 16511
5ff904cd 16512
c7e4ee3a 16513// f2c.h -- Standard Fortran to C header file //
5ff904cd 16514
c7e4ee3a 16515/// barf [ba:rf] 2. "He suggested using FORTRAN, and everybody barfed."
5ff904cd 16516
c7e4ee3a 16517 - From The Shogakukan DICTIONARY OF NEW ENGLISH (Second edition) //
5ff904cd 16518
5ff904cd 16519
5ff904cd 16520
5ff904cd 16521
c7e4ee3a
CB
16522// F2C_INTEGER will normally be `int' but would be `long' on 16-bit systems //
16523// we assume short, float are OK //
16524typedef long int // long int // integer;
16525typedef char *address;
16526typedef short int shortint;
16527typedef float real;
16528typedef double doublereal;
16529typedef struct { real r, i; } complex;
16530typedef struct { doublereal r, i; } doublecomplex;
16531typedef long int // long int // logical;
16532typedef short int shortlogical;
16533typedef char logical1;
16534typedef char integer1;
16535// typedef long long longint; // // system-dependent //
5ff904cd 16536
5ff904cd 16537
5ff904cd 16538
5ff904cd 16539
c7e4ee3a 16540// Extern is for use with -E //
5ff904cd 16541
5ff904cd 16542
5ff904cd 16543
5ff904cd 16544
c7e4ee3a 16545// I/O stuff //
5ff904cd 16546
5ff904cd 16547
5ff904cd 16548
5ff904cd 16549
5ff904cd 16550
5ff904cd 16551
5ff904cd 16552
5ff904cd 16553
c7e4ee3a
CB
16554typedef long int // int or long int // flag;
16555typedef long int // int or long int // ftnlen;
16556typedef long int // int or long int // ftnint;
5ff904cd 16557
5ff904cd 16558
c7e4ee3a
CB
16559//external read, write//
16560typedef struct
16561{ flag cierr;
16562 ftnint ciunit;
16563 flag ciend;
16564 char *cifmt;
16565 ftnint cirec;
16566} cilist;
5ff904cd 16567
c7e4ee3a
CB
16568//internal read, write//
16569typedef struct
16570{ flag icierr;
16571 char *iciunit;
16572 flag iciend;
16573 char *icifmt;
16574 ftnint icirlen;
16575 ftnint icirnum;
16576} icilist;
5ff904cd 16577
c7e4ee3a
CB
16578//open//
16579typedef struct
16580{ flag oerr;
16581 ftnint ounit;
16582 char *ofnm;
16583 ftnlen ofnmlen;
16584 char *osta;
16585 char *oacc;
16586 char *ofm;
16587 ftnint orl;
16588 char *oblnk;
16589} olist;
5ff904cd 16590
c7e4ee3a
CB
16591//close//
16592typedef struct
16593{ flag cerr;
16594 ftnint cunit;
16595 char *csta;
16596} cllist;
5ff904cd 16597
c7e4ee3a
CB
16598//rewind, backspace, endfile//
16599typedef struct
16600{ flag aerr;
16601 ftnint aunit;
16602} alist;
5ff904cd 16603
c7e4ee3a
CB
16604// inquire //
16605typedef struct
16606{ flag inerr;
16607 ftnint inunit;
16608 char *infile;
16609 ftnlen infilen;
16610 ftnint *inex; //parameters in standard's order//
16611 ftnint *inopen;
16612 ftnint *innum;
16613 ftnint *innamed;
16614 char *inname;
16615 ftnlen innamlen;
16616 char *inacc;
16617 ftnlen inacclen;
16618 char *inseq;
16619 ftnlen inseqlen;
16620 char *indir;
16621 ftnlen indirlen;
16622 char *infmt;
16623 ftnlen infmtlen;
16624 char *inform;
16625 ftnint informlen;
16626 char *inunf;
16627 ftnlen inunflen;
16628 ftnint *inrecl;
16629 ftnint *innrec;
16630 char *inblank;
16631 ftnlen inblanklen;
16632} inlist;
5ff904cd 16633
5ff904cd 16634
5ff904cd 16635
c7e4ee3a
CB
16636union Multitype { // for multiple entry points //
16637 integer1 g;
16638 shortint h;
16639 integer i;
16640 // longint j; //
16641 real r;
16642 doublereal d;
16643 complex c;
16644 doublecomplex z;
16645 };
16646
16647typedef union Multitype Multitype;
5ff904cd 16648
c7e4ee3a 16649typedef long Long; // No longer used; formerly in Namelist //
5ff904cd 16650
c7e4ee3a
CB
16651struct Vardesc { // for Namelist //
16652 char *name;
16653 char *addr;
16654 ftnlen *dims;
16655 int type;
16656 };
16657typedef struct Vardesc Vardesc;
5ff904cd 16658
c7e4ee3a
CB
16659struct Namelist {
16660 char *name;
16661 Vardesc **vars;
16662 int nvars;
16663 };
16664typedef struct Namelist Namelist;
5ff904cd 16665
5ff904cd 16666
5ff904cd 16667
5ff904cd 16668
5ff904cd 16669
5ff904cd 16670
5ff904cd 16671
5ff904cd 16672
c7e4ee3a 16673// procedure parameter types for -A and -C++ //
5ff904cd 16674
5ff904cd 16675
5ff904cd 16676
5ff904cd 16677
c7e4ee3a
CB
16678typedef int // Unknown procedure type // (*U_fp)();
16679typedef shortint (*J_fp)();
16680typedef integer (*I_fp)();
16681typedef real (*R_fp)();
16682typedef doublereal (*D_fp)(), (*E_fp)();
16683typedef // Complex // void (*C_fp)();
16684typedef // Double Complex // void (*Z_fp)();
16685typedef logical (*L_fp)();
16686typedef shortlogical (*K_fp)();
16687typedef // Character // void (*H_fp)();
16688typedef // Subroutine // int (*S_fp)();
5ff904cd 16689
c7e4ee3a
CB
16690// E_fp is for real functions when -R is not specified //
16691typedef void C_f; // complex function //
16692typedef void H_f; // character function //
16693typedef void Z_f; // double complex function //
16694typedef doublereal E_f; // real function with -R not specified //
5ff904cd 16695
c7e4ee3a 16696// undef any lower-case symbols that your C compiler predefines, e.g.: //
5ff904cd 16697
5ff904cd 16698
c7e4ee3a
CB
16699// (No such symbols should be defined in a strict ANSI C compiler.
16700 We can avoid trouble with f2c-translated code by using
16701 gcc -ansi [-traditional].) //
16702
5ff904cd 16703
5ff904cd 16704
5ff904cd 16705
5ff904cd 16706
5ff904cd 16707
5ff904cd 16708
5ff904cd 16709
5ff904cd 16710
5ff904cd 16711
5ff904cd 16712
5ff904cd 16713
5ff904cd 16714
5ff904cd 16715
5ff904cd 16716
5ff904cd 16717
5ff904cd 16718
5ff904cd 16719
5ff904cd 16720
5ff904cd 16721
5ff904cd 16722
5ff904cd 16723
5ff904cd 16724
c7e4ee3a
CB
16725// Main program // MAIN__()
16726{
16727 // System generated locals //
16728 integer i__1;
16729 real r__1, r__2;
16730 doublereal d__1, d__2;
16731 complex q__1;
16732 doublecomplex z__1, z__2, z__3;
16733 logical L__1;
16734 char ch__1[1];
16735
16736 // Builtin functions //
16737 void c_div();
16738 integer pow_ii();
16739 double pow_ri(), pow_di();
16740 void pow_ci();
16741 double pow_dd();
16742 void pow_zz();
16743 double acos(), r_imag(), r_int(), log(), r_lg10(), r_mod(), r_nint(),
16744 asin(), atan(), atan2(), c_abs();
16745 void c_cos(), c_exp(), c_log(), r_cnjg();
16746 double cos(), cosh();
16747 void c_sin(), c_sqrt();
16748 double d_dim(), exp(), r_dim(), d_int(), d_lg10(), d_mod(), d_nint(),
16749 d_sign(), sin(), sinh(), sqrt(), tan(), tanh();
16750 integer i_dim(), i_dnnt(), i_indx(), i_sign(), i_len();
16751 logical l_ge(), l_gt(), l_le(), l_lt();
16752 integer i_nint();
16753 double r_sign();
16754
16755 // Local variables //
16756 extern // Subroutine // int fooa_(), fooc_(), food_(), fooi_(), foor_(),
16757 fool_(), fooz_(), getem_();
16758 static char a1[10], a2[10];
16759 static complex c1, c2;
16760 static doublereal d1, d2;
16761 static integer i1, i2;
16762 static real r1, r2;
16763
16764
16765 getem_(a1, a2, &c1, &c2, &i1, &i2, &r1, &r2, &d1, &d2, 10L, 10L);
16766// / //
16767 i__1 = i1 / i2;
16768 fooi_(&i__1);
16769 r__1 = r1 / i1;
16770 foor_(&r__1);
16771 d__1 = d1 / i1;
16772 food_(&d__1);
16773 d__1 = (doublereal) i1;
16774 q__1.r = c1.r / d__1, q__1.i = c1.i / d__1;
16775 fooc_(&q__1);
16776 r__1 = r1 / r2;
16777 foor_(&r__1);
16778 d__1 = r1 / d1;
16779 food_(&d__1);
16780 d__1 = d1 / d2;
16781 food_(&d__1);
16782 d__1 = d1 / r1;
16783 food_(&d__1);
16784 c_div(&q__1, &c1, &c2);
16785 fooc_(&q__1);
16786 q__1.r = c1.r / r1, q__1.i = c1.i / r1;
16787 fooc_(&q__1);
16788 z__1.r = c1.r / d1, z__1.i = c1.i / d1;
16789 fooz_(&z__1);
16790// ** //
16791 i__1 = pow_ii(&i1, &i2);
16792 fooi_(&i__1);
16793 r__1 = pow_ri(&r1, &i1);
16794 foor_(&r__1);
16795 d__1 = pow_di(&d1, &i1);
16796 food_(&d__1);
16797 pow_ci(&q__1, &c1, &i1);
16798 fooc_(&q__1);
16799 d__1 = (doublereal) r1;
16800 d__2 = (doublereal) r2;
16801 r__1 = pow_dd(&d__1, &d__2);
16802 foor_(&r__1);
16803 d__2 = (doublereal) r1;
16804 d__1 = pow_dd(&d__2, &d1);
16805 food_(&d__1);
16806 d__1 = pow_dd(&d1, &d2);
16807 food_(&d__1);
16808 d__2 = (doublereal) r1;
16809 d__1 = pow_dd(&d1, &d__2);
16810 food_(&d__1);
16811 z__2.r = c1.r, z__2.i = c1.i;
16812 z__3.r = c2.r, z__3.i = c2.i;
16813 pow_zz(&z__1, &z__2, &z__3);
16814 q__1.r = z__1.r, q__1.i = z__1.i;
16815 fooc_(&q__1);
16816 z__2.r = c1.r, z__2.i = c1.i;
16817 z__3.r = r1, z__3.i = 0.;
16818 pow_zz(&z__1, &z__2, &z__3);
16819 q__1.r = z__1.r, q__1.i = z__1.i;
16820 fooc_(&q__1);
16821 z__2.r = c1.r, z__2.i = c1.i;
16822 z__3.r = d1, z__3.i = 0.;
16823 pow_zz(&z__1, &z__2, &z__3);
16824 fooz_(&z__1);
16825// FFEINTRIN_impABS //
16826 r__1 = (doublereal)(( r1 ) >= 0 ? ( r1 ) : -( r1 )) ;
16827 foor_(&r__1);
16828// FFEINTRIN_impACOS //
16829 r__1 = acos(r1);
16830 foor_(&r__1);
16831// FFEINTRIN_impAIMAG //
16832 r__1 = r_imag(&c1);
16833 foor_(&r__1);
16834// FFEINTRIN_impAINT //
16835 r__1 = r_int(&r1);
16836 foor_(&r__1);
16837// FFEINTRIN_impALOG //
16838 r__1 = log(r1);
16839 foor_(&r__1);
16840// FFEINTRIN_impALOG10 //
16841 r__1 = r_lg10(&r1);
16842 foor_(&r__1);
16843// FFEINTRIN_impAMAX0 //
16844 r__1 = (real) (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
16845 foor_(&r__1);
16846// FFEINTRIN_impAMAX1 //
16847 r__1 = (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
16848 foor_(&r__1);
16849// FFEINTRIN_impAMIN0 //
16850 r__1 = (real) (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
16851 foor_(&r__1);
16852// FFEINTRIN_impAMIN1 //
16853 r__1 = (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
16854 foor_(&r__1);
16855// FFEINTRIN_impAMOD //
16856 r__1 = r_mod(&r1, &r2);
16857 foor_(&r__1);
16858// FFEINTRIN_impANINT //
16859 r__1 = r_nint(&r1);
16860 foor_(&r__1);
16861// FFEINTRIN_impASIN //
16862 r__1 = asin(r1);
16863 foor_(&r__1);
16864// FFEINTRIN_impATAN //
16865 r__1 = atan(r1);
16866 foor_(&r__1);
16867// FFEINTRIN_impATAN2 //
16868 r__1 = atan2(r1, r2);
16869 foor_(&r__1);
16870// FFEINTRIN_impCABS //
16871 r__1 = c_abs(&c1);
16872 foor_(&r__1);
16873// FFEINTRIN_impCCOS //
16874 c_cos(&q__1, &c1);
16875 fooc_(&q__1);
16876// FFEINTRIN_impCEXP //
16877 c_exp(&q__1, &c1);
16878 fooc_(&q__1);
16879// FFEINTRIN_impCHAR //
16880 *(unsigned char *)&ch__1[0] = i1;
16881 fooa_(ch__1, 1L);
16882// FFEINTRIN_impCLOG //
16883 c_log(&q__1, &c1);
16884 fooc_(&q__1);
16885// FFEINTRIN_impCONJG //
16886 r_cnjg(&q__1, &c1);
16887 fooc_(&q__1);
16888// FFEINTRIN_impCOS //
16889 r__1 = cos(r1);
16890 foor_(&r__1);
16891// FFEINTRIN_impCOSH //
16892 r__1 = cosh(r1);
16893 foor_(&r__1);
16894// FFEINTRIN_impCSIN //
16895 c_sin(&q__1, &c1);
16896 fooc_(&q__1);
16897// FFEINTRIN_impCSQRT //
16898 c_sqrt(&q__1, &c1);
16899 fooc_(&q__1);
16900// FFEINTRIN_impDABS //
16901 d__1 = (( d1 ) >= 0 ? ( d1 ) : -( d1 )) ;
16902 food_(&d__1);
16903// FFEINTRIN_impDACOS //
16904 d__1 = acos(d1);
16905 food_(&d__1);
16906// FFEINTRIN_impDASIN //
16907 d__1 = asin(d1);
16908 food_(&d__1);
16909// FFEINTRIN_impDATAN //
16910 d__1 = atan(d1);
16911 food_(&d__1);
16912// FFEINTRIN_impDATAN2 //
16913 d__1 = atan2(d1, d2);
16914 food_(&d__1);
16915// FFEINTRIN_impDCOS //
16916 d__1 = cos(d1);
16917 food_(&d__1);
16918// FFEINTRIN_impDCOSH //
16919 d__1 = cosh(d1);
16920 food_(&d__1);
16921// FFEINTRIN_impDDIM //
16922 d__1 = d_dim(&d1, &d2);
16923 food_(&d__1);
16924// FFEINTRIN_impDEXP //
16925 d__1 = exp(d1);
16926 food_(&d__1);
16927// FFEINTRIN_impDIM //
16928 r__1 = r_dim(&r1, &r2);
16929 foor_(&r__1);
16930// FFEINTRIN_impDINT //
16931 d__1 = d_int(&d1);
16932 food_(&d__1);
16933// FFEINTRIN_impDLOG //
16934 d__1 = log(d1);
16935 food_(&d__1);
16936// FFEINTRIN_impDLOG10 //
16937 d__1 = d_lg10(&d1);
16938 food_(&d__1);
16939// FFEINTRIN_impDMAX1 //
16940 d__1 = (( d1 ) >= ( d2 ) ? ( d1 ) : ( d2 )) ;
16941 food_(&d__1);
16942// FFEINTRIN_impDMIN1 //
16943 d__1 = (( d1 ) <= ( d2 ) ? ( d1 ) : ( d2 )) ;
16944 food_(&d__1);
16945// FFEINTRIN_impDMOD //
16946 d__1 = d_mod(&d1, &d2);
16947 food_(&d__1);
16948// FFEINTRIN_impDNINT //
16949 d__1 = d_nint(&d1);
16950 food_(&d__1);
16951// FFEINTRIN_impDPROD //
16952 d__1 = (doublereal) r1 * r2;
16953 food_(&d__1);
16954// FFEINTRIN_impDSIGN //
16955 d__1 = d_sign(&d1, &d2);
16956 food_(&d__1);
16957// FFEINTRIN_impDSIN //
16958 d__1 = sin(d1);
16959 food_(&d__1);
16960// FFEINTRIN_impDSINH //
16961 d__1 = sinh(d1);
16962 food_(&d__1);
16963// FFEINTRIN_impDSQRT //
16964 d__1 = sqrt(d1);
16965 food_(&d__1);
16966// FFEINTRIN_impDTAN //
16967 d__1 = tan(d1);
16968 food_(&d__1);
16969// FFEINTRIN_impDTANH //
16970 d__1 = tanh(d1);
16971 food_(&d__1);
16972// FFEINTRIN_impEXP //
16973 r__1 = exp(r1);
16974 foor_(&r__1);
16975// FFEINTRIN_impIABS //
16976 i__1 = (( i1 ) >= 0 ? ( i1 ) : -( i1 )) ;
16977 fooi_(&i__1);
16978// FFEINTRIN_impICHAR //
16979 i__1 = *(unsigned char *)a1;
16980 fooi_(&i__1);
16981// FFEINTRIN_impIDIM //
16982 i__1 = i_dim(&i1, &i2);
16983 fooi_(&i__1);
16984// FFEINTRIN_impIDNINT //
16985 i__1 = i_dnnt(&d1);
16986 fooi_(&i__1);
16987// FFEINTRIN_impINDEX //
16988 i__1 = i_indx(a1, a2, 10L, 10L);
16989 fooi_(&i__1);
16990// FFEINTRIN_impISIGN //
16991 i__1 = i_sign(&i1, &i2);
16992 fooi_(&i__1);
16993// FFEINTRIN_impLEN //
16994 i__1 = i_len(a1, 10L);
16995 fooi_(&i__1);
16996// FFEINTRIN_impLGE //
16997 L__1 = l_ge(a1, a2, 10L, 10L);
16998 fool_(&L__1);
16999// FFEINTRIN_impLGT //
17000 L__1 = l_gt(a1, a2, 10L, 10L);
17001 fool_(&L__1);
17002// FFEINTRIN_impLLE //
17003 L__1 = l_le(a1, a2, 10L, 10L);
17004 fool_(&L__1);
17005// FFEINTRIN_impLLT //
17006 L__1 = l_lt(a1, a2, 10L, 10L);
17007 fool_(&L__1);
17008// FFEINTRIN_impMAX0 //
17009 i__1 = (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
17010 fooi_(&i__1);
17011// FFEINTRIN_impMAX1 //
17012 i__1 = (integer) (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
17013 fooi_(&i__1);
17014// FFEINTRIN_impMIN0 //
17015 i__1 = (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
17016 fooi_(&i__1);
17017// FFEINTRIN_impMIN1 //
17018 i__1 = (integer) (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
17019 fooi_(&i__1);
17020// FFEINTRIN_impMOD //
17021 i__1 = i1 % i2;
17022 fooi_(&i__1);
17023// FFEINTRIN_impNINT //
17024 i__1 = i_nint(&r1);
17025 fooi_(&i__1);
17026// FFEINTRIN_impSIGN //
17027 r__1 = r_sign(&r1, &r2);
17028 foor_(&r__1);
17029// FFEINTRIN_impSIN //
17030 r__1 = sin(r1);
17031 foor_(&r__1);
17032// FFEINTRIN_impSINH //
17033 r__1 = sinh(r1);
17034 foor_(&r__1);
17035// FFEINTRIN_impSQRT //
17036 r__1 = sqrt(r1);
17037 foor_(&r__1);
17038// FFEINTRIN_impTAN //
17039 r__1 = tan(r1);
17040 foor_(&r__1);
17041// FFEINTRIN_impTANH //
17042 r__1 = tanh(r1);
17043 foor_(&r__1);
17044// FFEINTRIN_imp_CMPLX_C //
17045 r__1 = c1.r;
17046 r__2 = c2.r;
17047 q__1.r = r__1, q__1.i = r__2;
17048 fooc_(&q__1);
17049// FFEINTRIN_imp_CMPLX_D //
17050 z__1.r = d1, z__1.i = d2;
17051 fooz_(&z__1);
17052// FFEINTRIN_imp_CMPLX_I //
17053 r__1 = (real) i1;
17054 r__2 = (real) i2;
17055 q__1.r = r__1, q__1.i = r__2;
17056 fooc_(&q__1);
17057// FFEINTRIN_imp_CMPLX_R //
17058 q__1.r = r1, q__1.i = r2;
17059 fooc_(&q__1);
17060// FFEINTRIN_imp_DBLE_C //
17061 d__1 = (doublereal) c1.r;
17062 food_(&d__1);
17063// FFEINTRIN_imp_DBLE_D //
17064 d__1 = d1;
17065 food_(&d__1);
17066// FFEINTRIN_imp_DBLE_I //
17067 d__1 = (doublereal) i1;
17068 food_(&d__1);
17069// FFEINTRIN_imp_DBLE_R //
17070 d__1 = (doublereal) r1;
17071 food_(&d__1);
17072// FFEINTRIN_imp_INT_C //
17073 i__1 = (integer) c1.r;
17074 fooi_(&i__1);
17075// FFEINTRIN_imp_INT_D //
17076 i__1 = (integer) d1;
17077 fooi_(&i__1);
17078// FFEINTRIN_imp_INT_I //
17079 i__1 = i1;
17080 fooi_(&i__1);
17081// FFEINTRIN_imp_INT_R //
17082 i__1 = (integer) r1;
17083 fooi_(&i__1);
17084// FFEINTRIN_imp_REAL_C //
17085 r__1 = c1.r;
17086 foor_(&r__1);
17087// FFEINTRIN_imp_REAL_D //
17088 r__1 = (real) d1;
17089 foor_(&r__1);
17090// FFEINTRIN_imp_REAL_I //
17091 r__1 = (real) i1;
17092 foor_(&r__1);
17093// FFEINTRIN_imp_REAL_R //
17094 r__1 = r1;
17095 foor_(&r__1);
17096
17097// FFEINTRIN_imp_INT_D: //
17098
17099// FFEINTRIN_specIDINT //
17100 i__1 = (integer) d1;
17101 fooi_(&i__1);
17102
17103// FFEINTRIN_imp_INT_R: //
17104
17105// FFEINTRIN_specIFIX //
17106 i__1 = (integer) r1;
17107 fooi_(&i__1);
17108// FFEINTRIN_specINT //
17109 i__1 = (integer) r1;
17110 fooi_(&i__1);
17111
17112// FFEINTRIN_imp_REAL_D: //
5ff904cd 17113
c7e4ee3a
CB
17114// FFEINTRIN_specSNGL //
17115 r__1 = (real) d1;
17116 foor_(&r__1);
5ff904cd 17117
c7e4ee3a 17118// FFEINTRIN_imp_REAL_I: //
5ff904cd 17119
c7e4ee3a
CB
17120// FFEINTRIN_specFLOAT //
17121 r__1 = (real) i1;
17122 foor_(&r__1);
17123// FFEINTRIN_specREAL //
17124 r__1 = (real) i1;
17125 foor_(&r__1);
5ff904cd 17126
c7e4ee3a 17127} // MAIN__ //
5ff904cd 17128
c7e4ee3a 17129-------- (end output file from f2c)
5ff904cd 17130
c7e4ee3a 17131*/
This page took 3.258677 seconds and 5 git commands to generate.