]> gcc.gnu.org Git - gcc.git/blame - gcc/f/com.c
* varasm.c (output_constant): Recompute CODE after lang-specific fn.
[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"
5ff904cd
JL
92#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
93
94#define FFECOM_GCC_INCLUDE 1 /* Enable -I. */
95
96/* BEGIN stuff from gcc/cccp.c. */
97
98/* The following symbols should be autoconfigured:
99 HAVE_FCNTL_H
100 HAVE_STDLIB_H
101 HAVE_SYS_TIME_H
102 HAVE_UNISTD_H
103 STDC_HEADERS
104 TIME_WITH_SYS_TIME
105 In the mean time, we'll get by with approximations based
106 on existing GCC configuration symbols. */
107
108#ifdef POSIX
109# ifndef HAVE_STDLIB_H
110# define HAVE_STDLIB_H 1
111# endif
112# ifndef HAVE_UNISTD_H
113# define HAVE_UNISTD_H 1
114# endif
115# ifndef STDC_HEADERS
116# define STDC_HEADERS 1
117# endif
118#endif /* defined (POSIX) */
119
120#if defined (POSIX) || (defined (USG) && !defined (VMS))
121# ifndef HAVE_FCNTL_H
122# define HAVE_FCNTL_H 1
123# endif
124#endif
125
0d5d970b 126#ifdef RLIMIT_STACK
5ff904cd
JL
127# include <sys/resource.h>
128#endif
129
130#if HAVE_FCNTL_H
131# include <fcntl.h>
132#endif
133
134/* This defines "errno" properly for VMS, and gives us EACCES. */
135#include <errno.h>
136
137#if HAVE_STDLIB_H
138# include <stdlib.h>
139#else
140char *getenv ();
141#endif
142
5ff904cd
JL
143#if HAVE_UNISTD_H
144# include <unistd.h>
145#endif
146
147/* VMS-specific definitions */
148#ifdef VMS
149#include <descrip.h>
150#define O_RDONLY 0 /* Open arg for Read/Only */
151#define O_WRONLY 1 /* Open arg for Write/Only */
152#define read(fd,buf,size) VMS_read (fd,buf,size)
153#define write(fd,buf,size) VMS_write (fd,buf,size)
154#define open(fname,mode,prot) VMS_open (fname,mode,prot)
155#define fopen(fname,mode) VMS_fopen (fname,mode)
156#define freopen(fname,mode,ofile) VMS_freopen (fname,mode,ofile)
157#define strncat(dst,src,cnt) VMS_strncat (dst,src,cnt)
158#define fstat(fd,stbuf) VMS_fstat (fd,stbuf)
159static int VMS_fstat (), VMS_stat ();
160static char * VMS_strncat ();
161static int VMS_read ();
162static int VMS_write ();
163static int VMS_open ();
164static FILE * VMS_fopen ();
165static FILE * VMS_freopen ();
166static void hack_vms_include_specification ();
167typedef struct { unsigned :16, :16, :16; } vms_ino_t;
168#define ino_t vms_ino_t
169#define INCLUDE_LEN_FUDGE 10 /* leave room for VMS syntax conversion */
5ff904cd
JL
170#endif /* VMS */
171
172#ifndef O_RDONLY
173#define O_RDONLY 0
174#endif
175
176/* END stuff from gcc/cccp.c. */
177
5ff904cd
JL
178#define FFECOM_DETERMINE_TYPES 1 /* for com.h */
179#include "com.h"
180#include "bad.h"
181#include "bld.h"
182#include "equiv.h"
183#include "expr.h"
184#include "implic.h"
185#include "info.h"
186#include "malloc.h"
187#include "src.h"
188#include "st.h"
189#include "storag.h"
190#include "symbol.h"
191#include "target.h"
192#include "top.h"
193#include "type.h"
194
195/* Externals defined here. */
196
5ff904cd
JL
197#if FFECOM_targetCURRENT == FFECOM_targetGCC
198
c7e4ee3a
CB
199/* ~~gcc/tree.h *should* declare this, because toplev.c and dwarfout.c
200 reference it. */
5ff904cd 201
f425a887 202const char * const language_string = "GNU F77";
5ff904cd 203
77f77701
DB
204/* Stream for reading from the input file. */
205FILE *finput;
206
5ff904cd
JL
207/* These definitions parallel those in c-decl.c so that code from that
208 module can be used pretty much as is. Much of these defs aren't
209 otherwise used, i.e. by g77 code per se, except some of them are used
210 to build some of them that are. The ones that are global (i.e. not
211 "static") are those that ste.c and such might use (directly
212 or by using com macros that reference them in their definitions). */
213
5ff904cd
JL
214tree string_type_node;
215
5ff904cd
JL
216/* The rest of these are inventions for g77, though there might be
217 similar things in the C front end. As they are found, these
218 inventions should be renamed to be canonical. Note that only
219 the ones currently required to be global are so. */
220
221static tree ffecom_tree_fun_type_void;
5ff904cd
JL
222
223tree ffecom_integer_type_node; /* Abbrev for _tree_type[blah][blah]. */
224tree ffecom_integer_zero_node; /* Like *_*_* with g77's integer type. */
225tree ffecom_integer_one_node; /* " */
226tree ffecom_tree_type[FFEINFO_basictype][FFEINFO_kindtype];
227
228/* _fun_type things are the f2c-specific versions. For -fno-f2c,
229 just use build_function_type and build_pointer_type on the
230 appropriate _tree_type array element. */
231
232static tree ffecom_tree_fun_type[FFEINFO_basictype][FFEINFO_kindtype];
233static tree ffecom_tree_ptr_to_fun_type[FFEINFO_basictype][FFEINFO_kindtype];
234static tree ffecom_tree_subr_type;
235static tree ffecom_tree_ptr_to_subr_type;
236static tree ffecom_tree_blockdata_type;
237
238static tree ffecom_tree_xargc_;
239
240ffecomSymbol ffecom_symbol_null_
241=
242{
243 NULL_TREE,
244 NULL_TREE,
245 NULL_TREE,
0816ebdd
KG
246 NULL_TREE,
247 false
5ff904cd
JL
248};
249ffeinfoKindtype ffecom_pointer_kind_ = FFEINFO_basictypeNONE;
250ffeinfoKindtype ffecom_label_kind_ = FFEINFO_basictypeNONE;
251
252int ffecom_f2c_typecode_[FFEINFO_basictype][FFEINFO_kindtype];
253tree ffecom_f2c_integer_type_node;
254tree ffecom_f2c_ptr_to_integer_type_node;
255tree ffecom_f2c_address_type_node;
256tree ffecom_f2c_real_type_node;
257tree ffecom_f2c_ptr_to_real_type_node;
258tree ffecom_f2c_doublereal_type_node;
259tree ffecom_f2c_complex_type_node;
260tree ffecom_f2c_doublecomplex_type_node;
261tree ffecom_f2c_longint_type_node;
262tree ffecom_f2c_logical_type_node;
263tree ffecom_f2c_flag_type_node;
264tree ffecom_f2c_ftnlen_type_node;
265tree ffecom_f2c_ftnlen_zero_node;
266tree ffecom_f2c_ftnlen_one_node;
267tree ffecom_f2c_ftnlen_two_node;
268tree ffecom_f2c_ptr_to_ftnlen_type_node;
269tree ffecom_f2c_ftnint_type_node;
270tree ffecom_f2c_ptr_to_ftnint_type_node;
271#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
272
273/* Simple definitions and enumerations. */
274
275#ifndef FFECOM_sizeMAXSTACKITEM
276#define FFECOM_sizeMAXSTACKITEM 32*1024 /* Keep user-declared things
277 larger than this # bytes
278 off stack if possible. */
279#endif
280
281/* For systems that have large enough stacks, they should define
282 this to 0, and here, for ease of use later on, we just undefine
283 it if it is 0. */
284
285#if FFECOM_sizeMAXSTACKITEM == 0
286#undef FFECOM_sizeMAXSTACKITEM
287#endif
288
289typedef enum
290 {
291 FFECOM_rttypeVOID_,
6d433196 292 FFECOM_rttypeVOIDSTAR_, /* C's `void *' type. */
795232f7
JL
293 FFECOM_rttypeFTNINT_, /* f2c's `ftnint' type. */
294 FFECOM_rttypeINTEGER_, /* f2c's `integer' type. */
295 FFECOM_rttypeLONGINT_, /* f2c's `longint' type. */
296 FFECOM_rttypeLOGICAL_, /* f2c's `logical' type. */
297 FFECOM_rttypeREAL_F2C_, /* f2c's `real' returned as `double'. */
298 FFECOM_rttypeREAL_GNU_, /* `real' returned as such. */
5ff904cd 299 FFECOM_rttypeCOMPLEX_F2C_, /* f2c's `complex' returned via 1st arg. */
795232f7 300 FFECOM_rttypeCOMPLEX_GNU_, /* f2c's `complex' returned directly. */
5ff904cd 301 FFECOM_rttypeDOUBLE_, /* C's `double' type. */
795232f7 302 FFECOM_rttypeDOUBLEREAL_, /* f2c's `doublereal' type. */
5ff904cd 303 FFECOM_rttypeDBLCMPLX_F2C_, /* f2c's `doublecomplex' returned via 1st arg. */
795232f7 304 FFECOM_rttypeDBLCMPLX_GNU_, /* f2c's `doublecomplex' returned directly. */
5ff904cd
JL
305 FFECOM_rttypeCHARACTER_, /* f2c `char *'/`ftnlen' pair. */
306 FFECOM_rttype_
307 } ffecomRttype_;
308
309/* Internal typedefs. */
310
311#if FFECOM_targetCURRENT == FFECOM_targetGCC
312typedef struct _ffecom_concat_list_ ffecomConcatList_;
5ff904cd
JL
313#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
314
315/* Private include files. */
316
317
318/* Internal structure definitions. */
319
320#if FFECOM_targetCURRENT == FFECOM_targetGCC
321struct _ffecom_concat_list_
322 {
323 ffebld *exprs;
324 int count;
325 int max;
326 ffetargetCharacterSize minlen;
327 ffetargetCharacterSize maxlen;
328 };
5ff904cd
JL
329#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
330
331/* Static functions (internal). */
332
333#if FFECOM_targetCURRENT == FFECOM_targetGCC
26f096f9 334static tree ffecom_arglist_expr_ (const char *argstring, ffebld args);
5ff904cd
JL
335static tree ffecom_widest_expr_type_ (ffebld list);
336static bool ffecom_overlap_ (tree dest_decl, tree dest_offset,
337 tree dest_size, tree source_tree,
338 ffebld source, bool scalar_arg);
339static bool ffecom_args_overlapping_ (tree dest_tree, ffebld dest,
340 tree args, tree callee_commons,
341 bool scalar_args);
26f096f9 342static tree ffecom_build_f2c_string_ (int i, const char *s);
5ff904cd
JL
343static tree ffecom_call_ (tree fn, ffeinfoKindtype kt,
344 bool is_f2c_complex, tree type,
345 tree args, tree dest_tree,
346 ffebld dest, bool *dest_used,
c7e4ee3a 347 tree callee_commons, bool scalar_args, tree hook);
5ff904cd
JL
348static tree ffecom_call_binop_ (tree fn, ffeinfoKindtype kt,
349 bool is_f2c_complex, tree type,
350 ffebld left, ffebld right,
351 tree dest_tree, ffebld dest,
352 bool *dest_used, tree callee_commons,
95eb4fd9 353 bool scalar_args, bool ref, tree hook);
86fc7a6c
CB
354static void ffecom_char_args_x_ (tree *xitem, tree *length,
355 ffebld expr, bool with_null);
5ff904cd
JL
356static tree ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy);
357static tree ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s);
358static ffecomConcatList_
359 ffecom_concat_list_gather_ (ffecomConcatList_ catlist,
360 ffebld expr,
361 ffetargetCharacterSize max);
362static void ffecom_concat_list_kill_ (ffecomConcatList_ catlist);
363static ffecomConcatList_ ffecom_concat_list_new_ (ffebld expr,
364 ffetargetCharacterSize max);
26f096f9
KG
365static void ffecom_debug_kludge_ (tree aggr, const char *aggr_type,
366 ffesymbol member, tree member_type,
367 ffetargetOffset offset);
5ff904cd 368static void ffecom_do_entry_ (ffesymbol fn, int entrynum);
092a4ef8
RH
369static tree ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
370 bool *dest_used, bool assignp, bool widenp);
5ff904cd
JL
371static tree ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
372 ffebld dest, bool *dest_used);
c7e4ee3a 373static tree ffecom_expr_power_integer_ (ffebld expr);
5ff904cd 374static void ffecom_expr_transform_ (ffebld expr);
26f096f9 375static void ffecom_f2c_make_type_ (tree *type, int tcode, const char *name);
5ff904cd
JL
376static void ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size,
377 int code);
378static ffeglobal ffecom_finish_global_ (ffeglobal global);
379static ffesymbol ffecom_finish_symbol_transform_ (ffesymbol s);
26f096f9 380static tree ffecom_get_appended_identifier_ (char us, const char *text);
5ff904cd 381static tree ffecom_get_external_identifier_ (ffesymbol s);
26f096f9 382static tree ffecom_get_identifier_ (const char *text);
5ff904cd
JL
383static tree ffecom_gen_sfuncdef_ (ffesymbol s,
384 ffeinfoBasictype bt,
385 ffeinfoKindtype kt);
26f096f9 386static const char *ffecom_gfrt_args_ (ffecomGfrt ix);
5ff904cd
JL
387static tree ffecom_gfrt_tree_ (ffecomGfrt ix);
388static tree ffecom_init_zero_ (tree decl);
389static tree ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg,
390 tree *maybe_tree);
391static tree ffecom_intrinsic_len_ (ffebld expr);
392static void ffecom_let_char_ (tree dest_tree,
393 tree dest_length,
394 ffetargetCharacterSize dest_size,
395 ffebld source);
396static void ffecom_make_gfrt_ (ffecomGfrt ix);
397static void ffecom_member_phase1_ (ffestorag mst, ffestorag st);
5ff904cd 398static void ffecom_member_phase2_ (ffestorag mst, ffestorag st);
c7e4ee3a
CB
399static void ffecom_prepare_let_char_ (ffetargetCharacterSize dest_size,
400 ffebld source);
5ff904cd
JL
401static void ffecom_push_dummy_decls_ (ffebld dumlist,
402 bool stmtfunc);
403static void ffecom_start_progunit_ (void);
404static ffesymbol ffecom_sym_transform_ (ffesymbol s);
405static ffesymbol ffecom_sym_transform_assign_ (ffesymbol s);
406static void ffecom_transform_common_ (ffesymbol s);
407static void ffecom_transform_equiv_ (ffestorag st);
408static tree ffecom_transform_namelist_ (ffesymbol s);
409static void ffecom_tree_canonize_ptr_ (tree *decl, tree *offset,
410 tree t);
411static void ffecom_tree_canonize_ref_ (tree *decl, tree *offset,
412 tree *size, tree tree);
413static tree ffecom_tree_divide_ (tree tree_type, tree left, tree right,
414 tree dest_tree, ffebld dest,
c7e4ee3a 415 bool *dest_used, tree hook);
5ff904cd
JL
416static tree ffecom_type_localvar_ (ffesymbol s,
417 ffeinfoBasictype bt,
418 ffeinfoKindtype kt);
419static tree ffecom_type_namelist_ (void);
5ff904cd
JL
420static tree ffecom_type_vardesc_ (void);
421static tree ffecom_vardesc_ (ffebld expr);
422static tree ffecom_vardesc_array_ (ffesymbol s);
423static tree ffecom_vardesc_dims_ (ffesymbol s);
26f096f9
KG
424static tree ffecom_convert_narrow_ (tree type, tree expr);
425static tree ffecom_convert_widen_ (tree type, tree expr);
5ff904cd
JL
426#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
427
428/* These are static functions that parallel those found in the C front
429 end and thus have the same names. */
430
431#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a 432static tree bison_rule_compstmt_ (void);
5ff904cd 433static void bison_rule_pushlevel_ (void);
c7e4ee3a 434static void delete_block (tree block);
5ff904cd
JL
435static int duplicate_decls (tree newdecl, tree olddecl);
436static void finish_decl (tree decl, tree init, bool is_top_level);
437static void finish_function (int nested);
4b731ffa 438static const char *lang_printable_name (tree decl, int v);
5ff904cd
JL
439static tree lookup_name_current_level (tree name);
440static struct binding_level *make_binding_level (void);
441static void pop_f_function_context (void);
442static void push_f_function_context (void);
443static void push_parm_decl (tree parm);
444static tree pushdecl_top_level (tree decl);
c7e4ee3a 445static int kept_level_p (void);
5ff904cd
JL
446static tree storedecls (tree decls);
447static void store_parm_decls (int is_main_program);
448static tree start_decl (tree decl, bool is_top_level);
449static void start_function (tree name, tree type, int nested, int public);
450#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
451#if FFECOM_GCC_INCLUDE
b0791fa9 452static void ffecom_file_ (const char *name);
5ff904cd
JL
453static void ffecom_initialize_char_syntax_ (void);
454static void ffecom_close_include_ (FILE *f);
455static int ffecom_decode_include_option_ (char *spec);
456static FILE *ffecom_open_include_ (char *name, ffewhereLine l,
457 ffewhereColumn c);
458#endif /* FFECOM_GCC_INCLUDE */
459
460/* Static objects accessed by functions in this module. */
461
462static ffesymbol ffecom_primary_entry_ = NULL;
463static ffesymbol ffecom_nested_entry_ = NULL;
464static ffeinfoKind ffecom_primary_entry_kind_;
465static bool ffecom_primary_entry_is_proc_;
466#if FFECOM_targetCURRENT == FFECOM_targetGCC
467static tree ffecom_outer_function_decl_;
468static tree ffecom_previous_function_decl_;
469static tree ffecom_which_entrypoint_decl_;
5ff904cd
JL
470static tree ffecom_float_zero_ = NULL_TREE;
471static tree ffecom_float_half_ = NULL_TREE;
472static tree ffecom_double_zero_ = NULL_TREE;
473static tree ffecom_double_half_ = NULL_TREE;
474static tree ffecom_func_result_;/* For functions. */
475static tree ffecom_func_length_;/* For CHARACTER fns. */
476static ffebld ffecom_list_blockdata_;
477static ffebld ffecom_list_common_;
478static ffebld ffecom_master_arglist_;
479static ffeinfoBasictype ffecom_master_bt_;
480static ffeinfoKindtype ffecom_master_kt_;
481static ffetargetCharacterSize ffecom_master_size_;
482static int ffecom_num_fns_ = 0;
483static int ffecom_num_entrypoints_ = 0;
484static bool ffecom_is_altreturning_ = FALSE;
485static tree ffecom_multi_type_node_;
486static tree ffecom_multi_retval_;
487static tree
488 ffecom_multi_fields_[FFEINFO_basictype][FFEINFO_kindtype];
489static bool ffecom_member_namelisted_; /* _member_phase1_ namelisted? */
490static bool ffecom_doing_entry_ = FALSE;
491static bool ffecom_transform_only_dummies_ = FALSE;
ff852b44
CB
492static int ffecom_typesize_pointer_;
493static int ffecom_typesize_integer1_;
5ff904cd
JL
494
495/* Holds pointer-to-function expressions. */
496
497static tree ffecom_gfrt_[FFECOM_gfrt]
498=
499{
95eb4fd9 500#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) NULL_TREE,
5ff904cd
JL
501#include "com-rt.def"
502#undef DEFGFRT
503};
504
505/* Holds the external names of the functions. */
506
26f096f9 507static const char *ffecom_gfrt_name_[FFECOM_gfrt]
5ff904cd
JL
508=
509{
95eb4fd9 510#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) NAME,
5ff904cd
JL
511#include "com-rt.def"
512#undef DEFGFRT
513};
514
515/* Whether the function returns. */
516
517static bool ffecom_gfrt_volatile_[FFECOM_gfrt]
518=
519{
95eb4fd9 520#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) VOLATILE,
5ff904cd
JL
521#include "com-rt.def"
522#undef DEFGFRT
523};
524
525/* Whether the function returns type complex. */
526
527static bool ffecom_gfrt_complex_[FFECOM_gfrt]
528=
529{
95eb4fd9
TM
530#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) COMPLEX,
531#include "com-rt.def"
532#undef DEFGFRT
533};
534
535/* Whether the function is const
536 (i.e., has no side effects and only depends on its arguments). */
537
538static bool ffecom_gfrt_const_[FFECOM_gfrt]
539=
540{
541#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) CONST,
5ff904cd
JL
542#include "com-rt.def"
543#undef DEFGFRT
544};
545
546/* Type code for the function return value. */
547
548static ffecomRttype_ ffecom_gfrt_type_[FFECOM_gfrt]
549=
550{
95eb4fd9 551#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) TYPE,
5ff904cd
JL
552#include "com-rt.def"
553#undef DEFGFRT
554};
555
556/* String of codes for the function's arguments. */
557
26f096f9 558static const char *ffecom_gfrt_argstring_[FFECOM_gfrt]
5ff904cd
JL
559=
560{
95eb4fd9 561#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) ARGS,
5ff904cd
JL
562#include "com-rt.def"
563#undef DEFGFRT
564};
565#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
566
567/* Internal macros. */
568
569#if FFECOM_targetCURRENT == FFECOM_targetGCC
570
571/* We let tm.h override the types used here, to handle trivial differences
572 such as the choice of unsigned int or long unsigned int for size_t.
573 When machines start needing nontrivial differences in the size type,
574 it would be best to do something here to figure out automatically
575 from other information what type to use. */
576
ff852b44
CB
577#ifndef SIZE_TYPE
578#define SIZE_TYPE "long unsigned int"
579#endif
5ff904cd 580
5ff904cd
JL
581#define ffecom_concat_list_count_(catlist) ((catlist).count)
582#define ffecom_concat_list_expr_(catlist,i) ((catlist).exprs[(i)])
583#define ffecom_concat_list_maxlen_(catlist) ((catlist).maxlen)
584#define ffecom_concat_list_minlen_(catlist) ((catlist).minlen)
585
86fc7a6c
CB
586#define ffecom_char_args_(i,l,e) ffecom_char_args_x_((i),(l),(e),FALSE)
587#define ffecom_char_args_with_null_(i,l,e) ffecom_char_args_x_((i),(l),(e),TRUE)
588
5ff904cd
JL
589/* For each binding contour we allocate a binding_level structure
590 * which records the names defined in that contour.
591 * Contours include:
592 * 0) the global one
593 * 1) one for each function definition,
594 * where internal declarations of the parameters appear.
595 *
596 * The current meaning of a name can be found by searching the levels from
597 * the current one out to the global one.
598 */
599
600/* Note that the information in the `names' component of the global contour
601 is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers. */
602
603struct binding_level
604 {
c7e4ee3a
CB
605 /* A chain of _DECL nodes for all variables, constants, functions,
606 and typedef types. These are in the reverse of the order supplied.
607 */
5ff904cd
JL
608 tree names;
609
c7e4ee3a
CB
610 /* For each level (except not the global one),
611 a chain of BLOCK nodes for all the levels
612 that were entered and exited one level down. */
5ff904cd
JL
613 tree blocks;
614
c7e4ee3a
CB
615 /* The BLOCK node for this level, if one has been preallocated.
616 If 0, the BLOCK is allocated (if needed) when the level is popped. */
5ff904cd
JL
617 tree this_block;
618
619 /* The binding level which this one is contained in (inherits from). */
620 struct binding_level *level_chain;
c7e4ee3a
CB
621
622 /* 0: no ffecom_prepare_* functions called at this level yet;
623 1: ffecom_prepare* functions called, except not ffecom_prepare_end;
624 2: ffecom_prepare_end called. */
625 int prep_state;
5ff904cd
JL
626 };
627
628#define NULL_BINDING_LEVEL (struct binding_level *) NULL
629
630/* The binding level currently in effect. */
631
632static struct binding_level *current_binding_level;
633
634/* A chain of binding_level structures awaiting reuse. */
635
636static struct binding_level *free_binding_level;
637
638/* The outermost binding level, for names of file scope.
639 This is created when the compiler is started and exists
640 through the entire run. */
641
642static struct binding_level *global_binding_level;
643
644/* Binding level structures are initialized by copying this one. */
645
646static struct binding_level clear_binding_level
647=
c7e4ee3a 648{NULL, NULL, NULL, NULL_BINDING_LEVEL, 0};
5ff904cd
JL
649
650/* Language-dependent contents of an identifier. */
651
652struct lang_identifier
653 {
654 struct tree_identifier ignore;
655 tree global_value, local_value, label_value;
656 bool invented;
657 };
658
659/* Macros for access to language-specific slots in an identifier. */
660/* Each of these slots contains a DECL node or null. */
661
662/* This represents the value which the identifier has in the
663 file-scope namespace. */
664#define IDENTIFIER_GLOBAL_VALUE(NODE) \
665 (((struct lang_identifier *)(NODE))->global_value)
666/* This represents the value which the identifier has in the current
667 scope. */
668#define IDENTIFIER_LOCAL_VALUE(NODE) \
669 (((struct lang_identifier *)(NODE))->local_value)
670/* This represents the value which the identifier has as a label in
671 the current label scope. */
672#define IDENTIFIER_LABEL_VALUE(NODE) \
673 (((struct lang_identifier *)(NODE))->label_value)
674/* This is nonzero if the identifier was "made up" by g77 code. */
675#define IDENTIFIER_INVENTED(NODE) \
676 (((struct lang_identifier *)(NODE))->invented)
677
678/* In identifiers, C uses the following fields in a special way:
679 TREE_PUBLIC to record that there was a previous local extern decl.
680 TREE_USED to record that such a decl was used.
681 TREE_ADDRESSABLE to record that the address of such a decl was used. */
682
683/* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
684 that have names. Here so we can clear out their names' definitions
685 at the end of the function. */
686
687static tree named_labels;
688
689/* A list of LABEL_DECLs from outer contexts that are currently shadowed. */
690
691static tree shadowed_labels;
692
693#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
694\f
6b55276e
CB
695/* Return the subscript expression, modified to do range-checking.
696
697 `array' is the array to be checked against.
698 `element' is the subscript expression to check.
699 `dim' is the dimension number (starting at 0).
700 `total_dims' is the total number of dimensions (0 for CHARACTER substring).
701*/
702
703static tree
704ffecom_subscript_check_ (tree array, tree element, int dim, int total_dims,
3b304f5b 705 const char *array_name)
6b55276e
CB
706{
707 tree low = TYPE_MIN_VALUE (TYPE_DOMAIN (array));
708 tree high = TYPE_MAX_VALUE (TYPE_DOMAIN (array));
709 tree cond;
710 tree die;
711 tree args;
712
713 if (element == error_mark_node)
714 return element;
715
ff852b44
CB
716 if (TREE_TYPE (low) != TREE_TYPE (element))
717 {
718 if (TYPE_PRECISION (TREE_TYPE (low))
719 > TYPE_PRECISION (TREE_TYPE (element)))
720 element = convert (TREE_TYPE (low), element);
721 else
722 {
723 low = convert (TREE_TYPE (element), low);
724 if (high)
725 high = convert (TREE_TYPE (element), high);
726 }
727 }
728
6b55276e
CB
729 element = ffecom_save_tree (element);
730 cond = ffecom_2 (LE_EXPR, integer_type_node,
731 low,
732 element);
733 if (high)
734 {
735 cond = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
736 cond,
737 ffecom_2 (LE_EXPR, integer_type_node,
738 element,
739 high));
740 }
741
742 {
743 int len;
744 char *proc;
745 char *var;
746 tree arg3;
747 tree arg2;
748 tree arg1;
749 tree arg4;
750
751 switch (total_dims)
752 {
753 case 0:
754 var = xmalloc (strlen (array_name) + 20);
3b304f5b 755 sprintf (var, "%s[%s-substring]",
6b55276e
CB
756 array_name,
757 dim ? "end" : "start");
758 len = strlen (var) + 1;
3b304f5b
ZW
759 arg1 = build_string (len, var);
760 free (var);
6b55276e
CB
761 break;
762
763 case 1:
764 len = strlen (array_name) + 1;
3b304f5b 765 arg1 = build_string (len, array_name);
6b55276e
CB
766 break;
767
768 default:
769 var = xmalloc (strlen (array_name) + 40);
3b304f5b 770 sprintf (var, "%s[subscript-%d-of-%d]",
6b55276e
CB
771 array_name,
772 dim + 1, total_dims);
773 len = strlen (var) + 1;
3b304f5b
ZW
774 arg1 = build_string (len, var);
775 free (var);
6b55276e
CB
776 break;
777 }
778
6b55276e
CB
779 TREE_TYPE (arg1)
780 = build_type_variant (build_array_type (char_type_node,
781 build_range_type
782 (integer_type_node,
783 integer_one_node,
784 build_int_2 (len, 0))),
785 1, 0);
786 TREE_CONSTANT (arg1) = 1;
787 TREE_STATIC (arg1) = 1;
788 arg1 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg1)),
789 arg1);
790
791 /* s_rnge adds one to the element to print it, so bias against
792 that -- want to print a faithful *subscript* value. */
793 arg2 = convert (ffecom_f2c_ftnint_type_node,
794 ffecom_2 (MINUS_EXPR,
795 TREE_TYPE (element),
796 element,
797 convert (TREE_TYPE (element),
798 integer_one_node)));
799
800 proc = xmalloc ((len = strlen (input_filename)
801 + IDENTIFIER_LENGTH (DECL_NAME (current_function_decl))
802 + 2));
803
804 sprintf (&proc[0], "%s/%s",
805 input_filename,
806 IDENTIFIER_POINTER (DECL_NAME (current_function_decl)));
807 arg3 = build_string (len, proc);
808
809 free (proc);
810
811 TREE_TYPE (arg3)
812 = build_type_variant (build_array_type (char_type_node,
813 build_range_type
814 (integer_type_node,
815 integer_one_node,
816 build_int_2 (len, 0))),
817 1, 0);
818 TREE_CONSTANT (arg3) = 1;
819 TREE_STATIC (arg3) = 1;
820 arg3 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg3)),
821 arg3);
822
823 arg4 = convert (ffecom_f2c_ftnint_type_node,
824 build_int_2 (lineno, 0));
825
826 arg1 = build_tree_list (NULL_TREE, arg1);
827 arg2 = build_tree_list (NULL_TREE, arg2);
828 arg3 = build_tree_list (NULL_TREE, arg3);
829 arg4 = build_tree_list (NULL_TREE, arg4);
830 TREE_CHAIN (arg3) = arg4;
831 TREE_CHAIN (arg2) = arg3;
832 TREE_CHAIN (arg1) = arg2;
833
834 args = arg1;
835 }
836 die = ffecom_call_gfrt (FFECOM_gfrtRANGE,
837 args, NULL_TREE);
838 TREE_SIDE_EFFECTS (die) = 1;
839
840 element = ffecom_3 (COND_EXPR,
841 TREE_TYPE (element),
842 cond,
843 element,
844 die);
845
846 return element;
847}
848
849/* Return the computed element of an array reference.
850
ff852b44
CB
851 `item' is NULL_TREE, or the transformed pointer to the array.
852 `expr' is the original opARRAYREF expression, which is transformed
853 if `item' is NULL_TREE.
854 `want_ptr' is non-zero if a pointer to the element, instead of
6b55276e
CB
855 the element itself, is to be returned. */
856
857static tree
858ffecom_arrayref_ (tree item, ffebld expr, int want_ptr)
859{
860 ffebld dims[FFECOM_dimensionsMAX];
861 int i;
862 int total_dims;
ff852b44
CB
863 int flatten = ffe_is_flatten_arrays ();
864 int need_ptr;
6b55276e
CB
865 tree array;
866 tree element;
ff852b44
CB
867 tree tree_type;
868 tree tree_type_x;
3b304f5b 869 const char *array_name;
ff852b44
CB
870 ffetype type;
871 ffebld list;
6b55276e
CB
872
873 if (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER)
874 array_name = ffesymbol_text (ffebld_symter (ffebld_left (expr)));
875 else
876 array_name = "[expr?]";
877
878 /* Build up ARRAY_REFs in reverse order (since we're column major
879 here in Fortran land). */
880
ff852b44
CB
881 for (i = 0, list = ffebld_right (expr);
882 list != NULL;
883 ++i, list = ffebld_trail (list))
884 {
885 dims[i] = ffebld_head (list);
886 type = ffeinfo_type (ffebld_basictype (dims[i]),
887 ffebld_kindtype (dims[i]));
888 if (! flatten
889 && ffecom_typesize_pointer_ > ffecom_typesize_integer1_
890 && ffetype_size (type) > ffecom_typesize_integer1_)
891 /* E.g. ARRAY(INDEX), given INTEGER*8 INDEX, on a system with 64-bit
892 pointers and 32-bit integers. Do the full 64-bit pointer
893 arithmetic, for codes using arrays for nonstandard heap-like
894 work. */
895 flatten = 1;
896 }
6b55276e
CB
897
898 total_dims = i;
899
ff852b44
CB
900 need_ptr = want_ptr || flatten;
901
902 if (! item)
903 {
904 if (need_ptr)
905 item = ffecom_ptr_to_expr (ffebld_left (expr));
906 else
907 item = ffecom_expr (ffebld_left (expr));
908
909 if (item == error_mark_node)
910 return item;
911
912 if (ffeinfo_where (ffebld_info (expr)) == FFEINFO_whereFLEETING
913 && ! mark_addressable (item))
914 return error_mark_node;
915 }
916
917 if (item == error_mark_node)
918 return item;
919
6b55276e
CB
920 if (need_ptr)
921 {
ff852b44
CB
922 tree min;
923
6b55276e
CB
924 for (--i, array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
925 i >= 0;
926 --i, array = TYPE_MAIN_VARIANT (TREE_TYPE (array)))
927 {
ff852b44
CB
928 min = TYPE_MIN_VALUE (TYPE_DOMAIN (array));
929 element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
02f06e64 930 if (flag_bounds_check)
6b55276e
CB
931 element = ffecom_subscript_check_ (array, element, i, total_dims,
932 array_name);
ff852b44
CB
933 if (element == error_mark_node)
934 return element;
935
936 /* Widen integral arithmetic as desired while preserving
937 signedness. */
938 tree_type = TREE_TYPE (element);
939 tree_type_x = tree_type;
940 if (tree_type
941 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
942 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
943 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
944
945 if (TREE_TYPE (min) != tree_type_x)
946 min = convert (tree_type_x, min);
947 if (TREE_TYPE (element) != tree_type_x)
948 element = convert (tree_type_x, element);
949
6b55276e
CB
950 item = ffecom_2 (PLUS_EXPR,
951 build_pointer_type (TREE_TYPE (array)),
952 item,
953 size_binop (MULT_EXPR,
954 size_in_bytes (TREE_TYPE (array)),
fed3cef0
RK
955 convert (sizetype,
956 fold (build (MINUS_EXPR,
957 tree_type_x,
958 element, min)))));
6b55276e
CB
959 }
960 if (! want_ptr)
961 {
962 item = ffecom_1 (INDIRECT_REF,
963 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))),
964 item);
965 }
966 }
967 else
968 {
969 for (--i;
970 i >= 0;
971 --i)
972 {
973 array = TYPE_MAIN_VARIANT (TREE_TYPE (item));
974
975 element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
02f06e64 976 if (flag_bounds_check)
6b55276e
CB
977 element = ffecom_subscript_check_ (array, element, i, total_dims,
978 array_name);
ff852b44
CB
979 if (element == error_mark_node)
980 return element;
981
982 /* Widen integral arithmetic as desired while preserving
983 signedness. */
984 tree_type = TREE_TYPE (element);
985 tree_type_x = tree_type;
986 if (tree_type
987 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
988 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
989 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
990
991 element = convert (tree_type_x, element);
992
6b55276e
CB
993 item = ffecom_2 (ARRAY_REF,
994 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))),
995 item,
996 element);
997 }
998 }
999
1000 return item;
1001}
1002
5ff904cd
JL
1003/* This is like gcc's stabilize_reference -- in fact, most of the code
1004 comes from that -- but it handles the situation where the reference
1005 is going to have its subparts picked at, and it shouldn't change
1006 (or trigger extra invocations of functions in the subtrees) due to
1007 this. save_expr is a bit overzealous, because we don't need the
1008 entire thing calculated and saved like a temp. So, for DECLs, no
1009 change is needed, because these are stable aggregates, and ARRAY_REF
1010 and such might well be stable too, but for things like calculations,
1011 we do need to calculate a snapshot of a value before picking at it. */
1012
1013#if FFECOM_targetCURRENT == FFECOM_targetGCC
1014static tree
1015ffecom_stabilize_aggregate_ (tree ref)
1016{
1017 tree result;
1018 enum tree_code code = TREE_CODE (ref);
1019
1020 switch (code)
1021 {
1022 case VAR_DECL:
1023 case PARM_DECL:
1024 case RESULT_DECL:
1025 /* No action is needed in this case. */
1026 return ref;
1027
1028 case NOP_EXPR:
1029 case CONVERT_EXPR:
1030 case FLOAT_EXPR:
1031 case FIX_TRUNC_EXPR:
1032 case FIX_FLOOR_EXPR:
1033 case FIX_ROUND_EXPR:
1034 case FIX_CEIL_EXPR:
1035 result = build_nt (code, stabilize_reference (TREE_OPERAND (ref, 0)));
1036 break;
1037
1038 case INDIRECT_REF:
1039 result = build_nt (INDIRECT_REF,
1040 stabilize_reference_1 (TREE_OPERAND (ref, 0)));
1041 break;
1042
1043 case COMPONENT_REF:
1044 result = build_nt (COMPONENT_REF,
1045 stabilize_reference (TREE_OPERAND (ref, 0)),
1046 TREE_OPERAND (ref, 1));
1047 break;
1048
1049 case BIT_FIELD_REF:
1050 result = build_nt (BIT_FIELD_REF,
1051 stabilize_reference (TREE_OPERAND (ref, 0)),
1052 stabilize_reference_1 (TREE_OPERAND (ref, 1)),
1053 stabilize_reference_1 (TREE_OPERAND (ref, 2)));
1054 break;
1055
1056 case ARRAY_REF:
1057 result = build_nt (ARRAY_REF,
1058 stabilize_reference (TREE_OPERAND (ref, 0)),
1059 stabilize_reference_1 (TREE_OPERAND (ref, 1)));
1060 break;
1061
1062 case COMPOUND_EXPR:
1063 result = build_nt (COMPOUND_EXPR,
1064 stabilize_reference_1 (TREE_OPERAND (ref, 0)),
1065 stabilize_reference (TREE_OPERAND (ref, 1)));
1066 break;
1067
1068 case RTL_EXPR:
a8d0a42e 1069 abort ();
5ff904cd
JL
1070
1071
1072 default:
1073 return save_expr (ref);
1074
1075 case ERROR_MARK:
1076 return error_mark_node;
1077 }
1078
1079 TREE_TYPE (result) = TREE_TYPE (ref);
1080 TREE_READONLY (result) = TREE_READONLY (ref);
1081 TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (ref);
1082 TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (ref);
5ff904cd
JL
1083
1084 return result;
1085}
1086#endif
1087
1088/* A rip-off of gcc's convert.c convert_to_complex function,
1089 reworked to handle complex implemented as C structures
1090 (RECORD_TYPE with two fields, real and imaginary `r' and `i'). */
1091
1092#if FFECOM_targetCURRENT == FFECOM_targetGCC
1093static tree
1094ffecom_convert_to_complex_ (tree type, tree expr)
1095{
1096 register enum tree_code form = TREE_CODE (TREE_TYPE (expr));
1097 tree subtype;
1098
1099 assert (TREE_CODE (type) == RECORD_TYPE);
1100
1101 subtype = TREE_TYPE (TYPE_FIELDS (type));
1102
1103 if (form == REAL_TYPE || form == INTEGER_TYPE || form == ENUMERAL_TYPE)
1104 {
1105 expr = convert (subtype, expr);
1106 return ffecom_2 (COMPLEX_EXPR, type, expr,
1107 convert (subtype, integer_zero_node));
1108 }
1109
1110 if (form == RECORD_TYPE)
1111 {
1112 tree elt_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr)));
1113 if (TYPE_MAIN_VARIANT (elt_type) == TYPE_MAIN_VARIANT (subtype))
1114 return expr;
1115 else
1116 {
1117 expr = save_expr (expr);
1118 return ffecom_2 (COMPLEX_EXPR,
1119 type,
1120 convert (subtype,
1121 ffecom_1 (REALPART_EXPR,
1122 TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))),
1123 expr)),
1124 convert (subtype,
1125 ffecom_1 (IMAGPART_EXPR,
1126 TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))),
1127 expr)));
1128 }
1129 }
1130
1131 if (form == POINTER_TYPE || form == REFERENCE_TYPE)
1132 error ("pointer value used where a complex was expected");
1133 else
1134 error ("aggregate value used where a complex was expected");
1135
1136 return ffecom_2 (COMPLEX_EXPR, type,
1137 convert (subtype, integer_zero_node),
1138 convert (subtype, integer_zero_node));
1139}
1140#endif
1141
1142/* Like gcc's convert(), but crashes if widening might happen. */
1143
1144#if FFECOM_targetCURRENT == FFECOM_targetGCC
1145static tree
1146ffecom_convert_narrow_ (type, expr)
1147 tree type, expr;
1148{
1149 register tree e = expr;
1150 register enum tree_code code = TREE_CODE (type);
1151
1152 if (type == TREE_TYPE (e)
1153 || TREE_CODE (e) == ERROR_MARK)
1154 return e;
1155 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
1156 return fold (build1 (NOP_EXPR, type, e));
1157 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
1158 || code == ERROR_MARK)
1159 return error_mark_node;
1160 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
1161 {
1162 assert ("void value not ignored as it ought to be" == NULL);
1163 return error_mark_node;
1164 }
1165 assert (code != VOID_TYPE);
1166 if ((code != RECORD_TYPE)
1167 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
1168 assert ("converting COMPLEX to REAL" == NULL);
1169 assert (code != ENUMERAL_TYPE);
1170 if (code == INTEGER_TYPE)
1171 {
a74de6ea
CB
1172 assert ((TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE
1173 && TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)))
1174 || (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
1175 && (TYPE_PRECISION (type)
1176 == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (e))))));
5ff904cd
JL
1177 return fold (convert_to_integer (type, e));
1178 }
1179 if (code == POINTER_TYPE)
1180 {
1181 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
1182 return fold (convert_to_pointer (type, e));
1183 }
1184 if (code == REAL_TYPE)
1185 {
1186 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
1187 assert (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)));
1188 return fold (convert_to_real (type, e));
1189 }
1190 if (code == COMPLEX_TYPE)
1191 {
1192 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
1193 assert (TYPE_PRECISION (TREE_TYPE (type)) <= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
1194 return fold (convert_to_complex (type, e));
1195 }
1196 if (code == RECORD_TYPE)
1197 {
1198 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
270fc4e8
CB
1199 /* Check that at least the first field name agrees. */
1200 assert (DECL_NAME (TYPE_FIELDS (type))
1201 == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e))));
5ff904cd
JL
1202 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1203 <= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
270fc4e8
CB
1204 if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1205 == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))))
1206 return e;
5ff904cd
JL
1207 return fold (ffecom_convert_to_complex_ (type, e));
1208 }
1209
1210 assert ("conversion to non-scalar type requested" == NULL);
1211 return error_mark_node;
1212}
1213#endif
1214
1215/* Like gcc's convert(), but crashes if narrowing might happen. */
1216
1217#if FFECOM_targetCURRENT == FFECOM_targetGCC
1218static tree
1219ffecom_convert_widen_ (type, expr)
1220 tree type, expr;
1221{
1222 register tree e = expr;
1223 register enum tree_code code = TREE_CODE (type);
1224
1225 if (type == TREE_TYPE (e)
1226 || TREE_CODE (e) == ERROR_MARK)
1227 return e;
1228 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
1229 return fold (build1 (NOP_EXPR, type, e));
1230 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
1231 || code == ERROR_MARK)
1232 return error_mark_node;
1233 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
1234 {
1235 assert ("void value not ignored as it ought to be" == NULL);
1236 return error_mark_node;
1237 }
1238 assert (code != VOID_TYPE);
1239 if ((code != RECORD_TYPE)
1240 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
1241 assert ("narrowing COMPLEX to REAL" == NULL);
1242 assert (code != ENUMERAL_TYPE);
1243 if (code == INTEGER_TYPE)
1244 {
a74de6ea
CB
1245 assert ((TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE
1246 && TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)))
1247 || (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
1248 && (TYPE_PRECISION (type)
1249 == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (e))))));
5ff904cd
JL
1250 return fold (convert_to_integer (type, e));
1251 }
1252 if (code == POINTER_TYPE)
1253 {
1254 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
1255 return fold (convert_to_pointer (type, e));
1256 }
1257 if (code == REAL_TYPE)
1258 {
1259 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
1260 assert (TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)));
1261 return fold (convert_to_real (type, e));
1262 }
1263 if (code == COMPLEX_TYPE)
1264 {
1265 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
1266 assert (TYPE_PRECISION (TREE_TYPE (type)) >= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
1267 return fold (convert_to_complex (type, e));
1268 }
1269 if (code == RECORD_TYPE)
1270 {
1271 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
270fc4e8
CB
1272 /* Check that at least the first field name agrees. */
1273 assert (DECL_NAME (TYPE_FIELDS (type))
1274 == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e))));
5ff904cd
JL
1275 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1276 >= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
270fc4e8
CB
1277 if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1278 == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))))
1279 return e;
5ff904cd
JL
1280 return fold (ffecom_convert_to_complex_ (type, e));
1281 }
1282
1283 assert ("conversion to non-scalar type requested" == NULL);
1284 return error_mark_node;
1285}
1286#endif
1287
1288/* Handles making a COMPLEX type, either the standard
1289 (but buggy?) gbe way, or the safer (but less elegant?)
1290 f2c way. */
1291
1292#if FFECOM_targetCURRENT == FFECOM_targetGCC
1293static tree
1294ffecom_make_complex_type_ (tree subtype)
1295{
1296 tree type;
1297 tree realfield;
1298 tree imagfield;
1299
1300 if (ffe_is_emulate_complex ())
1301 {
1302 type = make_node (RECORD_TYPE);
1303 realfield = ffecom_decl_field (type, NULL_TREE, "r", subtype);
1304 imagfield = ffecom_decl_field (type, realfield, "i", subtype);
1305 TYPE_FIELDS (type) = realfield;
1306 layout_type (type);
1307 }
1308 else
1309 {
1310 type = make_node (COMPLEX_TYPE);
1311 TREE_TYPE (type) = subtype;
1312 layout_type (type);
1313 }
1314
1315 return type;
1316}
1317#endif
1318
1319/* Chooses either the gbe or the f2c way to build a
1320 complex constant. */
1321
1322#if FFECOM_targetCURRENT == FFECOM_targetGCC
1323static tree
1324ffecom_build_complex_constant_ (tree type, tree realpart, tree imagpart)
1325{
1326 tree bothparts;
1327
1328 if (ffe_is_emulate_complex ())
1329 {
1330 bothparts = build_tree_list (TYPE_FIELDS (type), realpart);
1331 TREE_CHAIN (bothparts) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), imagpart);
1332 bothparts = build (CONSTRUCTOR, type, NULL_TREE, bothparts);
1333 }
1334 else
1335 {
1336 bothparts = build_complex (type, realpart, imagpart);
1337 }
1338
1339 return bothparts;
1340}
1341#endif
1342
1343#if FFECOM_targetCURRENT == FFECOM_targetGCC
1344static tree
26f096f9 1345ffecom_arglist_expr_ (const char *c, ffebld expr)
5ff904cd
JL
1346{
1347 tree list;
1348 tree *plist = &list;
1349 tree trail = NULL_TREE; /* Append char length args here. */
1350 tree *ptrail = &trail;
1351 tree length;
1352 ffebld exprh;
1353 tree item;
1354 bool ptr = FALSE;
1355 tree wanted = NULL_TREE;
e2fa159e
JL
1356 static char zed[] = "0";
1357
1358 if (c == NULL)
1359 c = &zed[0];
5ff904cd
JL
1360
1361 while (expr != NULL)
1362 {
1363 if (*c != '\0')
1364 {
1365 ptr = FALSE;
1366 if (*c == '&')
1367 {
1368 ptr = TRUE;
1369 ++c;
1370 }
1371 switch (*(c++))
1372 {
1373 case '\0':
1374 ptr = TRUE;
1375 wanted = NULL_TREE;
1376 break;
1377
1378 case 'a':
1379 assert (ptr);
1380 wanted = NULL_TREE;
1381 break;
1382
1383 case 'c':
1384 wanted = ffecom_f2c_complex_type_node;
1385 break;
1386
1387 case 'd':
1388 wanted = ffecom_f2c_doublereal_type_node;
1389 break;
1390
1391 case 'e':
1392 wanted = ffecom_f2c_doublecomplex_type_node;
1393 break;
1394
1395 case 'f':
1396 wanted = ffecom_f2c_real_type_node;
1397 break;
1398
1399 case 'i':
1400 wanted = ffecom_f2c_integer_type_node;
1401 break;
1402
1403 case 'j':
1404 wanted = ffecom_f2c_longint_type_node;
1405 break;
1406
1407 default:
1408 assert ("bad argstring code" == NULL);
1409 wanted = NULL_TREE;
1410 break;
1411 }
1412 }
1413
1414 exprh = ffebld_head (expr);
1415 if (exprh == NULL)
1416 wanted = NULL_TREE;
1417
1418 if ((wanted == NULL_TREE)
1419 || (ptr
1420 && (TYPE_MODE
1421 (ffecom_tree_type[ffeinfo_basictype (ffebld_info (exprh))]
1422 [ffeinfo_kindtype (ffebld_info (exprh))])
1423 == TYPE_MODE (wanted))))
1424 *plist
1425 = build_tree_list (NULL_TREE,
1426 ffecom_arg_ptr_to_expr (exprh,
1427 &length));
1428 else
1429 {
1430 item = ffecom_arg_expr (exprh, &length);
1431 item = ffecom_convert_widen_ (wanted, item);
1432 if (ptr)
1433 {
1434 item = ffecom_1 (ADDR_EXPR,
1435 build_pointer_type (TREE_TYPE (item)),
1436 item);
1437 }
1438 *plist
1439 = build_tree_list (NULL_TREE,
1440 item);
1441 }
1442
1443 plist = &TREE_CHAIN (*plist);
1444 expr = ffebld_trail (expr);
1445 if (length != NULL_TREE)
1446 {
1447 *ptrail = build_tree_list (NULL_TREE, length);
1448 ptrail = &TREE_CHAIN (*ptrail);
1449 }
1450 }
1451
e2fa159e
JL
1452 /* We've run out of args in the call; if the implementation expects
1453 more, supply null pointers for them, which the implementation can
1454 check to see if an arg was omitted. */
1455
1456 while (*c != '\0' && *c != '0')
1457 {
1458 if (*c == '&')
1459 ++c;
1460 else
1461 assert ("missing arg to run-time routine!" == NULL);
1462
1463 switch (*(c++))
1464 {
1465 case '\0':
1466 case 'a':
1467 case 'c':
1468 case 'd':
1469 case 'e':
1470 case 'f':
1471 case 'i':
1472 case 'j':
1473 break;
1474
1475 default:
1476 assert ("bad arg string code" == NULL);
1477 break;
1478 }
1479 *plist
1480 = build_tree_list (NULL_TREE,
1481 null_pointer_node);
1482 plist = &TREE_CHAIN (*plist);
1483 }
1484
5ff904cd
JL
1485 *plist = trail;
1486
1487 return list;
1488}
1489#endif
1490
1491#if FFECOM_targetCURRENT == FFECOM_targetGCC
1492static tree
1493ffecom_widest_expr_type_ (ffebld list)
1494{
1495 ffebld item;
1496 ffebld widest = NULL;
1497 ffetype type;
1498 ffetype widest_type = NULL;
1499 tree t;
1500
1501 for (; list != NULL; list = ffebld_trail (list))
1502 {
1503 item = ffebld_head (list);
1504 if (item == NULL)
1505 continue;
1506 if ((widest != NULL)
1507 && (ffeinfo_basictype (ffebld_info (item))
1508 != ffeinfo_basictype (ffebld_info (widest))))
1509 continue;
1510 type = ffeinfo_type (ffeinfo_basictype (ffebld_info (item)),
1511 ffeinfo_kindtype (ffebld_info (item)));
1512 if ((widest == FFEINFO_kindtypeNONE)
1513 || (ffetype_size (type)
1514 > ffetype_size (widest_type)))
1515 {
1516 widest = item;
1517 widest_type = type;
1518 }
1519 }
1520
1521 assert (widest != NULL);
1522 t = ffecom_tree_type[ffeinfo_basictype (ffebld_info (widest))]
1523 [ffeinfo_kindtype (ffebld_info (widest))];
1524 assert (t != NULL_TREE);
1525 return t;
1526}
1527#endif
1528
d6cd84e0
CB
1529/* Check whether a partial overlap between two expressions is possible.
1530
1531 Can *starting* to write a portion of expr1 change the value
1532 computed (perhaps already, *partially*) by expr2?
1533
1534 Currently, this is a concern only for a COMPLEX expr1. But if it
1535 isn't in COMMON or local EQUIVALENCE, since we don't support
1536 aliasing of arguments, it isn't a concern. */
1537
1538static bool
b0791fa9 1539ffecom_possible_partial_overlap_ (ffebld expr1, ffebld expr2 ATTRIBUTE_UNUSED)
d6cd84e0
CB
1540{
1541 ffesymbol sym;
1542 ffestorag st;
1543
1544 switch (ffebld_op (expr1))
1545 {
1546 case FFEBLD_opSYMTER:
1547 sym = ffebld_symter (expr1);
1548 break;
1549
1550 case FFEBLD_opARRAYREF:
1551 if (ffebld_op (ffebld_left (expr1)) != FFEBLD_opSYMTER)
1552 return FALSE;
1553 sym = ffebld_symter (ffebld_left (expr1));
1554 break;
1555
1556 default:
1557 return FALSE;
1558 }
1559
1560 if (ffesymbol_where (sym) != FFEINFO_whereCOMMON
1561 && (ffesymbol_where (sym) != FFEINFO_whereLOCAL
1562 || ! (st = ffesymbol_storage (sym))
1563 || ! ffestorag_parent (st)))
1564 return FALSE;
1565
1566 /* It's in COMMON or local EQUIVALENCE. */
1567
1568 return TRUE;
1569}
1570
5ff904cd
JL
1571/* Check whether dest and source might overlap. ffebld versions of these
1572 might or might not be passed, will be NULL if not.
1573
1574 The test is really whether source_tree is modifiable and, if modified,
1575 might overlap destination such that the value(s) in the destination might
1576 change before it is finally modified. dest_* are the canonized
1577 destination itself. */
1578
1579#if FFECOM_targetCURRENT == FFECOM_targetGCC
1580static bool
1581ffecom_overlap_ (tree dest_decl, tree dest_offset, tree dest_size,
1582 tree source_tree, ffebld source UNUSED,
1583 bool scalar_arg)
1584{
1585 tree source_decl;
1586 tree source_offset;
1587 tree source_size;
1588 tree t;
1589
1590 if (source_tree == NULL_TREE)
1591 return FALSE;
1592
1593 switch (TREE_CODE (source_tree))
1594 {
1595 case ERROR_MARK:
1596 case IDENTIFIER_NODE:
1597 case INTEGER_CST:
1598 case REAL_CST:
1599 case COMPLEX_CST:
1600 case STRING_CST:
1601 case CONST_DECL:
1602 case VAR_DECL:
1603 case RESULT_DECL:
1604 case FIELD_DECL:
1605 case MINUS_EXPR:
1606 case MULT_EXPR:
1607 case TRUNC_DIV_EXPR:
1608 case CEIL_DIV_EXPR:
1609 case FLOOR_DIV_EXPR:
1610 case ROUND_DIV_EXPR:
1611 case TRUNC_MOD_EXPR:
1612 case CEIL_MOD_EXPR:
1613 case FLOOR_MOD_EXPR:
1614 case ROUND_MOD_EXPR:
1615 case RDIV_EXPR:
1616 case EXACT_DIV_EXPR:
1617 case FIX_TRUNC_EXPR:
1618 case FIX_CEIL_EXPR:
1619 case FIX_FLOOR_EXPR:
1620 case FIX_ROUND_EXPR:
1621 case FLOAT_EXPR:
1622 case EXPON_EXPR:
1623 case NEGATE_EXPR:
1624 case MIN_EXPR:
1625 case MAX_EXPR:
1626 case ABS_EXPR:
1627 case FFS_EXPR:
1628 case LSHIFT_EXPR:
1629 case RSHIFT_EXPR:
1630 case LROTATE_EXPR:
1631 case RROTATE_EXPR:
1632 case BIT_IOR_EXPR:
1633 case BIT_XOR_EXPR:
1634 case BIT_AND_EXPR:
1635 case BIT_ANDTC_EXPR:
1636 case BIT_NOT_EXPR:
1637 case TRUTH_ANDIF_EXPR:
1638 case TRUTH_ORIF_EXPR:
1639 case TRUTH_AND_EXPR:
1640 case TRUTH_OR_EXPR:
1641 case TRUTH_XOR_EXPR:
1642 case TRUTH_NOT_EXPR:
1643 case LT_EXPR:
1644 case LE_EXPR:
1645 case GT_EXPR:
1646 case GE_EXPR:
1647 case EQ_EXPR:
1648 case NE_EXPR:
1649 case COMPLEX_EXPR:
1650 case CONJ_EXPR:
1651 case REALPART_EXPR:
1652 case IMAGPART_EXPR:
1653 case LABEL_EXPR:
1654 case COMPONENT_REF:
1655 return FALSE;
1656
1657 case COMPOUND_EXPR:
1658 return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1659 TREE_OPERAND (source_tree, 1), NULL,
1660 scalar_arg);
1661
1662 case MODIFY_EXPR:
1663 return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1664 TREE_OPERAND (source_tree, 0), NULL,
1665 scalar_arg);
1666
1667 case CONVERT_EXPR:
1668 case NOP_EXPR:
1669 case NON_LVALUE_EXPR:
1670 case PLUS_EXPR:
1671 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1672 return TRUE;
1673
1674 ffecom_tree_canonize_ptr_ (&source_decl, &source_offset,
1675 source_tree);
1676 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1677 break;
1678
1679 case COND_EXPR:
1680 return
1681 ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1682 TREE_OPERAND (source_tree, 1), NULL,
1683 scalar_arg)
1684 || ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1685 TREE_OPERAND (source_tree, 2), NULL,
1686 scalar_arg);
1687
1688
1689 case ADDR_EXPR:
1690 ffecom_tree_canonize_ref_ (&source_decl, &source_offset,
1691 &source_size,
1692 TREE_OPERAND (source_tree, 0));
1693 break;
1694
1695 case PARM_DECL:
1696 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1697 return TRUE;
1698
1699 source_decl = source_tree;
76fa6b3b 1700 source_offset = bitsize_zero_node;
5ff904cd
JL
1701 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1702 break;
1703
1704 case SAVE_EXPR:
1705 case REFERENCE_EXPR:
1706 case PREDECREMENT_EXPR:
1707 case PREINCREMENT_EXPR:
1708 case POSTDECREMENT_EXPR:
1709 case POSTINCREMENT_EXPR:
1710 case INDIRECT_REF:
1711 case ARRAY_REF:
1712 case CALL_EXPR:
1713 default:
1714 return TRUE;
1715 }
1716
1717 /* Come here when source_decl, source_offset, and source_size filled
1718 in appropriately. */
1719
1720 if (source_decl == NULL_TREE)
1721 return FALSE; /* No decl involved, so no overlap. */
1722
1723 if (source_decl != dest_decl)
1724 return FALSE; /* Different decl, no overlap. */
1725
1726 if (TREE_CODE (dest_size) == ERROR_MARK)
1727 return TRUE; /* Assignment into entire assumed-size
1728 array? Shouldn't happen.... */
1729
1730 t = ffecom_2 (LE_EXPR, integer_type_node,
1731 ffecom_2 (PLUS_EXPR, TREE_TYPE (dest_offset),
1732 dest_offset,
1733 convert (TREE_TYPE (dest_offset),
1734 dest_size)),
1735 convert (TREE_TYPE (dest_offset),
1736 source_offset));
1737
1738 if (integer_onep (t))
1739 return FALSE; /* Destination precedes source. */
1740
1741 if (!scalar_arg
1742 || (source_size == NULL_TREE)
1743 || (TREE_CODE (source_size) == ERROR_MARK)
1744 || integer_zerop (source_size))
1745 return TRUE; /* No way to tell if dest follows source. */
1746
1747 t = ffecom_2 (LE_EXPR, integer_type_node,
1748 ffecom_2 (PLUS_EXPR, TREE_TYPE (source_offset),
1749 source_offset,
1750 convert (TREE_TYPE (source_offset),
1751 source_size)),
1752 convert (TREE_TYPE (source_offset),
1753 dest_offset));
1754
1755 if (integer_onep (t))
1756 return FALSE; /* Destination follows source. */
1757
1758 return TRUE; /* Destination and source overlap. */
1759}
1760#endif
1761
1762/* Check whether dest might overlap any of a list of arguments or is
1763 in a COMMON area the callee might know about (and thus modify). */
1764
1765#if FFECOM_targetCURRENT == FFECOM_targetGCC
1766static bool
1767ffecom_args_overlapping_ (tree dest_tree, ffebld dest UNUSED,
1768 tree args, tree callee_commons,
1769 bool scalar_args)
1770{
1771 tree arg;
1772 tree dest_decl;
1773 tree dest_offset;
1774 tree dest_size;
1775
1776 ffecom_tree_canonize_ref_ (&dest_decl, &dest_offset, &dest_size,
1777 dest_tree);
1778
1779 if (dest_decl == NULL_TREE)
1780 return FALSE; /* Seems unlikely! */
1781
1782 /* If the decl cannot be determined reliably, or if its in COMMON
1783 and the callee isn't known to not futz with COMMON via other
1784 means, overlap might happen. */
1785
1786 if ((TREE_CODE (dest_decl) == ERROR_MARK)
1787 || ((callee_commons != NULL_TREE)
1788 && TREE_PUBLIC (dest_decl)))
1789 return TRUE;
1790
1791 for (; args != NULL_TREE; args = TREE_CHAIN (args))
1792 {
1793 if (((arg = TREE_VALUE (args)) != NULL_TREE)
1794 && ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1795 arg, NULL, scalar_args))
1796 return TRUE;
1797 }
1798
1799 return FALSE;
1800}
1801#endif
1802
1803/* Build a string for a variable name as used by NAMELIST. This means that
1804 if we're using the f2c library, we build an uppercase string, since
1805 f2c does this. */
1806
1807#if FFECOM_targetCURRENT == FFECOM_targetGCC
1808static tree
26f096f9 1809ffecom_build_f2c_string_ (int i, const char *s)
5ff904cd
JL
1810{
1811 if (!ffe_is_f2c_library ())
1812 return build_string (i, s);
1813
1814 {
1815 char *tmp;
26f096f9 1816 const char *p;
5ff904cd
JL
1817 char *q;
1818 char space[34];
1819 tree t;
1820
1821 if (((size_t) i) > ARRAY_SIZE (space))
1822 tmp = malloc_new_ks (malloc_pool_image (), "f2c_string", i);
1823 else
1824 tmp = &space[0];
1825
1826 for (p = s, q = tmp; *p != '\0'; ++p, ++q)
f6bbde28 1827 *q = TOUPPER (*p);
5ff904cd
JL
1828 *q = '\0';
1829
1830 t = build_string (i, tmp);
1831
1832 if (((size_t) i) > ARRAY_SIZE (space))
1833 malloc_kill_ks (malloc_pool_image (), tmp, i);
1834
1835 return t;
1836 }
1837}
1838
1839#endif
1840/* Returns CALL_EXPR or equivalent with given type (pass NULL_TREE for
1841 type to just get whatever the function returns), handling the
1842 f2c value-returning convention, if required, by prepending
1843 to the arglist a pointer to a temporary to receive the return value. */
1844
1845#if FFECOM_targetCURRENT == FFECOM_targetGCC
1846static tree
1847ffecom_call_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1848 tree type, tree args, tree dest_tree,
1849 ffebld dest, bool *dest_used, tree callee_commons,
c7e4ee3a 1850 bool scalar_args, tree hook)
5ff904cd
JL
1851{
1852 tree item;
1853 tree tempvar;
1854
1855 if (dest_used != NULL)
1856 *dest_used = FALSE;
1857
1858 if (is_f2c_complex)
1859 {
1860 if ((dest_used == NULL)
1861 || (dest == NULL)
1862 || (ffeinfo_basictype (ffebld_info (dest))
1863 != FFEINFO_basictypeCOMPLEX)
1864 || (ffeinfo_kindtype (ffebld_info (dest)) != kt)
1865 || ((type != NULL_TREE) && (TREE_TYPE (dest_tree) != type))
1866 || ffecom_args_overlapping_ (dest_tree, dest, args,
1867 callee_commons,
1868 scalar_args))
1869 {
c7e4ee3a
CB
1870#ifdef HOHO
1871 tempvar = ffecom_make_tempvar (ffecom_tree_type
5ff904cd
JL
1872 [FFEINFO_basictypeCOMPLEX][kt],
1873 FFETARGET_charactersizeNONE,
c7e4ee3a
CB
1874 -1);
1875#else
1876 tempvar = hook;
1877 assert (tempvar);
1878#endif
5ff904cd
JL
1879 }
1880 else
1881 {
1882 *dest_used = TRUE;
1883 tempvar = dest_tree;
1884 type = NULL_TREE;
1885 }
1886
1887 item
1888 = build_tree_list (NULL_TREE,
1889 ffecom_1 (ADDR_EXPR,
c7e4ee3a 1890 build_pointer_type (TREE_TYPE (tempvar)),
5ff904cd
JL
1891 tempvar));
1892 TREE_CHAIN (item) = args;
1893
1894 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1895 item, NULL_TREE);
1896
1897 if (tempvar != dest_tree)
1898 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item, tempvar);
1899 }
1900 else
1901 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1902 args, NULL_TREE);
1903
1904 if ((type != NULL_TREE) && (TREE_TYPE (item) != type))
1905 item = ffecom_convert_narrow_ (type, item);
1906
1907 return item;
1908}
1909#endif
1910
1911/* Given two arguments, transform them and make a call to the given
1912 function via ffecom_call_. */
1913
1914#if FFECOM_targetCURRENT == FFECOM_targetGCC
1915static tree
1916ffecom_call_binop_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1917 tree type, ffebld left, ffebld right,
1918 tree dest_tree, ffebld dest, bool *dest_used,
95eb4fd9 1919 tree callee_commons, bool scalar_args, bool ref, tree hook)
5ff904cd
JL
1920{
1921 tree left_tree;
1922 tree right_tree;
1923 tree left_length;
1924 tree right_length;
1925
95eb4fd9
TM
1926 if (ref)
1927 {
1928 /* Pass arguments by reference. */
1929 left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
1930 right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
1931 }
1932 else
1933 {
1934 /* Pass arguments by value. */
1935 left_tree = ffecom_arg_expr (left, &left_length);
1936 right_tree = ffecom_arg_expr (right, &right_length);
1937 }
1938
5ff904cd
JL
1939
1940 left_tree = build_tree_list (NULL_TREE, left_tree);
1941 right_tree = build_tree_list (NULL_TREE, right_tree);
1942 TREE_CHAIN (left_tree) = right_tree;
1943
1944 if (left_length != NULL_TREE)
1945 {
1946 left_length = build_tree_list (NULL_TREE, left_length);
1947 TREE_CHAIN (right_tree) = left_length;
1948 }
1949
1950 if (right_length != NULL_TREE)
1951 {
1952 right_length = build_tree_list (NULL_TREE, right_length);
1953 if (left_length != NULL_TREE)
1954 TREE_CHAIN (left_length) = right_length;
1955 else
1956 TREE_CHAIN (right_tree) = right_length;
1957 }
1958
1959 return ffecom_call_ (fn, kt, is_f2c_complex, type, left_tree,
1960 dest_tree, dest, dest_used, callee_commons,
c7e4ee3a 1961 scalar_args, hook);
5ff904cd
JL
1962}
1963#endif
1964
c7e4ee3a 1965/* Return ptr/length args for char subexpression
5ff904cd
JL
1966
1967 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
1968 subexpressions by constructing the appropriate trees for the ptr-to-
1969 character-text and length-of-character-text arguments in a calling
86fc7a6c
CB
1970 sequence.
1971
1972 Note that if with_null is TRUE, and the expression is an opCONTER,
1973 a null byte is appended to the string. */
5ff904cd
JL
1974
1975#if FFECOM_targetCURRENT == FFECOM_targetGCC
1976static void
86fc7a6c 1977ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
5ff904cd
JL
1978{
1979 tree item;
1980 tree high;
1981 ffetargetCharacter1 val;
86fc7a6c 1982 ffetargetCharacterSize newlen;
5ff904cd
JL
1983
1984 switch (ffebld_op (expr))
1985 {
1986 case FFEBLD_opCONTER:
1987 val = ffebld_constant_character1 (ffebld_conter (expr));
86fc7a6c
CB
1988 newlen = ffetarget_length_character1 (val);
1989 if (with_null)
1990 {
c7e4ee3a 1991 /* Begin FFETARGET-NULL-KLUDGE. */
86fc7a6c 1992 if (newlen != 0)
c7e4ee3a 1993 ++newlen;
86fc7a6c
CB
1994 }
1995 *length = build_int_2 (newlen, 0);
5ff904cd 1996 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
86fc7a6c 1997 high = build_int_2 (newlen, 0);
5ff904cd 1998 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
c7e4ee3a 1999 item = build_string (newlen,
5ff904cd 2000 ffetarget_text_character1 (val));
c7e4ee3a 2001 /* End FFETARGET-NULL-KLUDGE. */
5ff904cd
JL
2002 TREE_TYPE (item)
2003 = build_type_variant
2004 (build_array_type
2005 (char_type_node,
2006 build_range_type
2007 (ffecom_f2c_ftnlen_type_node,
2008 ffecom_f2c_ftnlen_one_node,
2009 high)),
2010 1, 0);
2011 TREE_CONSTANT (item) = 1;
2012 TREE_STATIC (item) = 1;
2013 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
2014 item);
2015 break;
2016
2017 case FFEBLD_opSYMTER:
2018 {
2019 ffesymbol s = ffebld_symter (expr);
2020
2021 item = ffesymbol_hook (s).decl_tree;
2022 if (item == NULL_TREE)
2023 {
2024 s = ffecom_sym_transform_ (s);
2025 item = ffesymbol_hook (s).decl_tree;
2026 }
2027 if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
2028 {
2029 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
2030 *length = ffesymbol_hook (s).length_tree;
2031 else
2032 {
2033 *length = build_int_2 (ffesymbol_size (s), 0);
2034 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2035 }
2036 }
2037 else if (item == error_mark_node)
2038 *length = error_mark_node;
c7e4ee3a
CB
2039 else
2040 /* FFEINFO_kindFUNCTION. */
5ff904cd
JL
2041 *length = NULL_TREE;
2042 if (!ffesymbol_hook (s).addr
2043 && (item != error_mark_node))
2044 item = ffecom_1 (ADDR_EXPR,
2045 build_pointer_type (TREE_TYPE (item)),
2046 item);
2047 }
2048 break;
2049
2050 case FFEBLD_opARRAYREF:
2051 {
5ff904cd 2052 ffecom_char_args_ (&item, length, ffebld_left (expr));
5ff904cd
JL
2053
2054 if (item == error_mark_node || *length == error_mark_node)
2055 {
2056 item = *length = error_mark_node;
2057 break;
2058 }
2059
6b55276e 2060 item = ffecom_arrayref_ (item, expr, 1);
5ff904cd
JL
2061 }
2062 break;
2063
2064 case FFEBLD_opSUBSTR:
2065 {
2066 ffebld start;
2067 ffebld end;
2068 ffebld thing = ffebld_right (expr);
2069 tree start_tree;
2070 tree end_tree;
3b304f5b 2071 const char *char_name;
6b55276e
CB
2072 ffebld left_symter;
2073 tree array;
5ff904cd
JL
2074
2075 assert (ffebld_op (thing) == FFEBLD_opITEM);
2076 start = ffebld_head (thing);
2077 thing = ffebld_trail (thing);
2078 assert (ffebld_trail (thing) == NULL);
2079 end = ffebld_head (thing);
2080
6b55276e
CB
2081 /* Determine name for pretty-printing range-check errors. */
2082 for (left_symter = ffebld_left (expr);
2083 left_symter && ffebld_op (left_symter) == FFEBLD_opARRAYREF;
2084 left_symter = ffebld_left (left_symter))
2085 ;
2086 if (ffebld_op (left_symter) == FFEBLD_opSYMTER)
2087 char_name = ffesymbol_text (ffebld_symter (left_symter));
2088 else
2089 char_name = "[expr?]";
2090
5ff904cd 2091 ffecom_char_args_ (&item, length, ffebld_left (expr));
5ff904cd
JL
2092
2093 if (item == error_mark_node || *length == error_mark_node)
2094 {
2095 item = *length = error_mark_node;
2096 break;
2097 }
2098
6b55276e
CB
2099 array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
2100
ff852b44
CB
2101 /* ~~~~Handle INTEGER*8 start/end, a la FFEBLD_opARRAYREF. */
2102
5ff904cd
JL
2103 if (start == NULL)
2104 {
2105 if (end == NULL)
2106 ;
2107 else
2108 {
6b55276e 2109 end_tree = ffecom_expr (end);
02f06e64 2110 if (flag_bounds_check)
6b55276e
CB
2111 end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
2112 char_name);
5ff904cd 2113 end_tree = convert (ffecom_f2c_ftnlen_type_node,
6b55276e 2114 end_tree);
5ff904cd
JL
2115
2116 if (end_tree == error_mark_node)
2117 {
2118 item = *length = error_mark_node;
2119 break;
2120 }
2121
2122 *length = end_tree;
2123 }
2124 }
2125 else
2126 {
6b55276e 2127 start_tree = ffecom_expr (start);
02f06e64 2128 if (flag_bounds_check)
6b55276e
CB
2129 start_tree = ffecom_subscript_check_ (array, start_tree, 0, 0,
2130 char_name);
5ff904cd 2131 start_tree = convert (ffecom_f2c_ftnlen_type_node,
6b55276e 2132 start_tree);
5ff904cd
JL
2133
2134 if (start_tree == error_mark_node)
2135 {
2136 item = *length = error_mark_node;
2137 break;
2138 }
2139
2140 start_tree = ffecom_save_tree (start_tree);
2141
2142 item = ffecom_2 (PLUS_EXPR, TREE_TYPE (item),
2143 item,
2144 ffecom_2 (MINUS_EXPR,
2145 TREE_TYPE (start_tree),
2146 start_tree,
2147 ffecom_f2c_ftnlen_one_node));
2148
2149 if (end == NULL)
2150 {
2151 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
2152 ffecom_f2c_ftnlen_one_node,
2153 ffecom_2 (MINUS_EXPR,
2154 ffecom_f2c_ftnlen_type_node,
2155 *length,
2156 start_tree));
2157 }
2158 else
2159 {
6b55276e 2160 end_tree = ffecom_expr (end);
02f06e64 2161 if (flag_bounds_check)
6b55276e
CB
2162 end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
2163 char_name);
5ff904cd 2164 end_tree = convert (ffecom_f2c_ftnlen_type_node,
6b55276e 2165 end_tree);
5ff904cd
JL
2166
2167 if (end_tree == error_mark_node)
2168 {
2169 item = *length = error_mark_node;
2170 break;
2171 }
2172
2173 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
2174 ffecom_f2c_ftnlen_one_node,
2175 ffecom_2 (MINUS_EXPR,
2176 ffecom_f2c_ftnlen_type_node,
2177 end_tree, start_tree));
2178 }
2179 }
2180 }
2181 break;
2182
2183 case FFEBLD_opFUNCREF:
2184 {
2185 ffesymbol s = ffebld_symter (ffebld_left (expr));
2186 tree tempvar;
2187 tree args;
2188 ffetargetCharacterSize size = ffeinfo_size (ffebld_info (expr));
2189 ffecomGfrt ix;
2190
2191 if (size == FFETARGET_charactersizeNONE)
c7e4ee3a
CB
2192 /* ~~Kludge alert! This should someday be fixed. */
2193 size = 24;
5ff904cd
JL
2194
2195 *length = build_int_2 (size, 0);
2196 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2197
2198 if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
2199 == FFEINFO_whereINTRINSIC)
2200 {
2201 if (size == 1)
c7e4ee3a
CB
2202 {
2203 /* Invocation of an intrinsic returning CHARACTER*1. */
5ff904cd
JL
2204 item = ffecom_expr_intrinsic_ (expr, NULL_TREE,
2205 NULL, NULL);
2206 break;
2207 }
2208 ix = ffeintrin_gfrt_direct (ffebld_symter_implementation (ffebld_left (expr)));
2209 assert (ix != FFECOM_gfrt);
2210 item = ffecom_gfrt_tree_ (ix);
2211 }
2212 else
2213 {
2214 ix = FFECOM_gfrt;
2215 item = ffesymbol_hook (s).decl_tree;
2216 if (item == NULL_TREE)
2217 {
2218 s = ffecom_sym_transform_ (s);
2219 item = ffesymbol_hook (s).decl_tree;
2220 }
2221 if (item == error_mark_node)
2222 {
2223 item = *length = error_mark_node;
2224 break;
2225 }
2226
2227 if (!ffesymbol_hook (s).addr)
2228 item = ffecom_1_fn (item);
2229 }
2230
c7e4ee3a 2231#ifdef HOHO
5ff904cd 2232 tempvar = ffecom_push_tempvar (char_type_node, size, -1, TRUE);
c7e4ee3a
CB
2233#else
2234 tempvar = ffebld_nonter_hook (expr);
2235 assert (tempvar);
2236#endif
5ff904cd
JL
2237 tempvar = ffecom_1 (ADDR_EXPR,
2238 build_pointer_type (TREE_TYPE (tempvar)),
2239 tempvar);
2240
5ff904cd
JL
2241 args = build_tree_list (NULL_TREE, tempvar);
2242
2243 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT) /* Sfunc args by value. */
2244 TREE_CHAIN (args) = ffecom_list_expr (ffebld_right (expr));
2245 else
2246 {
2247 TREE_CHAIN (args) = build_tree_list (NULL_TREE, *length);
2248 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
2249 {
2250 TREE_CHAIN (TREE_CHAIN (args))
2251 = ffecom_arglist_expr_ (ffecom_gfrt_args_ (ix),
2252 ffebld_right (expr));
2253 }
2254 else
2255 {
2256 TREE_CHAIN (TREE_CHAIN (args))
2257 = ffecom_list_ptr_to_expr (ffebld_right (expr));
2258 }
2259 }
2260
2261 item = ffecom_3s (CALL_EXPR,
2262 TREE_TYPE (TREE_TYPE (TREE_TYPE (item))),
2263 item, args, NULL_TREE);
2264 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item,
2265 tempvar);
5ff904cd
JL
2266 }
2267 break;
2268
2269 case FFEBLD_opCONVERT:
2270
5ff904cd 2271 ffecom_char_args_ (&item, length, ffebld_left (expr));
5ff904cd
JL
2272
2273 if (item == error_mark_node || *length == error_mark_node)
2274 {
2275 item = *length = error_mark_node;
2276 break;
2277 }
2278
2279 if ((ffebld_size_known (ffebld_left (expr))
2280 == FFETARGET_charactersizeNONE)
2281 || (ffebld_size_known (ffebld_left (expr)) < (ffebld_size (expr))))
2282 { /* Possible blank-padding needed, copy into
2283 temporary. */
2284 tree tempvar;
2285 tree args;
2286 tree newlen;
2287
c7e4ee3a
CB
2288#ifdef HOHO
2289 tempvar = ffecom_make_tempvar (char_type_node,
2290 ffebld_size (expr), -1);
2291#else
2292 tempvar = ffebld_nonter_hook (expr);
2293 assert (tempvar);
2294#endif
5ff904cd
JL
2295 tempvar = ffecom_1 (ADDR_EXPR,
2296 build_pointer_type (TREE_TYPE (tempvar)),
2297 tempvar);
2298
2299 newlen = build_int_2 (ffebld_size (expr), 0);
2300 TREE_TYPE (newlen) = ffecom_f2c_ftnlen_type_node;
2301
2302 args = build_tree_list (NULL_TREE, tempvar);
2303 TREE_CHAIN (args) = build_tree_list (NULL_TREE, item);
2304 TREE_CHAIN (TREE_CHAIN (args)) = build_tree_list (NULL_TREE, newlen);
2305 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (args)))
2306 = build_tree_list (NULL_TREE, *length);
2307
c7e4ee3a 2308 item = ffecom_call_gfrt (FFECOM_gfrtCOPY, args, NULL_TREE);
5ff904cd
JL
2309 TREE_SIDE_EFFECTS (item) = 1;
2310 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), fold (item),
2311 tempvar);
2312 *length = newlen;
2313 }
2314 else
2315 { /* Just truncate the length. */
2316 *length = build_int_2 (ffebld_size (expr), 0);
2317 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2318 }
2319 break;
2320
2321 default:
2322 assert ("bad op for single char arg expr" == NULL);
2323 item = NULL_TREE;
2324 break;
2325 }
2326
2327 *xitem = item;
2328}
2329#endif
2330
2331/* Check the size of the type to be sure it doesn't overflow the
2332 "portable" capacities of the compiler back end. `dummy' types
2333 can generally overflow the normal sizes as long as the computations
2334 themselves don't overflow. A particular target of the back end
2335 must still enforce its size requirements, though, and the back
2336 end takes care of this in stor-layout.c. */
2337
2338#if FFECOM_targetCURRENT == FFECOM_targetGCC
2339static tree
2340ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy)
2341{
2342 if (TREE_CODE (type) == ERROR_MARK)
2343 return type;
2344
2345 if (TYPE_SIZE (type) == NULL_TREE)
2346 return type;
2347
2348 if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
2349 return type;
2350
2351 if ((tree_int_cst_sgn (TYPE_SIZE (type)) < 0)
2b0c2df0
CB
2352 || (!dummy && (((TREE_INT_CST_HIGH (TYPE_SIZE (type)) != 0))
2353 || TREE_OVERFLOW (TYPE_SIZE (type)))))
5ff904cd
JL
2354 {
2355 ffebad_start (FFEBAD_ARRAY_LARGE);
2356 ffebad_string (ffesymbol_text (s));
2357 ffebad_here (0, ffesymbol_where_line (s), ffesymbol_where_column (s));
2358 ffebad_finish ();
2359
2360 return error_mark_node;
2361 }
2362
2363 return type;
2364}
2365#endif
2366
2367/* Builds a length argument (PARM_DECL). Also wraps type in an array type
2368 where the dimension info is (1:size) where <size> is ffesymbol_size(s) if
2369 known, length_arg if not known (FFETARGET_charactersizeNONE). */
2370
2371#if FFECOM_targetCURRENT == FFECOM_targetGCC
2372static tree
2373ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s)
2374{
2375 ffetargetCharacterSize sz = ffesymbol_size (s);
2376 tree highval;
2377 tree tlen;
2378 tree type = *xtype;
2379
2380 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
2381 tlen = NULL_TREE; /* A statement function, no length passed. */
2382 else
2383 {
2384 if (ffesymbol_where (s) == FFEINFO_whereDUMMY)
2385 tlen = ffecom_get_invented_identifier ("__g77_length_%s",
14657de8 2386 ffesymbol_text (s));
5ff904cd 2387 else
14657de8 2388 tlen = ffecom_get_invented_identifier ("__g77_%s", "length");
5ff904cd
JL
2389 tlen = build_decl (PARM_DECL, tlen, ffecom_f2c_ftnlen_type_node);
2390#if BUILT_FOR_270
2391 DECL_ARTIFICIAL (tlen) = 1;
2392#endif
2393 }
2394
2395 if (sz == FFETARGET_charactersizeNONE)
2396 {
2397 assert (tlen != NULL_TREE);
2b0c2df0 2398 highval = variable_size (tlen);
5ff904cd
JL
2399 }
2400 else
2401 {
2402 highval = build_int_2 (sz, 0);
2403 TREE_TYPE (highval) = ffecom_f2c_ftnlen_type_node;
2404 }
2405
2406 type = build_array_type (type,
2407 build_range_type (ffecom_f2c_ftnlen_type_node,
2408 ffecom_f2c_ftnlen_one_node,
2409 highval));
2410
2411 *xtype = type;
2412 return tlen;
2413}
2414
2415#endif
2416/* ffecom_concat_list_gather_ -- Gather list of concatenated string exprs
2417
2418 ffecomConcatList_ catlist;
2419 ffebld expr; // expr of CHARACTER basictype.
2420 ffetargetCharacterSize max; // max chars to gather or _...NONE if no max
2421 catlist = ffecom_concat_list_gather_(catlist,expr,max);
2422
2423 Scans expr for character subexpressions, updates and returns catlist
2424 accordingly. */
2425
2426#if FFECOM_targetCURRENT == FFECOM_targetGCC
2427static ffecomConcatList_
2428ffecom_concat_list_gather_ (ffecomConcatList_ catlist, ffebld expr,
2429 ffetargetCharacterSize max)
2430{
2431 ffetargetCharacterSize sz;
2432
2433recurse: /* :::::::::::::::::::: */
2434
2435 if (expr == NULL)
2436 return catlist;
2437
2438 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen >= max))
2439 return catlist; /* Don't append any more items. */
2440
2441 switch (ffebld_op (expr))
2442 {
2443 case FFEBLD_opCONTER:
2444 case FFEBLD_opSYMTER:
2445 case FFEBLD_opARRAYREF:
2446 case FFEBLD_opFUNCREF:
2447 case FFEBLD_opSUBSTR:
2448 case FFEBLD_opCONVERT: /* Callers should strip this off beforehand
2449 if they don't need to preserve it. */
2450 if (catlist.count == catlist.max)
2451 { /* Make a (larger) list. */
2452 ffebld *newx;
2453 int newmax;
2454
2455 newmax = (catlist.max == 0) ? 8 : catlist.max * 2;
2456 newx = malloc_new_ks (malloc_pool_image (), "catlist",
2457 newmax * sizeof (newx[0]));
2458 if (catlist.max != 0)
2459 {
2460 memcpy (newx, catlist.exprs, catlist.max * sizeof (newx[0]));
2461 malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2462 catlist.max * sizeof (newx[0]));
2463 }
2464 catlist.max = newmax;
2465 catlist.exprs = newx;
2466 }
2467 if ((sz = ffebld_size_known (expr)) != FFETARGET_charactersizeNONE)
2468 catlist.minlen += sz;
2469 else
2470 ++catlist.minlen; /* Not true for F90; can be 0 length. */
2471 if ((sz = ffebld_size_max (expr)) == FFETARGET_charactersizeNONE)
2472 catlist.maxlen = sz;
2473 else
2474 catlist.maxlen += sz;
2475 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen > max))
2476 { /* This item overlaps (or is beyond) the end
2477 of the destination. */
2478 switch (ffebld_op (expr))
2479 {
2480 case FFEBLD_opCONTER:
2481 case FFEBLD_opSYMTER:
2482 case FFEBLD_opARRAYREF:
2483 case FFEBLD_opFUNCREF:
2484 case FFEBLD_opSUBSTR:
c7e4ee3a
CB
2485 /* ~~Do useful truncations here. */
2486 break;
5ff904cd
JL
2487
2488 default:
2489 assert ("op changed or inconsistent switches!" == NULL);
2490 break;
2491 }
2492 }
2493 catlist.exprs[catlist.count++] = expr;
2494 return catlist;
2495
2496 case FFEBLD_opPAREN:
2497 expr = ffebld_left (expr);
2498 goto recurse; /* :::::::::::::::::::: */
2499
2500 case FFEBLD_opCONCATENATE:
2501 catlist = ffecom_concat_list_gather_ (catlist, ffebld_left (expr), max);
2502 expr = ffebld_right (expr);
2503 goto recurse; /* :::::::::::::::::::: */
2504
2505#if 0 /* Breaks passing small actual arg to larger
2506 dummy arg of sfunc */
2507 case FFEBLD_opCONVERT:
2508 expr = ffebld_left (expr);
2509 {
2510 ffetargetCharacterSize cmax;
2511
2512 cmax = catlist.len + ffebld_size_known (expr);
2513
2514 if ((max == FFETARGET_charactersizeNONE) || (max > cmax))
2515 max = cmax;
2516 }
2517 goto recurse; /* :::::::::::::::::::: */
2518#endif
2519
2520 case FFEBLD_opANY:
2521 return catlist;
2522
2523 default:
2524 assert ("bad op in _gather_" == NULL);
2525 return catlist;
2526 }
2527}
2528
2529#endif
2530/* ffecom_concat_list_kill_ -- Kill list of concatenated string exprs
2531
2532 ffecomConcatList_ catlist;
2533 ffecom_concat_list_kill_(catlist);
2534
2535 Anything allocated within the list info is deallocated. */
2536
2537#if FFECOM_targetCURRENT == FFECOM_targetGCC
2538static void
2539ffecom_concat_list_kill_ (ffecomConcatList_ catlist)
2540{
2541 if (catlist.max != 0)
2542 malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2543 catlist.max * sizeof (catlist.exprs[0]));
2544}
2545
2546#endif
c7e4ee3a 2547/* Make list of concatenated string exprs.
5ff904cd
JL
2548
2549 Returns a flattened list of concatenated subexpressions given a
2550 tree of such expressions. */
2551
2552#if FFECOM_targetCURRENT == FFECOM_targetGCC
2553static ffecomConcatList_
2554ffecom_concat_list_new_ (ffebld expr, ffetargetCharacterSize max)
2555{
2556 ffecomConcatList_ catlist;
2557
2558 catlist.maxlen = catlist.minlen = catlist.max = catlist.count = 0;
2559 return ffecom_concat_list_gather_ (catlist, expr, max);
2560}
2561
2562#endif
2563
2564/* Provide some kind of useful info on member of aggregate area,
2565 since current g77/gcc technology does not provide debug info
2566 on these members. */
2567
2568#if FFECOM_targetCURRENT == FFECOM_targetGCC
2569static void
26f096f9 2570ffecom_debug_kludge_ (tree aggr, const char *aggr_type, ffesymbol member,
5ff904cd
JL
2571 tree member_type UNUSED, ffetargetOffset offset)
2572{
2573 tree value;
2574 tree decl;
2575 int len;
2576 char *buff;
2577 char space[120];
2578#if 0
2579 tree type_id;
2580
2581 for (type_id = member_type;
2582 TREE_CODE (type_id) != IDENTIFIER_NODE;
2583 )
2584 {
2585 switch (TREE_CODE (type_id))
2586 {
2587 case INTEGER_TYPE:
2588 case REAL_TYPE:
2589 type_id = TYPE_NAME (type_id);
2590 break;
2591
2592 case ARRAY_TYPE:
2593 case COMPLEX_TYPE:
2594 type_id = TREE_TYPE (type_id);
2595 break;
2596
2597 default:
2598 assert ("no IDENTIFIER_NODE for type!" == NULL);
2599 type_id = error_mark_node;
2600 break;
2601 }
2602 }
2603#endif
2604
2605 if (ffecom_transform_only_dummies_
2606 || !ffe_is_debug_kludge ())
2607 return; /* Can't do this yet, maybe later. */
2608
2609 len = 60
2610 + strlen (aggr_type)
2611 + IDENTIFIER_LENGTH (DECL_NAME (aggr));
2612#if 0
2613 + IDENTIFIER_LENGTH (type_id);
2614#endif
2615
2616 if (((size_t) len) >= ARRAY_SIZE (space))
2617 buff = malloc_new_ks (malloc_pool_image (), "debug_kludge", len + 1);
2618 else
2619 buff = &space[0];
2620
2621 sprintf (&buff[0], "At (%s) `%s' plus %ld bytes",
2622 aggr_type,
2623 IDENTIFIER_POINTER (DECL_NAME (aggr)),
2624 (long int) offset);
2625
2626 value = build_string (len, buff);
2627 TREE_TYPE (value)
2628 = build_type_variant (build_array_type (char_type_node,
2629 build_range_type
2630 (integer_type_node,
2631 integer_one_node,
2632 build_int_2 (strlen (buff), 0))),
2633 1, 0);
2634 decl = build_decl (VAR_DECL,
2635 ffecom_get_identifier_ (ffesymbol_text (member)),
2636 TREE_TYPE (value));
2637 TREE_CONSTANT (decl) = 1;
2638 TREE_STATIC (decl) = 1;
2639 DECL_INITIAL (decl) = error_mark_node;
2640 DECL_IN_SYSTEM_HEADER (decl) = 1; /* Don't let -Wunused complain. */
2641 decl = start_decl (decl, FALSE);
2642 finish_decl (decl, value, FALSE);
2643
2644 if (buff != &space[0])
2645 malloc_kill_ks (malloc_pool_image (), buff, len + 1);
2646}
2647#endif
2648
2649/* ffecom_do_entry_ -- Do compilation of a particular entrypoint
2650
2651 ffesymbol fn; // the SUBROUTINE, FUNCTION, or ENTRY symbol itself
2652 int i; // entry# for this entrypoint (used by master fn)
2653 ffecom_do_entrypoint_(s,i);
2654
2655 Makes a public entry point that calls our private master fn (already
2656 compiled). */
2657
2658#if FFECOM_targetCURRENT == FFECOM_targetGCC
2659static void
2660ffecom_do_entry_ (ffesymbol fn, int entrynum)
2661{
2662 ffebld item;
2663 tree type; /* Type of function. */
2664 tree multi_retval; /* Var holding return value (union). */
2665 tree result; /* Var holding result. */
2666 ffeinfoBasictype bt;
2667 ffeinfoKindtype kt;
2668 ffeglobal g;
2669 ffeglobalType gt;
2670 bool charfunc; /* All entry points return same type
2671 CHARACTER. */
2672 bool cmplxfunc; /* Use f2c way of returning COMPLEX. */
2673 bool multi; /* Master fn has multiple return types. */
2674 bool altreturning = FALSE; /* This entry point has alternate returns. */
44d2eabc 2675 int old_lineno = lineno;
3b304f5b 2676 const char *old_input_filename = input_filename;
44d2eabc
JL
2677
2678 input_filename = ffesymbol_where_filename (fn);
2679 lineno = ffesymbol_where_filelinenum (fn);
5ff904cd 2680
5ff904cd
JL
2681 ffecom_doing_entry_ = TRUE; /* Don't bother with array dimensions. */
2682
2683 switch (ffecom_primary_entry_kind_)
2684 {
2685 case FFEINFO_kindFUNCTION:
2686
2687 /* Determine actual return type for function. */
2688
2689 gt = FFEGLOBAL_typeFUNC;
2690 bt = ffesymbol_basictype (fn);
2691 kt = ffesymbol_kindtype (fn);
2692 if (bt == FFEINFO_basictypeNONE)
2693 {
2694 ffeimplic_establish_symbol (fn);
2695 if (ffesymbol_funcresult (fn) != NULL)
2696 ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
2697 bt = ffesymbol_basictype (fn);
2698 kt = ffesymbol_kindtype (fn);
2699 }
2700
2701 if (bt == FFEINFO_basictypeCHARACTER)
2702 charfunc = TRUE, cmplxfunc = FALSE;
2703 else if ((bt == FFEINFO_basictypeCOMPLEX)
2704 && ffesymbol_is_f2c (fn))
2705 charfunc = FALSE, cmplxfunc = TRUE;
2706 else
2707 charfunc = cmplxfunc = FALSE;
2708
2709 if (charfunc)
2710 type = ffecom_tree_fun_type_void;
2711 else if (ffesymbol_is_f2c (fn))
2712 type = ffecom_tree_fun_type[bt][kt];
2713 else
2714 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
2715
2716 if ((type == NULL_TREE)
2717 || (TREE_TYPE (type) == NULL_TREE))
2718 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */
2719
2720 multi = (ffecom_master_bt_ == FFEINFO_basictypeNONE);
2721 break;
2722
2723 case FFEINFO_kindSUBROUTINE:
2724 gt = FFEGLOBAL_typeSUBR;
2725 bt = FFEINFO_basictypeNONE;
2726 kt = FFEINFO_kindtypeNONE;
2727 if (ffecom_is_altreturning_)
2728 { /* Am _I_ altreturning? */
2729 for (item = ffesymbol_dummyargs (fn);
2730 item != NULL;
2731 item = ffebld_trail (item))
2732 {
2733 if (ffebld_op (ffebld_head (item)) == FFEBLD_opSTAR)
2734 {
2735 altreturning = TRUE;
2736 break;
2737 }
2738 }
2739 if (altreturning)
2740 type = ffecom_tree_subr_type;
2741 else
2742 type = ffecom_tree_fun_type_void;
2743 }
2744 else
2745 type = ffecom_tree_fun_type_void;
2746 charfunc = FALSE;
2747 cmplxfunc = FALSE;
2748 multi = FALSE;
2749 break;
2750
2751 default:
2752 assert ("say what??" == NULL);
2753 /* Fall through. */
2754 case FFEINFO_kindANY:
2755 gt = FFEGLOBAL_typeANY;
2756 bt = FFEINFO_basictypeNONE;
2757 kt = FFEINFO_kindtypeNONE;
2758 type = error_mark_node;
2759 charfunc = FALSE;
2760 cmplxfunc = FALSE;
2761 multi = FALSE;
2762 break;
2763 }
2764
2765 /* build_decl uses the current lineno and input_filename to set the decl
2766 source info. So, I've putzed with ffestd and ffeste code to update that
2767 source info to point to the appropriate statement just before calling
2768 ffecom_do_entrypoint (which calls this fn). */
2769
2770 start_function (ffecom_get_external_identifier_ (fn),
2771 type,
2772 0, /* nested/inline */
2773 1); /* TREE_PUBLIC */
2774
2775 if (((g = ffesymbol_global (fn)) != NULL)
2776 && ((ffeglobal_type (g) == gt)
2777 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
2778 {
2779 ffeglobal_set_hook (g, current_function_decl);
2780 }
2781
2782 /* Reset args in master arg list so they get retransitioned. */
2783
2784 for (item = ffecom_master_arglist_;
2785 item != NULL;
2786 item = ffebld_trail (item))
2787 {
2788 ffebld arg;
2789 ffesymbol s;
2790
2791 arg = ffebld_head (item);
2792 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2793 continue; /* Alternate return or some such thing. */
2794 s = ffebld_symter (arg);
2795 ffesymbol_hook (s).decl_tree = NULL_TREE;
2796 ffesymbol_hook (s).length_tree = NULL_TREE;
2797 }
2798
2799 /* Build dummy arg list for this entry point. */
2800
5ff904cd
JL
2801 if (charfunc || cmplxfunc)
2802 { /* Prepend arg for where result goes. */
2803 tree type;
2804 tree length;
2805
2806 if (charfunc)
2807 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
2808 else
2809 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
2810
14657de8 2811 result = ffecom_get_invented_identifier ("__g77_%s", "result");
5ff904cd
JL
2812
2813 /* Make length arg _and_ enhance type info for CHAR arg itself. */
2814
2815 if (charfunc)
2816 length = ffecom_char_enhance_arg_ (&type, fn);
2817 else
2818 length = NULL_TREE; /* Not ref'd if !charfunc. */
2819
2820 type = build_pointer_type (type);
2821 result = build_decl (PARM_DECL, result, type);
2822
2823 push_parm_decl (result);
2824 ffecom_func_result_ = result;
2825
2826 if (charfunc)
2827 {
2828 push_parm_decl (length);
2829 ffecom_func_length_ = length;
2830 }
2831 }
2832 else
2833 result = DECL_RESULT (current_function_decl);
2834
2835 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (fn), FALSE);
2836
5ff904cd
JL
2837 store_parm_decls (0);
2838
c7e4ee3a
CB
2839 ffecom_start_compstmt ();
2840 /* Disallow temp vars at this level. */
2841 current_binding_level->prep_state = 2;
5ff904cd
JL
2842
2843 /* Make local var to hold return type for multi-type master fn. */
2844
2845 if (multi)
2846 {
5ff904cd 2847 multi_retval = ffecom_get_invented_identifier ("__g77_%s",
14657de8 2848 "multi_retval");
5ff904cd
JL
2849 multi_retval = build_decl (VAR_DECL, multi_retval,
2850 ffecom_multi_type_node_);
2851 multi_retval = start_decl (multi_retval, FALSE);
2852 finish_decl (multi_retval, NULL_TREE, FALSE);
5ff904cd
JL
2853 }
2854 else
2855 multi_retval = NULL_TREE; /* Not actually ref'd if !multi. */
2856
2857 /* Here we emit the actual code for the entry point. */
2858
2859 {
2860 ffebld list;
2861 ffebld arg;
2862 ffesymbol s;
2863 tree arglist = NULL_TREE;
2864 tree *plist = &arglist;
2865 tree prepend;
2866 tree call;
2867 tree actarg;
2868 tree master_fn;
2869
2870 /* Prepare actual arg list based on master arg list. */
2871
2872 for (list = ffecom_master_arglist_;
2873 list != NULL;
2874 list = ffebld_trail (list))
2875 {
2876 arg = ffebld_head (list);
2877 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2878 continue;
2879 s = ffebld_symter (arg);
702edf1d
CB
2880 if (ffesymbol_hook (s).decl_tree == NULL_TREE
2881 || ffesymbol_hook (s).decl_tree == error_mark_node)
5ff904cd
JL
2882 actarg = null_pointer_node; /* We don't have this arg. */
2883 else
2884 actarg = ffesymbol_hook (s).decl_tree;
2885 *plist = build_tree_list (NULL_TREE, actarg);
2886 plist = &TREE_CHAIN (*plist);
2887 }
2888
2889 /* This code appends the length arguments for character
2890 variables/arrays. */
2891
2892 for (list = ffecom_master_arglist_;
2893 list != NULL;
2894 list = ffebld_trail (list))
2895 {
2896 arg = ffebld_head (list);
2897 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2898 continue;
2899 s = ffebld_symter (arg);
2900 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
2901 continue; /* Only looking for CHARACTER arguments. */
2902 if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
2903 continue; /* Only looking for variables and arrays. */
702edf1d
CB
2904 if (ffesymbol_hook (s).length_tree == NULL_TREE
2905 || ffesymbol_hook (s).length_tree == error_mark_node)
5ff904cd
JL
2906 actarg = ffecom_f2c_ftnlen_zero_node; /* We don't have this arg. */
2907 else
2908 actarg = ffesymbol_hook (s).length_tree;
2909 *plist = build_tree_list (NULL_TREE, actarg);
2910 plist = &TREE_CHAIN (*plist);
2911 }
2912
2913 /* Prepend character-value return info to actual arg list. */
2914
2915 if (charfunc)
2916 {
2917 prepend = build_tree_list (NULL_TREE, ffecom_func_result_);
2918 TREE_CHAIN (prepend)
2919 = build_tree_list (NULL_TREE, ffecom_func_length_);
2920 TREE_CHAIN (TREE_CHAIN (prepend)) = arglist;
2921 arglist = prepend;
2922 }
2923
2924 /* Prepend multi-type return value to actual arg list. */
2925
2926 if (multi)
2927 {
2928 prepend
2929 = build_tree_list (NULL_TREE,
2930 ffecom_1 (ADDR_EXPR,
2931 build_pointer_type (TREE_TYPE (multi_retval)),
2932 multi_retval));
2933 TREE_CHAIN (prepend) = arglist;
2934 arglist = prepend;
2935 }
2936
2937 /* Prepend my entry-point number to the actual arg list. */
2938
2939 prepend = build_tree_list (NULL_TREE, build_int_2 (entrynum, 0));
2940 TREE_CHAIN (prepend) = arglist;
2941 arglist = prepend;
2942
2943 /* Build the call to the master function. */
2944
2945 master_fn = ffecom_1_fn (ffecom_previous_function_decl_);
2946 call = ffecom_3s (CALL_EXPR,
2947 TREE_TYPE (TREE_TYPE (TREE_TYPE (master_fn))),
2948 master_fn, arglist, NULL_TREE);
2949
2950 /* Decide whether the master function is a function or subroutine, and
2951 handle the return value for my entry point. */
2952
2953 if (charfunc || ((ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
2954 && !altreturning))
2955 {
2956 expand_expr_stmt (call);
2957 expand_null_return ();
2958 }
2959 else if (multi && cmplxfunc)
2960 {
2961 expand_expr_stmt (call);
2962 result
2963 = ffecom_1 (INDIRECT_REF,
2964 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
2965 result);
2966 result = ffecom_modify (NULL_TREE, result,
2967 ffecom_2 (COMPONENT_REF, TREE_TYPE (result),
2968 multi_retval,
2969 ffecom_multi_fields_[bt][kt]));
2970 expand_expr_stmt (result);
2971 expand_null_return ();
2972 }
2973 else if (multi)
2974 {
2975 expand_expr_stmt (call);
2976 result
2977 = ffecom_modify (NULL_TREE, result,
2978 convert (TREE_TYPE (result),
2979 ffecom_2 (COMPONENT_REF,
2980 ffecom_tree_type[bt][kt],
2981 multi_retval,
2982 ffecom_multi_fields_[bt][kt])));
2983 expand_return (result);
2984 }
2985 else if (cmplxfunc)
2986 {
2987 result
2988 = ffecom_1 (INDIRECT_REF,
2989 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
2990 result);
2991 result = ffecom_modify (NULL_TREE, result, call);
2992 expand_expr_stmt (result);
2993 expand_null_return ();
2994 }
2995 else
2996 {
2997 result = ffecom_modify (NULL_TREE,
2998 result,
2999 convert (TREE_TYPE (result),
3000 call));
3001 expand_return (result);
3002 }
5ff904cd
JL
3003 }
3004
c7e4ee3a 3005 ffecom_end_compstmt ();
5ff904cd
JL
3006
3007 finish_function (0);
3008
44d2eabc
JL
3009 lineno = old_lineno;
3010 input_filename = old_input_filename;
3011
5ff904cd
JL
3012 ffecom_doing_entry_ = FALSE;
3013}
3014
3015#endif
3016/* Transform expr into gcc tree with possible destination
3017
3018 Recursive descent on expr while making corresponding tree nodes and
3019 attaching type info and such. If destination supplied and compatible
3020 with temporary that would be made in certain cases, temporary isn't
092a4ef8 3021 made, destination used instead, and dest_used flag set TRUE. */
5ff904cd
JL
3022
3023#if FFECOM_targetCURRENT == FFECOM_targetGCC
3024static tree
092a4ef8
RH
3025ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
3026 bool *dest_used, bool assignp, bool widenp)
5ff904cd
JL
3027{
3028 tree item;
3029 tree list;
3030 tree args;
3031 ffeinfoBasictype bt;
3032 ffeinfoKindtype kt;
3033 tree t;
5ff904cd 3034 tree dt; /* decl_tree for an ffesymbol. */
092a4ef8 3035 tree tree_type, tree_type_x;
af752698 3036 tree left, right;
5ff904cd
JL
3037 ffesymbol s;
3038 enum tree_code code;
3039
3040 assert (expr != NULL);
3041
3042 if (dest_used != NULL)
3043 *dest_used = FALSE;
3044
3045 bt = ffeinfo_basictype (ffebld_info (expr));
3046 kt = ffeinfo_kindtype (ffebld_info (expr));
af752698 3047 tree_type = ffecom_tree_type[bt][kt];
5ff904cd 3048
092a4ef8
RH
3049 /* Widen integral arithmetic as desired while preserving signedness. */
3050 tree_type_x = NULL_TREE;
3051 if (widenp && tree_type
3052 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
3053 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
3054 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
3055
5ff904cd
JL
3056 switch (ffebld_op (expr))
3057 {
3058 case FFEBLD_opACCTER:
5ff904cd
JL
3059 {
3060 ffebitCount i;
3061 ffebit bits = ffebld_accter_bits (expr);
3062 ffetargetOffset source_offset = 0;
a6fa6420 3063 ffetargetOffset dest_offset = ffebld_accter_pad (expr);
5ff904cd
JL
3064 tree purpose;
3065
a6fa6420
CB
3066 assert (dest_offset == 0
3067 || (bt == FFEINFO_basictypeCHARACTER
3068 && kt == FFEINFO_kindtypeCHARACTER1));
5ff904cd
JL
3069
3070 list = item = NULL;
3071 for (;;)
3072 {
3073 ffebldConstantUnion cu;
3074 ffebitCount length;
3075 bool value;
3076 ffebldConstantArray ca = ffebld_accter (expr);
3077
3078 ffebit_test (bits, source_offset, &value, &length);
3079 if (length == 0)
3080 break;
3081
3082 if (value)
3083 {
3084 for (i = 0; i < length; ++i)
3085 {
3086 cu = ffebld_constantarray_get (ca, bt, kt,
3087 source_offset + i);
3088
3089 t = ffecom_constantunion (&cu, bt, kt, tree_type);
3090
a6fa6420
CB
3091 if (i == 0
3092 && dest_offset != 0)
3093 purpose = build_int_2 (dest_offset, 0);
5ff904cd
JL
3094 else
3095 purpose = NULL_TREE;
3096
3097 if (list == NULL_TREE)
3098 list = item = build_tree_list (purpose, t);
3099 else
3100 {
3101 TREE_CHAIN (item) = build_tree_list (purpose, t);
3102 item = TREE_CHAIN (item);
3103 }
3104 }
3105 }
3106 source_offset += length;
a6fa6420 3107 dest_offset += length;
5ff904cd
JL
3108 }
3109 }
3110
a6fa6420
CB
3111 item = build_int_2 ((ffebld_accter_size (expr)
3112 + ffebld_accter_pad (expr)) - 1, 0);
5ff904cd
JL
3113 ffebit_kill (ffebld_accter_bits (expr));
3114 TREE_TYPE (item) = ffecom_integer_type_node;
3115 item
3116 = build_array_type
3117 (tree_type,
3118 build_range_type (ffecom_integer_type_node,
3119 ffecom_integer_zero_node,
3120 item));
3121 list = build (CONSTRUCTOR, item, NULL_TREE, list);
3122 TREE_CONSTANT (list) = 1;
3123 TREE_STATIC (list) = 1;
3124 return list;
3125
3126 case FFEBLD_opARRTER:
5ff904cd
JL
3127 {
3128 ffetargetOffset i;
3129
a6fa6420
CB
3130 list = NULL_TREE;
3131 if (ffebld_arrter_pad (expr) == 0)
3132 item = NULL_TREE;
3133 else
3134 {
3135 assert (bt == FFEINFO_basictypeCHARACTER
3136 && kt == FFEINFO_kindtypeCHARACTER1);
3137
3138 /* Becomes PURPOSE first time through loop. */
3139 item = build_int_2 (ffebld_arrter_pad (expr), 0);
3140 }
3141
5ff904cd
JL
3142 for (i = 0; i < ffebld_arrter_size (expr); ++i)
3143 {
3144 ffebldConstantUnion cu
3145 = ffebld_constantarray_get (ffebld_arrter (expr), bt, kt, i);
3146
3147 t = ffecom_constantunion (&cu, bt, kt, tree_type);
3148
3149 if (list == NULL_TREE)
a6fa6420
CB
3150 /* Assume item is PURPOSE first time through loop. */
3151 list = item = build_tree_list (item, t);
5ff904cd
JL
3152 else
3153 {
3154 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
3155 item = TREE_CHAIN (item);
3156 }
3157 }
3158 }
3159
a6fa6420
CB
3160 item = build_int_2 ((ffebld_arrter_size (expr)
3161 + ffebld_arrter_pad (expr)) - 1, 0);
5ff904cd
JL
3162 TREE_TYPE (item) = ffecom_integer_type_node;
3163 item
3164 = build_array_type
3165 (tree_type,
3166 build_range_type (ffecom_integer_type_node,
a6fa6420 3167 ffecom_integer_zero_node,
5ff904cd
JL
3168 item));
3169 list = build (CONSTRUCTOR, item, NULL_TREE, list);
3170 TREE_CONSTANT (list) = 1;
3171 TREE_STATIC (list) = 1;
3172 return list;
3173
3174 case FFEBLD_opCONTER:
c264f113 3175 assert (ffebld_conter_pad (expr) == 0);
5ff904cd
JL
3176 item
3177 = ffecom_constantunion (&ffebld_constant_union (ffebld_conter (expr)),
3178 bt, kt, tree_type);
3179 return item;
3180
3181 case FFEBLD_opSYMTER:
3182 if ((ffebld_symter_generic (expr) != FFEINTRIN_genNONE)
3183 || (ffebld_symter_specific (expr) != FFEINTRIN_specNONE))
3184 return ffecom_ptr_to_expr (expr); /* Same as %REF(intrinsic). */
3185 s = ffebld_symter (expr);
3186 t = ffesymbol_hook (s).decl_tree;
3187
3188 if (assignp)
3189 { /* ASSIGN'ed-label expr. */
3190 if (ffe_is_ugly_assign ())
3191 {
3192 /* User explicitly wants ASSIGN'ed variables to be at the same
3193 memory address as the variables when used in non-ASSIGN
3194 contexts. That can make old, arcane, non-standard code
3195 work, but don't try to do it when a pointer wouldn't fit
3196 in the normal variable (take other approach, and warn,
3197 instead). */
3198
3199 if (t == NULL_TREE)
3200 {
3201 s = ffecom_sym_transform_ (s);
3202 t = ffesymbol_hook (s).decl_tree;
3203 assert (t != NULL_TREE);
3204 }
3205
3206 if (t == error_mark_node)
3207 return t;
3208
3209 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (t)))
3210 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
3211 {
3212 if (ffesymbol_hook (s).addr)
3213 t = ffecom_1 (INDIRECT_REF,
3214 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
3215 return t;
3216 }
3217
3218 if (ffesymbol_hook (s).assign_tree == NULL_TREE)
3219 {
3220 ffebad_start_msg ("ASSIGN'ed label cannot fit into `%A' at %0 -- using wider sibling",
3221 FFEBAD_severityWARNING);
3222 ffebad_string (ffesymbol_text (s));
3223 ffebad_here (0, ffesymbol_where_line (s),
3224 ffesymbol_where_column (s));
3225 ffebad_finish ();
3226 }
3227 }
3228
3229 /* Don't use the normal variable's tree for ASSIGN, though mark
3230 it as in the system header (housekeeping). Use an explicit,
3231 specially created sibling that is known to be wide enough
3232 to hold pointers to labels. */
3233
3234 if (t != NULL_TREE
3235 && TREE_CODE (t) == VAR_DECL)
3236 DECL_IN_SYSTEM_HEADER (t) = 1; /* Don't let -Wunused complain. */
3237
3238 t = ffesymbol_hook (s).assign_tree;
3239 if (t == NULL_TREE)
3240 {
3241 s = ffecom_sym_transform_assign_ (s);
3242 t = ffesymbol_hook (s).assign_tree;
3243 assert (t != NULL_TREE);
3244 }
3245 }
3246 else
3247 {
3248 if (t == NULL_TREE)
3249 {
3250 s = ffecom_sym_transform_ (s);
3251 t = ffesymbol_hook (s).decl_tree;
3252 assert (t != NULL_TREE);
3253 }
3254 if (ffesymbol_hook (s).addr)
3255 t = ffecom_1 (INDIRECT_REF,
3256 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
3257 }
3258 return t;
3259
3260 case FFEBLD_opARRAYREF:
ff852b44 3261 return ffecom_arrayref_ (NULL_TREE, expr, 0);
5ff904cd
JL
3262
3263 case FFEBLD_opUPLUS:
092a4ef8 3264 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
af752698 3265 return ffecom_1 (NOP_EXPR, tree_type, left);
5ff904cd 3266
c7e4ee3a
CB
3267 case FFEBLD_opPAREN:
3268 /* ~~~Make sure Fortran rules respected here */
092a4ef8 3269 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
af752698 3270 return ffecom_1 (NOP_EXPR, tree_type, left);
5ff904cd
JL
3271
3272 case FFEBLD_opUMINUS:
092a4ef8 3273 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3274 if (tree_type_x)
3275 {
3276 tree_type = tree_type_x;
3277 left = convert (tree_type, left);
3278 }
3279 return ffecom_1 (NEGATE_EXPR, tree_type, left);
5ff904cd
JL
3280
3281 case FFEBLD_opADD:
092a4ef8
RH
3282 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3283 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3284 if (tree_type_x)
3285 {
3286 tree_type = tree_type_x;
3287 left = convert (tree_type, left);
3288 right = convert (tree_type, right);
3289 }
3290 return ffecom_2 (PLUS_EXPR, tree_type, left, right);
5ff904cd
JL
3291
3292 case FFEBLD_opSUBTRACT:
092a4ef8
RH
3293 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3294 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3295 if (tree_type_x)
3296 {
3297 tree_type = tree_type_x;
3298 left = convert (tree_type, left);
3299 right = convert (tree_type, right);
3300 }
3301 return ffecom_2 (MINUS_EXPR, tree_type, left, right);
5ff904cd
JL
3302
3303 case FFEBLD_opMULTIPLY:
092a4ef8
RH
3304 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3305 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3306 if (tree_type_x)
3307 {
3308 tree_type = tree_type_x;
3309 left = convert (tree_type, left);
3310 right = convert (tree_type, right);
3311 }
3312 return ffecom_2 (MULT_EXPR, tree_type, left, right);
5ff904cd
JL
3313
3314 case FFEBLD_opDIVIDE:
092a4ef8
RH
3315 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3316 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3317 if (tree_type_x)
3318 {
3319 tree_type = tree_type_x;
3320 left = convert (tree_type, left);
3321 right = convert (tree_type, right);
3322 }
3323 return ffecom_tree_divide_ (tree_type, left, right,
c7e4ee3a
CB
3324 dest_tree, dest, dest_used,
3325 ffebld_nonter_hook (expr));
5ff904cd
JL
3326
3327 case FFEBLD_opPOWER:
5ff904cd
JL
3328 {
3329 ffebld left = ffebld_left (expr);
3330 ffebld right = ffebld_right (expr);
3331 ffecomGfrt code;
3332 ffeinfoKindtype rtkt;
270fc4e8 3333 ffeinfoKindtype ltkt;
95eb4fd9 3334 bool ref = TRUE;
5ff904cd
JL
3335
3336 switch (ffeinfo_basictype (ffebld_info (right)))
3337 {
95eb4fd9 3338
5ff904cd
JL
3339 case FFEINFO_basictypeINTEGER:
3340 if (1 || optimize)
3341 {
c7e4ee3a 3342 item = ffecom_expr_power_integer_ (expr);
5ff904cd
JL
3343 if (item != NULL_TREE)
3344 return item;
3345 }
3346
3347 rtkt = FFEINFO_kindtypeINTEGER1;
3348 switch (ffeinfo_basictype (ffebld_info (left)))
3349 {
3350 case FFEINFO_basictypeINTEGER:
3351 if ((ffeinfo_kindtype (ffebld_info (left))
3352 == FFEINFO_kindtypeINTEGER4)
3353 || (ffeinfo_kindtype (ffebld_info (right))
3354 == FFEINFO_kindtypeINTEGER4))
3355 {
3356 code = FFECOM_gfrtPOW_QQ;
270fc4e8 3357 ltkt = FFEINFO_kindtypeINTEGER4;
5ff904cd
JL
3358 rtkt = FFEINFO_kindtypeINTEGER4;
3359 }
3360 else
6a047254
CB
3361 {
3362 code = FFECOM_gfrtPOW_II;
3363 ltkt = FFEINFO_kindtypeINTEGER1;
3364 }
5ff904cd
JL
3365 break;
3366
3367 case FFEINFO_basictypeREAL:
3368 if (ffeinfo_kindtype (ffebld_info (left))
3369 == FFEINFO_kindtypeREAL1)
6a047254
CB
3370 {
3371 code = FFECOM_gfrtPOW_RI;
3372 ltkt = FFEINFO_kindtypeREAL1;
3373 }
5ff904cd 3374 else
6a047254
CB
3375 {
3376 code = FFECOM_gfrtPOW_DI;
3377 ltkt = FFEINFO_kindtypeREAL2;
3378 }
5ff904cd
JL
3379 break;
3380
3381 case FFEINFO_basictypeCOMPLEX:
3382 if (ffeinfo_kindtype (ffebld_info (left))
3383 == FFEINFO_kindtypeREAL1)
6a047254
CB
3384 {
3385 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */
3386 ltkt = FFEINFO_kindtypeREAL1;
3387 }
5ff904cd 3388 else
6a047254
CB
3389 {
3390 code = FFECOM_gfrtPOW_ZI; /* Overlapping result okay. */
3391 ltkt = FFEINFO_kindtypeREAL2;
3392 }
5ff904cd
JL
3393 break;
3394
3395 default:
3396 assert ("bad pow_*i" == NULL);
3397 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */
6a047254 3398 ltkt = FFEINFO_kindtypeREAL1;
5ff904cd
JL
3399 break;
3400 }
270fc4e8 3401 if (ffeinfo_kindtype (ffebld_info (left)) != ltkt)
5ff904cd 3402 left = ffeexpr_convert (left, NULL, NULL,
6a047254 3403 ffeinfo_basictype (ffebld_info (left)),
270fc4e8 3404 ltkt, 0,
5ff904cd
JL
3405 FFETARGET_charactersizeNONE,
3406 FFEEXPR_contextLET);
3407 if (ffeinfo_kindtype (ffebld_info (right)) != rtkt)
3408 right = ffeexpr_convert (right, NULL, NULL,
3409 FFEINFO_basictypeINTEGER,
3410 rtkt, 0,
3411 FFETARGET_charactersizeNONE,
3412 FFEEXPR_contextLET);
3413 break;
3414
3415 case FFEINFO_basictypeREAL:
3416 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3417 left = ffeexpr_convert (left, NULL, NULL, FFEINFO_basictypeREAL,
3418 FFEINFO_kindtypeREALDOUBLE, 0,
3419 FFETARGET_charactersizeNONE,
3420 FFEEXPR_contextLET);
3421 if (ffeinfo_kindtype (ffebld_info (right))
3422 == FFEINFO_kindtypeREAL1)
3423 right = ffeexpr_convert (right, NULL, NULL,
3424 FFEINFO_basictypeREAL,
3425 FFEINFO_kindtypeREALDOUBLE, 0,
3426 FFETARGET_charactersizeNONE,
3427 FFEEXPR_contextLET);
95eb4fd9
TM
3428 /* We used to call FFECOM_gfrtPOW_DD here,
3429 which passes arguments by reference. */
3430 code = FFECOM_gfrtL_POW;
3431 /* Pass arguments by value. */
3432 ref = FALSE;
5ff904cd
JL
3433 break;
3434
3435 case FFEINFO_basictypeCOMPLEX:
3436 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3437 left = ffeexpr_convert (left, NULL, NULL,
3438 FFEINFO_basictypeCOMPLEX,
3439 FFEINFO_kindtypeREALDOUBLE, 0,
3440 FFETARGET_charactersizeNONE,
3441 FFEEXPR_contextLET);
3442 if (ffeinfo_kindtype (ffebld_info (right))
3443 == FFEINFO_kindtypeREAL1)
3444 right = ffeexpr_convert (right, NULL, NULL,
3445 FFEINFO_basictypeCOMPLEX,
3446 FFEINFO_kindtypeREALDOUBLE, 0,
3447 FFETARGET_charactersizeNONE,
3448 FFEEXPR_contextLET);
3449 code = FFECOM_gfrtPOW_ZZ; /* Overlapping result okay. */
95eb4fd9 3450 ref = TRUE; /* Pass arguments by reference. */
5ff904cd
JL
3451 break;
3452
3453 default:
3454 assert ("bad pow_x*" == NULL);
3455 code = FFECOM_gfrtPOW_II;
3456 break;
3457 }
3458 return ffecom_call_binop_ (ffecom_gfrt_tree_ (code),
3459 ffecom_gfrt_kindtype (code),
3460 (ffe_is_f2c_library ()
3461 && ffecom_gfrt_complex_[code]),
3462 tree_type, left, right,
3463 dest_tree, dest, dest_used,
95eb4fd9 3464 NULL_TREE, FALSE, ref,
c7e4ee3a 3465 ffebld_nonter_hook (expr));
5ff904cd
JL
3466 }
3467
3468 case FFEBLD_opNOT:
5ff904cd
JL
3469 switch (bt)
3470 {
3471 case FFEINFO_basictypeLOGICAL:
83ffecd2 3472 item = ffecom_truth_value_invert (ffecom_expr (ffebld_left (expr)));
5ff904cd
JL
3473 return convert (tree_type, item);
3474
3475 case FFEINFO_basictypeINTEGER:
3476 return ffecom_1 (BIT_NOT_EXPR, tree_type,
3477 ffecom_expr (ffebld_left (expr)));
3478
3479 default:
3480 assert ("NOT bad basictype" == NULL);
3481 /* Fall through. */
3482 case FFEINFO_basictypeANY:
3483 return error_mark_node;
3484 }
3485 break;
3486
3487 case FFEBLD_opFUNCREF:
3488 assert (ffeinfo_basictype (ffebld_info (expr))
3489 != FFEINFO_basictypeCHARACTER);
3490 /* Fall through. */
3491 case FFEBLD_opSUBRREF:
5ff904cd
JL
3492 if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
3493 == FFEINFO_whereINTRINSIC)
3494 { /* Invocation of an intrinsic. */
3495 item = ffecom_expr_intrinsic_ (expr, dest_tree, dest,
3496 dest_used);
3497 return item;
3498 }
3499 s = ffebld_symter (ffebld_left (expr));
3500 dt = ffesymbol_hook (s).decl_tree;
3501 if (dt == NULL_TREE)
3502 {
3503 s = ffecom_sym_transform_ (s);
3504 dt = ffesymbol_hook (s).decl_tree;
3505 }
3506 if (dt == error_mark_node)
3507 return dt;
3508
3509 if (ffesymbol_hook (s).addr)
3510 item = dt;
3511 else
3512 item = ffecom_1_fn (dt);
3513
5ff904cd
JL
3514 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
3515 args = ffecom_list_expr (ffebld_right (expr));
3516 else
3517 args = ffecom_list_ptr_to_expr (ffebld_right (expr));
5ff904cd 3518
702edf1d
CB
3519 if (args == error_mark_node)
3520 return error_mark_node;
3521
5ff904cd
JL
3522 item = ffecom_call_ (item, kt,
3523 ffesymbol_is_f2c (s)
3524 && (bt == FFEINFO_basictypeCOMPLEX)
3525 && (ffesymbol_where (s)
3526 != FFEINFO_whereCONSTANT),
3527 tree_type,
3528 args,
3529 dest_tree, dest, dest_used,
c7e4ee3a
CB
3530 error_mark_node, FALSE,
3531 ffebld_nonter_hook (expr));
5ff904cd
JL
3532 TREE_SIDE_EFFECTS (item) = 1;
3533 return item;
3534
3535 case FFEBLD_opAND:
5ff904cd
JL
3536 switch (bt)
3537 {
3538 case FFEINFO_basictypeLOGICAL:
3539 item
3540 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3541 ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3542 ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3543 return convert (tree_type, item);
3544
3545 case FFEINFO_basictypeINTEGER:
3546 return ffecom_2 (BIT_AND_EXPR, tree_type,
3547 ffecom_expr (ffebld_left (expr)),
3548 ffecom_expr (ffebld_right (expr)));
3549
3550 default:
3551 assert ("AND bad basictype" == NULL);
3552 /* Fall through. */
3553 case FFEINFO_basictypeANY:
3554 return error_mark_node;
3555 }
3556 break;
3557
3558 case FFEBLD_opOR:
5ff904cd
JL
3559 switch (bt)
3560 {
3561 case FFEINFO_basictypeLOGICAL:
3562 item
3563 = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
3564 ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3565 ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3566 return convert (tree_type, item);
3567
3568 case FFEINFO_basictypeINTEGER:
3569 return ffecom_2 (BIT_IOR_EXPR, tree_type,
3570 ffecom_expr (ffebld_left (expr)),
3571 ffecom_expr (ffebld_right (expr)));
3572
3573 default:
3574 assert ("OR bad basictype" == NULL);
3575 /* Fall through. */
3576 case FFEINFO_basictypeANY:
3577 return error_mark_node;
3578 }
3579 break;
3580
3581 case FFEBLD_opXOR:
3582 case FFEBLD_opNEQV:
5ff904cd
JL
3583 switch (bt)
3584 {
3585 case FFEINFO_basictypeLOGICAL:
3586 item
3587 = ffecom_2 (NE_EXPR, integer_type_node,
3588 ffecom_expr (ffebld_left (expr)),
3589 ffecom_expr (ffebld_right (expr)));
3590 return convert (tree_type, ffecom_truth_value (item));
3591
3592 case FFEINFO_basictypeINTEGER:
3593 return ffecom_2 (BIT_XOR_EXPR, tree_type,
3594 ffecom_expr (ffebld_left (expr)),
3595 ffecom_expr (ffebld_right (expr)));
3596
3597 default:
3598 assert ("XOR/NEQV bad basictype" == NULL);
3599 /* Fall through. */
3600 case FFEINFO_basictypeANY:
3601 return error_mark_node;
3602 }
3603 break;
3604
3605 case FFEBLD_opEQV:
5ff904cd
JL
3606 switch (bt)
3607 {
3608 case FFEINFO_basictypeLOGICAL:
3609 item
3610 = ffecom_2 (EQ_EXPR, integer_type_node,
3611 ffecom_expr (ffebld_left (expr)),
3612 ffecom_expr (ffebld_right (expr)));
3613 return convert (tree_type, ffecom_truth_value (item));
3614
3615 case FFEINFO_basictypeINTEGER:
3616 return
3617 ffecom_1 (BIT_NOT_EXPR, tree_type,
3618 ffecom_2 (BIT_XOR_EXPR, tree_type,
3619 ffecom_expr (ffebld_left (expr)),
3620 ffecom_expr (ffebld_right (expr))));
3621
3622 default:
3623 assert ("EQV bad basictype" == NULL);
3624 /* Fall through. */
3625 case FFEINFO_basictypeANY:
3626 return error_mark_node;
3627 }
3628 break;
3629
3630 case FFEBLD_opCONVERT:
3631 if (ffebld_op (ffebld_left (expr)) == FFEBLD_opANY)
3632 return error_mark_node;
3633
5ff904cd
JL
3634 switch (bt)
3635 {
3636 case FFEINFO_basictypeLOGICAL:
3637 case FFEINFO_basictypeINTEGER:
3638 case FFEINFO_basictypeREAL:
3639 return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3640
3641 case FFEINFO_basictypeCOMPLEX:
3642 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3643 {
3644 case FFEINFO_basictypeINTEGER:
3645 case FFEINFO_basictypeLOGICAL:
3646 case FFEINFO_basictypeREAL:
3647 item = ffecom_expr (ffebld_left (expr));
3648 if (item == error_mark_node)
3649 return error_mark_node;
3650 /* convert() takes care of converting to the subtype first,
3651 at least in gcc-2.7.2. */
3652 item = convert (tree_type, item);
3653 return item;
3654
3655 case FFEINFO_basictypeCOMPLEX:
3656 return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3657
3658 default:
3659 assert ("CONVERT COMPLEX bad basictype" == NULL);
3660 /* Fall through. */
3661 case FFEINFO_basictypeANY:
3662 return error_mark_node;
3663 }
3664 break;
3665
3666 default:
3667 assert ("CONVERT bad basictype" == NULL);
3668 /* Fall through. */
3669 case FFEINFO_basictypeANY:
3670 return error_mark_node;
3671 }
3672 break;
3673
3674 case FFEBLD_opLT:
3675 code = LT_EXPR;
3676 goto relational; /* :::::::::::::::::::: */
3677
3678 case FFEBLD_opLE:
3679 code = LE_EXPR;
3680 goto relational; /* :::::::::::::::::::: */
3681
3682 case FFEBLD_opEQ:
3683 code = EQ_EXPR;
3684 goto relational; /* :::::::::::::::::::: */
3685
3686 case FFEBLD_opNE:
3687 code = NE_EXPR;
3688 goto relational; /* :::::::::::::::::::: */
3689
3690 case FFEBLD_opGT:
3691 code = GT_EXPR;
3692 goto relational; /* :::::::::::::::::::: */
3693
3694 case FFEBLD_opGE:
3695 code = GE_EXPR;
3696
3697 relational: /* :::::::::::::::::::: */
5ff904cd
JL
3698 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3699 {
3700 case FFEINFO_basictypeLOGICAL:
3701 case FFEINFO_basictypeINTEGER:
3702 case FFEINFO_basictypeREAL:
3703 item = ffecom_2 (code, integer_type_node,
3704 ffecom_expr (ffebld_left (expr)),
3705 ffecom_expr (ffebld_right (expr)));
3706 return convert (tree_type, item);
3707
3708 case FFEINFO_basictypeCOMPLEX:
3709 assert (code == EQ_EXPR || code == NE_EXPR);
3710 {
3711 tree real_type;
3712 tree arg1 = ffecom_expr (ffebld_left (expr));
3713 tree arg2 = ffecom_expr (ffebld_right (expr));
3714
3715 if (arg1 == error_mark_node || arg2 == error_mark_node)
3716 return error_mark_node;
3717
3718 arg1 = ffecom_save_tree (arg1);
3719 arg2 = ffecom_save_tree (arg2);
3720
3721 if (TREE_CODE (TREE_TYPE (arg1)) == COMPLEX_TYPE)
3722 {
3723 real_type = TREE_TYPE (TREE_TYPE (arg1));
3724 assert (real_type == TREE_TYPE (TREE_TYPE (arg2)));
3725 }
3726 else
3727 {
3728 real_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg1)));
3729 assert (real_type == TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg2))));
3730 }
3731
3732 item
3733 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3734 ffecom_2 (EQ_EXPR, integer_type_node,
3735 ffecom_1 (REALPART_EXPR, real_type, arg1),
3736 ffecom_1 (REALPART_EXPR, real_type, arg2)),
3737 ffecom_2 (EQ_EXPR, integer_type_node,
3738 ffecom_1 (IMAGPART_EXPR, real_type, arg1),
3739 ffecom_1 (IMAGPART_EXPR, real_type,
3740 arg2)));
3741 if (code == EQ_EXPR)
3742 item = ffecom_truth_value (item);
3743 else
3744 item = ffecom_truth_value_invert (item);
3745 return convert (tree_type, item);
3746 }
3747
3748 case FFEINFO_basictypeCHARACTER:
5ff904cd
JL
3749 {
3750 ffebld left = ffebld_left (expr);
3751 ffebld right = ffebld_right (expr);
3752 tree left_tree;
3753 tree right_tree;
3754 tree left_length;
3755 tree right_length;
3756
3757 /* f2c run-time functions do the implicit blank-padding for us,
3758 so we don't usually have to implement blank-padding ourselves.
3759 (The exception is when we pass an argument to a separately
3760 compiled statement function -- if we know the arg is not the
3761 same length as the dummy, we must truncate or extend it. If
3762 we "inline" statement functions, that necessity goes away as
3763 well.)
3764
3765 Strip off the CONVERT operators that blank-pad. (Truncation by
3766 CONVERT shouldn't happen here, but it can happen in
3767 assignments.) */
3768
3769 while (ffebld_op (left) == FFEBLD_opCONVERT)
3770 left = ffebld_left (left);
3771 while (ffebld_op (right) == FFEBLD_opCONVERT)
3772 right = ffebld_left (right);
3773
3774 left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
3775 right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
3776
3777 if (left_tree == error_mark_node || left_length == error_mark_node
3778 || right_tree == error_mark_node
3779 || right_length == error_mark_node)
c7e4ee3a 3780 return error_mark_node;
5ff904cd
JL
3781
3782 if ((ffebld_size_known (left) == 1)
3783 && (ffebld_size_known (right) == 1))
3784 {
3785 left_tree
3786 = ffecom_1 (INDIRECT_REF,
3787 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3788 left_tree);
3789 right_tree
3790 = ffecom_1 (INDIRECT_REF,
3791 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3792 right_tree);
3793
3794 item
3795 = ffecom_2 (code, integer_type_node,
3796 ffecom_2 (ARRAY_REF,
3797 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3798 left_tree,
3799 integer_one_node),
3800 ffecom_2 (ARRAY_REF,
3801 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3802 right_tree,
3803 integer_one_node));
3804 }
3805 else
3806 {
3807 item = build_tree_list (NULL_TREE, left_tree);
3808 TREE_CHAIN (item) = build_tree_list (NULL_TREE, right_tree);
3809 TREE_CHAIN (TREE_CHAIN (item)) = build_tree_list (NULL_TREE,
3810 left_length);
3811 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
3812 = build_tree_list (NULL_TREE, right_length);
c7e4ee3a 3813 item = ffecom_call_gfrt (FFECOM_gfrtCMP, item, NULL_TREE);
5ff904cd
JL
3814 item = ffecom_2 (code, integer_type_node,
3815 item,
3816 convert (TREE_TYPE (item),
3817 integer_zero_node));
3818 }
3819 item = convert (tree_type, item);
3820 }
3821
5ff904cd
JL
3822 return item;
3823
3824 default:
3825 assert ("relational bad basictype" == NULL);
3826 /* Fall through. */
3827 case FFEINFO_basictypeANY:
3828 return error_mark_node;
3829 }
3830 break;
3831
3832 case FFEBLD_opPERCENT_LOC:
5ff904cd
JL
3833 item = ffecom_arg_ptr_to_expr (ffebld_left (expr), &list);
3834 return convert (tree_type, item);
3835
3836 case FFEBLD_opITEM:
3837 case FFEBLD_opSTAR:
3838 case FFEBLD_opBOUNDS:
3839 case FFEBLD_opREPEAT:
3840 case FFEBLD_opLABTER:
3841 case FFEBLD_opLABTOK:
3842 case FFEBLD_opIMPDO:
3843 case FFEBLD_opCONCATENATE:
3844 case FFEBLD_opSUBSTR:
3845 default:
3846 assert ("bad op" == NULL);
3847 /* Fall through. */
3848 case FFEBLD_opANY:
3849 return error_mark_node;
3850 }
3851
3852#if 1
3853 assert ("didn't think anything got here anymore!!" == NULL);
3854#else
3855 switch (ffebld_arity (expr))
3856 {
3857 case 2:
3858 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3859 TREE_OPERAND (item, 1) = ffecom_expr (ffebld_right (expr));
3860 if (TREE_OPERAND (item, 0) == error_mark_node
3861 || TREE_OPERAND (item, 1) == error_mark_node)
3862 return error_mark_node;
3863 break;
3864
3865 case 1:
3866 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3867 if (TREE_OPERAND (item, 0) == error_mark_node)
3868 return error_mark_node;
3869 break;
3870
3871 default:
3872 break;
3873 }
3874
3875 return fold (item);
3876#endif
3877}
3878
3879#endif
3880/* Returns the tree that does the intrinsic invocation.
3881
3882 Note: this function applies only to intrinsics returning
3883 CHARACTER*1 or non-CHARACTER results, and to intrinsic
3884 subroutines. */
3885
3886#if FFECOM_targetCURRENT == FFECOM_targetGCC
3887static tree
3888ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
3889 ffebld dest, bool *dest_used)
3890{
3891 tree expr_tree;
3892 tree saved_expr1; /* For those who need it. */
3893 tree saved_expr2; /* For those who need it. */
3894 ffeinfoBasictype bt;
3895 ffeinfoKindtype kt;
3896 tree tree_type;
3897 tree arg1_type;
3898 tree real_type; /* REAL type corresponding to COMPLEX. */
3899 tree tempvar;
3900 ffebld list = ffebld_right (expr); /* List of (some) args. */
3901 ffebld arg1; /* For handy reference. */
3902 ffebld arg2;
3903 ffebld arg3;
3904 ffeintrinImp codegen_imp;
3905 ffecomGfrt gfrt;
3906
3907 assert (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER);
3908
3909 if (dest_used != NULL)
3910 *dest_used = FALSE;
3911
3912 bt = ffeinfo_basictype (ffebld_info (expr));
3913 kt = ffeinfo_kindtype (ffebld_info (expr));
3914 tree_type = ffecom_tree_type[bt][kt];
3915
3916 if (list != NULL)
3917 {
3918 arg1 = ffebld_head (list);
3919 if (arg1 != NULL && ffebld_op (arg1) == FFEBLD_opANY)
3920 return error_mark_node;
3921 if ((list = ffebld_trail (list)) != NULL)
3922 {
3923 arg2 = ffebld_head (list);
3924 if (arg2 != NULL && ffebld_op (arg2) == FFEBLD_opANY)
3925 return error_mark_node;
3926 if ((list = ffebld_trail (list)) != NULL)
3927 {
3928 arg3 = ffebld_head (list);
3929 if (arg3 != NULL && ffebld_op (arg3) == FFEBLD_opANY)
3930 return error_mark_node;
3931 }
3932 else
3933 arg3 = NULL;
3934 }
3935 else
3936 arg2 = arg3 = NULL;
3937 }
3938 else
3939 arg1 = arg2 = arg3 = NULL;
3940
3941 /* <list> ends up at the opITEM of the 3rd arg, or NULL if there are < 3
3942 args. This is used by the MAX/MIN expansions. */
3943
3944 if (arg1 != NULL)
3945 arg1_type = ffecom_tree_type
3946 [ffeinfo_basictype (ffebld_info (arg1))]
3947 [ffeinfo_kindtype (ffebld_info (arg1))];
3948 else
3949 arg1_type = NULL_TREE; /* Really not needed, but might catch bugs
3950 here. */
3951
3952 /* There are several ways for each of the cases in the following switch
3953 statements to exit (from simplest to use to most complicated):
3954
3955 break; (when expr_tree == NULL)
3956
3957 A standard call is made to the specific intrinsic just as if it had been
3958 passed in as a dummy procedure and called as any old procedure. This
3959 method can produce slower code but in some cases it's the easiest way for
3960 now. However, if a (presumably faster) direct call is available,
3961 that is used, so this is the easiest way in many more cases now.
3962
3963 gfrt = FFECOM_gfrtWHATEVER;
3964 break;
3965
3966 gfrt contains the gfrt index of a library function to call, passing the
3967 argument(s) by value rather than by reference. Used when a more
3968 careful choice of library function is needed than that provided
3969 by the vanilla `break;'.
3970
3971 return expr_tree;
3972
3973 The expr_tree has been completely set up and is ready to be returned
3974 as is. No further actions are taken. Use this when the tree is not
3975 in the simple form for one of the arity_n labels. */
3976
3977 /* For info on how the switch statement cases were written, see the files
3978 enclosed in comments below the switch statement. */
3979
3980 codegen_imp = ffebld_symter_implementation (ffebld_left (expr));
3981 gfrt = ffeintrin_gfrt_direct (codegen_imp);
3982 if (gfrt == FFECOM_gfrt)
3983 gfrt = ffeintrin_gfrt_indirect (codegen_imp);
3984
3985 switch (codegen_imp)
3986 {
3987 case FFEINTRIN_impABS:
3988 case FFEINTRIN_impCABS:
3989 case FFEINTRIN_impCDABS:
3990 case FFEINTRIN_impDABS:
3991 case FFEINTRIN_impIABS:
3992 if (ffeinfo_basictype (ffebld_info (arg1))
3993 == FFEINFO_basictypeCOMPLEX)
3994 {
3995 if (kt == FFEINFO_kindtypeREAL1)
3996 gfrt = FFECOM_gfrtCABS;
3997 else if (kt == FFEINFO_kindtypeREAL2)
3998 gfrt = FFECOM_gfrtCDABS;
3999 break;
4000 }
4001 return ffecom_1 (ABS_EXPR, tree_type,
4002 convert (tree_type, ffecom_expr (arg1)));
4003
4004 case FFEINTRIN_impACOS:
4005 case FFEINTRIN_impDACOS:
4006 break;
4007
4008 case FFEINTRIN_impAIMAG:
4009 case FFEINTRIN_impDIMAG:
4010 case FFEINTRIN_impIMAGPART:
4011 if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
4012 arg1_type = TREE_TYPE (arg1_type);
4013 else
4014 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
4015
4016 return
4017 convert (tree_type,
4018 ffecom_1 (IMAGPART_EXPR, arg1_type,
4019 ffecom_expr (arg1)));
4020
4021 case FFEINTRIN_impAINT:
4022 case FFEINTRIN_impDINT:
c7e4ee3a
CB
4023#if 0
4024 /* ~~Someday implement FIX_TRUNC_EXPR yielding same type as arg. */
5ff904cd
JL
4025 return ffecom_1 (FIX_TRUNC_EXPR, tree_type, ffecom_expr (arg1));
4026#else /* in the meantime, must use floor to avoid range problems with ints */
4027 /* r__1 = r1 >= 0 ? floor(r1) : -floor(-r1); */
4028 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4029 return
4030 convert (tree_type,
4031 ffecom_3 (COND_EXPR, double_type_node,
4032 ffecom_truth_value
4033 (ffecom_2 (GE_EXPR, integer_type_node,
4034 saved_expr1,
4035 convert (arg1_type,
4036 ffecom_float_zero_))),
4037 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4038 build_tree_list (NULL_TREE,
4039 convert (double_type_node,
c7e4ee3a
CB
4040 saved_expr1)),
4041 NULL_TREE),
5ff904cd
JL
4042 ffecom_1 (NEGATE_EXPR, double_type_node,
4043 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4044 build_tree_list (NULL_TREE,
4045 convert (double_type_node,
4046 ffecom_1 (NEGATE_EXPR,
4047 arg1_type,
c7e4ee3a
CB
4048 saved_expr1))),
4049 NULL_TREE)
5ff904cd
JL
4050 ))
4051 );
4052#endif
4053
4054 case FFEINTRIN_impANINT:
4055 case FFEINTRIN_impDNINT:
4056#if 0 /* This way of doing it won't handle real
4057 numbers of large magnitudes. */
4058 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4059 expr_tree = convert (tree_type,
4060 convert (integer_type_node,
4061 ffecom_3 (COND_EXPR, tree_type,
4062 ffecom_truth_value
4063 (ffecom_2 (GE_EXPR,
4064 integer_type_node,
4065 saved_expr1,
4066 ffecom_float_zero_)),
4067 ffecom_2 (PLUS_EXPR,
4068 tree_type,
4069 saved_expr1,
4070 ffecom_float_half_),
4071 ffecom_2 (MINUS_EXPR,
4072 tree_type,
4073 saved_expr1,
4074 ffecom_float_half_))));
4075 return expr_tree;
4076#else /* So we instead call floor. */
4077 /* r__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1) */
4078 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4079 return
4080 convert (tree_type,
4081 ffecom_3 (COND_EXPR, double_type_node,
4082 ffecom_truth_value
4083 (ffecom_2 (GE_EXPR, integer_type_node,
4084 saved_expr1,
4085 convert (arg1_type,
4086 ffecom_float_zero_))),
4087 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4088 build_tree_list (NULL_TREE,
4089 convert (double_type_node,
4090 ffecom_2 (PLUS_EXPR,
4091 arg1_type,
4092 saved_expr1,
4093 convert (arg1_type,
c7e4ee3a
CB
4094 ffecom_float_half_)))),
4095 NULL_TREE),
5ff904cd
JL
4096 ffecom_1 (NEGATE_EXPR, double_type_node,
4097 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4098 build_tree_list (NULL_TREE,
4099 convert (double_type_node,
4100 ffecom_2 (MINUS_EXPR,
4101 arg1_type,
4102 convert (arg1_type,
4103 ffecom_float_half_),
c7e4ee3a
CB
4104 saved_expr1))),
4105 NULL_TREE))
5ff904cd
JL
4106 )
4107 );
4108#endif
4109
4110 case FFEINTRIN_impASIN:
4111 case FFEINTRIN_impDASIN:
4112 case FFEINTRIN_impATAN:
4113 case FFEINTRIN_impDATAN:
4114 case FFEINTRIN_impATAN2:
4115 case FFEINTRIN_impDATAN2:
4116 break;
4117
4118 case FFEINTRIN_impCHAR:
4119 case FFEINTRIN_impACHAR:
c7e4ee3a
CB
4120#ifdef HOHO
4121 tempvar = ffecom_make_tempvar (char_type_node, 1, -1);
4122#else
4123 tempvar = ffebld_nonter_hook (expr);
4124 assert (tempvar);
4125#endif
5ff904cd
JL
4126 {
4127 tree tmv = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (tempvar)));
4128
4129 expr_tree = ffecom_modify (tmv,
4130 ffecom_2 (ARRAY_REF, tmv, tempvar,
4131 integer_one_node),
4132 convert (tmv, ffecom_expr (arg1)));
4133 }
4134 expr_tree = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar),
4135 expr_tree,
4136 tempvar);
4137 expr_tree = ffecom_1 (ADDR_EXPR,
4138 build_pointer_type (TREE_TYPE (expr_tree)),
4139 expr_tree);
4140 return expr_tree;
4141
4142 case FFEINTRIN_impCMPLX:
4143 case FFEINTRIN_impDCMPLX:
4144 if (arg2 == NULL)
4145 return
4146 convert (tree_type, ffecom_expr (arg1));
4147
4148 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
4149 return
4150 ffecom_2 (COMPLEX_EXPR, tree_type,
4151 convert (real_type, ffecom_expr (arg1)),
4152 convert (real_type,
4153 ffecom_expr (arg2)));
4154
4155 case FFEINTRIN_impCOMPLEX:
4156 return
4157 ffecom_2 (COMPLEX_EXPR, tree_type,
4158 ffecom_expr (arg1),
4159 ffecom_expr (arg2));
4160
4161 case FFEINTRIN_impCONJG:
4162 case FFEINTRIN_impDCONJG:
4163 {
4164 tree arg1_tree;
4165
4166 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
4167 arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4168 return
4169 ffecom_2 (COMPLEX_EXPR, tree_type,
4170 ffecom_1 (REALPART_EXPR, real_type, arg1_tree),
4171 ffecom_1 (NEGATE_EXPR, real_type,
4172 ffecom_1 (IMAGPART_EXPR, real_type, arg1_tree)));
4173 }
4174
4175 case FFEINTRIN_impCOS:
4176 case FFEINTRIN_impCCOS:
4177 case FFEINTRIN_impCDCOS:
4178 case FFEINTRIN_impDCOS:
4179 if (bt == FFEINFO_basictypeCOMPLEX)
4180 {
4181 if (kt == FFEINFO_kindtypeREAL1)
4182 gfrt = FFECOM_gfrtCCOS; /* Overlapping result okay. */
4183 else if (kt == FFEINFO_kindtypeREAL2)
4184 gfrt = FFECOM_gfrtCDCOS; /* Overlapping result okay. */
4185 }
4186 break;
4187
4188 case FFEINTRIN_impCOSH:
4189 case FFEINTRIN_impDCOSH:
4190 break;
4191
4192 case FFEINTRIN_impDBLE:
4193 case FFEINTRIN_impDFLOAT:
4194 case FFEINTRIN_impDREAL:
4195 case FFEINTRIN_impFLOAT:
4196 case FFEINTRIN_impIDINT:
4197 case FFEINTRIN_impIFIX:
4198 case FFEINTRIN_impINT2:
4199 case FFEINTRIN_impINT8:
4200 case FFEINTRIN_impINT:
4201 case FFEINTRIN_impLONG:
4202 case FFEINTRIN_impREAL:
4203 case FFEINTRIN_impSHORT:
4204 case FFEINTRIN_impSNGL:
4205 return convert (tree_type, ffecom_expr (arg1));
4206
4207 case FFEINTRIN_impDIM:
4208 case FFEINTRIN_impDDIM:
4209 case FFEINTRIN_impIDIM:
4210 saved_expr1 = ffecom_save_tree (convert (tree_type,
4211 ffecom_expr (arg1)));
4212 saved_expr2 = ffecom_save_tree (convert (tree_type,
4213 ffecom_expr (arg2)));
4214 return
4215 ffecom_3 (COND_EXPR, tree_type,
4216 ffecom_truth_value
4217 (ffecom_2 (GT_EXPR, integer_type_node,
4218 saved_expr1,
4219 saved_expr2)),
4220 ffecom_2 (MINUS_EXPR, tree_type,
4221 saved_expr1,
4222 saved_expr2),
4223 convert (tree_type, ffecom_float_zero_));
4224
4225 case FFEINTRIN_impDPROD:
4226 return
4227 ffecom_2 (MULT_EXPR, tree_type,
4228 convert (tree_type, ffecom_expr (arg1)),
4229 convert (tree_type, ffecom_expr (arg2)));
4230
4231 case FFEINTRIN_impEXP:
4232 case FFEINTRIN_impCDEXP:
4233 case FFEINTRIN_impCEXP:
4234 case FFEINTRIN_impDEXP:
4235 if (bt == FFEINFO_basictypeCOMPLEX)
4236 {
4237 if (kt == FFEINFO_kindtypeREAL1)
4238 gfrt = FFECOM_gfrtCEXP; /* Overlapping result okay. */
4239 else if (kt == FFEINFO_kindtypeREAL2)
4240 gfrt = FFECOM_gfrtCDEXP; /* Overlapping result okay. */
4241 }
4242 break;
4243
4244 case FFEINTRIN_impICHAR:
4245 case FFEINTRIN_impIACHAR:
4246#if 0 /* The simple approach. */
4247 ffecom_char_args_ (&expr_tree, &saved_expr1 /* Ignored */ , arg1);
4248 expr_tree
4249 = ffecom_1 (INDIRECT_REF,
4250 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
4251 expr_tree);
4252 expr_tree
4253 = ffecom_2 (ARRAY_REF,
4254 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
4255 expr_tree,
4256 integer_one_node);
4257 return convert (tree_type, expr_tree);
4258#else /* The more interesting (and more optimal) approach. */
4259 expr_tree = ffecom_intrinsic_ichar_ (tree_type, arg1, &saved_expr1);
4260 expr_tree = ffecom_3 (COND_EXPR, tree_type,
4261 saved_expr1,
4262 expr_tree,
4263 convert (tree_type, integer_zero_node));
4264 return expr_tree;
4265#endif
4266
4267 case FFEINTRIN_impINDEX:
4268 break;
4269
4270 case FFEINTRIN_impLEN:
4271#if 0
4272 break; /* The simple approach. */
4273#else
4274 return ffecom_intrinsic_len_ (arg1); /* The more optimal approach. */
4275#endif
4276
4277 case FFEINTRIN_impLGE:
4278 case FFEINTRIN_impLGT:
4279 case FFEINTRIN_impLLE:
4280 case FFEINTRIN_impLLT:
4281 break;
4282
4283 case FFEINTRIN_impLOG:
4284 case FFEINTRIN_impALOG:
4285 case FFEINTRIN_impCDLOG:
4286 case FFEINTRIN_impCLOG:
4287 case FFEINTRIN_impDLOG:
4288 if (bt == FFEINFO_basictypeCOMPLEX)
4289 {
4290 if (kt == FFEINFO_kindtypeREAL1)
4291 gfrt = FFECOM_gfrtCLOG; /* Overlapping result okay. */
4292 else if (kt == FFEINFO_kindtypeREAL2)
4293 gfrt = FFECOM_gfrtCDLOG; /* Overlapping result okay. */
4294 }
4295 break;
4296
4297 case FFEINTRIN_impLOG10:
4298 case FFEINTRIN_impALOG10:
4299 case FFEINTRIN_impDLOG10:
4300 if (gfrt != FFECOM_gfrt)
4301 break; /* Already picked one, stick with it. */
4302
4303 if (kt == FFEINFO_kindtypeREAL1)
95eb4fd9
TM
4304 /* We used to call FFECOM_gfrtALOG10 here. */
4305 gfrt = FFECOM_gfrtL_LOG10;
5ff904cd 4306 else if (kt == FFEINFO_kindtypeREAL2)
95eb4fd9
TM
4307 /* We used to call FFECOM_gfrtDLOG10 here. */
4308 gfrt = FFECOM_gfrtL_LOG10;
5ff904cd
JL
4309 break;
4310
4311 case FFEINTRIN_impMAX:
4312 case FFEINTRIN_impAMAX0:
4313 case FFEINTRIN_impAMAX1:
4314 case FFEINTRIN_impDMAX1:
4315 case FFEINTRIN_impMAX0:
4316 case FFEINTRIN_impMAX1:
4317 if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4318 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4319 else
4320 arg1_type = tree_type;
4321 expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4322 convert (arg1_type, ffecom_expr (arg1)),
4323 convert (arg1_type, ffecom_expr (arg2)));
4324 for (; list != NULL; list = ffebld_trail (list))
4325 {
4326 if ((ffebld_head (list) == NULL)
4327 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4328 continue;
4329 expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4330 expr_tree,
4331 convert (arg1_type,
4332 ffecom_expr (ffebld_head (list))));
4333 }
4334 return convert (tree_type, expr_tree);
4335
4336 case FFEINTRIN_impMIN:
4337 case FFEINTRIN_impAMIN0:
4338 case FFEINTRIN_impAMIN1:
4339 case FFEINTRIN_impDMIN1:
4340 case FFEINTRIN_impMIN0:
4341 case FFEINTRIN_impMIN1:
4342 if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4343 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4344 else
4345 arg1_type = tree_type;
4346 expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4347 convert (arg1_type, ffecom_expr (arg1)),
4348 convert (arg1_type, ffecom_expr (arg2)));
4349 for (; list != NULL; list = ffebld_trail (list))
4350 {
4351 if ((ffebld_head (list) == NULL)
4352 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4353 continue;
4354 expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4355 expr_tree,
4356 convert (arg1_type,
4357 ffecom_expr (ffebld_head (list))));
4358 }
4359 return convert (tree_type, expr_tree);
4360
4361 case FFEINTRIN_impMOD:
4362 case FFEINTRIN_impAMOD:
4363 case FFEINTRIN_impDMOD:
4364 if (bt != FFEINFO_basictypeREAL)
4365 return ffecom_2 (TRUNC_MOD_EXPR, tree_type,
4366 convert (tree_type, ffecom_expr (arg1)),
4367 convert (tree_type, ffecom_expr (arg2)));
4368
4369 if (kt == FFEINFO_kindtypeREAL1)
95eb4fd9
TM
4370 /* We used to call FFECOM_gfrtAMOD here. */
4371 gfrt = FFECOM_gfrtL_FMOD;
5ff904cd 4372 else if (kt == FFEINFO_kindtypeREAL2)
95eb4fd9
TM
4373 /* We used to call FFECOM_gfrtDMOD here. */
4374 gfrt = FFECOM_gfrtL_FMOD;
5ff904cd
JL
4375 break;
4376
4377 case FFEINTRIN_impNINT:
4378 case FFEINTRIN_impIDNINT:
c7e4ee3a
CB
4379#if 0
4380 /* ~~Ideally FIX_ROUND_EXPR would be implemented, but it ain't yet. */
5ff904cd
JL
4381 return ffecom_1 (FIX_ROUND_EXPR, tree_type, ffecom_expr (arg1));
4382#else
4383 /* i__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1); */
4384 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4385 return
4386 convert (ffecom_integer_type_node,
4387 ffecom_3 (COND_EXPR, arg1_type,
4388 ffecom_truth_value
4389 (ffecom_2 (GE_EXPR, integer_type_node,
4390 saved_expr1,
4391 convert (arg1_type,
4392 ffecom_float_zero_))),
4393 ffecom_2 (PLUS_EXPR, arg1_type,
4394 saved_expr1,
4395 convert (arg1_type,
4396 ffecom_float_half_)),
4397 ffecom_2 (MINUS_EXPR, arg1_type,
4398 saved_expr1,
4399 convert (arg1_type,
4400 ffecom_float_half_))));
4401#endif
4402
4403 case FFEINTRIN_impSIGN:
4404 case FFEINTRIN_impDSIGN:
4405 case FFEINTRIN_impISIGN:
4406 {
4407 tree arg2_tree = ffecom_expr (arg2);
4408
4409 saved_expr1
4410 = ffecom_save_tree
4411 (ffecom_1 (ABS_EXPR, tree_type,
4412 convert (tree_type,
4413 ffecom_expr (arg1))));
4414 expr_tree
4415 = ffecom_3 (COND_EXPR, tree_type,
4416 ffecom_truth_value
4417 (ffecom_2 (GE_EXPR, integer_type_node,
4418 arg2_tree,
4419 convert (TREE_TYPE (arg2_tree),
4420 integer_zero_node))),
4421 saved_expr1,
4422 ffecom_1 (NEGATE_EXPR, tree_type, saved_expr1));
4423 /* Make sure SAVE_EXPRs get referenced early enough. */
4424 expr_tree
4425 = ffecom_2 (COMPOUND_EXPR, tree_type,
4426 convert (void_type_node, saved_expr1),
4427 expr_tree);
4428 }
4429 return expr_tree;
4430
4431 case FFEINTRIN_impSIN:
4432 case FFEINTRIN_impCDSIN:
4433 case FFEINTRIN_impCSIN:
4434 case FFEINTRIN_impDSIN:
4435 if (bt == FFEINFO_basictypeCOMPLEX)
4436 {
4437 if (kt == FFEINFO_kindtypeREAL1)
4438 gfrt = FFECOM_gfrtCSIN; /* Overlapping result okay. */
4439 else if (kt == FFEINFO_kindtypeREAL2)
4440 gfrt = FFECOM_gfrtCDSIN; /* Overlapping result okay. */
4441 }
4442 break;
4443
4444 case FFEINTRIN_impSINH:
4445 case FFEINTRIN_impDSINH:
4446 break;
4447
4448 case FFEINTRIN_impSQRT:
4449 case FFEINTRIN_impCDSQRT:
4450 case FFEINTRIN_impCSQRT:
4451 case FFEINTRIN_impDSQRT:
4452 if (bt == FFEINFO_basictypeCOMPLEX)
4453 {
4454 if (kt == FFEINFO_kindtypeREAL1)
4455 gfrt = FFECOM_gfrtCSQRT; /* Overlapping result okay. */
4456 else if (kt == FFEINFO_kindtypeREAL2)
4457 gfrt = FFECOM_gfrtCDSQRT; /* Overlapping result okay. */
4458 }
4459 break;
4460
4461 case FFEINTRIN_impTAN:
4462 case FFEINTRIN_impDTAN:
4463 case FFEINTRIN_impTANH:
4464 case FFEINTRIN_impDTANH:
4465 break;
4466
4467 case FFEINTRIN_impREALPART:
4468 if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
4469 arg1_type = TREE_TYPE (arg1_type);
4470 else
4471 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
4472
4473 return
4474 convert (tree_type,
4475 ffecom_1 (REALPART_EXPR, arg1_type,
4476 ffecom_expr (arg1)));
4477
4478 case FFEINTRIN_impIAND:
4479 case FFEINTRIN_impAND:
4480 return ffecom_2 (BIT_AND_EXPR, tree_type,
4481 convert (tree_type,
4482 ffecom_expr (arg1)),
4483 convert (tree_type,
4484 ffecom_expr (arg2)));
4485
4486 case FFEINTRIN_impIOR:
4487 case FFEINTRIN_impOR:
4488 return ffecom_2 (BIT_IOR_EXPR, tree_type,
4489 convert (tree_type,
4490 ffecom_expr (arg1)),
4491 convert (tree_type,
4492 ffecom_expr (arg2)));
4493
4494 case FFEINTRIN_impIEOR:
4495 case FFEINTRIN_impXOR:
4496 return ffecom_2 (BIT_XOR_EXPR, tree_type,
4497 convert (tree_type,
4498 ffecom_expr (arg1)),
4499 convert (tree_type,
4500 ffecom_expr (arg2)));
4501
4502 case FFEINTRIN_impLSHIFT:
4503 return ffecom_2 (LSHIFT_EXPR, tree_type,
4504 ffecom_expr (arg1),
4505 convert (integer_type_node,
4506 ffecom_expr (arg2)));
4507
4508 case FFEINTRIN_impRSHIFT:
4509 return ffecom_2 (RSHIFT_EXPR, tree_type,
4510 ffecom_expr (arg1),
4511 convert (integer_type_node,
4512 ffecom_expr (arg2)));
4513
4514 case FFEINTRIN_impNOT:
4515 return ffecom_1 (BIT_NOT_EXPR, tree_type, ffecom_expr (arg1));
4516
4517 case FFEINTRIN_impBIT_SIZE:
4518 return convert (tree_type, TYPE_SIZE (arg1_type));
4519
4520 case FFEINTRIN_impBTEST:
4521 {
4522 ffetargetLogical1 true;
4523 ffetargetLogical1 false;
4524 tree true_tree;
4525 tree false_tree;
4526
4527 ffetarget_logical1 (&true, TRUE);
4528 ffetarget_logical1 (&false, FALSE);
4529 if (true == 1)
4530 true_tree = convert (tree_type, integer_one_node);
4531 else
4532 true_tree = convert (tree_type, build_int_2 (true, 0));
4533 if (false == 0)
4534 false_tree = convert (tree_type, integer_zero_node);
4535 else
4536 false_tree = convert (tree_type, build_int_2 (false, 0));
4537
4538 return
4539 ffecom_3 (COND_EXPR, tree_type,
4540 ffecom_truth_value
4541 (ffecom_2 (EQ_EXPR, integer_type_node,
4542 ffecom_2 (BIT_AND_EXPR, arg1_type,
4543 ffecom_expr (arg1),
4544 ffecom_2 (LSHIFT_EXPR, arg1_type,
4545 convert (arg1_type,
4546 integer_one_node),
4547 convert (integer_type_node,
4548 ffecom_expr (arg2)))),
4549 convert (arg1_type,
4550 integer_zero_node))),
4551 false_tree,
4552 true_tree);
4553 }
4554
4555 case FFEINTRIN_impIBCLR:
4556 return
4557 ffecom_2 (BIT_AND_EXPR, tree_type,
4558 ffecom_expr (arg1),
4559 ffecom_1 (BIT_NOT_EXPR, tree_type,
4560 ffecom_2 (LSHIFT_EXPR, tree_type,
4561 convert (tree_type,
4562 integer_one_node),
4563 convert (integer_type_node,
4564 ffecom_expr (arg2)))));
4565
4566 case FFEINTRIN_impIBITS:
4567 {
4568 tree arg3_tree = ffecom_save_tree (convert (integer_type_node,
4569 ffecom_expr (arg3)));
4570 tree uns_type
4571 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4572
4573 expr_tree
4574 = ffecom_2 (BIT_AND_EXPR, tree_type,
4575 ffecom_2 (RSHIFT_EXPR, tree_type,
4576 ffecom_expr (arg1),
4577 convert (integer_type_node,
4578 ffecom_expr (arg2))),
4579 convert (tree_type,
4580 ffecom_2 (RSHIFT_EXPR, uns_type,
4581 ffecom_1 (BIT_NOT_EXPR,
4582 uns_type,
4583 convert (uns_type,
4584 integer_zero_node)),
4585 ffecom_2 (MINUS_EXPR,
4586 integer_type_node,
4587 TYPE_SIZE (uns_type),
4588 arg3_tree))));
4589#if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4590 expr_tree
4591 = ffecom_3 (COND_EXPR, tree_type,
4592 ffecom_truth_value
4593 (ffecom_2 (NE_EXPR, integer_type_node,
4594 arg3_tree,
4595 integer_zero_node)),
4596 expr_tree,
4597 convert (tree_type, integer_zero_node));
4598#endif
4599 }
4600 return expr_tree;
4601
4602 case FFEINTRIN_impIBSET:
4603 return
4604 ffecom_2 (BIT_IOR_EXPR, tree_type,
4605 ffecom_expr (arg1),
4606 ffecom_2 (LSHIFT_EXPR, tree_type,
4607 convert (tree_type, integer_one_node),
4608 convert (integer_type_node,
4609 ffecom_expr (arg2))));
4610
4611 case FFEINTRIN_impISHFT:
4612 {
4613 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4614 tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4615 ffecom_expr (arg2)));
4616 tree uns_type
4617 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4618
4619 expr_tree
4620 = ffecom_3 (COND_EXPR, tree_type,
4621 ffecom_truth_value
4622 (ffecom_2 (GE_EXPR, integer_type_node,
4623 arg2_tree,
4624 integer_zero_node)),
4625 ffecom_2 (LSHIFT_EXPR, tree_type,
4626 arg1_tree,
4627 arg2_tree),
4628 convert (tree_type,
4629 ffecom_2 (RSHIFT_EXPR, uns_type,
4630 convert (uns_type, arg1_tree),
4631 ffecom_1 (NEGATE_EXPR,
4632 integer_type_node,
4633 arg2_tree))));
4634#if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4635 expr_tree
4636 = ffecom_3 (COND_EXPR, tree_type,
4637 ffecom_truth_value
4638 (ffecom_2 (NE_EXPR, integer_type_node,
4639 arg2_tree,
4640 TYPE_SIZE (uns_type))),
4641 expr_tree,
4642 convert (tree_type, integer_zero_node));
4643#endif
4644 /* Make sure SAVE_EXPRs get referenced early enough. */
4645 expr_tree
4646 = ffecom_2 (COMPOUND_EXPR, tree_type,
4647 convert (void_type_node, arg1_tree),
4648 ffecom_2 (COMPOUND_EXPR, tree_type,
4649 convert (void_type_node, arg2_tree),
4650 expr_tree));
4651 }
4652 return expr_tree;
4653
4654 case FFEINTRIN_impISHFTC:
4655 {
4656 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4657 tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4658 ffecom_expr (arg2)));
4659 tree arg3_tree = (arg3 == NULL) ? TYPE_SIZE (tree_type)
4660 : ffecom_save_tree (convert (integer_type_node, ffecom_expr (arg3)));
4661 tree shift_neg;
4662 tree shift_pos;
4663 tree mask_arg1;
4664 tree masked_arg1;
4665 tree uns_type
4666 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4667
4668 mask_arg1
4669 = ffecom_2 (LSHIFT_EXPR, tree_type,
4670 ffecom_1 (BIT_NOT_EXPR, tree_type,
4671 convert (tree_type, integer_zero_node)),
4672 arg3_tree);
4673#if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4674 mask_arg1
4675 = ffecom_3 (COND_EXPR, tree_type,
4676 ffecom_truth_value
4677 (ffecom_2 (NE_EXPR, integer_type_node,
4678 arg3_tree,
4679 TYPE_SIZE (uns_type))),
4680 mask_arg1,
4681 convert (tree_type, integer_zero_node));
4682#endif
4683 mask_arg1 = ffecom_save_tree (mask_arg1);
4684 masked_arg1
4685 = ffecom_2 (BIT_AND_EXPR, tree_type,
4686 arg1_tree,
4687 ffecom_1 (BIT_NOT_EXPR, tree_type,
4688 mask_arg1));
4689 masked_arg1 = ffecom_save_tree (masked_arg1);
4690 shift_neg
4691 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4692 convert (tree_type,
4693 ffecom_2 (RSHIFT_EXPR, uns_type,
4694 convert (uns_type, masked_arg1),
4695 ffecom_1 (NEGATE_EXPR,
4696 integer_type_node,
4697 arg2_tree))),
4698 ffecom_2 (LSHIFT_EXPR, tree_type,
4699 arg1_tree,
4700 ffecom_2 (PLUS_EXPR, integer_type_node,
4701 arg2_tree,
4702 arg3_tree)));
4703 shift_pos
4704 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4705 ffecom_2 (LSHIFT_EXPR, tree_type,
4706 arg1_tree,
4707 arg2_tree),
4708 convert (tree_type,
4709 ffecom_2 (RSHIFT_EXPR, uns_type,
4710 convert (uns_type, masked_arg1),
4711 ffecom_2 (MINUS_EXPR,
4712 integer_type_node,
4713 arg3_tree,
4714 arg2_tree))));
4715 expr_tree
4716 = ffecom_3 (COND_EXPR, tree_type,
4717 ffecom_truth_value
4718 (ffecom_2 (LT_EXPR, integer_type_node,
4719 arg2_tree,
4720 integer_zero_node)),
4721 shift_neg,
4722 shift_pos);
4723 expr_tree
4724 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4725 ffecom_2 (BIT_AND_EXPR, tree_type,
4726 mask_arg1,
4727 arg1_tree),
4728 ffecom_2 (BIT_AND_EXPR, tree_type,
4729 ffecom_1 (BIT_NOT_EXPR, tree_type,
4730 mask_arg1),
4731 expr_tree));
4732 expr_tree
4733 = ffecom_3 (COND_EXPR, tree_type,
4734 ffecom_truth_value
4735 (ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
4736 ffecom_2 (EQ_EXPR, integer_type_node,
4737 ffecom_1 (ABS_EXPR,
4738 integer_type_node,
4739 arg2_tree),
4740 arg3_tree),
4741 ffecom_2 (EQ_EXPR, integer_type_node,
4742 arg2_tree,
4743 integer_zero_node))),
4744 arg1_tree,
4745 expr_tree);
4746 /* Make sure SAVE_EXPRs get referenced early enough. */
4747 expr_tree
4748 = ffecom_2 (COMPOUND_EXPR, tree_type,
4749 convert (void_type_node, arg1_tree),
4750 ffecom_2 (COMPOUND_EXPR, tree_type,
4751 convert (void_type_node, arg2_tree),
4752 ffecom_2 (COMPOUND_EXPR, tree_type,
4753 convert (void_type_node,
4754 mask_arg1),
4755 ffecom_2 (COMPOUND_EXPR, tree_type,
4756 convert (void_type_node,
4757 masked_arg1),
4758 expr_tree))));
4759 expr_tree
4760 = ffecom_2 (COMPOUND_EXPR, tree_type,
4761 convert (void_type_node,
4762 arg3_tree),
4763 expr_tree);
4764 }
4765 return expr_tree;
4766
4767 case FFEINTRIN_impLOC:
4768 {
4769 tree arg1_tree = ffecom_expr (arg1);
4770
4771 expr_tree
4772 = convert (tree_type,
4773 ffecom_1 (ADDR_EXPR,
4774 build_pointer_type (TREE_TYPE (arg1_tree)),
4775 arg1_tree));
4776 }
4777 return expr_tree;
4778
4779 case FFEINTRIN_impMVBITS:
4780 {
4781 tree arg1_tree;
4782 tree arg2_tree;
4783 tree arg3_tree;
4784 ffebld arg4 = ffebld_head (ffebld_trail (list));
4785 tree arg4_tree;
4786 tree arg4_type;
4787 ffebld arg5 = ffebld_head (ffebld_trail (ffebld_trail (list)));
4788 tree arg5_tree;
4789 tree prep_arg1;
4790 tree prep_arg4;
4791 tree arg5_plus_arg3;
4792
5ff904cd
JL
4793 arg2_tree = convert (integer_type_node,
4794 ffecom_expr (arg2));
4795 arg3_tree = ffecom_save_tree (convert (integer_type_node,
4796 ffecom_expr (arg3)));
c7e4ee3a 4797 arg4_tree = ffecom_expr_rw (NULL_TREE, arg4);
5ff904cd
JL
4798 arg4_type = TREE_TYPE (arg4_tree);
4799
4800 arg1_tree = ffecom_save_tree (convert (arg4_type,
4801 ffecom_expr (arg1)));
4802
4803 arg5_tree = ffecom_save_tree (convert (integer_type_node,
4804 ffecom_expr (arg5)));
4805
5ff904cd
JL
4806 prep_arg1
4807 = ffecom_2 (LSHIFT_EXPR, arg4_type,
4808 ffecom_2 (BIT_AND_EXPR, arg4_type,
4809 ffecom_2 (RSHIFT_EXPR, arg4_type,
4810 arg1_tree,
4811 arg2_tree),
4812 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4813 ffecom_2 (LSHIFT_EXPR, arg4_type,
4814 ffecom_1 (BIT_NOT_EXPR,
4815 arg4_type,
4816 convert
4817 (arg4_type,
4818 integer_zero_node)),
4819 arg3_tree))),
4820 arg5_tree);
4821 arg5_plus_arg3
4822 = ffecom_save_tree (ffecom_2 (PLUS_EXPR, arg4_type,
4823 arg5_tree,
4824 arg3_tree));
4825 prep_arg4
4826 = ffecom_2 (LSHIFT_EXPR, arg4_type,
4827 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4828 convert (arg4_type,
4829 integer_zero_node)),
4830 arg5_plus_arg3);
4831#if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4832 prep_arg4
4833 = ffecom_3 (COND_EXPR, arg4_type,
4834 ffecom_truth_value
4835 (ffecom_2 (NE_EXPR, integer_type_node,
4836 arg5_plus_arg3,
4837 convert (TREE_TYPE (arg5_plus_arg3),
4838 TYPE_SIZE (arg4_type)))),
4839 prep_arg4,
4840 convert (arg4_type, integer_zero_node));
4841#endif
4842 prep_arg4
4843 = ffecom_2 (BIT_AND_EXPR, arg4_type,
4844 arg4_tree,
4845 ffecom_2 (BIT_IOR_EXPR, arg4_type,
4846 prep_arg4,
4847 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4848 ffecom_2 (LSHIFT_EXPR, arg4_type,
4849 ffecom_1 (BIT_NOT_EXPR,
4850 arg4_type,
4851 convert
4852 (arg4_type,
4853 integer_zero_node)),
4854 arg5_tree))));
4855 prep_arg1
4856 = ffecom_2 (BIT_IOR_EXPR, arg4_type,
4857 prep_arg1,
4858 prep_arg4);
4859#if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4860 prep_arg1
4861 = ffecom_3 (COND_EXPR, arg4_type,
4862 ffecom_truth_value
4863 (ffecom_2 (NE_EXPR, integer_type_node,
4864 arg3_tree,
4865 convert (TREE_TYPE (arg3_tree),
4866 integer_zero_node))),
4867 prep_arg1,
4868 arg4_tree);
4869 prep_arg1
4870 = ffecom_3 (COND_EXPR, arg4_type,
4871 ffecom_truth_value
4872 (ffecom_2 (NE_EXPR, integer_type_node,
4873 arg3_tree,
4874 convert (TREE_TYPE (arg3_tree),
4875 TYPE_SIZE (arg4_type)))),
4876 prep_arg1,
4877 arg1_tree);
4878#endif
4879 expr_tree
4880 = ffecom_2s (MODIFY_EXPR, void_type_node,
4881 arg4_tree,
4882 prep_arg1);
4883 /* Make sure SAVE_EXPRs get referenced early enough. */
4884 expr_tree
4885 = ffecom_2 (COMPOUND_EXPR, void_type_node,
4886 arg1_tree,
4887 ffecom_2 (COMPOUND_EXPR, void_type_node,
4888 arg3_tree,
4889 ffecom_2 (COMPOUND_EXPR, void_type_node,
4890 arg5_tree,
4891 ffecom_2 (COMPOUND_EXPR, void_type_node,
4892 arg5_plus_arg3,
4893 expr_tree))));
4894 expr_tree
4895 = ffecom_2 (COMPOUND_EXPR, void_type_node,
4896 arg4_tree,
4897 expr_tree);
4898
4899 }
4900 return expr_tree;
4901
4902 case FFEINTRIN_impDERF:
4903 case FFEINTRIN_impERF:
4904 case FFEINTRIN_impDERFC:
4905 case FFEINTRIN_impERFC:
4906 break;
4907
4908 case FFEINTRIN_impIARGC:
4909 /* extern int xargc; i__1 = xargc - 1; */
4910 expr_tree = ffecom_2 (MINUS_EXPR, TREE_TYPE (ffecom_tree_xargc_),
4911 ffecom_tree_xargc_,
4912 convert (TREE_TYPE (ffecom_tree_xargc_),
4913 integer_one_node));
4914 return expr_tree;
4915
4916 case FFEINTRIN_impSIGNAL_func:
4917 case FFEINTRIN_impSIGNAL_subr:
4918 {
4919 tree arg1_tree;
4920 tree arg2_tree;
4921 tree arg3_tree;
4922
5ff904cd
JL
4923 arg1_tree = convert (ffecom_f2c_integer_type_node,
4924 ffecom_expr (arg1));
4925 arg1_tree = ffecom_1 (ADDR_EXPR,
4926 build_pointer_type (TREE_TYPE (arg1_tree)),
4927 arg1_tree);
4928
4929 /* Pass procedure as a pointer to it, anything else by value. */
4930 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
4931 arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
4932 else
4933 arg2_tree = ffecom_ptr_to_expr (arg2);
4934 arg2_tree = convert (TREE_TYPE (null_pointer_node),
4935 arg2_tree);
4936
4937 if (arg3 != NULL)
c7e4ee3a 4938 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
4939 else
4940 arg3_tree = NULL_TREE;
4941
5ff904cd
JL
4942 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4943 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4944 TREE_CHAIN (arg1_tree) = arg2_tree;
4945
4946 expr_tree
4947 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4948 ffecom_gfrt_kindtype (gfrt),
4949 FALSE,
4950 ((codegen_imp == FFEINTRIN_impSIGNAL_subr) ?
4951 NULL_TREE :
4952 tree_type),
4953 arg1_tree,
c7e4ee3a
CB
4954 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
4955 ffebld_nonter_hook (expr));
5ff904cd
JL
4956
4957 if (arg3_tree != NULL_TREE)
4958 expr_tree
4959 = ffecom_modify (NULL_TREE, arg3_tree,
4960 convert (TREE_TYPE (arg3_tree),
4961 expr_tree));
4962 }
4963 return expr_tree;
4964
4965 case FFEINTRIN_impALARM:
4966 {
4967 tree arg1_tree;
4968 tree arg2_tree;
4969 tree arg3_tree;
4970
5ff904cd
JL
4971 arg1_tree = convert (ffecom_f2c_integer_type_node,
4972 ffecom_expr (arg1));
4973 arg1_tree = ffecom_1 (ADDR_EXPR,
4974 build_pointer_type (TREE_TYPE (arg1_tree)),
4975 arg1_tree);
4976
4977 /* Pass procedure as a pointer to it, anything else by value. */
4978 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
4979 arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
4980 else
4981 arg2_tree = ffecom_ptr_to_expr (arg2);
4982 arg2_tree = convert (TREE_TYPE (null_pointer_node),
4983 arg2_tree);
4984
4985 if (arg3 != NULL)
c7e4ee3a 4986 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
4987 else
4988 arg3_tree = NULL_TREE;
4989
5ff904cd
JL
4990 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4991 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4992 TREE_CHAIN (arg1_tree) = arg2_tree;
4993
4994 expr_tree
4995 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4996 ffecom_gfrt_kindtype (gfrt),
4997 FALSE,
4998 NULL_TREE,
4999 arg1_tree,
c7e4ee3a
CB
5000 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5001 ffebld_nonter_hook (expr));
5ff904cd
JL
5002
5003 if (arg3_tree != NULL_TREE)
5004 expr_tree
5005 = ffecom_modify (NULL_TREE, arg3_tree,
5006 convert (TREE_TYPE (arg3_tree),
5007 expr_tree));
5008 }
5009 return expr_tree;
5010
5011 case FFEINTRIN_impCHDIR_subr:
5012 case FFEINTRIN_impFDATE_subr:
5013 case FFEINTRIN_impFGET_subr:
5014 case FFEINTRIN_impFPUT_subr:
5015 case FFEINTRIN_impGETCWD_subr:
5016 case FFEINTRIN_impHOSTNM_subr:
5017 case FFEINTRIN_impSYSTEM_subr:
5018 case FFEINTRIN_impUNLINK_subr:
5019 {
5020 tree arg1_len = integer_zero_node;
5021 tree arg1_tree;
5022 tree arg2_tree;
5023
5ff904cd
JL
5024 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5025
5026 if (arg2 != NULL)
c7e4ee3a 5027 arg2_tree = ffecom_expr_w (NULL_TREE, arg2);
5ff904cd
JL
5028 else
5029 arg2_tree = NULL_TREE;
5030
5ff904cd
JL
5031 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5032 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5033 TREE_CHAIN (arg1_tree) = arg1_len;
5034
5035 expr_tree
5036 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5037 ffecom_gfrt_kindtype (gfrt),
5038 FALSE,
5039 NULL_TREE,
5040 arg1_tree,
c7e4ee3a
CB
5041 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5042 ffebld_nonter_hook (expr));
5ff904cd
JL
5043
5044 if (arg2_tree != NULL_TREE)
5045 expr_tree
5046 = ffecom_modify (NULL_TREE, arg2_tree,
5047 convert (TREE_TYPE (arg2_tree),
5048 expr_tree));
5049 }
5050 return expr_tree;
5051
5052 case FFEINTRIN_impEXIT:
5053 if (arg1 != NULL)
5054 break;
5055
5056 expr_tree = build_tree_list (NULL_TREE,
5057 ffecom_1 (ADDR_EXPR,
5058 build_pointer_type
5059 (ffecom_integer_type_node),
5060 integer_zero_node));
5061
5062 return
5063 ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5064 ffecom_gfrt_kindtype (gfrt),
5065 FALSE,
5066 void_type_node,
5067 expr_tree,
c7e4ee3a
CB
5068 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5069 ffebld_nonter_hook (expr));
5ff904cd
JL
5070
5071 case FFEINTRIN_impFLUSH:
5072 if (arg1 == NULL)
5073 gfrt = FFECOM_gfrtFLUSH;
5074 else
5075 gfrt = FFECOM_gfrtFLUSH1;
5076 break;
5077
5078 case FFEINTRIN_impCHMOD_subr:
5079 case FFEINTRIN_impLINK_subr:
5080 case FFEINTRIN_impRENAME_subr:
5081 case FFEINTRIN_impSYMLNK_subr:
5082 {
5083 tree arg1_len = integer_zero_node;
5084 tree arg1_tree;
5085 tree arg2_len = integer_zero_node;
5086 tree arg2_tree;
5087 tree arg3_tree;
5088
5ff904cd
JL
5089 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5090 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
5091 if (arg3 != NULL)
c7e4ee3a 5092 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
5093 else
5094 arg3_tree = NULL_TREE;
5095
5ff904cd
JL
5096 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5097 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5098 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5099 arg2_len = build_tree_list (NULL_TREE, arg2_len);
5100 TREE_CHAIN (arg1_tree) = arg2_tree;
5101 TREE_CHAIN (arg2_tree) = arg1_len;
5102 TREE_CHAIN (arg1_len) = arg2_len;
5103 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5104 ffecom_gfrt_kindtype (gfrt),
5105 FALSE,
5106 NULL_TREE,
5107 arg1_tree,
c7e4ee3a
CB
5108 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5109 ffebld_nonter_hook (expr));
5ff904cd
JL
5110 if (arg3_tree != NULL_TREE)
5111 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5112 convert (TREE_TYPE (arg3_tree),
5113 expr_tree));
5114 }
5115 return expr_tree;
5116
5117 case FFEINTRIN_impLSTAT_subr:
5118 case FFEINTRIN_impSTAT_subr:
5119 {
5120 tree arg1_len = integer_zero_node;
5121 tree arg1_tree;
5122 tree arg2_tree;
5123 tree arg3_tree;
5124
5ff904cd
JL
5125 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5126
5127 arg2_tree = ffecom_ptr_to_expr (arg2);
5128
5129 if (arg3 != NULL)
c7e4ee3a 5130 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
5131 else
5132 arg3_tree = NULL_TREE;
5133
5ff904cd
JL
5134 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5135 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5136 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5137 TREE_CHAIN (arg1_tree) = arg2_tree;
5138 TREE_CHAIN (arg2_tree) = arg1_len;
5139 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5140 ffecom_gfrt_kindtype (gfrt),
5141 FALSE,
5142 NULL_TREE,
5143 arg1_tree,
c7e4ee3a
CB
5144 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5145 ffebld_nonter_hook (expr));
5ff904cd
JL
5146 if (arg3_tree != NULL_TREE)
5147 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5148 convert (TREE_TYPE (arg3_tree),
5149 expr_tree));
5150 }
5151 return expr_tree;
5152
5153 case FFEINTRIN_impFGETC_subr:
5154 case FFEINTRIN_impFPUTC_subr:
5155 {
5156 tree arg1_tree;
5157 tree arg2_tree;
5158 tree arg2_len = integer_zero_node;
5159 tree arg3_tree;
5160
5ff904cd
JL
5161 arg1_tree = convert (ffecom_f2c_integer_type_node,
5162 ffecom_expr (arg1));
5163 arg1_tree = ffecom_1 (ADDR_EXPR,
5164 build_pointer_type (TREE_TYPE (arg1_tree)),
5165 arg1_tree);
5166
5167 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
62b3b9db
TM
5168 if (arg3 != NULL)
5169 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5170 else
5171 arg3_tree = NULL_TREE;
5ff904cd
JL
5172
5173 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5174 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5175 arg2_len = build_tree_list (NULL_TREE, arg2_len);
5176 TREE_CHAIN (arg1_tree) = arg2_tree;
5177 TREE_CHAIN (arg2_tree) = arg2_len;
5178
5179 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5180 ffecom_gfrt_kindtype (gfrt),
5181 FALSE,
5182 NULL_TREE,
5183 arg1_tree,
c7e4ee3a
CB
5184 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5185 ffebld_nonter_hook (expr));
62b3b9db
TM
5186 if (arg3_tree != NULL_TREE)
5187 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5188 convert (TREE_TYPE (arg3_tree),
5189 expr_tree));
5ff904cd
JL
5190 }
5191 return expr_tree;
5192
5193 case FFEINTRIN_impFSTAT_subr:
5194 {
5195 tree arg1_tree;
5196 tree arg2_tree;
5197 tree arg3_tree;
5198
5ff904cd
JL
5199 arg1_tree = convert (ffecom_f2c_integer_type_node,
5200 ffecom_expr (arg1));
5201 arg1_tree = ffecom_1 (ADDR_EXPR,
5202 build_pointer_type (TREE_TYPE (arg1_tree)),
5203 arg1_tree);
5204
5205 arg2_tree = convert (ffecom_f2c_ptr_to_integer_type_node,
5206 ffecom_ptr_to_expr (arg2));
5207
5208 if (arg3 == NULL)
5209 arg3_tree = NULL_TREE;
5210 else
c7e4ee3a 5211 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
5212
5213 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5214 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5215 TREE_CHAIN (arg1_tree) = arg2_tree;
5216 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5217 ffecom_gfrt_kindtype (gfrt),
5218 FALSE,
5219 NULL_TREE,
5220 arg1_tree,
c7e4ee3a
CB
5221 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5222 ffebld_nonter_hook (expr));
5ff904cd
JL
5223 if (arg3_tree != NULL_TREE) {
5224 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5225 convert (TREE_TYPE (arg3_tree),
5226 expr_tree));
5227 }
5228 }
5229 return expr_tree;
5230
5231 case FFEINTRIN_impKILL_subr:
5232 {
5233 tree arg1_tree;
5234 tree arg2_tree;
5235 tree arg3_tree;
5236
5ff904cd
JL
5237 arg1_tree = convert (ffecom_f2c_integer_type_node,
5238 ffecom_expr (arg1));
5239 arg1_tree = ffecom_1 (ADDR_EXPR,
5240 build_pointer_type (TREE_TYPE (arg1_tree)),
5241 arg1_tree);
5242
5243 arg2_tree = convert (ffecom_f2c_integer_type_node,
5244 ffecom_expr (arg2));
5245 arg2_tree = ffecom_1 (ADDR_EXPR,
5246 build_pointer_type (TREE_TYPE (arg2_tree)),
5247 arg2_tree);
5248
5249 if (arg3 == NULL)
5250 arg3_tree = NULL_TREE;
5251 else
c7e4ee3a 5252 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
5253
5254 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5255 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5256 TREE_CHAIN (arg1_tree) = arg2_tree;
5257 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5258 ffecom_gfrt_kindtype (gfrt),
5259 FALSE,
5260 NULL_TREE,
5261 arg1_tree,
c7e4ee3a
CB
5262 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5263 ffebld_nonter_hook (expr));
5ff904cd
JL
5264 if (arg3_tree != NULL_TREE) {
5265 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5266 convert (TREE_TYPE (arg3_tree),
5267 expr_tree));
5268 }
5269 }
5270 return expr_tree;
5271
5272 case FFEINTRIN_impCTIME_subr:
5273 case FFEINTRIN_impTTYNAM_subr:
5274 {
5275 tree arg1_len = integer_zero_node;
5276 tree arg1_tree;
5277 tree arg2_tree;
5278
2b0bdd9a 5279 arg1_tree = ffecom_arg_ptr_to_expr (arg2, &arg1_len);
5ff904cd 5280
c56f65d6 5281 arg2_tree = convert (((codegen_imp == FFEINTRIN_impCTIME_subr) ?
5ff904cd
JL
5282 ffecom_f2c_longint_type_node :
5283 ffecom_f2c_integer_type_node),
2b0bdd9a 5284 ffecom_expr (arg1));
5ff904cd
JL
5285 arg2_tree = ffecom_1 (ADDR_EXPR,
5286 build_pointer_type (TREE_TYPE (arg2_tree)),
5287 arg2_tree);
5288
5ff904cd
JL
5289 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5290 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5291 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5292 TREE_CHAIN (arg1_len) = arg2_tree;
5293 TREE_CHAIN (arg1_tree) = arg1_len;
5294
5295 expr_tree
5296 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5297 ffecom_gfrt_kindtype (gfrt),
5298 FALSE,
5299 NULL_TREE,
5300 arg1_tree,
c7e4ee3a
CB
5301 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5302 ffebld_nonter_hook (expr));
2b0bdd9a 5303 TREE_SIDE_EFFECTS (expr_tree) = 1;
5ff904cd
JL
5304 }
5305 return expr_tree;
5306
5307 case FFEINTRIN_impIRAND:
5308 case FFEINTRIN_impRAND:
5309 /* Arg defaults to 0 (normal random case) */
5310 {
5311 tree arg1_tree;
5312
5313 if (arg1 == NULL)
5314 arg1_tree = ffecom_integer_zero_node;
5315 else
5316 arg1_tree = ffecom_expr (arg1);
5317 arg1_tree = convert (ffecom_f2c_integer_type_node,
5318 arg1_tree);
5319 arg1_tree = ffecom_1 (ADDR_EXPR,
5320 build_pointer_type (TREE_TYPE (arg1_tree)),
5321 arg1_tree);
5322 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5323
5324 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5325 ffecom_gfrt_kindtype (gfrt),
5326 FALSE,
5327 ((codegen_imp == FFEINTRIN_impIRAND) ?
5328 ffecom_f2c_integer_type_node :
de7f278a 5329 ffecom_f2c_real_type_node),
5ff904cd
JL
5330 arg1_tree,
5331 dest_tree, dest, dest_used,
c7e4ee3a
CB
5332 NULL_TREE, TRUE,
5333 ffebld_nonter_hook (expr));
5ff904cd
JL
5334 }
5335 return expr_tree;
5336
5337 case FFEINTRIN_impFTELL_subr:
5338 case FFEINTRIN_impUMASK_subr:
5339 {
5340 tree arg1_tree;
5341 tree arg2_tree;
5342
5ff904cd
JL
5343 arg1_tree = convert (ffecom_f2c_integer_type_node,
5344 ffecom_expr (arg1));
5345 arg1_tree = ffecom_1 (ADDR_EXPR,
5346 build_pointer_type (TREE_TYPE (arg1_tree)),
5347 arg1_tree);
5348
5349 if (arg2 == NULL)
5350 arg2_tree = NULL_TREE;
5351 else
c7e4ee3a 5352 arg2_tree = ffecom_expr_w (NULL_TREE, arg2);
5ff904cd
JL
5353
5354 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5355 ffecom_gfrt_kindtype (gfrt),
5356 FALSE,
5357 NULL_TREE,
5358 build_tree_list (NULL_TREE, arg1_tree),
5359 NULL_TREE, NULL, NULL, NULL_TREE,
c7e4ee3a
CB
5360 TRUE,
5361 ffebld_nonter_hook (expr));
5ff904cd
JL
5362 if (arg2_tree != NULL_TREE) {
5363 expr_tree = ffecom_modify (NULL_TREE, arg2_tree,
5364 convert (TREE_TYPE (arg2_tree),
5365 expr_tree));
5366 }
5367 }
5368 return expr_tree;
5369
5370 case FFEINTRIN_impCPU_TIME:
5371 case FFEINTRIN_impSECOND_subr:
5372 {
5373 tree arg1_tree;
5374
c7e4ee3a 5375 arg1_tree = ffecom_expr_w (NULL_TREE, arg1);
5ff904cd
JL
5376
5377 expr_tree
5378 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5379 ffecom_gfrt_kindtype (gfrt),
5380 FALSE,
5381 NULL_TREE,
5382 NULL_TREE,
c7e4ee3a
CB
5383 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5384 ffebld_nonter_hook (expr));
5ff904cd
JL
5385
5386 expr_tree
5387 = ffecom_modify (NULL_TREE, arg1_tree,
5388 convert (TREE_TYPE (arg1_tree),
5389 expr_tree));
5390 }
5391 return expr_tree;
5392
5393 case FFEINTRIN_impDTIME_subr:
5394 case FFEINTRIN_impETIME_subr:
5395 {
5396 tree arg1_tree;
2b0bdd9a 5397 tree result_tree;
5ff904cd 5398
2b0bdd9a 5399 result_tree = ffecom_expr_w (NULL_TREE, arg2);
5ff904cd 5400
2b0bdd9a 5401 arg1_tree = ffecom_ptr_to_expr (arg1);
5ff904cd 5402
5ff904cd
JL
5403 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5404 ffecom_gfrt_kindtype (gfrt),
5405 FALSE,
5406 NULL_TREE,
2b0bdd9a 5407 build_tree_list (NULL_TREE, arg1_tree),
5ff904cd 5408 NULL_TREE, NULL, NULL, NULL_TREE,
c7e4ee3a
CB
5409 TRUE,
5410 ffebld_nonter_hook (expr));
2b0bdd9a
CB
5411 expr_tree = ffecom_modify (NULL_TREE, result_tree,
5412 convert (TREE_TYPE (result_tree),
5ff904cd
JL
5413 expr_tree));
5414 }
5415 return expr_tree;
5416
c7e4ee3a 5417 /* Straightforward calls of libf2c routines: */
5ff904cd
JL
5418 case FFEINTRIN_impABORT:
5419 case FFEINTRIN_impACCESS:
5420 case FFEINTRIN_impBESJ0:
5421 case FFEINTRIN_impBESJ1:
5422 case FFEINTRIN_impBESJN:
5423 case FFEINTRIN_impBESY0:
5424 case FFEINTRIN_impBESY1:
5425 case FFEINTRIN_impBESYN:
5426 case FFEINTRIN_impCHDIR_func:
5427 case FFEINTRIN_impCHMOD_func:
5428 case FFEINTRIN_impDATE:
9e8e701d 5429 case FFEINTRIN_impDATE_AND_TIME:
5ff904cd
JL
5430 case FFEINTRIN_impDBESJ0:
5431 case FFEINTRIN_impDBESJ1:
5432 case FFEINTRIN_impDBESJN:
5433 case FFEINTRIN_impDBESY0:
5434 case FFEINTRIN_impDBESY1:
5435 case FFEINTRIN_impDBESYN:
5436 case FFEINTRIN_impDTIME_func:
5437 case FFEINTRIN_impETIME_func:
5438 case FFEINTRIN_impFGETC_func:
5439 case FFEINTRIN_impFGET_func:
5440 case FFEINTRIN_impFNUM:
5441 case FFEINTRIN_impFPUTC_func:
5442 case FFEINTRIN_impFPUT_func:
5443 case FFEINTRIN_impFSEEK:
5444 case FFEINTRIN_impFSTAT_func:
5445 case FFEINTRIN_impFTELL_func:
5446 case FFEINTRIN_impGERROR:
5447 case FFEINTRIN_impGETARG:
5448 case FFEINTRIN_impGETCWD_func:
5449 case FFEINTRIN_impGETENV:
5450 case FFEINTRIN_impGETGID:
5451 case FFEINTRIN_impGETLOG:
5452 case FFEINTRIN_impGETPID:
5453 case FFEINTRIN_impGETUID:
5454 case FFEINTRIN_impGMTIME:
5455 case FFEINTRIN_impHOSTNM_func:
5456 case FFEINTRIN_impIDATE_unix:
5457 case FFEINTRIN_impIDATE_vxt:
5458 case FFEINTRIN_impIERRNO:
5459 case FFEINTRIN_impISATTY:
5460 case FFEINTRIN_impITIME:
5461 case FFEINTRIN_impKILL_func:
5462 case FFEINTRIN_impLINK_func:
5463 case FFEINTRIN_impLNBLNK:
5464 case FFEINTRIN_impLSTAT_func:
5465 case FFEINTRIN_impLTIME:
5466 case FFEINTRIN_impMCLOCK8:
5467 case FFEINTRIN_impMCLOCK:
5468 case FFEINTRIN_impPERROR:
5469 case FFEINTRIN_impRENAME_func:
5470 case FFEINTRIN_impSECNDS:
5471 case FFEINTRIN_impSECOND_func:
5472 case FFEINTRIN_impSLEEP:
5473 case FFEINTRIN_impSRAND:
5474 case FFEINTRIN_impSTAT_func:
5475 case FFEINTRIN_impSYMLNK_func:
5476 case FFEINTRIN_impSYSTEM_CLOCK:
5477 case FFEINTRIN_impSYSTEM_func:
5478 case FFEINTRIN_impTIME8:
5479 case FFEINTRIN_impTIME_unix:
5480 case FFEINTRIN_impTIME_vxt:
5481 case FFEINTRIN_impUMASK_func:
5482 case FFEINTRIN_impUNLINK_func:
5483 break;
5484
5485 case FFEINTRIN_impCTIME_func: /* CHARACTER functions not handled here. */
5486 case FFEINTRIN_impFDATE_func: /* CHARACTER functions not handled here. */
5487 case FFEINTRIN_impTTYNAM_func: /* CHARACTER functions not handled here. */
5488 case FFEINTRIN_impNONE:
5489 case FFEINTRIN_imp: /* Hush up gcc warning. */
5490 fprintf (stderr, "No %s implementation.\n",
5491 ffeintrin_name_implementation (ffebld_symter_implementation (ffebld_left (expr))));
5492 assert ("unimplemented intrinsic" == NULL);
5493 return error_mark_node;
5494 }
5495
5496 assert (gfrt != FFECOM_gfrt); /* Must have an implementation! */
5497
5ff904cd
JL
5498 expr_tree = ffecom_arglist_expr_ (ffecom_gfrt_args_ (gfrt),
5499 ffebld_right (expr));
5ff904cd
JL
5500
5501 return ffecom_call_ (ffecom_gfrt_tree_ (gfrt), ffecom_gfrt_kindtype (gfrt),
5502 (ffe_is_f2c_library () && ffecom_gfrt_complex_[gfrt]),
5503 tree_type,
5504 expr_tree, dest_tree, dest, dest_used,
c7e4ee3a
CB
5505 NULL_TREE, TRUE,
5506 ffebld_nonter_hook (expr));
5ff904cd 5507
c7e4ee3a
CB
5508 /* See bottom of this file for f2c transforms used to determine
5509 many of the above implementations. The info seems to confuse
5510 Emacs's C mode indentation, which is why it's been moved to
5511 the bottom of this source file. */
5512}
5ff904cd 5513
c7e4ee3a
CB
5514#endif
5515/* For power (exponentiation) where right-hand operand is type INTEGER,
5516 generate in-line code to do it the fast way (which, if the operand
5517 is a constant, might just mean a series of multiplies). */
5ff904cd 5518
c7e4ee3a
CB
5519#if FFECOM_targetCURRENT == FFECOM_targetGCC
5520static tree
5521ffecom_expr_power_integer_ (ffebld expr)
5522{
5523 tree l = ffecom_expr (ffebld_left (expr));
5524 tree r = ffecom_expr (ffebld_right (expr));
5525 tree ltype = TREE_TYPE (l);
5526 tree rtype = TREE_TYPE (r);
5527 tree result = NULL_TREE;
5ff904cd 5528
c7e4ee3a
CB
5529 if (l == error_mark_node
5530 || r == error_mark_node)
5531 return error_mark_node;
5ff904cd 5532
c7e4ee3a
CB
5533 if (TREE_CODE (r) == INTEGER_CST)
5534 {
5535 int sgn = tree_int_cst_sgn (r);
5ff904cd 5536
c7e4ee3a
CB
5537 if (sgn == 0)
5538 return convert (ltype, integer_one_node);
5ff904cd 5539
c7e4ee3a
CB
5540 if ((TREE_CODE (ltype) == INTEGER_TYPE)
5541 && (sgn < 0))
5542 {
5543 /* Reciprocal of integer is either 0, -1, or 1, so after
5544 calculating that (which we leave to the back end to do
5545 or not do optimally), don't bother with any multiplying. */
5ff904cd 5546
c7e4ee3a
CB
5547 result = ffecom_tree_divide_ (ltype,
5548 convert (ltype, integer_one_node),
5549 l,
5550 NULL_TREE, NULL, NULL, NULL_TREE);
5551 r = ffecom_1 (NEGATE_EXPR,
5552 rtype,
5553 r);
5554 if ((TREE_INT_CST_LOW (r) & 1) == 0)
5555 result = ffecom_1 (ABS_EXPR, rtype,
5556 result);
5557 }
5ff904cd 5558
c7e4ee3a
CB
5559 /* Generate appropriate series of multiplies, preceded
5560 by divide if the exponent is negative. */
5ff904cd 5561
c7e4ee3a 5562 l = save_expr (l);
5ff904cd 5563
c7e4ee3a
CB
5564 if (sgn < 0)
5565 {
5566 l = ffecom_tree_divide_ (ltype,
5567 convert (ltype, integer_one_node),
5568 l,
5569 NULL_TREE, NULL, NULL,
5570 ffebld_nonter_hook (expr));
5571 r = ffecom_1 (NEGATE_EXPR, rtype, r);
5572 assert (TREE_CODE (r) == INTEGER_CST);
5ff904cd 5573
c7e4ee3a
CB
5574 if (tree_int_cst_sgn (r) < 0)
5575 { /* The "most negative" number. */
5576 r = ffecom_1 (NEGATE_EXPR, rtype,
5577 ffecom_2 (RSHIFT_EXPR, rtype,
5578 r,
5579 integer_one_node));
5580 l = save_expr (l);
5581 l = ffecom_2 (MULT_EXPR, ltype,
5582 l,
5583 l);
5584 }
5585 }
5ff904cd 5586
c7e4ee3a
CB
5587 for (;;)
5588 {
5589 if (TREE_INT_CST_LOW (r) & 1)
5590 {
5591 if (result == NULL_TREE)
5592 result = l;
5593 else
5594 result = ffecom_2 (MULT_EXPR, ltype,
5595 result,
5596 l);
5597 }
5ff904cd 5598
c7e4ee3a
CB
5599 r = ffecom_2 (RSHIFT_EXPR, rtype,
5600 r,
5601 integer_one_node);
5602 if (integer_zerop (r))
5603 break;
5604 assert (TREE_CODE (r) == INTEGER_CST);
5ff904cd 5605
c7e4ee3a
CB
5606 l = save_expr (l);
5607 l = ffecom_2 (MULT_EXPR, ltype,
5608 l,
5609 l);
5610 }
5611 return result;
5612 }
5ff904cd 5613
c7e4ee3a
CB
5614 /* Though rhs isn't a constant, in-line code cannot be expanded
5615 while transforming dummies
5616 because the back end cannot be easily convinced to generate
5617 stores (MODIFY_EXPR), handle temporaries, and so on before
5618 all the appropriate rtx's have been generated for things like
5619 dummy args referenced in rhs -- which doesn't happen until
5620 store_parm_decls() is called (expand_function_start, I believe,
5621 does the actual rtx-stuffing of PARM_DECLs).
5ff904cd 5622
c7e4ee3a
CB
5623 So, in this case, let the caller generate the call to the
5624 run-time-library function to evaluate the power for us. */
5ff904cd 5625
c7e4ee3a
CB
5626 if (ffecom_transform_only_dummies_)
5627 return NULL_TREE;
5ff904cd 5628
c7e4ee3a
CB
5629 /* Right-hand operand not a constant, expand in-line code to figure
5630 out how to do the multiplies, &c.
5ff904cd 5631
c7e4ee3a
CB
5632 The returned expression is expressed this way in GNU C, where l and
5633 r are the "inputs":
5ff904cd 5634
c7e4ee3a
CB
5635 ({ typeof (r) rtmp = r;
5636 typeof (l) ltmp = l;
5637 typeof (l) result;
5ff904cd 5638
c7e4ee3a
CB
5639 if (rtmp == 0)
5640 result = 1;
5641 else
5642 {
5643 if ((basetypeof (l) == basetypeof (int))
5644 && (rtmp < 0))
5645 {
5646 result = ((typeof (l)) 1) / ltmp;
5647 if ((ltmp < 0) && (((-rtmp) & 1) == 0))
5648 result = -result;
5649 }
5650 else
5651 {
5652 result = 1;
5653 if ((basetypeof (l) != basetypeof (int))
5654 && (rtmp < 0))
5655 {
5656 ltmp = ((typeof (l)) 1) / ltmp;
5657 rtmp = -rtmp;
5658 if (rtmp < 0)
5659 {
5660 rtmp = -(rtmp >> 1);
5661 ltmp *= ltmp;
5662 }
5663 }
5664 for (;;)
5665 {
5666 if (rtmp & 1)
5667 result *= ltmp;
5668 if ((rtmp >>= 1) == 0)
5669 break;
5670 ltmp *= ltmp;
5671 }
5672 }
5673 }
5674 result;
5675 })
5ff904cd 5676
c7e4ee3a
CB
5677 Note that some of the above is compile-time collapsable, such as
5678 the first part of the if statements that checks the base type of
5679 l against int. The if statements are phrased that way to suggest
5680 an easy way to generate the if/else constructs here, knowing that
5681 the back end should (and probably does) eliminate the resulting
5682 dead code (either the int case or the non-int case), something
5683 it couldn't do without the redundant phrasing, requiring explicit
5684 dead-code elimination here, which would be kind of difficult to
5685 read. */
5ff904cd 5686
c7e4ee3a
CB
5687 {
5688 tree rtmp;
5689 tree ltmp;
5690 tree divide;
5691 tree basetypeof_l_is_int;
5692 tree se;
5693 tree t;
5ff904cd 5694
c7e4ee3a
CB
5695 basetypeof_l_is_int
5696 = build_int_2 ((TREE_CODE (ltype) == INTEGER_TYPE), 0);
5ff904cd 5697
c7e4ee3a 5698 se = expand_start_stmt_expr ();
5ff904cd 5699
c7e4ee3a
CB
5700 ffecom_start_compstmt ();
5701
5702#ifndef HAHA
5703 rtmp = ffecom_make_tempvar ("power_r", rtype,
5704 FFETARGET_charactersizeNONE, -1);
5705 ltmp = ffecom_make_tempvar ("power_l", ltype,
5706 FFETARGET_charactersizeNONE, -1);
5707 result = ffecom_make_tempvar ("power_res", ltype,
5708 FFETARGET_charactersizeNONE, -1);
5709 if (TREE_CODE (ltype) == COMPLEX_TYPE
5710 || TREE_CODE (ltype) == RECORD_TYPE)
5711 divide = ffecom_make_tempvar ("power_div", ltype,
5712 FFETARGET_charactersizeNONE, -1);
5713 else
5714 divide = NULL_TREE;
5715#else /* HAHA */
5716 {
5717 tree hook;
5718
5719 hook = ffebld_nonter_hook (expr);
5720 assert (hook);
5721 assert (TREE_CODE (hook) == TREE_VEC);
5722 assert (TREE_VEC_LENGTH (hook) == 4);
5723 rtmp = TREE_VEC_ELT (hook, 0);
5724 ltmp = TREE_VEC_ELT (hook, 1);
5725 result = TREE_VEC_ELT (hook, 2);
5726 divide = TREE_VEC_ELT (hook, 3);
5727 if (TREE_CODE (ltype) == COMPLEX_TYPE
5728 || TREE_CODE (ltype) == RECORD_TYPE)
5729 assert (divide);
5730 else
5731 assert (! divide);
5732 }
5733#endif /* HAHA */
5ff904cd 5734
c7e4ee3a
CB
5735 expand_expr_stmt (ffecom_modify (void_type_node,
5736 rtmp,
5737 r));
5738 expand_expr_stmt (ffecom_modify (void_type_node,
5739 ltmp,
5740 l));
5741 expand_start_cond (ffecom_truth_value
5742 (ffecom_2 (EQ_EXPR, integer_type_node,
5743 rtmp,
5744 convert (rtype, integer_zero_node))),
5745 0);
5746 expand_expr_stmt (ffecom_modify (void_type_node,
5747 result,
5748 convert (ltype, integer_one_node)));
5749 expand_start_else ();
5750 if (! integer_zerop (basetypeof_l_is_int))
5751 {
5752 expand_start_cond (ffecom_2 (LT_EXPR, integer_type_node,
5753 rtmp,
5754 convert (rtype,
5755 integer_zero_node)),
5756 0);
5757 expand_expr_stmt (ffecom_modify (void_type_node,
5758 result,
5759 ffecom_tree_divide_
5760 (ltype,
5761 convert (ltype, integer_one_node),
5762 ltmp,
5763 NULL_TREE, NULL, NULL,
5764 divide)));
5765 expand_start_cond (ffecom_truth_value
5766 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
5767 ffecom_2 (LT_EXPR, integer_type_node,
5768 ltmp,
5769 convert (ltype,
5770 integer_zero_node)),
5771 ffecom_2 (EQ_EXPR, integer_type_node,
5772 ffecom_2 (BIT_AND_EXPR,
5773 rtype,
5774 ffecom_1 (NEGATE_EXPR,
5775 rtype,
5776 rtmp),
5777 convert (rtype,
5778 integer_one_node)),
5779 convert (rtype,
5780 integer_zero_node)))),
5781 0);
5782 expand_expr_stmt (ffecom_modify (void_type_node,
5783 result,
5784 ffecom_1 (NEGATE_EXPR,
5785 ltype,
5786 result)));
5787 expand_end_cond ();
5788 expand_start_else ();
5789 }
5790 expand_expr_stmt (ffecom_modify (void_type_node,
5791 result,
5792 convert (ltype, integer_one_node)));
5793 expand_start_cond (ffecom_truth_value
5794 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
5795 ffecom_truth_value_invert
5796 (basetypeof_l_is_int),
5797 ffecom_2 (LT_EXPR, integer_type_node,
5798 rtmp,
5799 convert (rtype,
5800 integer_zero_node)))),
5801 0);
5802 expand_expr_stmt (ffecom_modify (void_type_node,
5803 ltmp,
5804 ffecom_tree_divide_
5805 (ltype,
5806 convert (ltype, integer_one_node),
5807 ltmp,
5808 NULL_TREE, NULL, NULL,
5809 divide)));
5810 expand_expr_stmt (ffecom_modify (void_type_node,
5811 rtmp,
5812 ffecom_1 (NEGATE_EXPR, rtype,
5813 rtmp)));
5814 expand_start_cond (ffecom_truth_value
5815 (ffecom_2 (LT_EXPR, integer_type_node,
5816 rtmp,
5817 convert (rtype, integer_zero_node))),
5818 0);
5819 expand_expr_stmt (ffecom_modify (void_type_node,
5820 rtmp,
5821 ffecom_1 (NEGATE_EXPR, rtype,
5822 ffecom_2 (RSHIFT_EXPR,
5823 rtype,
5824 rtmp,
5825 integer_one_node))));
5826 expand_expr_stmt (ffecom_modify (void_type_node,
5827 ltmp,
5828 ffecom_2 (MULT_EXPR, ltype,
5829 ltmp,
5830 ltmp)));
5831 expand_end_cond ();
5832 expand_end_cond ();
5833 expand_start_loop (1);
5834 expand_start_cond (ffecom_truth_value
5835 (ffecom_2 (BIT_AND_EXPR, rtype,
5836 rtmp,
5837 convert (rtype, integer_one_node))),
5838 0);
5839 expand_expr_stmt (ffecom_modify (void_type_node,
5840 result,
5841 ffecom_2 (MULT_EXPR, ltype,
5842 result,
5843 ltmp)));
5844 expand_end_cond ();
5845 expand_exit_loop_if_false (NULL,
5846 ffecom_truth_value
5847 (ffecom_modify (rtype,
5848 rtmp,
5849 ffecom_2 (RSHIFT_EXPR,
5850 rtype,
5851 rtmp,
5852 integer_one_node))));
5853 expand_expr_stmt (ffecom_modify (void_type_node,
5854 ltmp,
5855 ffecom_2 (MULT_EXPR, ltype,
5856 ltmp,
5857 ltmp)));
5858 expand_end_loop ();
5859 expand_end_cond ();
5860 if (!integer_zerop (basetypeof_l_is_int))
5861 expand_end_cond ();
5862 expand_expr_stmt (result);
5ff904cd 5863
c7e4ee3a 5864 t = ffecom_end_compstmt ();
5ff904cd 5865
c7e4ee3a 5866 result = expand_end_stmt_expr (se);
5ff904cd 5867
c7e4ee3a 5868 /* This code comes from c-parse.in, after its expand_end_stmt_expr. */
5ff904cd 5869
c7e4ee3a
CB
5870 if (TREE_CODE (t) == BLOCK)
5871 {
5872 /* Make a BIND_EXPR for the BLOCK already made. */
5873 result = build (BIND_EXPR, TREE_TYPE (result),
5874 NULL_TREE, result, t);
5875 /* Remove the block from the tree at this point.
5876 It gets put back at the proper place
5877 when the BIND_EXPR is expanded. */
5878 delete_block (t);
5879 }
5880 else
5881 result = t;
5882 }
5ff904cd 5883
c7e4ee3a
CB
5884 return result;
5885}
5ff904cd 5886
c7e4ee3a
CB
5887#endif
5888/* ffecom_expr_transform_ -- Transform symbols in expr
5ff904cd 5889
c7e4ee3a
CB
5890 ffebld expr; // FFE expression.
5891 ffecom_expr_transform_ (expr);
5ff904cd 5892
c7e4ee3a 5893 Recursive descent on expr while transforming any untransformed SYMTERs. */
5ff904cd 5894
c7e4ee3a
CB
5895#if FFECOM_targetCURRENT == FFECOM_targetGCC
5896static void
5897ffecom_expr_transform_ (ffebld expr)
5898{
5899 tree t;
5900 ffesymbol s;
5ff904cd 5901
c7e4ee3a 5902tail_recurse: /* :::::::::::::::::::: */
5ff904cd 5903
c7e4ee3a
CB
5904 if (expr == NULL)
5905 return;
5ff904cd 5906
c7e4ee3a
CB
5907 switch (ffebld_op (expr))
5908 {
5909 case FFEBLD_opSYMTER:
5910 s = ffebld_symter (expr);
5911 t = ffesymbol_hook (s).decl_tree;
5912 if ((t == NULL_TREE)
5913 && ((ffesymbol_kind (s) != FFEINFO_kindNONE)
5914 || ((ffesymbol_where (s) != FFEINFO_whereNONE)
5915 && (ffesymbol_where (s) != FFEINFO_whereINTRINSIC))))
5916 {
5917 s = ffecom_sym_transform_ (s);
5918 t = ffesymbol_hook (s).decl_tree; /* Sfunc expr non-dummy,
5919 DIMENSION expr? */
5920 }
5921 break; /* Ok if (t == NULL) here. */
5ff904cd 5922
c7e4ee3a
CB
5923 case FFEBLD_opITEM:
5924 ffecom_expr_transform_ (ffebld_head (expr));
5925 expr = ffebld_trail (expr);
5926 goto tail_recurse; /* :::::::::::::::::::: */
5ff904cd 5927
c7e4ee3a
CB
5928 default:
5929 break;
5930 }
5ff904cd 5931
c7e4ee3a
CB
5932 switch (ffebld_arity (expr))
5933 {
5934 case 2:
5935 ffecom_expr_transform_ (ffebld_left (expr));
5936 expr = ffebld_right (expr);
5937 goto tail_recurse; /* :::::::::::::::::::: */
5ff904cd 5938
c7e4ee3a
CB
5939 case 1:
5940 expr = ffebld_left (expr);
5941 goto tail_recurse; /* :::::::::::::::::::: */
5ff904cd 5942
c7e4ee3a
CB
5943 default:
5944 break;
5945 }
5ff904cd 5946
c7e4ee3a
CB
5947 return;
5948}
5ff904cd 5949
c7e4ee3a
CB
5950#endif
5951/* Make a type based on info in live f2c.h file. */
5ff904cd 5952
c7e4ee3a
CB
5953#if FFECOM_targetCURRENT == FFECOM_targetGCC
5954static void
5955ffecom_f2c_make_type_ (tree *type, int tcode, const char *name)
5956{
5957 switch (tcode)
5958 {
5959 case FFECOM_f2ccodeCHAR:
5960 *type = make_signed_type (CHAR_TYPE_SIZE);
5961 break;
5ff904cd 5962
c7e4ee3a
CB
5963 case FFECOM_f2ccodeSHORT:
5964 *type = make_signed_type (SHORT_TYPE_SIZE);
5965 break;
5ff904cd 5966
c7e4ee3a
CB
5967 case FFECOM_f2ccodeINT:
5968 *type = make_signed_type (INT_TYPE_SIZE);
5969 break;
5ff904cd 5970
c7e4ee3a
CB
5971 case FFECOM_f2ccodeLONG:
5972 *type = make_signed_type (LONG_TYPE_SIZE);
5973 break;
5ff904cd 5974
c7e4ee3a
CB
5975 case FFECOM_f2ccodeLONGLONG:
5976 *type = make_signed_type (LONG_LONG_TYPE_SIZE);
5977 break;
5ff904cd 5978
c7e4ee3a
CB
5979 case FFECOM_f2ccodeCHARPTR:
5980 *type = build_pointer_type (DEFAULT_SIGNED_CHAR
5981 ? signed_char_type_node
5982 : unsigned_char_type_node);
5983 break;
5ff904cd 5984
c7e4ee3a
CB
5985 case FFECOM_f2ccodeFLOAT:
5986 *type = make_node (REAL_TYPE);
5987 TYPE_PRECISION (*type) = FLOAT_TYPE_SIZE;
5988 layout_type (*type);
5989 break;
5990
5991 case FFECOM_f2ccodeDOUBLE:
5992 *type = make_node (REAL_TYPE);
5993 TYPE_PRECISION (*type) = DOUBLE_TYPE_SIZE;
5994 layout_type (*type);
5995 break;
5996
5997 case FFECOM_f2ccodeLONGDOUBLE:
5998 *type = make_node (REAL_TYPE);
5999 TYPE_PRECISION (*type) = LONG_DOUBLE_TYPE_SIZE;
6000 layout_type (*type);
6001 break;
5ff904cd 6002
c7e4ee3a
CB
6003 case FFECOM_f2ccodeTWOREALS:
6004 *type = ffecom_make_complex_type_ (ffecom_f2c_real_type_node);
6005 break;
5ff904cd 6006
c7e4ee3a
CB
6007 case FFECOM_f2ccodeTWODOUBLEREALS:
6008 *type = ffecom_make_complex_type_ (ffecom_f2c_doublereal_type_node);
6009 break;
5ff904cd 6010
c7e4ee3a
CB
6011 default:
6012 assert ("unexpected FFECOM_f2ccodeXYZZY!" == NULL);
6013 *type = error_mark_node;
6014 return;
6015 }
5ff904cd 6016
c7e4ee3a 6017 pushdecl (build_decl (TYPE_DECL,
14657de8 6018 ffecom_get_invented_identifier ("__g77_f2c_%s", name),
c7e4ee3a
CB
6019 *type));
6020}
5ff904cd 6021
c7e4ee3a
CB
6022#endif
6023#if FFECOM_targetCURRENT == FFECOM_targetGCC
6024/* Set the f2c list-directed-I/O code for whatever (integral) type has the
6025 given size. */
5ff904cd 6026
c7e4ee3a
CB
6027static void
6028ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size,
6029 int code)
6030{
6031 int j;
6032 tree t;
5ff904cd 6033
c7e4ee3a 6034 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
05bccae2
RK
6035 if ((t = ffecom_tree_type[bt][j]) != NULL_TREE
6036 && compare_tree_int (TYPE_SIZE (t), size) == 0)
c7e4ee3a
CB
6037 {
6038 assert (code != -1);
6039 ffecom_f2c_typecode_[bt][j] = code;
6040 code = -1;
6041 }
6042}
5ff904cd 6043
c7e4ee3a
CB
6044#endif
6045/* Finish up globals after doing all program units in file
5ff904cd 6046
c7e4ee3a 6047 Need to handle only uninitialized COMMON areas. */
5ff904cd 6048
c7e4ee3a
CB
6049#if FFECOM_targetCURRENT == FFECOM_targetGCC
6050static ffeglobal
6051ffecom_finish_global_ (ffeglobal global)
6052{
6053 tree cbtype;
6054 tree cbt;
6055 tree size;
5ff904cd 6056
c7e4ee3a
CB
6057 if (ffeglobal_type (global) != FFEGLOBAL_typeCOMMON)
6058 return global;
5ff904cd 6059
c7e4ee3a
CB
6060 if (ffeglobal_common_init (global))
6061 return global;
5ff904cd 6062
c7e4ee3a
CB
6063 cbt = ffeglobal_hook (global);
6064 if ((cbt == NULL_TREE)
6065 || !ffeglobal_common_have_size (global))
6066 return global; /* No need to make common, never ref'd. */
5ff904cd 6067
c7e4ee3a 6068 DECL_EXTERNAL (cbt) = 0;
5ff904cd 6069
c7e4ee3a 6070 /* Give the array a size now. */
5ff904cd 6071
c7e4ee3a
CB
6072 size = build_int_2 ((ffeglobal_common_size (global)
6073 + ffeglobal_common_pad (global)) - 1,
6074 0);
5ff904cd 6075
c7e4ee3a
CB
6076 cbtype = TREE_TYPE (cbt);
6077 TYPE_DOMAIN (cbtype) = build_range_type (integer_type_node,
6078 integer_zero_node,
6079 size);
6080 if (!TREE_TYPE (size))
6081 TREE_TYPE (size) = TYPE_DOMAIN (cbtype);
6082 layout_type (cbtype);
5ff904cd 6083
c7e4ee3a
CB
6084 cbt = start_decl (cbt, FALSE);
6085 assert (cbt == ffeglobal_hook (global));
5ff904cd 6086
c7e4ee3a 6087 finish_decl (cbt, NULL_TREE, FALSE);
5ff904cd 6088
c7e4ee3a
CB
6089 return global;
6090}
5ff904cd 6091
c7e4ee3a
CB
6092#endif
6093/* Finish up any untransformed symbols. */
5ff904cd 6094
c7e4ee3a
CB
6095#if FFECOM_targetCURRENT == FFECOM_targetGCC
6096static ffesymbol
6097ffecom_finish_symbol_transform_ (ffesymbol s)
5ff904cd 6098{
c7e4ee3a
CB
6099 if ((s == NULL) || (TREE_CODE (current_function_decl) == ERROR_MARK))
6100 return s;
5ff904cd 6101
c7e4ee3a
CB
6102 /* It's easy to know to transform an untransformed symbol, to make sure
6103 we put out debugging info for it. But COMMON variables, unlike
6104 EQUIVALENCE ones, aren't given declarations in addition to the
6105 tree expressions that specify offsets, because COMMON variables
6106 can be referenced in the outer scope where only dummy arguments
6107 (PARM_DECLs) should really be seen. To be safe, just don't do any
6108 VAR_DECLs for COMMON variables when we transform them for real
6109 use, and therefore we do all the VAR_DECL creating here. */
5ff904cd 6110
c7e4ee3a
CB
6111 if (ffesymbol_hook (s).decl_tree == NULL_TREE)
6112 {
6113 if (ffesymbol_kind (s) != FFEINFO_kindNONE
6114 || (ffesymbol_where (s) != FFEINFO_whereNONE
6115 && ffesymbol_where (s) != FFEINFO_whereINTRINSIC
6116 && ffesymbol_where (s) != FFEINFO_whereDUMMY))
6117 /* Not transformed, and not CHARACTER*(*), and not a dummy
6118 argument, which can happen only if the entry point names
6119 it "rides in on" are all invalidated for other reasons. */
6120 s = ffecom_sym_transform_ (s);
6121 }
5ff904cd 6122
c7e4ee3a
CB
6123 if ((ffesymbol_where (s) == FFEINFO_whereCOMMON)
6124 && (ffesymbol_hook (s).decl_tree != error_mark_node))
6125 {
c7e4ee3a
CB
6126 /* This isn't working, at least for dbxout. The .s file looks
6127 okay to me (burley), but in gdb 4.9 at least, the variables
6128 appear to reside somewhere outside of the common area, so
6129 it doesn't make sense to mislead anyone by generating the info
6130 on those variables until this is fixed. NOTE: Same problem
6131 with EQUIVALENCE, sadly...see similar #if later. */
6132 ffecom_member_phase2_ (ffesymbol_storage (ffesymbol_common (s)),
6133 ffesymbol_storage (s));
5ff904cd
JL
6134 }
6135
c7e4ee3a
CB
6136 return s;
6137}
5ff904cd 6138
c7e4ee3a
CB
6139#endif
6140/* Append underscore(s) to name before calling get_identifier. "us"
6141 is nonzero if the name already contains an underscore and thus
6142 needs two underscores appended. */
5ff904cd 6143
c7e4ee3a
CB
6144#if FFECOM_targetCURRENT == FFECOM_targetGCC
6145static tree
6146ffecom_get_appended_identifier_ (char us, const char *name)
6147{
6148 int i;
6149 char *newname;
6150 tree id;
5ff904cd 6151
c7e4ee3a
CB
6152 newname = xmalloc ((i = strlen (name)) + 1
6153 + ffe_is_underscoring ()
6154 + us);
6155 memcpy (newname, name, i);
6156 newname[i] = '_';
6157 newname[i + us] = '_';
6158 newname[i + 1 + us] = '\0';
6159 id = get_identifier (newname);
5ff904cd 6160
c7e4ee3a 6161 free (newname);
5ff904cd 6162
c7e4ee3a
CB
6163 return id;
6164}
5ff904cd 6165
c7e4ee3a
CB
6166#endif
6167/* Decide whether to append underscore to name before calling
6168 get_identifier. */
5ff904cd 6169
c7e4ee3a
CB
6170#if FFECOM_targetCURRENT == FFECOM_targetGCC
6171static tree
6172ffecom_get_external_identifier_ (ffesymbol s)
6173{
6174 char us;
6175 const char *name = ffesymbol_text (s);
5ff904cd 6176
c7e4ee3a 6177 /* If name is a built-in name, just return it as is. */
5ff904cd 6178
c7e4ee3a
CB
6179 if (!ffe_is_underscoring ()
6180 || (strcmp (name, FFETARGET_nameBLANK_COMMON) == 0)
6181#if FFETARGET_isENFORCED_MAIN_NAME
6182 || (strcmp (name, FFETARGET_nameENFORCED_NAME) == 0)
6183#else
6184 || (strcmp (name, FFETARGET_nameUNNAMED_MAIN) == 0)
6185#endif
6186 || (strcmp (name, FFETARGET_nameUNNAMED_BLOCK_DATA) == 0))
6187 return get_identifier (name);
5ff904cd 6188
c7e4ee3a
CB
6189 us = ffe_is_second_underscore ()
6190 ? (strchr (name, '_') != NULL)
6191 : 0;
5ff904cd 6192
c7e4ee3a
CB
6193 return ffecom_get_appended_identifier_ (us, name);
6194}
5ff904cd 6195
c7e4ee3a
CB
6196#endif
6197/* Decide whether to append underscore to internal name before calling
6198 get_identifier.
6199
6200 This is for non-external, top-function-context names only. Transform
6201 identifier so it doesn't conflict with the transformed result
6202 of using a _different_ external name. E.g. if "CALL FOO" is
6203 transformed into "FOO_();", then the variable in "FOO_ = 3"
6204 must be transformed into something that does not conflict, since
6205 these two things should be independent.
5ff904cd 6206
c7e4ee3a
CB
6207 The transformation is as follows. If the name does not contain
6208 an underscore, there is no possible conflict, so just return.
6209 If the name does contain an underscore, then transform it just
6210 like we transform an external identifier. */
5ff904cd 6211
c7e4ee3a
CB
6212#if FFECOM_targetCURRENT == FFECOM_targetGCC
6213static tree
6214ffecom_get_identifier_ (const char *name)
6215{
6216 /* If name does not contain an underscore, just return it as is. */
6217
6218 if (!ffe_is_underscoring ()
6219 || (strchr (name, '_') == NULL))
6220 return get_identifier (name);
6221
6222 return ffecom_get_appended_identifier_ (ffe_is_second_underscore (),
6223 name);
5ff904cd
JL
6224}
6225
6226#endif
c7e4ee3a 6227/* ffecom_gen_sfuncdef_ -- Generate definition of statement function
5ff904cd 6228
c7e4ee3a
CB
6229 tree t;
6230 ffesymbol s; // kindFUNCTION, whereIMMEDIATE.
6231 t = ffecom_gen_sfuncdef_(s,ffesymbol_basictype(s),
6232 ffesymbol_kindtype(s));
5ff904cd 6233
c7e4ee3a
CB
6234 Call after setting up containing function and getting trees for all
6235 other symbols. */
5ff904cd
JL
6236
6237#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
6238static tree
6239ffecom_gen_sfuncdef_ (ffesymbol s, ffeinfoBasictype bt, ffeinfoKindtype kt)
5ff904cd 6240{
c7e4ee3a
CB
6241 ffebld expr = ffesymbol_sfexpr (s);
6242 tree type;
6243 tree func;
6244 tree result;
6245 bool charfunc = (bt == FFEINFO_basictypeCHARACTER);
6246 static bool recurse = FALSE;
c7e4ee3a 6247 int old_lineno = lineno;
3b304f5b 6248 const char *old_input_filename = input_filename;
5ff904cd 6249
c7e4ee3a 6250 ffecom_nested_entry_ = s;
5ff904cd 6251
c7e4ee3a
CB
6252 /* For now, we don't have a handy pointer to where the sfunc is actually
6253 defined, though that should be easy to add to an ffesymbol. (The
6254 token/where info available might well point to the place where the type
6255 of the sfunc is declared, especially if that precedes the place where
6256 the sfunc itself is defined, which is typically the case.) We should
6257 put out a null pointer rather than point somewhere wrong, but I want to
6258 see how it works at this point. */
5ff904cd 6259
c7e4ee3a
CB
6260 input_filename = ffesymbol_where_filename (s);
6261 lineno = ffesymbol_where_filelinenum (s);
5ff904cd 6262
c7e4ee3a
CB
6263 /* Pretransform the expression so any newly discovered things belong to the
6264 outer program unit, not to the statement function. */
5ff904cd 6265
c7e4ee3a 6266 ffecom_expr_transform_ (expr);
5ff904cd 6267
c7e4ee3a
CB
6268 /* Make sure no recursive invocation of this fn (a specific case of failing
6269 to pretransform an sfunc's expression, i.e. where its expression
6270 references another untransformed sfunc) happens. */
6271
6272 assert (!recurse);
6273 recurse = TRUE;
6274
c7e4ee3a
CB
6275 push_f_function_context ();
6276
6277 if (charfunc)
6278 type = void_type_node;
6279 else
5ff904cd 6280 {
c7e4ee3a
CB
6281 type = ffecom_tree_type[bt][kt];
6282 if (type == NULL_TREE)
6283 type = integer_type_node; /* _sym_exec_transition reports
6284 error. */
6285 }
5ff904cd 6286
c7e4ee3a
CB
6287 start_function (ffecom_get_identifier_ (ffesymbol_text (s)),
6288 build_function_type (type, NULL_TREE),
6289 1, /* nested/inline */
6290 0); /* TREE_PUBLIC */
5ff904cd 6291
c7e4ee3a
CB
6292 /* We don't worry about COMPLEX return values here, because this is
6293 entirely internal to our code, and gcc has the ability to return COMPLEX
6294 directly as a value. */
6295
c7e4ee3a
CB
6296 if (charfunc)
6297 { /* Prepend arg for where result goes. */
6298 tree type;
6299
6300 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
6301
14657de8 6302 result = ffecom_get_invented_identifier ("__g77_%s", "result");
c7e4ee3a
CB
6303
6304 ffecom_char_enhance_arg_ (&type, s); /* Ignore returned length. */
6305
6306 type = build_pointer_type (type);
6307 result = build_decl (PARM_DECL, result, type);
6308
6309 push_parm_decl (result);
5ff904cd 6310 }
c7e4ee3a
CB
6311 else
6312 result = NULL_TREE; /* Not ref'd if !charfunc. */
5ff904cd 6313
c7e4ee3a 6314 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (s), TRUE);
5ff904cd 6315
c7e4ee3a
CB
6316 store_parm_decls (0);
6317
6318 ffecom_start_compstmt ();
6319
6320 if (expr != NULL)
5ff904cd 6321 {
c7e4ee3a
CB
6322 if (charfunc)
6323 {
6324 ffetargetCharacterSize sz = ffesymbol_size (s);
6325 tree result_length;
5ff904cd 6326
c7e4ee3a
CB
6327 result_length = build_int_2 (sz, 0);
6328 TREE_TYPE (result_length) = ffecom_f2c_ftnlen_type_node;
5ff904cd 6329
c7e4ee3a 6330 ffecom_prepare_let_char_ (sz, expr);
5ff904cd 6331
c7e4ee3a 6332 ffecom_prepare_end ();
5ff904cd 6333
c7e4ee3a
CB
6334 ffecom_let_char_ (result, result_length, sz, expr);
6335 expand_null_return ();
6336 }
6337 else
6338 {
6339 ffecom_prepare_expr (expr);
5ff904cd 6340
c7e4ee3a 6341 ffecom_prepare_end ();
5ff904cd 6342
c7e4ee3a
CB
6343 expand_return (ffecom_modify (NULL_TREE,
6344 DECL_RESULT (current_function_decl),
6345 ffecom_expr (expr)));
6346 }
c7e4ee3a 6347 }
5ff904cd 6348
c7e4ee3a 6349 ffecom_end_compstmt ();
5ff904cd 6350
c7e4ee3a
CB
6351 func = current_function_decl;
6352 finish_function (1);
5ff904cd 6353
c7e4ee3a 6354 pop_f_function_context ();
5ff904cd 6355
c7e4ee3a
CB
6356 recurse = FALSE;
6357
6358 lineno = old_lineno;
6359 input_filename = old_input_filename;
6360
6361 ffecom_nested_entry_ = NULL;
6362
6363 return func;
5ff904cd
JL
6364}
6365
6366#endif
5ff904cd 6367
c7e4ee3a
CB
6368#if FFECOM_targetCURRENT == FFECOM_targetGCC
6369static const char *
6370ffecom_gfrt_args_ (ffecomGfrt ix)
5ff904cd 6371{
c7e4ee3a
CB
6372 return ffecom_gfrt_argstring_[ix];
6373}
5ff904cd 6374
c7e4ee3a
CB
6375#endif
6376#if FFECOM_targetCURRENT == FFECOM_targetGCC
6377static tree
6378ffecom_gfrt_tree_ (ffecomGfrt ix)
6379{
6380 if (ffecom_gfrt_[ix] == NULL_TREE)
6381 ffecom_make_gfrt_ (ix);
6382
6383 return ffecom_1 (ADDR_EXPR,
6384 build_pointer_type (TREE_TYPE (ffecom_gfrt_[ix])),
6385 ffecom_gfrt_[ix]);
5ff904cd
JL
6386}
6387
6388#endif
c7e4ee3a 6389/* Return initialize-to-zero expression for this VAR_DECL. */
5ff904cd
JL
6390
6391#if FFECOM_targetCURRENT == FFECOM_targetGCC
7189a4b0
GK
6392/* A somewhat evil way to prevent the garbage collector
6393 from collecting 'tree' structures. */
6394#define NUM_TRACKED_CHUNK 63
6395static struct tree_ggc_tracker
6396{
6397 struct tree_ggc_tracker *next;
6398 tree trees[NUM_TRACKED_CHUNK];
6399} *tracker_head = NULL;
6400
6401static void
54551044 6402mark_tracker_head (void *arg)
7189a4b0
GK
6403{
6404 struct tree_ggc_tracker *head;
6405 int i;
6406
6407 for (head = * (struct tree_ggc_tracker **) arg;
6408 head != NULL;
6409 head = head->next)
6410 {
6411 ggc_mark (head);
6412 for (i = 0; i < NUM_TRACKED_CHUNK; i++)
6413 ggc_mark_tree (head->trees[i]);
6414 }
6415}
6416
6417void
6418ffecom_save_tree_forever (tree t)
6419{
6420 int i;
6421 if (tracker_head != NULL)
6422 for (i = 0; i < NUM_TRACKED_CHUNK; i++)
6423 if (tracker_head->trees[i] == NULL)
6424 {
6425 tracker_head->trees[i] = t;
6426 return;
6427 }
6428
6429 {
6430 /* Need to allocate a new block. */
6431 struct tree_ggc_tracker *old_head = tracker_head;
6432
6433 tracker_head = ggc_alloc (sizeof (*tracker_head));
6434 tracker_head->next = old_head;
6435 tracker_head->trees[0] = t;
6436 for (i = 1; i < NUM_TRACKED_CHUNK; i++)
6437 tracker_head->trees[i] = NULL;
6438 }
6439}
6440
c7e4ee3a
CB
6441static tree
6442ffecom_init_zero_ (tree decl)
5ff904cd 6443{
c7e4ee3a
CB
6444 tree init;
6445 int incremental = TREE_STATIC (decl);
6446 tree type = TREE_TYPE (decl);
5ff904cd 6447
c7e4ee3a
CB
6448 if (incremental)
6449 {
6c418184 6450 make_decl_rtl (decl, NULL);
c7e4ee3a 6451 assemble_variable (decl, TREE_PUBLIC (decl) ? 1 : 0, 0, 1);
c7e4ee3a 6452 }
5ff904cd 6453
c7e4ee3a
CB
6454 if ((TREE_CODE (type) != ARRAY_TYPE)
6455 && (TREE_CODE (type) != RECORD_TYPE)
6456 && (TREE_CODE (type) != UNION_TYPE)
6457 && !incremental)
6458 init = convert (type, integer_zero_node);
6459 else if (!incremental)
6460 {
c7e4ee3a
CB
6461 init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
6462 TREE_CONSTANT (init) = 1;
6463 TREE_STATIC (init) = 1;
c7e4ee3a
CB
6464 }
6465 else
6466 {
c7e4ee3a
CB
6467 assemble_zeros (int_size_in_bytes (type));
6468 init = error_mark_node;
c7e4ee3a 6469 }
5ff904cd 6470
c7e4ee3a 6471 return init;
5ff904cd
JL
6472}
6473
6474#endif
5ff904cd 6475#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
6476static tree
6477ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg,
6478 tree *maybe_tree)
5ff904cd 6479{
c7e4ee3a
CB
6480 tree expr_tree;
6481 tree length_tree;
5ff904cd 6482
c7e4ee3a 6483 switch (ffebld_op (arg))
6829256f 6484 {
c7e4ee3a
CB
6485 case FFEBLD_opCONTER: /* For F90, check 0-length. */
6486 if (ffetarget_length_character1
6487 (ffebld_constant_character1
6488 (ffebld_conter (arg))) == 0)
6489 {
6490 *maybe_tree = integer_zero_node;
6491 return convert (tree_type, integer_zero_node);
6492 }
5ff904cd 6493
c7e4ee3a
CB
6494 *maybe_tree = integer_one_node;
6495 expr_tree = build_int_2 (*ffetarget_text_character1
6496 (ffebld_constant_character1
6497 (ffebld_conter (arg))),
6498 0);
6499 TREE_TYPE (expr_tree) = tree_type;
6500 return expr_tree;
5ff904cd 6501
c7e4ee3a
CB
6502 case FFEBLD_opSYMTER:
6503 case FFEBLD_opARRAYREF:
6504 case FFEBLD_opFUNCREF:
6505 case FFEBLD_opSUBSTR:
6506 ffecom_char_args_ (&expr_tree, &length_tree, arg);
5ff904cd 6507
c7e4ee3a
CB
6508 if ((expr_tree == error_mark_node)
6509 || (length_tree == error_mark_node))
6510 {
6511 *maybe_tree = error_mark_node;
6512 return error_mark_node;
6513 }
5ff904cd 6514
c7e4ee3a
CB
6515 if (integer_zerop (length_tree))
6516 {
6517 *maybe_tree = integer_zero_node;
6518 return convert (tree_type, integer_zero_node);
6519 }
6520
6521 expr_tree
6522 = ffecom_1 (INDIRECT_REF,
6523 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
6524 expr_tree);
6525 expr_tree
6526 = ffecom_2 (ARRAY_REF,
6527 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
6528 expr_tree,
6529 integer_one_node);
6530 expr_tree = convert (tree_type, expr_tree);
6531
6532 if (TREE_CODE (length_tree) == INTEGER_CST)
6533 *maybe_tree = integer_one_node;
6534 else /* Must check length at run time. */
6535 *maybe_tree
6536 = ffecom_truth_value
6537 (ffecom_2 (GT_EXPR, integer_type_node,
6538 length_tree,
6539 ffecom_f2c_ftnlen_zero_node));
6540 return expr_tree;
6541
6542 case FFEBLD_opPAREN:
6543 case FFEBLD_opCONVERT:
6544 if (ffeinfo_size (ffebld_info (arg)) == 0)
6545 {
6546 *maybe_tree = integer_zero_node;
6547 return convert (tree_type, integer_zero_node);
6548 }
6549 return ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
6550 maybe_tree);
6551
6552 case FFEBLD_opCONCATENATE:
6553 {
6554 tree maybe_left;
6555 tree maybe_right;
6556 tree expr_left;
6557 tree expr_right;
6558
6559 expr_left = ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
6560 &maybe_left);
6561 expr_right = ffecom_intrinsic_ichar_ (tree_type, ffebld_right (arg),
6562 &maybe_right);
6563 *maybe_tree = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
6564 maybe_left,
6565 maybe_right);
6566 expr_tree = ffecom_3 (COND_EXPR, tree_type,
6567 maybe_left,
6568 expr_left,
6569 expr_right);
6570 return expr_tree;
6571 }
6572
6573 default:
6574 assert ("bad op in ICHAR" == NULL);
6575 return error_mark_node;
6576 }
5ff904cd
JL
6577}
6578
6579#endif
c7e4ee3a
CB
6580/* ffecom_intrinsic_len_ -- Return length info for char arg (LEN())
6581
6582 tree length_arg;
6583 ffebld expr;
6584 length_arg = ffecom_intrinsic_len_ (expr);
6585
6586 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
6587 subexpressions by constructing the appropriate tree for the
6588 length-of-character-text argument in a calling sequence. */
5ff904cd
JL
6589
6590#if FFECOM_targetCURRENT == FFECOM_targetGCC
6591static tree
c7e4ee3a 6592ffecom_intrinsic_len_ (ffebld expr)
5ff904cd 6593{
c7e4ee3a
CB
6594 ffetargetCharacter1 val;
6595 tree length;
6596
6597 switch (ffebld_op (expr))
6598 {
6599 case FFEBLD_opCONTER:
6600 val = ffebld_constant_character1 (ffebld_conter (expr));
6601 length = build_int_2 (ffetarget_length_character1 (val), 0);
6602 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6603 break;
6604
6605 case FFEBLD_opSYMTER:
6606 {
6607 ffesymbol s = ffebld_symter (expr);
6608 tree item;
6609
6610 item = ffesymbol_hook (s).decl_tree;
6611 if (item == NULL_TREE)
6612 {
6613 s = ffecom_sym_transform_ (s);
6614 item = ffesymbol_hook (s).decl_tree;
6615 }
6616 if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
6617 {
6618 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
6619 length = ffesymbol_hook (s).length_tree;
6620 else
6621 {
6622 length = build_int_2 (ffesymbol_size (s), 0);
6623 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6624 }
6625 }
6626 else if (item == error_mark_node)
6627 length = error_mark_node;
6628 else /* FFEINFO_kindFUNCTION: */
6629 length = NULL_TREE;
6630 }
6631 break;
5ff904cd 6632
c7e4ee3a
CB
6633 case FFEBLD_opARRAYREF:
6634 length = ffecom_intrinsic_len_ (ffebld_left (expr));
6635 break;
5ff904cd 6636
c7e4ee3a
CB
6637 case FFEBLD_opSUBSTR:
6638 {
6639 ffebld start;
6640 ffebld end;
6641 ffebld thing = ffebld_right (expr);
6642 tree start_tree;
6643 tree end_tree;
5ff904cd 6644
c7e4ee3a
CB
6645 assert (ffebld_op (thing) == FFEBLD_opITEM);
6646 start = ffebld_head (thing);
6647 thing = ffebld_trail (thing);
6648 assert (ffebld_trail (thing) == NULL);
6649 end = ffebld_head (thing);
5ff904cd 6650
c7e4ee3a 6651 length = ffecom_intrinsic_len_ (ffebld_left (expr));
5ff904cd 6652
c7e4ee3a
CB
6653 if (length == error_mark_node)
6654 break;
5ff904cd 6655
c7e4ee3a
CB
6656 if (start == NULL)
6657 {
6658 if (end == NULL)
6659 ;
6660 else
6661 {
6662 length = convert (ffecom_f2c_ftnlen_type_node,
6663 ffecom_expr (end));
6664 }
6665 }
6666 else
6667 {
6668 start_tree = convert (ffecom_f2c_ftnlen_type_node,
6669 ffecom_expr (start));
5ff904cd 6670
c7e4ee3a
CB
6671 if (start_tree == error_mark_node)
6672 {
6673 length = error_mark_node;
6674 break;
6675 }
5ff904cd 6676
c7e4ee3a
CB
6677 if (end == NULL)
6678 {
6679 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6680 ffecom_f2c_ftnlen_one_node,
6681 ffecom_2 (MINUS_EXPR,
6682 ffecom_f2c_ftnlen_type_node,
6683 length,
6684 start_tree));
6685 }
6686 else
6687 {
6688 end_tree = convert (ffecom_f2c_ftnlen_type_node,
6689 ffecom_expr (end));
5ff904cd 6690
c7e4ee3a
CB
6691 if (end_tree == error_mark_node)
6692 {
6693 length = error_mark_node;
6694 break;
6695 }
5ff904cd 6696
c7e4ee3a
CB
6697 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6698 ffecom_f2c_ftnlen_one_node,
6699 ffecom_2 (MINUS_EXPR,
6700 ffecom_f2c_ftnlen_type_node,
6701 end_tree, start_tree));
6702 }
6703 }
6704 }
6705 break;
5ff904cd 6706
c7e4ee3a
CB
6707 case FFEBLD_opCONCATENATE:
6708 length
6709 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6710 ffecom_intrinsic_len_ (ffebld_left (expr)),
6711 ffecom_intrinsic_len_ (ffebld_right (expr)));
6712 break;
5ff904cd 6713
c7e4ee3a
CB
6714 case FFEBLD_opFUNCREF:
6715 case FFEBLD_opCONVERT:
6716 length = build_int_2 (ffebld_size (expr), 0);
6717 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6718 break;
5ff904cd 6719
c7e4ee3a
CB
6720 default:
6721 assert ("bad op for single char arg expr" == NULL);
6722 length = ffecom_f2c_ftnlen_zero_node;
6723 break;
6724 }
5ff904cd 6725
c7e4ee3a 6726 assert (length != NULL_TREE);
5ff904cd 6727
c7e4ee3a 6728 return length;
5ff904cd
JL
6729}
6730
6731#endif
c7e4ee3a 6732/* Handle CHARACTER assignments.
5ff904cd 6733
c7e4ee3a
CB
6734 Generates code to do the assignment. Used by ordinary assignment
6735 statement handler ffecom_let_stmt and by statement-function
6736 handler to generate code for a statement function. */
5ff904cd
JL
6737
6738#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
6739static void
6740ffecom_let_char_ (tree dest_tree, tree dest_length,
6741 ffetargetCharacterSize dest_size, ffebld source)
5ff904cd 6742{
c7e4ee3a
CB
6743 ffecomConcatList_ catlist;
6744 tree source_length;
6745 tree source_tree;
6746 tree expr_tree;
5ff904cd 6747
c7e4ee3a
CB
6748 if ((dest_tree == error_mark_node)
6749 || (dest_length == error_mark_node))
6750 return;
5ff904cd 6751
c7e4ee3a
CB
6752 assert (dest_tree != NULL_TREE);
6753 assert (dest_length != NULL_TREE);
5ff904cd 6754
c7e4ee3a
CB
6755 /* Source might be an opCONVERT, which just means it is a different size
6756 than the destination. Since the underlying implementation here handles
6757 that (directly or via the s_copy or s_cat run-time-library functions),
6758 we don't need the "convenience" of an opCONVERT that tells us to
6759 truncate or blank-pad, particularly since the resulting implementation
6760 would probably be slower than otherwise. */
5ff904cd 6761
c7e4ee3a
CB
6762 while (ffebld_op (source) == FFEBLD_opCONVERT)
6763 source = ffebld_left (source);
5ff904cd 6764
c7e4ee3a
CB
6765 catlist = ffecom_concat_list_new_ (source, dest_size);
6766 switch (ffecom_concat_list_count_ (catlist))
6767 {
6768 case 0: /* Shouldn't happen, but in case it does... */
6769 ffecom_concat_list_kill_ (catlist);
6770 source_tree = null_pointer_node;
6771 source_length = ffecom_f2c_ftnlen_zero_node;
6772 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6773 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
6774 TREE_CHAIN (TREE_CHAIN (expr_tree))
6775 = build_tree_list (NULL_TREE, dest_length);
6776 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6777 = build_tree_list (NULL_TREE, source_length);
5ff904cd 6778
c7e4ee3a
CB
6779 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree, NULL_TREE);
6780 TREE_SIDE_EFFECTS (expr_tree) = 1;
5ff904cd 6781
c7e4ee3a 6782 expand_expr_stmt (expr_tree);
5ff904cd 6783
c7e4ee3a 6784 return;
5ff904cd 6785
c7e4ee3a
CB
6786 case 1: /* The (fairly) easy case. */
6787 ffecom_char_args_ (&source_tree, &source_length,
6788 ffecom_concat_list_expr_ (catlist, 0));
6789 ffecom_concat_list_kill_ (catlist);
6790 assert (source_tree != NULL_TREE);
6791 assert (source_length != NULL_TREE);
6792
6793 if ((source_tree == error_mark_node)
6794 || (source_length == error_mark_node))
6795 return;
6796
6797 if (dest_size == 1)
6798 {
6799 dest_tree
6800 = ffecom_1 (INDIRECT_REF,
6801 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6802 (dest_tree))),
6803 dest_tree);
6804 dest_tree
6805 = ffecom_2 (ARRAY_REF,
6806 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6807 (dest_tree))),
6808 dest_tree,
6809 integer_one_node);
6810 source_tree
6811 = ffecom_1 (INDIRECT_REF,
6812 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6813 (source_tree))),
6814 source_tree);
6815 source_tree
6816 = ffecom_2 (ARRAY_REF,
6817 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6818 (source_tree))),
6819 source_tree,
6820 integer_one_node);
5ff904cd 6821
c7e4ee3a 6822 expr_tree = ffecom_modify (void_type_node, dest_tree, source_tree);
5ff904cd 6823
c7e4ee3a 6824 expand_expr_stmt (expr_tree);
5ff904cd 6825
c7e4ee3a
CB
6826 return;
6827 }
5ff904cd 6828
c7e4ee3a
CB
6829 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6830 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
6831 TREE_CHAIN (TREE_CHAIN (expr_tree))
6832 = build_tree_list (NULL_TREE, dest_length);
6833 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6834 = build_tree_list (NULL_TREE, source_length);
5ff904cd 6835
c7e4ee3a
CB
6836 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree, NULL_TREE);
6837 TREE_SIDE_EFFECTS (expr_tree) = 1;
5ff904cd 6838
c7e4ee3a 6839 expand_expr_stmt (expr_tree);
5ff904cd 6840
c7e4ee3a 6841 return;
5ff904cd 6842
c7e4ee3a
CB
6843 default: /* Must actually concatenate things. */
6844 break;
6845 }
5ff904cd 6846
c7e4ee3a 6847 /* Heavy-duty concatenation. */
5ff904cd 6848
c7e4ee3a
CB
6849 {
6850 int count = ffecom_concat_list_count_ (catlist);
6851 int i;
6852 tree lengths;
6853 tree items;
6854 tree length_array;
6855 tree item_array;
6856 tree citem;
6857 tree clength;
5ff904cd 6858
c7e4ee3a
CB
6859#ifdef HOHO
6860 length_array
6861 = lengths
6862 = ffecom_push_tempvar (ffecom_f2c_ftnlen_type_node,
6863 FFETARGET_charactersizeNONE, count, TRUE);
6864 item_array = items = ffecom_push_tempvar (ffecom_f2c_address_type_node,
6865 FFETARGET_charactersizeNONE,
6866 count, TRUE);
6867#else
6868 {
6869 tree hook;
6870
6871 hook = ffebld_nonter_hook (source);
6872 assert (hook);
6873 assert (TREE_CODE (hook) == TREE_VEC);
6874 assert (TREE_VEC_LENGTH (hook) == 2);
6875 length_array = lengths = TREE_VEC_ELT (hook, 0);
6876 item_array = items = TREE_VEC_ELT (hook, 1);
5ff904cd 6877 }
c7e4ee3a 6878#endif
5ff904cd 6879
c7e4ee3a
CB
6880 for (i = 0; i < count; ++i)
6881 {
6882 ffecom_char_args_ (&citem, &clength,
6883 ffecom_concat_list_expr_ (catlist, i));
6884 if ((citem == error_mark_node)
6885 || (clength == error_mark_node))
6886 {
6887 ffecom_concat_list_kill_ (catlist);
6888 return;
6889 }
5ff904cd 6890
c7e4ee3a
CB
6891 items
6892 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
6893 ffecom_modify (void_type_node,
6894 ffecom_2 (ARRAY_REF,
6895 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
6896 item_array,
6897 build_int_2 (i, 0)),
6898 citem),
6899 items);
6900 lengths
6901 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
6902 ffecom_modify (void_type_node,
6903 ffecom_2 (ARRAY_REF,
6904 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
6905 length_array,
6906 build_int_2 (i, 0)),
6907 clength),
6908 lengths);
6909 }
5ff904cd 6910
c7e4ee3a
CB
6911 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6912 TREE_CHAIN (expr_tree)
6913 = build_tree_list (NULL_TREE,
6914 ffecom_1 (ADDR_EXPR,
6915 build_pointer_type (TREE_TYPE (items)),
6916 items));
6917 TREE_CHAIN (TREE_CHAIN (expr_tree))
6918 = build_tree_list (NULL_TREE,
6919 ffecom_1 (ADDR_EXPR,
6920 build_pointer_type (TREE_TYPE (lengths)),
6921 lengths));
6922 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6923 = build_tree_list
6924 (NULL_TREE,
6925 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
6926 convert (ffecom_f2c_ftnlen_type_node,
6927 build_int_2 (count, 0))));
6928 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree))))
6929 = build_tree_list (NULL_TREE, dest_length);
5ff904cd 6930
c7e4ee3a
CB
6931 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCAT, expr_tree, NULL_TREE);
6932 TREE_SIDE_EFFECTS (expr_tree) = 1;
5ff904cd 6933
c7e4ee3a
CB
6934 expand_expr_stmt (expr_tree);
6935 }
5ff904cd 6936
c7e4ee3a
CB
6937 ffecom_concat_list_kill_ (catlist);
6938}
5ff904cd 6939
c7e4ee3a
CB
6940#endif
6941/* ffecom_make_gfrt_ -- Make initial info for run-time routine
5ff904cd 6942
c7e4ee3a
CB
6943 ffecomGfrt ix;
6944 ffecom_make_gfrt_(ix);
5ff904cd 6945
c7e4ee3a
CB
6946 Assumes gfrt_[ix] is NULL_TREE, and replaces it with the FUNCTION_DECL
6947 for the indicated run-time routine (ix). */
5ff904cd 6948
c7e4ee3a
CB
6949#if FFECOM_targetCURRENT == FFECOM_targetGCC
6950static void
6951ffecom_make_gfrt_ (ffecomGfrt ix)
6952{
6953 tree t;
6954 tree ttype;
5ff904cd 6955
c7e4ee3a
CB
6956 switch (ffecom_gfrt_type_[ix])
6957 {
6958 case FFECOM_rttypeVOID_:
6959 ttype = void_type_node;
6960 break;
5ff904cd 6961
c7e4ee3a
CB
6962 case FFECOM_rttypeVOIDSTAR_:
6963 ttype = TREE_TYPE (null_pointer_node); /* `void *'. */
6964 break;
5ff904cd 6965
c7e4ee3a
CB
6966 case FFECOM_rttypeFTNINT_:
6967 ttype = ffecom_f2c_ftnint_type_node;
6968 break;
5ff904cd 6969
c7e4ee3a
CB
6970 case FFECOM_rttypeINTEGER_:
6971 ttype = ffecom_f2c_integer_type_node;
6972 break;
5ff904cd 6973
c7e4ee3a
CB
6974 case FFECOM_rttypeLONGINT_:
6975 ttype = ffecom_f2c_longint_type_node;
6976 break;
5ff904cd 6977
c7e4ee3a
CB
6978 case FFECOM_rttypeLOGICAL_:
6979 ttype = ffecom_f2c_logical_type_node;
6980 break;
5ff904cd 6981
c7e4ee3a
CB
6982 case FFECOM_rttypeREAL_F2C_:
6983 ttype = double_type_node;
6984 break;
5ff904cd 6985
c7e4ee3a
CB
6986 case FFECOM_rttypeREAL_GNU_:
6987 ttype = float_type_node;
6988 break;
5ff904cd 6989
c7e4ee3a
CB
6990 case FFECOM_rttypeCOMPLEX_F2C_:
6991 ttype = void_type_node;
6992 break;
5ff904cd 6993
c7e4ee3a
CB
6994 case FFECOM_rttypeCOMPLEX_GNU_:
6995 ttype = ffecom_f2c_complex_type_node;
6996 break;
5ff904cd 6997
c7e4ee3a
CB
6998 case FFECOM_rttypeDOUBLE_:
6999 ttype = double_type_node;
7000 break;
5ff904cd 7001
c7e4ee3a
CB
7002 case FFECOM_rttypeDOUBLEREAL_:
7003 ttype = ffecom_f2c_doublereal_type_node;
7004 break;
5ff904cd 7005
c7e4ee3a
CB
7006 case FFECOM_rttypeDBLCMPLX_F2C_:
7007 ttype = void_type_node;
7008 break;
5ff904cd 7009
c7e4ee3a
CB
7010 case FFECOM_rttypeDBLCMPLX_GNU_:
7011 ttype = ffecom_f2c_doublecomplex_type_node;
7012 break;
5ff904cd 7013
c7e4ee3a
CB
7014 case FFECOM_rttypeCHARACTER_:
7015 ttype = void_type_node;
7016 break;
7017
7018 default:
7019 ttype = NULL;
7020 assert ("bad rttype" == NULL);
7021 break;
5ff904cd 7022 }
5ff904cd 7023
c7e4ee3a
CB
7024 ttype = build_function_type (ttype, NULL_TREE);
7025 t = build_decl (FUNCTION_DECL,
7026 get_identifier (ffecom_gfrt_name_[ix]),
7027 ttype);
7028 DECL_EXTERNAL (t) = 1;
95eb4fd9 7029 TREE_READONLY (t) = ffecom_gfrt_const_[ix] ? 1 : 0;
c7e4ee3a
CB
7030 TREE_PUBLIC (t) = 1;
7031 TREE_THIS_VOLATILE (t) = ffecom_gfrt_volatile_[ix] ? 1 : 0;
5ff904cd 7032
95eb4fd9
TM
7033 /* Sanity check: A function that's const cannot be volatile. */
7034
7035 assert (ffecom_gfrt_const_[ix] ? !ffecom_gfrt_volatile_[ix] : 1);
7036
7037 /* Sanity check: A function that's const cannot return complex. */
7038
7039 assert (ffecom_gfrt_const_[ix] ? !ffecom_gfrt_complex_[ix] : 1);
7040
c7e4ee3a 7041 t = start_decl (t, TRUE);
5ff904cd 7042
c7e4ee3a 7043 finish_decl (t, NULL_TREE, TRUE);
5ff904cd 7044
c7e4ee3a 7045 ffecom_gfrt_[ix] = t;
5ff904cd
JL
7046}
7047
7048#endif
c7e4ee3a
CB
7049/* Phase 1 pass over each member of a COMMON/EQUIVALENCE group. */
7050
5ff904cd 7051#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
7052static void
7053ffecom_member_phase1_ (ffestorag mst UNUSED, ffestorag st)
5ff904cd 7054{
c7e4ee3a 7055 ffesymbol s = ffestorag_symbol (st);
5ff904cd 7056
c7e4ee3a
CB
7057 if (ffesymbol_namelisted (s))
7058 ffecom_member_namelisted_ = TRUE;
7059}
5ff904cd 7060
c7e4ee3a
CB
7061#endif
7062/* Phase 2 pass over each member of a COMMON/EQUIVALENCE group. Declare
7063 the member so debugger will see it. Otherwise nobody should be
7064 referencing the member. */
5ff904cd 7065
c7e4ee3a 7066#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
7067static void
7068ffecom_member_phase2_ (ffestorag mst, ffestorag st)
7069{
7070 ffesymbol s;
7071 tree t;
7072 tree mt;
7073 tree type;
5ff904cd 7074
c7e4ee3a
CB
7075 if ((mst == NULL)
7076 || ((mt = ffestorag_hook (mst)) == NULL)
7077 || (mt == error_mark_node))
7078 return;
5ff904cd 7079
c7e4ee3a
CB
7080 if ((st == NULL)
7081 || ((s = ffestorag_symbol (st)) == NULL))
7082 return;
5ff904cd 7083
c7e4ee3a
CB
7084 type = ffecom_type_localvar_ (s,
7085 ffesymbol_basictype (s),
7086 ffesymbol_kindtype (s));
7087 if (type == error_mark_node)
7088 return;
5ff904cd 7089
c7e4ee3a
CB
7090 t = build_decl (VAR_DECL,
7091 ffecom_get_identifier_ (ffesymbol_text (s)),
7092 type);
5ff904cd 7093
c7e4ee3a
CB
7094 TREE_STATIC (t) = TREE_STATIC (mt);
7095 DECL_INITIAL (t) = NULL_TREE;
7096 TREE_ASM_WRITTEN (t) = 1;
045edebe 7097 TREE_USED (t) = 1;
5ff904cd 7098
c7e4ee3a
CB
7099 DECL_RTL (t)
7100 = gen_rtx (MEM, TYPE_MODE (type),
7101 plus_constant (XEXP (DECL_RTL (mt), 0),
7102 ffestorag_modulo (mst)
7103 + ffestorag_offset (st)
7104 - ffestorag_offset (mst)));
5ff904cd 7105
c7e4ee3a 7106 t = start_decl (t, FALSE);
5ff904cd 7107
c7e4ee3a 7108 finish_decl (t, NULL_TREE, FALSE);
5ff904cd
JL
7109}
7110
c7e4ee3a
CB
7111#endif
7112/* Prepare source expression for assignment into a destination perhaps known
7113 to be of a specific size. */
5ff904cd 7114
c7e4ee3a
CB
7115static void
7116ffecom_prepare_let_char_ (ffetargetCharacterSize dest_size, ffebld source)
5ff904cd 7117{
c7e4ee3a
CB
7118 ffecomConcatList_ catlist;
7119 int count;
7120 int i;
7121 tree ltmp;
7122 tree itmp;
7123 tree tempvar = NULL_TREE;
5ff904cd 7124
c7e4ee3a
CB
7125 while (ffebld_op (source) == FFEBLD_opCONVERT)
7126 source = ffebld_left (source);
5ff904cd 7127
c7e4ee3a
CB
7128 catlist = ffecom_concat_list_new_ (source, dest_size);
7129 count = ffecom_concat_list_count_ (catlist);
5ff904cd 7130
c7e4ee3a
CB
7131 if (count >= 2)
7132 {
7133 ltmp
7134 = ffecom_make_tempvar ("let_char_len", ffecom_f2c_ftnlen_type_node,
7135 FFETARGET_charactersizeNONE, count);
7136 itmp
7137 = ffecom_make_tempvar ("let_char_item", ffecom_f2c_address_type_node,
7138 FFETARGET_charactersizeNONE, count);
7139
7140 tempvar = make_tree_vec (2);
7141 TREE_VEC_ELT (tempvar, 0) = ltmp;
7142 TREE_VEC_ELT (tempvar, 1) = itmp;
7143 }
5ff904cd 7144
c7e4ee3a
CB
7145 for (i = 0; i < count; ++i)
7146 ffecom_prepare_arg_ptr_to_expr (ffecom_concat_list_expr_ (catlist, i));
5ff904cd 7147
c7e4ee3a 7148 ffecom_concat_list_kill_ (catlist);
5ff904cd 7149
c7e4ee3a
CB
7150 if (tempvar)
7151 {
7152 ffebld_nonter_set_hook (source, tempvar);
7153 current_binding_level->prep_state = 1;
7154 }
7155}
5ff904cd 7156
c7e4ee3a 7157/* ffecom_push_dummy_decls_ -- Transform dummy args, push parm decls in order
5ff904cd 7158
c7e4ee3a
CB
7159 Ignores STAR (alternate-return) dummies. All other get exec-transitioned
7160 (which generates their trees) and then their trees get push_parm_decl'd.
5ff904cd 7161
c7e4ee3a
CB
7162 The second arg is TRUE if the dummies are for a statement function, in
7163 which case lengths are not pushed for character arguments (since they are
7164 always known by both the caller and the callee, though the code allows
7165 for someday permitting CHAR*(*) stmtfunc dummies). */
5ff904cd 7166
c7e4ee3a
CB
7167#if FFECOM_targetCURRENT == FFECOM_targetGCC
7168static void
7169ffecom_push_dummy_decls_ (ffebld dummy_list, bool stmtfunc)
7170{
7171 ffebld dummy;
7172 ffebld dumlist;
7173 ffesymbol s;
7174 tree parm;
5ff904cd 7175
c7e4ee3a 7176 ffecom_transform_only_dummies_ = TRUE;
5ff904cd 7177
c7e4ee3a 7178 /* First push the parms corresponding to actual dummy "contents". */
5ff904cd 7179
c7e4ee3a
CB
7180 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
7181 {
7182 dummy = ffebld_head (dumlist);
7183 switch (ffebld_op (dummy))
7184 {
7185 case FFEBLD_opSTAR:
7186 case FFEBLD_opANY:
7187 continue; /* Forget alternate returns. */
5ff904cd 7188
c7e4ee3a
CB
7189 default:
7190 break;
7191 }
7192 assert (ffebld_op (dummy) == FFEBLD_opSYMTER);
7193 s = ffebld_symter (dummy);
7194 parm = ffesymbol_hook (s).decl_tree;
7195 if (parm == NULL_TREE)
7196 {
7197 s = ffecom_sym_transform_ (s);
7198 parm = ffesymbol_hook (s).decl_tree;
7199 assert (parm != NULL_TREE);
7200 }
7201 if (parm != error_mark_node)
7202 push_parm_decl (parm);
5ff904cd
JL
7203 }
7204
c7e4ee3a 7205 /* Then, for CHARACTER dummies, push the parms giving their lengths. */
5ff904cd 7206
c7e4ee3a
CB
7207 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
7208 {
7209 dummy = ffebld_head (dumlist);
7210 switch (ffebld_op (dummy))
7211 {
7212 case FFEBLD_opSTAR:
7213 case FFEBLD_opANY:
7214 continue; /* Forget alternate returns, they mean
7215 NOTHING! */
7216
7217 default:
7218 break;
7219 }
7220 s = ffebld_symter (dummy);
7221 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
7222 continue; /* Only looking for CHARACTER arguments. */
7223 if (stmtfunc && (ffesymbol_size (s) != FFETARGET_charactersizeNONE))
7224 continue; /* Stmtfunc arg with known size needs no
7225 length param. */
7226 if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
7227 continue; /* Only looking for variables and arrays. */
7228 parm = ffesymbol_hook (s).length_tree;
7229 assert (parm != NULL_TREE);
7230 if (parm != error_mark_node)
7231 push_parm_decl (parm);
7232 }
7233
7234 ffecom_transform_only_dummies_ = FALSE;
5ff904cd
JL
7235}
7236
7237#endif
c7e4ee3a 7238/* ffecom_start_progunit_ -- Beginning of program unit
5ff904cd 7239
c7e4ee3a
CB
7240 Does GNU back end stuff necessary to teach it about the start of its
7241 equivalent of a Fortran program unit. */
5ff904cd
JL
7242
7243#if FFECOM_targetCURRENT == FFECOM_targetGCC
7244static void
c7e4ee3a 7245ffecom_start_progunit_ ()
5ff904cd 7246{
c7e4ee3a
CB
7247 ffesymbol fn = ffecom_primary_entry_;
7248 ffebld arglist;
7249 tree id; /* Identifier (name) of function. */
7250 tree type; /* Type of function. */
7251 tree result; /* Result of function. */
7252 ffeinfoBasictype bt;
7253 ffeinfoKindtype kt;
7254 ffeglobal g;
7255 ffeglobalType gt;
7256 ffeglobalType egt = FFEGLOBAL_type;
7257 bool charfunc;
7258 bool cmplxfunc;
7259 bool altentries = (ffecom_num_entrypoints_ != 0);
7260 bool multi
7261 = altentries
7262 && (ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
7263 && (ffecom_master_bt_ == FFEINFO_basictypeNONE);
7264 bool main_program = FALSE;
7265 int old_lineno = lineno;
3b304f5b 7266 const char *old_input_filename = input_filename;
5ff904cd 7267
c7e4ee3a
CB
7268 assert (fn != NULL);
7269 assert (ffesymbol_hook (fn).decl_tree == NULL_TREE);
5ff904cd 7270
c7e4ee3a
CB
7271 input_filename = ffesymbol_where_filename (fn);
7272 lineno = ffesymbol_where_filelinenum (fn);
5ff904cd 7273
c7e4ee3a
CB
7274 switch (ffecom_primary_entry_kind_)
7275 {
7276 case FFEINFO_kindPROGRAM:
7277 main_program = TRUE;
7278 gt = FFEGLOBAL_typeMAIN;
7279 bt = FFEINFO_basictypeNONE;
7280 kt = FFEINFO_kindtypeNONE;
7281 type = ffecom_tree_fun_type_void;
7282 charfunc = FALSE;
7283 cmplxfunc = FALSE;
7284 break;
7285
7286 case FFEINFO_kindBLOCKDATA:
7287 gt = FFEGLOBAL_typeBDATA;
7288 bt = FFEINFO_basictypeNONE;
7289 kt = FFEINFO_kindtypeNONE;
7290 type = ffecom_tree_fun_type_void;
7291 charfunc = FALSE;
7292 cmplxfunc = FALSE;
7293 break;
7294
7295 case FFEINFO_kindFUNCTION:
7296 gt = FFEGLOBAL_typeFUNC;
7297 egt = FFEGLOBAL_typeEXT;
7298 bt = ffesymbol_basictype (fn);
7299 kt = ffesymbol_kindtype (fn);
7300 if (bt == FFEINFO_basictypeNONE)
7301 {
7302 ffeimplic_establish_symbol (fn);
7303 if (ffesymbol_funcresult (fn) != NULL)
7304 ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
7305 bt = ffesymbol_basictype (fn);
7306 kt = ffesymbol_kindtype (fn);
7307 }
7308
7309 if (multi)
7310 charfunc = cmplxfunc = FALSE;
7311 else if (bt == FFEINFO_basictypeCHARACTER)
7312 charfunc = TRUE, cmplxfunc = FALSE;
7313 else if ((bt == FFEINFO_basictypeCOMPLEX)
7314 && ffesymbol_is_f2c (fn)
7315 && !altentries)
7316 charfunc = FALSE, cmplxfunc = TRUE;
7317 else
7318 charfunc = cmplxfunc = FALSE;
7319
7320 if (multi || charfunc)
7321 type = ffecom_tree_fun_type_void;
7322 else if (ffesymbol_is_f2c (fn) && !altentries)
7323 type = ffecom_tree_fun_type[bt][kt];
7324 else
7325 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
7326
7327 if ((type == NULL_TREE)
7328 || (TREE_TYPE (type) == NULL_TREE))
7329 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */
7330 break;
7331
7332 case FFEINFO_kindSUBROUTINE:
7333 gt = FFEGLOBAL_typeSUBR;
7334 egt = FFEGLOBAL_typeEXT;
7335 bt = FFEINFO_basictypeNONE;
7336 kt = FFEINFO_kindtypeNONE;
7337 if (ffecom_is_altreturning_)
7338 type = ffecom_tree_subr_type;
7339 else
7340 type = ffecom_tree_fun_type_void;
7341 charfunc = FALSE;
7342 cmplxfunc = FALSE;
7343 break;
5ff904cd 7344
c7e4ee3a
CB
7345 default:
7346 assert ("say what??" == NULL);
7347 /* Fall through. */
7348 case FFEINFO_kindANY:
7349 gt = FFEGLOBAL_typeANY;
7350 bt = FFEINFO_basictypeNONE;
7351 kt = FFEINFO_kindtypeNONE;
7352 type = error_mark_node;
7353 charfunc = FALSE;
7354 cmplxfunc = FALSE;
7355 break;
7356 }
5ff904cd 7357
c7e4ee3a 7358 if (altentries)
5ff904cd 7359 {
c7e4ee3a 7360 id = ffecom_get_invented_identifier ("__g77_masterfun_%s",
14657de8 7361 ffesymbol_text (fn));
c7e4ee3a
CB
7362 }
7363#if FFETARGET_isENFORCED_MAIN
7364 else if (main_program)
7365 id = get_identifier (FFETARGET_nameENFORCED_MAIN_NAME);
7366#endif
7367 else
7368 id = ffecom_get_external_identifier_ (fn);
5ff904cd 7369
c7e4ee3a
CB
7370 start_function (id,
7371 type,
7372 0, /* nested/inline */
7373 !altentries); /* TREE_PUBLIC */
5ff904cd 7374
c7e4ee3a 7375 TREE_USED (current_function_decl) = 1; /* Avoid spurious warning if altentries. */
5ff904cd 7376
c7e4ee3a
CB
7377 if (!altentries
7378 && ((g = ffesymbol_global (fn)) != NULL)
7379 && ((ffeglobal_type (g) == gt)
7380 || (ffeglobal_type (g) == egt)))
7381 {
7382 ffeglobal_set_hook (g, current_function_decl);
7383 }
5ff904cd 7384
c7e4ee3a
CB
7385 /* Arg handling needs exec-transitioned ffesymbols to work with. But
7386 exec-transitioning needs current_function_decl to be filled in. So we
7387 do these things in two phases. */
5ff904cd 7388
c7e4ee3a
CB
7389 if (altentries)
7390 { /* 1st arg identifies which entrypoint. */
7391 ffecom_which_entrypoint_decl_
7392 = build_decl (PARM_DECL,
7393 ffecom_get_invented_identifier ("__g77_%s",
14657de8 7394 "which_entrypoint"),
c7e4ee3a
CB
7395 integer_type_node);
7396 push_parm_decl (ffecom_which_entrypoint_decl_);
7397 }
5ff904cd 7398
c7e4ee3a
CB
7399 if (charfunc
7400 || cmplxfunc
7401 || multi)
7402 { /* Arg for result (return value). */
7403 tree type;
7404 tree length;
5ff904cd 7405
c7e4ee3a
CB
7406 if (charfunc)
7407 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
7408 else if (cmplxfunc)
7409 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
7410 else
7411 type = ffecom_multi_type_node_;
5ff904cd 7412
14657de8 7413 result = ffecom_get_invented_identifier ("__g77_%s", "result");
5ff904cd 7414
c7e4ee3a 7415 /* Make length arg _and_ enhance type info for CHAR arg itself. */
5ff904cd 7416
c7e4ee3a
CB
7417 if (charfunc)
7418 length = ffecom_char_enhance_arg_ (&type, fn);
7419 else
7420 length = NULL_TREE; /* Not ref'd if !charfunc. */
5ff904cd 7421
c7e4ee3a
CB
7422 type = build_pointer_type (type);
7423 result = build_decl (PARM_DECL, result, type);
5ff904cd 7424
c7e4ee3a
CB
7425 push_parm_decl (result);
7426 if (multi)
7427 ffecom_multi_retval_ = result;
7428 else
7429 ffecom_func_result_ = result;
5ff904cd 7430
c7e4ee3a
CB
7431 if (charfunc)
7432 {
7433 push_parm_decl (length);
7434 ffecom_func_length_ = length;
7435 }
5ff904cd
JL
7436 }
7437
c7e4ee3a
CB
7438 if (ffecom_primary_entry_is_proc_)
7439 {
7440 if (altentries)
7441 arglist = ffecom_master_arglist_;
7442 else
7443 arglist = ffesymbol_dummyargs (fn);
7444 ffecom_push_dummy_decls_ (arglist, FALSE);
7445 }
5ff904cd 7446
c7e4ee3a
CB
7447 if (TREE_CODE (current_function_decl) != ERROR_MARK)
7448 store_parm_decls (main_program ? 1 : 0);
5ff904cd 7449
c7e4ee3a
CB
7450 ffecom_start_compstmt ();
7451 /* Disallow temp vars at this level. */
7452 current_binding_level->prep_state = 2;
5ff904cd 7453
c7e4ee3a
CB
7454 lineno = old_lineno;
7455 input_filename = old_input_filename;
5ff904cd 7456
c7e4ee3a
CB
7457 /* This handles any symbols still untransformed, in case -g specified.
7458 This used to be done in ffecom_finish_progunit, but it turns out to
7459 be necessary to do it here so that statement functions are
7460 expanded before code. But don't bother for BLOCK DATA. */
5ff904cd 7461
c7e4ee3a
CB
7462 if (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
7463 ffesymbol_drive (ffecom_finish_symbol_transform_);
5ff904cd
JL
7464}
7465
7466#endif
c7e4ee3a 7467/* ffecom_sym_transform_ -- Transform FFE sym into backend sym
5ff904cd 7468
c7e4ee3a
CB
7469 ffesymbol s;
7470 ffecom_sym_transform_(s);
7471
7472 The ffesymbol_hook info for s is updated with appropriate backend info
7473 on the symbol. */
7474
7475#if FFECOM_targetCURRENT == FFECOM_targetGCC
7476static ffesymbol
7477ffecom_sym_transform_ (ffesymbol s)
7478{
7479 tree t; /* Transformed thingy. */
7480 tree tlen; /* Length if CHAR*(*). */
7481 bool addr; /* Is t the address of the thingy? */
7482 ffeinfoBasictype bt;
7483 ffeinfoKindtype kt;
7484 ffeglobal g;
c7e4ee3a 7485 int old_lineno = lineno;
3b304f5b 7486 const char *old_input_filename = input_filename;
5ff904cd 7487
c7e4ee3a
CB
7488 /* Must ensure special ASSIGN variables are declared at top of outermost
7489 block, else they'll end up in the innermost block when their first
7490 ASSIGN is seen, which leaves them out of scope when they're the
7491 subject of a GOTO or I/O statement.
5ff904cd 7492
c7e4ee3a
CB
7493 We make this variable even if -fugly-assign. Just let it go unused,
7494 in case it turns out there are cases where we really want to use this
7495 variable anyway (e.g. ASSIGN to INTEGER*2 variable). */
5ff904cd 7496
c7e4ee3a
CB
7497 if (! ffecom_transform_only_dummies_
7498 && ffesymbol_assigned (s)
7499 && ! ffesymbol_hook (s).assign_tree)
7500 s = ffecom_sym_transform_assign_ (s);
5ff904cd 7501
c7e4ee3a 7502 if (ffesymbol_sfdummyparent (s) == NULL)
5ff904cd 7503 {
c7e4ee3a
CB
7504 input_filename = ffesymbol_where_filename (s);
7505 lineno = ffesymbol_where_filelinenum (s);
7506 }
7507 else
7508 {
7509 ffesymbol sf = ffesymbol_sfdummyparent (s);
5ff904cd 7510
c7e4ee3a
CB
7511 input_filename = ffesymbol_where_filename (sf);
7512 lineno = ffesymbol_where_filelinenum (sf);
7513 }
6d433196 7514
c7e4ee3a
CB
7515 bt = ffeinfo_basictype (ffebld_info (s));
7516 kt = ffeinfo_kindtype (ffebld_info (s));
5ff904cd 7517
c7e4ee3a
CB
7518 t = NULL_TREE;
7519 tlen = NULL_TREE;
7520 addr = FALSE;
5ff904cd 7521
c7e4ee3a
CB
7522 switch (ffesymbol_kind (s))
7523 {
7524 case FFEINFO_kindNONE:
7525 switch (ffesymbol_where (s))
7526 {
7527 case FFEINFO_whereDUMMY: /* Subroutine or function. */
7528 assert (ffecom_transform_only_dummies_);
5ff904cd 7529
c7e4ee3a
CB
7530 /* Before 0.4, this could be ENTITY/DUMMY, but see
7531 ffestu_sym_end_transition -- no longer true (in particular, if
7532 it could be an ENTITY, it _will_ be made one, so that
7533 possibility won't come through here). So we never make length
7534 arg for CHARACTER type. */
5ff904cd 7535
c7e4ee3a
CB
7536 t = build_decl (PARM_DECL,
7537 ffecom_get_identifier_ (ffesymbol_text (s)),
7538 ffecom_tree_ptr_to_subr_type);
7539#if BUILT_FOR_270
7540 DECL_ARTIFICIAL (t) = 1;
7541#endif
7542 addr = TRUE;
7543 break;
5ff904cd 7544
c7e4ee3a
CB
7545 case FFEINFO_whereGLOBAL: /* Subroutine or function. */
7546 assert (!ffecom_transform_only_dummies_);
5ff904cd 7547
c7e4ee3a
CB
7548 if (((g = ffesymbol_global (s)) != NULL)
7549 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
7550 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
7551 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
7552 && (ffeglobal_hook (g) != NULL_TREE)
7553 && ffe_is_globals ())
7554 {
7555 t = ffeglobal_hook (g);
7556 break;
7557 }
5ff904cd 7558
c7e4ee3a
CB
7559 t = build_decl (FUNCTION_DECL,
7560 ffecom_get_external_identifier_ (s),
7561 ffecom_tree_subr_type); /* Assume subr. */
7562 DECL_EXTERNAL (t) = 1;
7563 TREE_PUBLIC (t) = 1;
5ff904cd 7564
c7e4ee3a
CB
7565 t = start_decl (t, FALSE);
7566 finish_decl (t, NULL_TREE, FALSE);
795232f7 7567
c7e4ee3a
CB
7568 if ((g != NULL)
7569 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
7570 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
7571 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
7572 ffeglobal_set_hook (g, t);
5ff904cd 7573
7189a4b0 7574 ffecom_save_tree_forever (t);
5ff904cd 7575
c7e4ee3a 7576 break;
5ff904cd 7577
c7e4ee3a
CB
7578 default:
7579 assert ("NONE where unexpected" == NULL);
7580 /* Fall through. */
7581 case FFEINFO_whereANY:
7582 break;
7583 }
5ff904cd 7584 break;
5ff904cd 7585
c7e4ee3a
CB
7586 case FFEINFO_kindENTITY:
7587 switch (ffeinfo_where (ffesymbol_info (s)))
7588 {
5ff904cd 7589
c7e4ee3a
CB
7590 case FFEINFO_whereCONSTANT:
7591 /* ~~Debugging info needed? */
7592 assert (!ffecom_transform_only_dummies_);
7593 t = error_mark_node; /* Shouldn't ever see this in expr. */
7594 break;
5ff904cd 7595
c7e4ee3a
CB
7596 case FFEINFO_whereLOCAL:
7597 assert (!ffecom_transform_only_dummies_);
5ff904cd 7598
c7e4ee3a
CB
7599 {
7600 ffestorag st = ffesymbol_storage (s);
7601 tree type;
5ff904cd 7602
c7e4ee3a
CB
7603 if ((st != NULL)
7604 && (ffestorag_size (st) == 0))
7605 {
7606 t = error_mark_node;
7607 break;
7608 }
5ff904cd 7609
c7e4ee3a 7610 type = ffecom_type_localvar_ (s, bt, kt);
5ff904cd 7611
c7e4ee3a
CB
7612 if (type == error_mark_node)
7613 {
7614 t = error_mark_node;
7615 break;
7616 }
5ff904cd 7617
c7e4ee3a
CB
7618 if ((st != NULL)
7619 && (ffestorag_parent (st) != NULL))
7620 { /* Child of EQUIVALENCE parent. */
7621 ffestorag est;
7622 tree et;
c7e4ee3a 7623 ffetargetOffset offset;
5ff904cd 7624
c7e4ee3a
CB
7625 est = ffestorag_parent (st);
7626 ffecom_transform_equiv_ (est);
5ff904cd 7627
c7e4ee3a
CB
7628 et = ffestorag_hook (est);
7629 assert (et != NULL_TREE);
5ff904cd 7630
c7e4ee3a
CB
7631 if (! TREE_STATIC (et))
7632 put_var_into_stack (et);
5ff904cd 7633
c7e4ee3a
CB
7634 offset = ffestorag_modulo (est)
7635 + ffestorag_offset (ffesymbol_storage (s))
7636 - ffestorag_offset (est);
5ff904cd 7637
c7e4ee3a 7638 ffecom_debug_kludge_ (et, "EQUIVALENCE", s, type, offset);
5ff904cd 7639
c7e4ee3a 7640 /* (t_type *) (((char *) &et) + offset) */
5ff904cd 7641
c7e4ee3a
CB
7642 t = convert (string_type_node, /* (char *) */
7643 ffecom_1 (ADDR_EXPR,
7644 build_pointer_type (TREE_TYPE (et)),
7645 et));
7646 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
7647 t,
7648 build_int_2 (offset, 0));
7649 t = convert (build_pointer_type (type),
7650 t);
d50108c7 7651 TREE_CONSTANT (t) = staticp (et);
5ff904cd 7652
c7e4ee3a 7653 addr = TRUE;
c7e4ee3a
CB
7654 }
7655 else
7656 {
7657 tree initexpr;
7658 bool init = ffesymbol_is_init (s);
5ff904cd 7659
c7e4ee3a
CB
7660 t = build_decl (VAR_DECL,
7661 ffecom_get_identifier_ (ffesymbol_text (s)),
7662 type);
5ff904cd 7663
c7e4ee3a
CB
7664 if (init
7665 || ffesymbol_namelisted (s)
7666#ifdef FFECOM_sizeMAXSTACKITEM
7667 || ((st != NULL)
7668 && (ffestorag_size (st) > FFECOM_sizeMAXSTACKITEM))
7669#endif
7670 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
7671 && (ffecom_primary_entry_kind_
7672 != FFEINFO_kindBLOCKDATA)
7673 && (ffesymbol_is_save (s) || ffe_is_saveall ())))
7674 TREE_STATIC (t) = !ffesymbol_attr (s, FFESYMBOL_attrADJUSTABLE);
7675 else
7676 TREE_STATIC (t) = 0; /* No need to make static. */
5ff904cd 7677
c7e4ee3a
CB
7678 if (init || ffe_is_init_local_zero ())
7679 DECL_INITIAL (t) = error_mark_node;
5ff904cd 7680
c7e4ee3a
CB
7681 /* Keep -Wunused from complaining about var if it
7682 is used as sfunc arg or DATA implied-DO. */
7683 if (ffesymbol_attrs (s) & FFESYMBOL_attrsSFARG)
7684 DECL_IN_SYSTEM_HEADER (t) = 1;
5ff904cd 7685
c7e4ee3a 7686 t = start_decl (t, FALSE);
5ff904cd 7687
c7e4ee3a
CB
7688 if (init)
7689 {
7690 if (ffesymbol_init (s) != NULL)
7691 initexpr = ffecom_expr (ffesymbol_init (s));
7692 else
7693 initexpr = ffecom_init_zero_ (t);
7694 }
7695 else if (ffe_is_init_local_zero ())
7696 initexpr = ffecom_init_zero_ (t);
7697 else
7698 initexpr = NULL_TREE; /* Not ref'd if !init. */
5ff904cd 7699
c7e4ee3a 7700 finish_decl (t, initexpr, FALSE);
5ff904cd 7701
06ceef4e 7702 if (st != NULL && DECL_SIZE (t) != error_mark_node)
c7e4ee3a 7703 {
06ceef4e 7704 assert (TREE_CODE (DECL_SIZE_UNIT (t)) == INTEGER_CST);
05bccae2
RK
7705 assert (0 == compare_tree_int (DECL_SIZE_UNIT (t),
7706 ffestorag_size (st)));
c7e4ee3a 7707 }
c7e4ee3a
CB
7708 }
7709 }
5ff904cd 7710 break;
5ff904cd 7711
c7e4ee3a
CB
7712 case FFEINFO_whereRESULT:
7713 assert (!ffecom_transform_only_dummies_);
5ff904cd 7714
c7e4ee3a
CB
7715 if (bt == FFEINFO_basictypeCHARACTER)
7716 { /* Result is already in list of dummies, use
7717 it (& length). */
7718 t = ffecom_func_result_;
7719 tlen = ffecom_func_length_;
7720 addr = TRUE;
7721 break;
7722 }
7723 if ((ffecom_num_entrypoints_ == 0)
7724 && (bt == FFEINFO_basictypeCOMPLEX)
7725 && (ffesymbol_is_f2c (ffecom_primary_entry_)))
7726 { /* Result is already in list of dummies, use
7727 it. */
7728 t = ffecom_func_result_;
7729 addr = TRUE;
7730 break;
7731 }
7732 if (ffecom_func_result_ != NULL_TREE)
7733 {
7734 t = ffecom_func_result_;
7735 break;
7736 }
7737 if ((ffecom_num_entrypoints_ != 0)
7738 && (ffecom_master_bt_ == FFEINFO_basictypeNONE))
7739 {
c7e4ee3a
CB
7740 assert (ffecom_multi_retval_ != NULL_TREE);
7741 t = ffecom_1 (INDIRECT_REF, ffecom_multi_type_node_,
7742 ffecom_multi_retval_);
7743 t = ffecom_2 (COMPONENT_REF, ffecom_tree_type[bt][kt],
7744 t, ffecom_multi_fields_[bt][kt]);
5ff904cd 7745
c7e4ee3a
CB
7746 break;
7747 }
5ff904cd 7748
c7e4ee3a
CB
7749 t = build_decl (VAR_DECL,
7750 ffecom_get_identifier_ (ffesymbol_text (s)),
7751 ffecom_tree_type[bt][kt]);
7752 TREE_STATIC (t) = 0; /* Put result on stack. */
7753 t = start_decl (t, FALSE);
7754 finish_decl (t, NULL_TREE, FALSE);
5ff904cd 7755
c7e4ee3a 7756 ffecom_func_result_ = t;
5ff904cd 7757
c7e4ee3a 7758 break;
5ff904cd 7759
c7e4ee3a
CB
7760 case FFEINFO_whereDUMMY:
7761 {
7762 tree type;
7763 ffebld dl;
7764 ffebld dim;
7765 tree low;
7766 tree high;
7767 tree old_sizes;
7768 bool adjustable = FALSE; /* Conditionally adjustable? */
5ff904cd 7769
c7e4ee3a
CB
7770 type = ffecom_tree_type[bt][kt];
7771 if (ffesymbol_sfdummyparent (s) != NULL)
7772 {
7773 if (current_function_decl == ffecom_outer_function_decl_)
7774 { /* Exec transition before sfunc
7775 context; get it later. */
7776 break;
7777 }
7778 t = ffecom_get_identifier_ (ffesymbol_text
7779 (ffesymbol_sfdummyparent (s)));
7780 }
7781 else
7782 t = ffecom_get_identifier_ (ffesymbol_text (s));
5ff904cd 7783
c7e4ee3a 7784 assert (ffecom_transform_only_dummies_);
5ff904cd 7785
c7e4ee3a
CB
7786 old_sizes = get_pending_sizes ();
7787 put_pending_sizes (old_sizes);
5ff904cd 7788
c7e4ee3a
CB
7789 if (bt == FFEINFO_basictypeCHARACTER)
7790 tlen = ffecom_char_enhance_arg_ (&type, s);
7791 type = ffecom_check_size_overflow_ (s, type, TRUE);
5ff904cd 7792
c7e4ee3a
CB
7793 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
7794 {
7795 if (type == error_mark_node)
7796 break;
5ff904cd 7797
c7e4ee3a
CB
7798 dim = ffebld_head (dl);
7799 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
7800 if ((ffebld_left (dim) == NULL) || ffecom_doing_entry_)
7801 low = ffecom_integer_one_node;
7802 else
7803 low = ffecom_expr (ffebld_left (dim));
7804 assert (ffebld_right (dim) != NULL);
7805 if ((ffebld_op (ffebld_right (dim)) == FFEBLD_opSTAR)
7806 || ffecom_doing_entry_)
7807 {
7808 /* Used to just do high=low. But for ffecom_tree_
7809 canonize_ref_, it probably is important to correctly
7810 assess the size. E.g. given COMPLEX C(*),CFUNC and
7811 C(2)=CFUNC(C), overlap can happen, while it can't
7812 for, say, C(1)=CFUNC(C(2)). */
7813 /* Even more recently used to set to INT_MAX, but that
7814 broke when some overflow checking went into the back
7815 end. Now we just leave the upper bound unspecified. */
7816 high = NULL;
7817 }
7818 else
7819 high = ffecom_expr (ffebld_right (dim));
5ff904cd 7820
c7e4ee3a
CB
7821 /* Determine whether array is conditionally adjustable,
7822 to decide whether back-end magic is needed.
5ff904cd 7823
c7e4ee3a
CB
7824 Normally the front end uses the back-end function
7825 variable_size to wrap SAVE_EXPR's around expressions
7826 affecting the size/shape of an array so that the
7827 size/shape info doesn't change during execution
7828 of the compiled code even though variables and
7829 functions referenced in those expressions might.
5ff904cd 7830
c7e4ee3a
CB
7831 variable_size also makes sure those saved expressions
7832 get evaluated immediately upon entry to the
7833 compiled procedure -- the front end normally doesn't
7834 have to worry about that.
3cf0cea4 7835
c7e4ee3a
CB
7836 However, there is a problem with this that affects
7837 g77's implementation of entry points, and that is
7838 that it is _not_ true that each invocation of the
7839 compiled procedure is permitted to evaluate
7840 array size/shape info -- because it is possible
7841 that, for some invocations, that info is invalid (in
7842 which case it is "promised" -- i.e. a violation of
7843 the Fortran standard -- that the compiled code
7844 won't reference the array or its size/shape
7845 during that particular invocation).
5ff904cd 7846
c7e4ee3a 7847 To phrase this in C terms, consider this gcc function:
5ff904cd 7848
c7e4ee3a
CB
7849 void foo (int *n, float (*a)[*n])
7850 {
7851 // a is "pointer to array ...", fyi.
7852 }
5ff904cd 7853
c7e4ee3a
CB
7854 Suppose that, for some invocations, it is permitted
7855 for a caller of foo to do this:
5ff904cd 7856
c7e4ee3a 7857 foo (NULL, NULL);
5ff904cd 7858
c7e4ee3a
CB
7859 Now the _written_ code for foo can take such a call
7860 into account by either testing explicitly for whether
7861 (a == NULL) || (n == NULL) -- presumably it is
7862 not permitted to reference *a in various fashions
7863 if (n == NULL) I suppose -- or it can avoid it by
7864 looking at other info (other arguments, static/global
7865 data, etc.).
5ff904cd 7866
c7e4ee3a
CB
7867 However, this won't work in gcc 2.5.8 because it'll
7868 automatically emit the code to save the "*n"
7869 expression, which'll yield a NULL dereference for
7870 the "foo (NULL, NULL)" call, something the code
7871 for foo cannot prevent.
5ff904cd 7872
c7e4ee3a
CB
7873 g77 definitely needs to avoid executing such
7874 code anytime the pointer to the adjustable array
7875 is NULL, because even if its bounds expressions
7876 don't have any references to possible "absent"
7877 variables like "*n" -- say all variable references
7878 are to COMMON variables, i.e. global (though in C,
7879 local static could actually make sense) -- the
7880 expressions could yield other run-time problems
7881 for allowably "dead" values in those variables.
5ff904cd 7882
c7e4ee3a
CB
7883 For example, let's consider a more complicated
7884 version of foo:
5ff904cd 7885
c7e4ee3a
CB
7886 extern int i;
7887 extern int j;
5ff904cd 7888
c7e4ee3a
CB
7889 void foo (float (*a)[i/j])
7890 {
7891 ...
7892 }
5ff904cd 7893
c7e4ee3a
CB
7894 The above is (essentially) quite valid for Fortran
7895 but, again, for a call like "foo (NULL);", it is
7896 permitted for i and j to be undefined when the
7897 call is made. If j happened to be zero, for
7898 example, emitting the code to evaluate "i/j"
7899 could result in a run-time error.
5ff904cd 7900
c7e4ee3a
CB
7901 Offhand, though I don't have my F77 or F90
7902 standards handy, it might even be valid for a
7903 bounds expression to contain a function reference,
7904 in which case I doubt it is permitted for an
7905 implementation to invoke that function in the
7906 Fortran case involved here (invocation of an
7907 alternate ENTRY point that doesn't have the adjustable
7908 array as one of its arguments).
5ff904cd 7909
c7e4ee3a
CB
7910 So, the code that the compiler would normally emit
7911 to preevaluate the size/shape info for an
7912 adjustable array _must not_ be executed at run time
7913 in certain cases. Specifically, for Fortran,
7914 the case is when the pointer to the adjustable
7915 array == NULL. (For gnu-ish C, it might be nice
7916 for the source code itself to specify an expression
7917 that, if TRUE, inhibits execution of the code. Or
7918 reverse the sense for elegance.)
5ff904cd 7919
c7e4ee3a
CB
7920 (Note that g77 could use a different test than NULL,
7921 actually, since it happens to always pass an
7922 integer to the called function that specifies which
7923 entry point is being invoked. Hmm, this might
7924 solve the next problem.)
7925
7926 One way a user could, I suppose, write "foo" so
7927 it works is to insert COND_EXPR's for the
7928 size/shape info so the dangerous stuff isn't
7929 actually done, as in:
7930
7931 void foo (int *n, float (*a)[(a == NULL) ? 0 : *n])
7932 {
7933 ...
7934 }
5ff904cd 7935
c7e4ee3a
CB
7936 The next problem is that the front end needs to
7937 be able to tell the back end about the array's
7938 decl _before_ it tells it about the conditional
7939 expression to inhibit evaluation of size/shape info,
7940 as shown above.
5ff904cd 7941
c7e4ee3a
CB
7942 To solve this, the front end needs to be able
7943 to give the back end the expression to inhibit
7944 generation of the preevaluation code _after_
7945 it makes the decl for the adjustable array.
5ff904cd 7946
c7e4ee3a
CB
7947 Until then, the above example using the COND_EXPR
7948 doesn't pass muster with gcc because the "(a == NULL)"
7949 part has a reference to "a", which is still
7950 undefined at that point.
5ff904cd 7951
c7e4ee3a
CB
7952 g77 will therefore use a different mechanism in the
7953 meantime. */
5ff904cd 7954
c7e4ee3a
CB
7955 if (!adjustable
7956 && ((TREE_CODE (low) != INTEGER_CST)
7957 || (high && TREE_CODE (high) != INTEGER_CST)))
7958 adjustable = TRUE;
5ff904cd 7959
c7e4ee3a
CB
7960#if 0 /* Old approach -- see below. */
7961 if (TREE_CODE (low) != INTEGER_CST)
7962 low = ffecom_3 (COND_EXPR, integer_type_node,
7963 ffecom_adjarray_passed_ (s),
7964 low,
7965 ffecom_integer_zero_node);
5ff904cd 7966
c7e4ee3a
CB
7967 if (high && TREE_CODE (high) != INTEGER_CST)
7968 high = ffecom_3 (COND_EXPR, integer_type_node,
7969 ffecom_adjarray_passed_ (s),
7970 high,
7971 ffecom_integer_zero_node);
7972#endif
5ff904cd 7973
c7e4ee3a
CB
7974 /* ~~~gcc/stor-layout.c (layout_type) should do this,
7975 probably. Fixes 950302-1.f. */
5ff904cd 7976
c7e4ee3a
CB
7977 if (TREE_CODE (low) != INTEGER_CST)
7978 low = variable_size (low);
5ff904cd 7979
c7e4ee3a
CB
7980 /* ~~~Similarly, this fixes dumb0.f. The C front end
7981 does this, which is why dumb0.c would work. */
5ff904cd 7982
c7e4ee3a
CB
7983 if (high && TREE_CODE (high) != INTEGER_CST)
7984 high = variable_size (high);
5ff904cd 7985
c7e4ee3a
CB
7986 type
7987 = build_array_type
7988 (type,
7989 build_range_type (ffecom_integer_type_node,
7990 low, high));
7991 type = ffecom_check_size_overflow_ (s, type, TRUE);
7992 }
5ff904cd 7993
c7e4ee3a
CB
7994 if (type == error_mark_node)
7995 {
7996 t = error_mark_node;
7997 break;
7998 }
5ff904cd 7999
c7e4ee3a
CB
8000 if ((ffesymbol_sfdummyparent (s) == NULL)
8001 || (ffesymbol_basictype (s) == FFEINFO_basictypeCHARACTER))
8002 {
8003 type = build_pointer_type (type);
8004 addr = TRUE;
8005 }
5ff904cd 8006
c7e4ee3a 8007 t = build_decl (PARM_DECL, t, type);
5ff904cd 8008#if BUILT_FOR_270
c7e4ee3a 8009 DECL_ARTIFICIAL (t) = 1;
5ff904cd 8010#endif
5ff904cd 8011
c7e4ee3a
CB
8012 /* If this arg is present in every entry point's list of
8013 dummy args, then we're done. */
5ff904cd 8014
c7e4ee3a
CB
8015 if (ffesymbol_numentries (s)
8016 == (ffecom_num_entrypoints_ + 1))
5ff904cd 8017 break;
5ff904cd 8018
c7e4ee3a 8019#if 1
5ff904cd 8020
c7e4ee3a
CB
8021 /* If variable_size in stor-layout has been called during
8022 the above, then get_pending_sizes should have the
8023 yet-to-be-evaluated saved expressions pending.
8024 Make the whole lot of them get emitted, conditionally
8025 on whether the array decl ("t" above) is not NULL. */
5ff904cd 8026
c7e4ee3a
CB
8027 {
8028 tree sizes = get_pending_sizes ();
8029 tree tem;
5ff904cd 8030
c7e4ee3a
CB
8031 for (tem = sizes;
8032 tem != old_sizes;
8033 tem = TREE_CHAIN (tem))
8034 {
8035 tree temv = TREE_VALUE (tem);
5ff904cd 8036
c7e4ee3a
CB
8037 if (sizes == tem)
8038 sizes = temv;
8039 else
8040 sizes
8041 = ffecom_2 (COMPOUND_EXPR,
8042 TREE_TYPE (sizes),
8043 temv,
8044 sizes);
8045 }
5ff904cd 8046
c7e4ee3a
CB
8047 if (sizes != tem)
8048 {
8049 sizes
8050 = ffecom_3 (COND_EXPR,
8051 TREE_TYPE (sizes),
8052 ffecom_2 (NE_EXPR,
8053 integer_type_node,
8054 t,
8055 null_pointer_node),
8056 sizes,
8057 convert (TREE_TYPE (sizes),
8058 integer_zero_node));
8059 sizes = ffecom_save_tree (sizes);
5ff904cd 8060
c7e4ee3a
CB
8061 sizes
8062 = tree_cons (NULL_TREE, sizes, tem);
8063 }
5ff904cd 8064
c7e4ee3a
CB
8065 if (sizes)
8066 put_pending_sizes (sizes);
8067 }
5ff904cd 8068
c7e4ee3a
CB
8069#else
8070#if 0
8071 if (adjustable
8072 && (ffesymbol_numentries (s)
8073 != ffecom_num_entrypoints_ + 1))
8074 DECL_SOMETHING (t)
8075 = ffecom_2 (NE_EXPR, integer_type_node,
8076 t,
8077 null_pointer_node);
8078#else
8079#if 0
8080 if (adjustable
8081 && (ffesymbol_numentries (s)
8082 != ffecom_num_entrypoints_ + 1))
8083 {
8084 ffebad_start (FFEBAD_MISSING_ADJARRAY_UNSUPPORTED);
8085 ffebad_here (0, ffesymbol_where_line (s),
8086 ffesymbol_where_column (s));
8087 ffebad_string (ffesymbol_text (s));
8088 ffebad_finish ();
8089 }
8090#endif
8091#endif
8092#endif
8093 }
5ff904cd
JL
8094 break;
8095
c7e4ee3a 8096 case FFEINFO_whereCOMMON:
5ff904cd 8097 {
c7e4ee3a
CB
8098 ffesymbol cs;
8099 ffeglobal cg;
8100 tree ct;
5ff904cd
JL
8101 ffestorag st = ffesymbol_storage (s);
8102 tree type;
8103
c7e4ee3a
CB
8104 cs = ffesymbol_common (s); /* The COMMON area itself. */
8105 if (st != NULL) /* Else not laid out. */
5ff904cd 8106 {
c7e4ee3a
CB
8107 ffecom_transform_common_ (cs);
8108 st = ffesymbol_storage (s);
5ff904cd
JL
8109 }
8110
c7e4ee3a 8111 type = ffecom_type_localvar_ (s, bt, kt);
5ff904cd 8112
c7e4ee3a
CB
8113 cg = ffesymbol_global (cs); /* The global COMMON info. */
8114 if ((cg == NULL)
8115 || (ffeglobal_type (cg) != FFEGLOBAL_typeCOMMON))
8116 ct = NULL_TREE;
8117 else
8118 ct = ffeglobal_hook (cg); /* The common area's tree. */
5ff904cd 8119
c7e4ee3a
CB
8120 if ((ct == NULL_TREE)
8121 || (st == NULL)
8122 || (type == error_mark_node))
8123 t = error_mark_node;
8124 else
8125 {
8126 ffetargetOffset offset;
8127 ffestorag cst;
5ff904cd 8128
c7e4ee3a
CB
8129 cst = ffestorag_parent (st);
8130 assert (cst == ffesymbol_storage (cs));
5ff904cd 8131
c7e4ee3a
CB
8132 offset = ffestorag_modulo (cst)
8133 + ffestorag_offset (st)
8134 - ffestorag_offset (cst);
5ff904cd 8135
c7e4ee3a 8136 ffecom_debug_kludge_ (ct, "COMMON", s, type, offset);
5ff904cd 8137
c7e4ee3a 8138 /* (t_type *) (((char *) &ct) + offset) */
5ff904cd
JL
8139
8140 t = convert (string_type_node, /* (char *) */
8141 ffecom_1 (ADDR_EXPR,
c7e4ee3a
CB
8142 build_pointer_type (TREE_TYPE (ct)),
8143 ct));
5ff904cd
JL
8144 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
8145 t,
8146 build_int_2 (offset, 0));
8147 t = convert (build_pointer_type (type),
8148 t);
d50108c7 8149 TREE_CONSTANT (t) = 1;
5ff904cd
JL
8150
8151 addr = TRUE;
5ff904cd 8152 }
c7e4ee3a
CB
8153 }
8154 break;
5ff904cd 8155
c7e4ee3a
CB
8156 case FFEINFO_whereIMMEDIATE:
8157 case FFEINFO_whereGLOBAL:
8158 case FFEINFO_whereFLEETING:
8159 case FFEINFO_whereFLEETING_CADDR:
8160 case FFEINFO_whereFLEETING_IADDR:
8161 case FFEINFO_whereINTRINSIC:
8162 case FFEINFO_whereCONSTANT_SUBOBJECT:
8163 default:
8164 assert ("ENTITY where unheard of" == NULL);
8165 /* Fall through. */
8166 case FFEINFO_whereANY:
8167 t = error_mark_node;
8168 break;
8169 }
8170 break;
5ff904cd 8171
c7e4ee3a
CB
8172 case FFEINFO_kindFUNCTION:
8173 switch (ffeinfo_where (ffesymbol_info (s)))
8174 {
8175 case FFEINFO_whereLOCAL: /* Me. */
8176 assert (!ffecom_transform_only_dummies_);
8177 t = current_function_decl;
5ff904cd
JL
8178 break;
8179
c7e4ee3a 8180 case FFEINFO_whereGLOBAL:
5ff904cd
JL
8181 assert (!ffecom_transform_only_dummies_);
8182
c7e4ee3a
CB
8183 if (((g = ffesymbol_global (s)) != NULL)
8184 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8185 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8186 && (ffeglobal_hook (g) != NULL_TREE)
8187 && ffe_is_globals ())
5ff904cd 8188 {
c7e4ee3a 8189 t = ffeglobal_hook (g);
5ff904cd
JL
8190 break;
8191 }
5ff904cd 8192
c7e4ee3a
CB
8193 if (ffesymbol_is_f2c (s)
8194 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
8195 t = ffecom_tree_fun_type[bt][kt];
8196 else
8197 t = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
5ff904cd 8198
c7e4ee3a
CB
8199 t = build_decl (FUNCTION_DECL,
8200 ffecom_get_external_identifier_ (s),
8201 t);
8202 DECL_EXTERNAL (t) = 1;
8203 TREE_PUBLIC (t) = 1;
5ff904cd 8204
5ff904cd
JL
8205 t = start_decl (t, FALSE);
8206 finish_decl (t, NULL_TREE, FALSE);
8207
c7e4ee3a
CB
8208 if ((g != NULL)
8209 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8210 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8211 ffeglobal_set_hook (g, t);
8212
7189a4b0 8213 ffecom_save_tree_forever (t);
5ff904cd 8214
5ff904cd
JL
8215 break;
8216
8217 case FFEINFO_whereDUMMY:
c7e4ee3a 8218 assert (ffecom_transform_only_dummies_);
5ff904cd 8219
c7e4ee3a
CB
8220 if (ffesymbol_is_f2c (s)
8221 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
8222 t = ffecom_tree_ptr_to_fun_type[bt][kt];
8223 else
8224 t = build_pointer_type
8225 (build_function_type (ffecom_tree_type[bt][kt], NULL_TREE));
8226
8227 t = build_decl (PARM_DECL,
8228 ffecom_get_identifier_ (ffesymbol_text (s)),
8229 t);
8230#if BUILT_FOR_270
8231 DECL_ARTIFICIAL (t) = 1;
8232#endif
8233 addr = TRUE;
8234 break;
8235
8236 case FFEINFO_whereCONSTANT: /* Statement function. */
8237 assert (!ffecom_transform_only_dummies_);
8238 t = ffecom_gen_sfuncdef_ (s, bt, kt);
8239 break;
8240
8241 case FFEINFO_whereINTRINSIC:
8242 assert (!ffecom_transform_only_dummies_);
8243 break; /* Let actual references generate their
8244 decls. */
8245
8246 default:
8247 assert ("FUNCTION where unheard of" == NULL);
8248 /* Fall through. */
8249 case FFEINFO_whereANY:
8250 t = error_mark_node;
8251 break;
8252 }
8253 break;
8254
8255 case FFEINFO_kindSUBROUTINE:
8256 switch (ffeinfo_where (ffesymbol_info (s)))
8257 {
8258 case FFEINFO_whereLOCAL: /* Me. */
8259 assert (!ffecom_transform_only_dummies_);
8260 t = current_function_decl;
8261 break;
5ff904cd 8262
c7e4ee3a
CB
8263 case FFEINFO_whereGLOBAL:
8264 assert (!ffecom_transform_only_dummies_);
5ff904cd 8265
c7e4ee3a
CB
8266 if (((g = ffesymbol_global (s)) != NULL)
8267 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8268 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8269 && (ffeglobal_hook (g) != NULL_TREE)
8270 && ffe_is_globals ())
8271 {
8272 t = ffeglobal_hook (g);
8273 break;
8274 }
5ff904cd 8275
c7e4ee3a
CB
8276 t = build_decl (FUNCTION_DECL,
8277 ffecom_get_external_identifier_ (s),
8278 ffecom_tree_subr_type);
8279 DECL_EXTERNAL (t) = 1;
8280 TREE_PUBLIC (t) = 1;
5ff904cd 8281
c7e4ee3a
CB
8282 t = start_decl (t, FALSE);
8283 finish_decl (t, NULL_TREE, FALSE);
5ff904cd 8284
c7e4ee3a
CB
8285 if ((g != NULL)
8286 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8287 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8288 ffeglobal_set_hook (g, t);
5ff904cd 8289
7189a4b0 8290 ffecom_save_tree_forever (t);
5ff904cd 8291
c7e4ee3a 8292 break;
5ff904cd 8293
c7e4ee3a
CB
8294 case FFEINFO_whereDUMMY:
8295 assert (ffecom_transform_only_dummies_);
5ff904cd 8296
c7e4ee3a
CB
8297 t = build_decl (PARM_DECL,
8298 ffecom_get_identifier_ (ffesymbol_text (s)),
8299 ffecom_tree_ptr_to_subr_type);
8300#if BUILT_FOR_270
8301 DECL_ARTIFICIAL (t) = 1;
8302#endif
8303 addr = TRUE;
8304 break;
5ff904cd 8305
c7e4ee3a
CB
8306 case FFEINFO_whereINTRINSIC:
8307 assert (!ffecom_transform_only_dummies_);
8308 break; /* Let actual references generate their
8309 decls. */
5ff904cd 8310
c7e4ee3a
CB
8311 default:
8312 assert ("SUBROUTINE where unheard of" == NULL);
8313 /* Fall through. */
8314 case FFEINFO_whereANY:
8315 t = error_mark_node;
8316 break;
8317 }
8318 break;
5ff904cd 8319
c7e4ee3a
CB
8320 case FFEINFO_kindPROGRAM:
8321 switch (ffeinfo_where (ffesymbol_info (s)))
8322 {
8323 case FFEINFO_whereLOCAL: /* Me. */
8324 assert (!ffecom_transform_only_dummies_);
8325 t = current_function_decl;
8326 break;
5ff904cd 8327
c7e4ee3a
CB
8328 case FFEINFO_whereCOMMON:
8329 case FFEINFO_whereDUMMY:
8330 case FFEINFO_whereGLOBAL:
8331 case FFEINFO_whereRESULT:
8332 case FFEINFO_whereFLEETING:
8333 case FFEINFO_whereFLEETING_CADDR:
8334 case FFEINFO_whereFLEETING_IADDR:
8335 case FFEINFO_whereIMMEDIATE:
8336 case FFEINFO_whereINTRINSIC:
8337 case FFEINFO_whereCONSTANT:
8338 case FFEINFO_whereCONSTANT_SUBOBJECT:
8339 default:
8340 assert ("PROGRAM where unheard of" == NULL);
8341 /* Fall through. */
8342 case FFEINFO_whereANY:
8343 t = error_mark_node;
8344 break;
8345 }
8346 break;
5ff904cd 8347
c7e4ee3a
CB
8348 case FFEINFO_kindBLOCKDATA:
8349 switch (ffeinfo_where (ffesymbol_info (s)))
8350 {
8351 case FFEINFO_whereLOCAL: /* Me. */
8352 assert (!ffecom_transform_only_dummies_);
8353 t = current_function_decl;
8354 break;
5ff904cd 8355
c7e4ee3a
CB
8356 case FFEINFO_whereGLOBAL:
8357 assert (!ffecom_transform_only_dummies_);
5ff904cd 8358
c7e4ee3a
CB
8359 t = build_decl (FUNCTION_DECL,
8360 ffecom_get_external_identifier_ (s),
8361 ffecom_tree_blockdata_type);
8362 DECL_EXTERNAL (t) = 1;
8363 TREE_PUBLIC (t) = 1;
5ff904cd 8364
c7e4ee3a
CB
8365 t = start_decl (t, FALSE);
8366 finish_decl (t, NULL_TREE, FALSE);
5ff904cd 8367
7189a4b0 8368 ffecom_save_tree_forever (t);
5ff904cd 8369
c7e4ee3a 8370 break;
5ff904cd 8371
c7e4ee3a
CB
8372 case FFEINFO_whereCOMMON:
8373 case FFEINFO_whereDUMMY:
8374 case FFEINFO_whereRESULT:
8375 case FFEINFO_whereFLEETING:
8376 case FFEINFO_whereFLEETING_CADDR:
8377 case FFEINFO_whereFLEETING_IADDR:
8378 case FFEINFO_whereIMMEDIATE:
8379 case FFEINFO_whereINTRINSIC:
8380 case FFEINFO_whereCONSTANT:
8381 case FFEINFO_whereCONSTANT_SUBOBJECT:
8382 default:
8383 assert ("BLOCKDATA where unheard of" == NULL);
8384 /* Fall through. */
8385 case FFEINFO_whereANY:
8386 t = error_mark_node;
8387 break;
8388 }
8389 break;
5ff904cd 8390
c7e4ee3a
CB
8391 case FFEINFO_kindCOMMON:
8392 switch (ffeinfo_where (ffesymbol_info (s)))
8393 {
8394 case FFEINFO_whereLOCAL:
8395 assert (!ffecom_transform_only_dummies_);
8396 ffecom_transform_common_ (s);
8397 break;
8398
8399 case FFEINFO_whereNONE:
8400 case FFEINFO_whereCOMMON:
8401 case FFEINFO_whereDUMMY:
8402 case FFEINFO_whereGLOBAL:
8403 case FFEINFO_whereRESULT:
8404 case FFEINFO_whereFLEETING:
8405 case FFEINFO_whereFLEETING_CADDR:
8406 case FFEINFO_whereFLEETING_IADDR:
8407 case FFEINFO_whereIMMEDIATE:
8408 case FFEINFO_whereINTRINSIC:
8409 case FFEINFO_whereCONSTANT:
8410 case FFEINFO_whereCONSTANT_SUBOBJECT:
8411 default:
8412 assert ("COMMON where unheard of" == NULL);
8413 /* Fall through. */
8414 case FFEINFO_whereANY:
8415 t = error_mark_node;
8416 break;
8417 }
8418 break;
5ff904cd 8419
c7e4ee3a
CB
8420 case FFEINFO_kindCONSTRUCT:
8421 switch (ffeinfo_where (ffesymbol_info (s)))
8422 {
8423 case FFEINFO_whereLOCAL:
8424 assert (!ffecom_transform_only_dummies_);
8425 break;
5ff904cd 8426
c7e4ee3a
CB
8427 case FFEINFO_whereNONE:
8428 case FFEINFO_whereCOMMON:
8429 case FFEINFO_whereDUMMY:
8430 case FFEINFO_whereGLOBAL:
8431 case FFEINFO_whereRESULT:
8432 case FFEINFO_whereFLEETING:
8433 case FFEINFO_whereFLEETING_CADDR:
8434 case FFEINFO_whereFLEETING_IADDR:
8435 case FFEINFO_whereIMMEDIATE:
8436 case FFEINFO_whereINTRINSIC:
8437 case FFEINFO_whereCONSTANT:
8438 case FFEINFO_whereCONSTANT_SUBOBJECT:
8439 default:
8440 assert ("CONSTRUCT where unheard of" == NULL);
8441 /* Fall through. */
8442 case FFEINFO_whereANY:
8443 t = error_mark_node;
8444 break;
8445 }
8446 break;
5ff904cd 8447
c7e4ee3a
CB
8448 case FFEINFO_kindNAMELIST:
8449 switch (ffeinfo_where (ffesymbol_info (s)))
8450 {
8451 case FFEINFO_whereLOCAL:
8452 assert (!ffecom_transform_only_dummies_);
8453 t = ffecom_transform_namelist_ (s);
8454 break;
5ff904cd 8455
c7e4ee3a
CB
8456 case FFEINFO_whereNONE:
8457 case FFEINFO_whereCOMMON:
8458 case FFEINFO_whereDUMMY:
8459 case FFEINFO_whereGLOBAL:
8460 case FFEINFO_whereRESULT:
8461 case FFEINFO_whereFLEETING:
8462 case FFEINFO_whereFLEETING_CADDR:
8463 case FFEINFO_whereFLEETING_IADDR:
8464 case FFEINFO_whereIMMEDIATE:
8465 case FFEINFO_whereINTRINSIC:
8466 case FFEINFO_whereCONSTANT:
8467 case FFEINFO_whereCONSTANT_SUBOBJECT:
8468 default:
8469 assert ("NAMELIST where unheard of" == NULL);
8470 /* Fall through. */
8471 case FFEINFO_whereANY:
8472 t = error_mark_node;
8473 break;
8474 }
8475 break;
5ff904cd 8476
c7e4ee3a
CB
8477 default:
8478 assert ("kind unheard of" == NULL);
8479 /* Fall through. */
8480 case FFEINFO_kindANY:
8481 t = error_mark_node;
8482 break;
8483 }
5ff904cd 8484
c7e4ee3a
CB
8485 ffesymbol_hook (s).decl_tree = t;
8486 ffesymbol_hook (s).length_tree = tlen;
8487 ffesymbol_hook (s).addr = addr;
5ff904cd 8488
c7e4ee3a
CB
8489 lineno = old_lineno;
8490 input_filename = old_input_filename;
5ff904cd 8491
c7e4ee3a
CB
8492 return s;
8493}
5ff904cd 8494
5ff904cd 8495#endif
c7e4ee3a 8496/* Transform into ASSIGNable symbol.
5ff904cd 8497
c7e4ee3a
CB
8498 Symbol has already been transformed, but for whatever reason, the
8499 resulting decl_tree has been deemed not usable for an ASSIGN target.
8500 (E.g. it isn't wide enough to hold a pointer.) So, here we invent
8501 another local symbol of type void * and stuff that in the assign_tree
8502 argument. The F77/F90 standards allow this implementation. */
5ff904cd 8503
c7e4ee3a
CB
8504#if FFECOM_targetCURRENT == FFECOM_targetGCC
8505static ffesymbol
8506ffecom_sym_transform_assign_ (ffesymbol s)
8507{
8508 tree t; /* Transformed thingy. */
c7e4ee3a 8509 int old_lineno = lineno;
3b304f5b 8510 const char *old_input_filename = input_filename;
5ff904cd 8511
c7e4ee3a
CB
8512 if (ffesymbol_sfdummyparent (s) == NULL)
8513 {
8514 input_filename = ffesymbol_where_filename (s);
8515 lineno = ffesymbol_where_filelinenum (s);
8516 }
8517 else
8518 {
8519 ffesymbol sf = ffesymbol_sfdummyparent (s);
5ff904cd 8520
c7e4ee3a
CB
8521 input_filename = ffesymbol_where_filename (sf);
8522 lineno = ffesymbol_where_filelinenum (sf);
8523 }
5ff904cd 8524
c7e4ee3a 8525 assert (!ffecom_transform_only_dummies_);
5ff904cd 8526
c7e4ee3a
CB
8527 t = build_decl (VAR_DECL,
8528 ffecom_get_invented_identifier ("__g77_ASSIGN_%s",
14657de8 8529 ffesymbol_text (s)),
c7e4ee3a 8530 TREE_TYPE (null_pointer_node));
5ff904cd 8531
c7e4ee3a
CB
8532 switch (ffesymbol_where (s))
8533 {
8534 case FFEINFO_whereLOCAL:
8535 /* Unlike for regular vars, SAVE status is easy to determine for
8536 ASSIGNed vars, since there's no initialization, there's no
8537 effective storage association (so "SAVE J" does not apply to
8538 K even given "EQUIVALENCE (J,K)"), there's no size issue
8539 to worry about, etc. */
8540 if ((ffesymbol_is_save (s) || ffe_is_saveall ())
8541 && (ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
8542 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA))
8543 TREE_STATIC (t) = 1; /* SAVEd in proc, make static. */
8544 else
8545 TREE_STATIC (t) = 0; /* No need to make static. */
8546 break;
5ff904cd 8547
c7e4ee3a
CB
8548 case FFEINFO_whereCOMMON:
8549 TREE_STATIC (t) = 1; /* Assume COMMONs always SAVEd. */
8550 break;
5ff904cd 8551
c7e4ee3a
CB
8552 case FFEINFO_whereDUMMY:
8553 /* Note that twinning a DUMMY means the caller won't see
8554 the ASSIGNed value. But both F77 and F90 allow implementations
8555 to do this, i.e. disallow Fortran code that would try and
8556 take advantage of actually putting a label into a variable
8557 via a dummy argument (or any other storage association, for
8558 that matter). */
8559 TREE_STATIC (t) = 0;
8560 break;
5ff904cd 8561
c7e4ee3a
CB
8562 default:
8563 TREE_STATIC (t) = 0;
8564 break;
8565 }
5ff904cd 8566
c7e4ee3a
CB
8567 t = start_decl (t, FALSE);
8568 finish_decl (t, NULL_TREE, FALSE);
5ff904cd 8569
c7e4ee3a 8570 ffesymbol_hook (s).assign_tree = t;
5ff904cd 8571
c7e4ee3a
CB
8572 lineno = old_lineno;
8573 input_filename = old_input_filename;
5ff904cd 8574
c7e4ee3a
CB
8575 return s;
8576}
5ff904cd 8577
c7e4ee3a
CB
8578#endif
8579/* Implement COMMON area in back end.
5ff904cd 8580
c7e4ee3a
CB
8581 Because COMMON-based variables can be referenced in the dimension
8582 expressions of dummy (adjustable) arrays, and because dummies
8583 (in the gcc back end) need to be put in the outer binding level
8584 of a function (which has two binding levels, the outer holding
8585 the dummies and the inner holding the other vars), special care
8586 must be taken to handle COMMON areas.
5ff904cd 8587
c7e4ee3a
CB
8588 The current strategy is basically to always tell the back end about
8589 the COMMON area as a top-level external reference to just a block
8590 of storage of the master type of that area (e.g. integer, real,
8591 character, whatever -- not a structure). As a distinct action,
8592 if initial values are provided, tell the back end about the area
8593 as a top-level non-external (initialized) area and remember not to
8594 allow further initialization or expansion of the area. Meanwhile,
8595 if no initialization happens at all, tell the back end about
8596 the largest size we've seen declared so the space does get reserved.
8597 (This function doesn't handle all that stuff, but it does some
8598 of the important things.)
5ff904cd 8599
c7e4ee3a
CB
8600 Meanwhile, for COMMON variables themselves, just keep creating
8601 references like *((float *) (&common_area + offset)) each time
8602 we reference the variable. In other words, don't make a VAR_DECL
8603 or any kind of component reference (like we used to do before 0.4),
8604 though we might do that as well just for debugging purposes (and
8605 stuff the rtl with the appropriate offset expression). */
5ff904cd 8606
c7e4ee3a
CB
8607#if FFECOM_targetCURRENT == FFECOM_targetGCC
8608static void
8609ffecom_transform_common_ (ffesymbol s)
8610{
8611 ffestorag st = ffesymbol_storage (s);
8612 ffeglobal g = ffesymbol_global (s);
8613 tree cbt;
8614 tree cbtype;
8615 tree init;
8616 tree high;
8617 bool is_init = ffestorag_is_init (st);
5ff904cd 8618
c7e4ee3a 8619 assert (st != NULL);
5ff904cd 8620
c7e4ee3a
CB
8621 if ((g == NULL)
8622 || (ffeglobal_type (g) != FFEGLOBAL_typeCOMMON))
8623 return;
5ff904cd 8624
c7e4ee3a 8625 /* First update the size of the area in global terms. */
5ff904cd 8626
c7e4ee3a 8627 ffeglobal_size_common (s, ffestorag_size (st));
5ff904cd 8628
c7e4ee3a
CB
8629 if (!ffeglobal_common_init (g))
8630 is_init = FALSE; /* No explicit init, don't let erroneous joins init. */
5ff904cd 8631
c7e4ee3a 8632 cbt = ffeglobal_hook (g);
5ff904cd 8633
c7e4ee3a
CB
8634 /* If we already have declared this common block for a previous program
8635 unit, and either we already initialized it or we don't have new
8636 initialization for it, just return what we have without changing it. */
5ff904cd 8637
c7e4ee3a
CB
8638 if ((cbt != NULL_TREE)
8639 && (!is_init
8640 || !DECL_EXTERNAL (cbt)))
b7a80862
AV
8641 {
8642 if (st->hook == NULL) ffestorag_set_hook (st, cbt);
8643 return;
8644 }
5ff904cd 8645
c7e4ee3a 8646 /* Process inits. */
5ff904cd 8647
c7e4ee3a
CB
8648 if (is_init)
8649 {
8650 if (ffestorag_init (st) != NULL)
5ff904cd 8651 {
c7e4ee3a 8652 ffebld sexp;
5ff904cd 8653
c7e4ee3a
CB
8654 /* Set the padding for the expression, so ffecom_expr
8655 knows to insert that many zeros. */
8656 switch (ffebld_op (sexp = ffestorag_init (st)))
5ff904cd 8657 {
c7e4ee3a
CB
8658 case FFEBLD_opCONTER:
8659 ffebld_conter_set_pad (sexp, ffestorag_modulo (st));
5ff904cd 8660 break;
5ff904cd 8661
c7e4ee3a
CB
8662 case FFEBLD_opARRTER:
8663 ffebld_arrter_set_pad (sexp, ffestorag_modulo (st));
8664 break;
5ff904cd 8665
c7e4ee3a
CB
8666 case FFEBLD_opACCTER:
8667 ffebld_accter_set_pad (sexp, ffestorag_modulo (st));
8668 break;
5ff904cd 8669
c7e4ee3a
CB
8670 default:
8671 assert ("bad op for cmn init (pad)" == NULL);
8672 break;
8673 }
5ff904cd 8674
c7e4ee3a
CB
8675 init = ffecom_expr (sexp);
8676 if (init == error_mark_node)
8677 { /* Hopefully the back end complained! */
8678 init = NULL_TREE;
8679 if (cbt != NULL_TREE)
8680 return;
8681 }
8682 }
8683 else
8684 init = error_mark_node;
8685 }
8686 else
8687 init = NULL_TREE;
5ff904cd 8688
c7e4ee3a 8689 /* cbtype must be permanently allocated! */
5ff904cd 8690
c7e4ee3a
CB
8691 /* Allocate the MAX of the areas so far, seen filewide. */
8692 high = build_int_2 ((ffeglobal_common_size (g)
8693 + ffeglobal_common_pad (g)) - 1, 0);
8694 TREE_TYPE (high) = ffecom_integer_type_node;
5ff904cd 8695
c7e4ee3a
CB
8696 if (init)
8697 cbtype = build_array_type (char_type_node,
8698 build_range_type (integer_type_node,
8699 integer_zero_node,
8700 high));
8701 else
8702 cbtype = build_array_type (char_type_node, NULL_TREE);
5ff904cd 8703
c7e4ee3a
CB
8704 if (cbt == NULL_TREE)
8705 {
8706 cbt
8707 = build_decl (VAR_DECL,
8708 ffecom_get_external_identifier_ (s),
8709 cbtype);
8710 TREE_STATIC (cbt) = 1;
8711 TREE_PUBLIC (cbt) = 1;
8712 }
8713 else
8714 {
8715 assert (is_init);
8716 TREE_TYPE (cbt) = cbtype;
8717 }
8718 DECL_EXTERNAL (cbt) = init ? 0 : 1;
8719 DECL_INITIAL (cbt) = init ? error_mark_node : NULL_TREE;
5ff904cd 8720
c7e4ee3a
CB
8721 cbt = start_decl (cbt, TRUE);
8722 if (ffeglobal_hook (g) != NULL)
8723 assert (cbt == ffeglobal_hook (g));
5ff904cd 8724
c7e4ee3a 8725 assert (!init || !DECL_EXTERNAL (cbt));
5ff904cd 8726
c7e4ee3a
CB
8727 /* Make sure that any type can live in COMMON and be referenced
8728 without getting a bus error. We could pick the most restrictive
8729 alignment of all entities actually placed in the COMMON, but
8730 this seems easy enough. */
5ff904cd 8731
c7e4ee3a 8732 DECL_ALIGN (cbt) = BIGGEST_ALIGNMENT;
11cf4d18 8733 DECL_USER_ALIGN (cbt) = 0;
5ff904cd 8734
c7e4ee3a
CB
8735 if (is_init && (ffestorag_init (st) == NULL))
8736 init = ffecom_init_zero_ (cbt);
5ff904cd 8737
c7e4ee3a 8738 finish_decl (cbt, init, TRUE);
5ff904cd 8739
c7e4ee3a
CB
8740 if (is_init)
8741 ffestorag_set_init (st, ffebld_new_any ());
5ff904cd 8742
c7e4ee3a
CB
8743 if (init)
8744 {
06ceef4e
RK
8745 assert (DECL_SIZE_UNIT (cbt) != NULL_TREE);
8746 assert (TREE_CODE (DECL_SIZE_UNIT (cbt)) == INTEGER_CST);
05bccae2
RK
8747 assert (0 == compare_tree_int (DECL_SIZE_UNIT (cbt),
8748 (ffeglobal_common_size (g)
8749 + ffeglobal_common_pad (g))));
c7e4ee3a 8750 }
5ff904cd 8751
c7e4ee3a 8752 ffeglobal_set_hook (g, cbt);
5ff904cd 8753
c7e4ee3a 8754 ffestorag_set_hook (st, cbt);
5ff904cd 8755
7189a4b0 8756 ffecom_save_tree_forever (cbt);
c7e4ee3a 8757}
5ff904cd 8758
c7e4ee3a
CB
8759#endif
8760/* Make master area for local EQUIVALENCE. */
5ff904cd 8761
c7e4ee3a
CB
8762#if FFECOM_targetCURRENT == FFECOM_targetGCC
8763static void
8764ffecom_transform_equiv_ (ffestorag eqst)
8765{
8766 tree eqt;
8767 tree eqtype;
8768 tree init;
8769 tree high;
8770 bool is_init = ffestorag_is_init (eqst);
5ff904cd 8771
c7e4ee3a 8772 assert (eqst != NULL);
5ff904cd 8773
c7e4ee3a 8774 eqt = ffestorag_hook (eqst);
5ff904cd 8775
c7e4ee3a
CB
8776 if (eqt != NULL_TREE)
8777 return;
5ff904cd 8778
c7e4ee3a
CB
8779 /* Process inits. */
8780
8781 if (is_init)
8782 {
8783 if (ffestorag_init (eqst) != NULL)
5ff904cd 8784 {
c7e4ee3a 8785 ffebld sexp;
5ff904cd 8786
c7e4ee3a
CB
8787 /* Set the padding for the expression, so ffecom_expr
8788 knows to insert that many zeros. */
8789 switch (ffebld_op (sexp = ffestorag_init (eqst)))
8790 {
8791 case FFEBLD_opCONTER:
8792 ffebld_conter_set_pad (sexp, ffestorag_modulo (eqst));
8793 break;
5ff904cd 8794
c7e4ee3a
CB
8795 case FFEBLD_opARRTER:
8796 ffebld_arrter_set_pad (sexp, ffestorag_modulo (eqst));
8797 break;
5ff904cd 8798
c7e4ee3a
CB
8799 case FFEBLD_opACCTER:
8800 ffebld_accter_set_pad (sexp, ffestorag_modulo (eqst));
8801 break;
5ff904cd 8802
c7e4ee3a
CB
8803 default:
8804 assert ("bad op for eqv init (pad)" == NULL);
8805 break;
8806 }
5ff904cd 8807
c7e4ee3a
CB
8808 init = ffecom_expr (sexp);
8809 if (init == error_mark_node)
8810 init = NULL_TREE; /* Hopefully the back end complained! */
8811 }
8812 else
8813 init = error_mark_node;
8814 }
8815 else if (ffe_is_init_local_zero ())
8816 init = error_mark_node;
8817 else
8818 init = NULL_TREE;
5ff904cd 8819
c7e4ee3a
CB
8820 ffecom_member_namelisted_ = FALSE;
8821 ffestorag_drive (ffestorag_list_equivs (eqst),
8822 &ffecom_member_phase1_,
8823 eqst);
5ff904cd 8824
c7e4ee3a
CB
8825 high = build_int_2 ((ffestorag_size (eqst)
8826 + ffestorag_modulo (eqst)) - 1, 0);
8827 TREE_TYPE (high) = ffecom_integer_type_node;
5ff904cd 8828
c7e4ee3a
CB
8829 eqtype = build_array_type (char_type_node,
8830 build_range_type (ffecom_integer_type_node,
8831 ffecom_integer_zero_node,
8832 high));
8833
8834 eqt = build_decl (VAR_DECL,
8835 ffecom_get_invented_identifier ("__g77_equiv_%s",
8836 ffesymbol_text
14657de8 8837 (ffestorag_symbol (eqst))),
c7e4ee3a
CB
8838 eqtype);
8839 DECL_EXTERNAL (eqt) = 0;
8840 if (is_init
8841 || ffecom_member_namelisted_
8842#ifdef FFECOM_sizeMAXSTACKITEM
8843 || (ffestorag_size (eqst) > FFECOM_sizeMAXSTACKITEM)
8844#endif
8845 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
8846 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
8847 && (ffestorag_is_save (eqst) || ffe_is_saveall ())))
8848 TREE_STATIC (eqt) = 1;
8849 else
8850 TREE_STATIC (eqt) = 0;
8851 TREE_PUBLIC (eqt) = 0;
a8e2bb76 8852 TREE_ADDRESSABLE (eqt) = 1; /* Ensure non-register allocation */
c7e4ee3a
CB
8853 DECL_CONTEXT (eqt) = current_function_decl;
8854 if (init)
8855 DECL_INITIAL (eqt) = error_mark_node;
8856 else
8857 DECL_INITIAL (eqt) = NULL_TREE;
5ff904cd 8858
c7e4ee3a 8859 eqt = start_decl (eqt, FALSE);
5ff904cd 8860
c7e4ee3a
CB
8861 /* Make sure that any type can live in EQUIVALENCE and be referenced
8862 without getting a bus error. We could pick the most restrictive
8863 alignment of all entities actually placed in the EQUIVALENCE, but
8864 this seems easy enough. */
5ff904cd 8865
c7e4ee3a 8866 DECL_ALIGN (eqt) = BIGGEST_ALIGNMENT;
11cf4d18 8867 DECL_USER_ALIGN (eqt) = 0;
5ff904cd 8868
c7e4ee3a
CB
8869 if ((!is_init && ffe_is_init_local_zero ())
8870 || (is_init && (ffestorag_init (eqst) == NULL)))
8871 init = ffecom_init_zero_ (eqt);
5ff904cd 8872
c7e4ee3a 8873 finish_decl (eqt, init, FALSE);
5ff904cd 8874
c7e4ee3a
CB
8875 if (is_init)
8876 ffestorag_set_init (eqst, ffebld_new_any ());
5ff904cd 8877
c7e4ee3a 8878 {
06ceef4e 8879 assert (TREE_CODE (DECL_SIZE_UNIT (eqt)) == INTEGER_CST);
05bccae2
RK
8880 assert (0 == compare_tree_int (DECL_SIZE_UNIT (eqt),
8881 (ffestorag_size (eqst)
8882 + ffestorag_modulo (eqst))));
c7e4ee3a 8883 }
5ff904cd 8884
c7e4ee3a 8885 ffestorag_set_hook (eqst, eqt);
5ff904cd 8886
c7e4ee3a
CB
8887 ffestorag_drive (ffestorag_list_equivs (eqst),
8888 &ffecom_member_phase2_,
8889 eqst);
5ff904cd
JL
8890}
8891
8892#endif
c7e4ee3a 8893/* Implement NAMELIST in back end. See f2c/format.c for more info. */
5ff904cd
JL
8894
8895#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
8896static tree
8897ffecom_transform_namelist_ (ffesymbol s)
5ff904cd 8898{
c7e4ee3a
CB
8899 tree nmlt;
8900 tree nmltype = ffecom_type_namelist_ ();
8901 tree nmlinits;
8902 tree nameinit;
8903 tree varsinit;
8904 tree nvarsinit;
8905 tree field;
8906 tree high;
c7e4ee3a
CB
8907 int i;
8908 static int mynumber = 0;
5ff904cd 8909
c7e4ee3a
CB
8910 nmlt = build_decl (VAR_DECL,
8911 ffecom_get_invented_identifier ("__g77_namelist_%d",
14657de8 8912 mynumber++),
c7e4ee3a
CB
8913 nmltype);
8914 TREE_STATIC (nmlt) = 1;
8915 DECL_INITIAL (nmlt) = error_mark_node;
5ff904cd 8916
c7e4ee3a 8917 nmlt = start_decl (nmlt, FALSE);
5ff904cd 8918
c7e4ee3a 8919 /* Process inits. */
5ff904cd 8920
c7e4ee3a 8921 i = strlen (ffesymbol_text (s));
5ff904cd 8922
c7e4ee3a
CB
8923 high = build_int_2 (i, 0);
8924 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
8925
8926 nameinit = ffecom_build_f2c_string_ (i + 1,
8927 ffesymbol_text (s));
8928 TREE_TYPE (nameinit)
8929 = build_type_variant
8930 (build_array_type
8931 (char_type_node,
8932 build_range_type (ffecom_f2c_ftnlen_type_node,
8933 ffecom_f2c_ftnlen_one_node,
8934 high)),
8935 1, 0);
8936 TREE_CONSTANT (nameinit) = 1;
8937 TREE_STATIC (nameinit) = 1;
8938 nameinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (nameinit)),
8939 nameinit);
8940
8941 varsinit = ffecom_vardesc_array_ (s);
8942 varsinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (varsinit)),
8943 varsinit);
8944 TREE_CONSTANT (varsinit) = 1;
8945 TREE_STATIC (varsinit) = 1;
8946
8947 {
8948 ffebld b;
8949
8950 for (i = 0, b = ffesymbol_namelist (s); b != NULL; b = ffebld_trail (b))
8951 ++i;
8952 }
8953 nvarsinit = build_int_2 (i, 0);
8954 TREE_TYPE (nvarsinit) = integer_type_node;
8955 TREE_CONSTANT (nvarsinit) = 1;
8956 TREE_STATIC (nvarsinit) = 1;
8957
8958 nmlinits = build_tree_list ((field = TYPE_FIELDS (nmltype)), nameinit);
8959 TREE_CHAIN (nmlinits) = build_tree_list ((field = TREE_CHAIN (field)),
8960 varsinit);
8961 TREE_CHAIN (TREE_CHAIN (nmlinits))
8962 = build_tree_list ((field = TREE_CHAIN (field)), nvarsinit);
8963
8964 nmlinits = build (CONSTRUCTOR, nmltype, NULL_TREE, nmlinits);
8965 TREE_CONSTANT (nmlinits) = 1;
8966 TREE_STATIC (nmlinits) = 1;
8967
8968 finish_decl (nmlt, nmlinits, FALSE);
8969
8970 nmlt = ffecom_1 (ADDR_EXPR, build_pointer_type (nmltype), nmlt);
8971
c7e4ee3a
CB
8972 return nmlt;
8973}
8974
8975#endif
8976
8977/* A subroutine of ffecom_tree_canonize_ref_. The incoming tree is
8978 analyzed on the assumption it is calculating a pointer to be
8979 indirected through. It must return the proper decl and offset,
8980 taking into account different units of measurements for offsets. */
8981
8982#if FFECOM_targetCURRENT == FFECOM_targetGCC
8983static void
8984ffecom_tree_canonize_ptr_ (tree *decl, tree *offset,
8985 tree t)
8986{
8987 switch (TREE_CODE (t))
8988 {
8989 case NOP_EXPR:
8990 case CONVERT_EXPR:
8991 case NON_LVALUE_EXPR:
8992 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
5ff904cd
JL
8993 break;
8994
c7e4ee3a
CB
8995 case PLUS_EXPR:
8996 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
8997 if ((*decl == NULL_TREE)
8998 || (*decl == error_mark_node))
8999 break;
9000
9001 if (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST)
9002 {
9003 /* An offset into COMMON. */
fed3cef0
RK
9004 *offset = fold (build (PLUS_EXPR, TREE_TYPE (*offset),
9005 *offset, TREE_OPERAND (t, 1)));
c7e4ee3a
CB
9006 /* Convert offset (presumably in bytes) into canonical units
9007 (presumably bits). */
76fa6b3b
ZW
9008 *offset = size_binop (MULT_EXPR,
9009 convert (bitsizetype, *offset),
9010 TYPE_SIZE (TREE_TYPE (TREE_TYPE (t))));
c7e4ee3a
CB
9011 break;
9012 }
9013 /* Not a COMMON reference, so an unrecognized pattern. */
9014 *decl = error_mark_node;
5ff904cd
JL
9015 break;
9016
c7e4ee3a
CB
9017 case PARM_DECL:
9018 *decl = t;
770ae6cc 9019 *offset = bitsize_zero_node;
5ff904cd
JL
9020 break;
9021
c7e4ee3a
CB
9022 case ADDR_EXPR:
9023 if (TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL)
9024 {
9025 /* A reference to COMMON. */
9026 *decl = TREE_OPERAND (t, 0);
770ae6cc 9027 *offset = bitsize_zero_node;
c7e4ee3a
CB
9028 break;
9029 }
9030 /* Fall through. */
5ff904cd 9031 default:
c7e4ee3a
CB
9032 /* Not a COMMON reference, so an unrecognized pattern. */
9033 *decl = error_mark_node;
5ff904cd
JL
9034 break;
9035 }
c7e4ee3a
CB
9036}
9037#endif
5ff904cd 9038
c7e4ee3a
CB
9039/* Given a tree that is possibly intended for use as an lvalue, return
9040 information representing a canonical view of that tree as a decl, an
9041 offset into that decl, and a size for the lvalue.
5ff904cd 9042
c7e4ee3a
CB
9043 If there's no applicable decl, NULL_TREE is returned for the decl,
9044 and the other fields are left undefined.
5ff904cd 9045
c7e4ee3a
CB
9046 If the tree doesn't fit the recognizable forms, an ERROR_MARK node
9047 is returned for the decl, and the other fields are left undefined.
5ff904cd 9048
c7e4ee3a
CB
9049 Otherwise, the decl returned currently is either a VAR_DECL or a
9050 PARM_DECL.
5ff904cd 9051
c7e4ee3a
CB
9052 The offset returned is always valid, but of course not necessarily
9053 a constant, and not necessarily converted into the appropriate
9054 type, leaving that up to the caller (so as to avoid that overhead
9055 if the decls being looked at are different anyway).
5ff904cd 9056
c7e4ee3a
CB
9057 If the size cannot be determined (e.g. an adjustable array),
9058 an ERROR_MARK node is returned for the size. Otherwise, the
9059 size returned is valid, not necessarily a constant, and not
9060 necessarily converted into the appropriate type as with the
9061 offset.
5ff904cd 9062
c7e4ee3a
CB
9063 Note that the offset and size expressions are expressed in the
9064 base storage units (usually bits) rather than in the units of
9065 the type of the decl, because two decls with different types
9066 might overlap but with apparently non-overlapping array offsets,
9067 whereas converting the array offsets to consistant offsets will
9068 reveal the overlap. */
5ff904cd
JL
9069
9070#if FFECOM_targetCURRENT == FFECOM_targetGCC
9071static void
c7e4ee3a
CB
9072ffecom_tree_canonize_ref_ (tree *decl, tree *offset,
9073 tree *size, tree t)
5ff904cd 9074{
c7e4ee3a
CB
9075 /* The default path is to report a nonexistant decl. */
9076 *decl = NULL_TREE;
5ff904cd 9077
c7e4ee3a 9078 if (t == NULL_TREE)
5ff904cd
JL
9079 return;
9080
c7e4ee3a
CB
9081 switch (TREE_CODE (t))
9082 {
9083 case ERROR_MARK:
9084 case IDENTIFIER_NODE:
9085 case INTEGER_CST:
9086 case REAL_CST:
9087 case COMPLEX_CST:
9088 case STRING_CST:
9089 case CONST_DECL:
9090 case PLUS_EXPR:
9091 case MINUS_EXPR:
9092 case MULT_EXPR:
9093 case TRUNC_DIV_EXPR:
9094 case CEIL_DIV_EXPR:
9095 case FLOOR_DIV_EXPR:
9096 case ROUND_DIV_EXPR:
9097 case TRUNC_MOD_EXPR:
9098 case CEIL_MOD_EXPR:
9099 case FLOOR_MOD_EXPR:
9100 case ROUND_MOD_EXPR:
9101 case RDIV_EXPR:
9102 case EXACT_DIV_EXPR:
9103 case FIX_TRUNC_EXPR:
9104 case FIX_CEIL_EXPR:
9105 case FIX_FLOOR_EXPR:
9106 case FIX_ROUND_EXPR:
9107 case FLOAT_EXPR:
9108 case EXPON_EXPR:
9109 case NEGATE_EXPR:
9110 case MIN_EXPR:
9111 case MAX_EXPR:
9112 case ABS_EXPR:
9113 case FFS_EXPR:
9114 case LSHIFT_EXPR:
9115 case RSHIFT_EXPR:
9116 case LROTATE_EXPR:
9117 case RROTATE_EXPR:
9118 case BIT_IOR_EXPR:
9119 case BIT_XOR_EXPR:
9120 case BIT_AND_EXPR:
9121 case BIT_ANDTC_EXPR:
9122 case BIT_NOT_EXPR:
9123 case TRUTH_ANDIF_EXPR:
9124 case TRUTH_ORIF_EXPR:
9125 case TRUTH_AND_EXPR:
9126 case TRUTH_OR_EXPR:
9127 case TRUTH_XOR_EXPR:
9128 case TRUTH_NOT_EXPR:
9129 case LT_EXPR:
9130 case LE_EXPR:
9131 case GT_EXPR:
9132 case GE_EXPR:
9133 case EQ_EXPR:
9134 case NE_EXPR:
9135 case COMPLEX_EXPR:
9136 case CONJ_EXPR:
9137 case REALPART_EXPR:
9138 case IMAGPART_EXPR:
9139 case LABEL_EXPR:
9140 case COMPONENT_REF:
9141 case COMPOUND_EXPR:
9142 case ADDR_EXPR:
9143 return;
5ff904cd 9144
c7e4ee3a
CB
9145 case VAR_DECL:
9146 case PARM_DECL:
9147 *decl = t;
770ae6cc 9148 *offset = bitsize_zero_node;
c7e4ee3a
CB
9149 *size = TYPE_SIZE (TREE_TYPE (t));
9150 return;
5ff904cd 9151
c7e4ee3a
CB
9152 case ARRAY_REF:
9153 {
9154 tree array = TREE_OPERAND (t, 0);
9155 tree element = TREE_OPERAND (t, 1);
9156 tree init_offset;
9157
9158 if ((array == NULL_TREE)
9159 || (element == NULL_TREE))
9160 {
9161 *decl = error_mark_node;
9162 return;
9163 }
9164
9165 ffecom_tree_canonize_ref_ (decl, &init_offset, size,
9166 array);
9167 if ((*decl == NULL_TREE)
9168 || (*decl == error_mark_node))
9169 return;
9170
76fa6b3b
ZW
9171 /* Calculate ((element - base) * NBBY) + init_offset. */
9172 *offset = fold (build (MINUS_EXPR, TREE_TYPE (element),
9173 element,
9174 TYPE_MIN_VALUE (TYPE_DOMAIN
9175 (TREE_TYPE (array)))));
9176
9177 *offset = size_binop (MULT_EXPR,
9178 convert (bitsizetype, *offset),
9179 TYPE_SIZE (TREE_TYPE (TREE_TYPE (array))));
9180
9181 *offset = size_binop (PLUS_EXPR, init_offset, *offset);
c7e4ee3a
CB
9182
9183 *size = TYPE_SIZE (TREE_TYPE (t));
9184 return;
9185 }
9186
9187 case INDIRECT_REF:
9188
9189 /* Most of this code is to handle references to COMMON. And so
9190 far that is useful only for calling library functions, since
9191 external (user) functions might reference common areas. But
9192 even calling an external function, it's worthwhile to decode
9193 COMMON references because if not storing into COMMON, we don't
9194 want COMMON-based arguments to gratuitously force use of a
9195 temporary. */
9196
9197 *size = TYPE_SIZE (TREE_TYPE (t));
5ff904cd 9198
c7e4ee3a
CB
9199 ffecom_tree_canonize_ptr_ (decl, offset,
9200 TREE_OPERAND (t, 0));
5ff904cd 9201
c7e4ee3a 9202 return;
5ff904cd 9203
c7e4ee3a
CB
9204 case CONVERT_EXPR:
9205 case NOP_EXPR:
9206 case MODIFY_EXPR:
9207 case NON_LVALUE_EXPR:
9208 case RESULT_DECL:
9209 case FIELD_DECL:
9210 case COND_EXPR: /* More cases than we can handle. */
9211 case SAVE_EXPR:
9212 case REFERENCE_EXPR:
9213 case PREDECREMENT_EXPR:
9214 case PREINCREMENT_EXPR:
9215 case POSTDECREMENT_EXPR:
9216 case POSTINCREMENT_EXPR:
9217 case CALL_EXPR:
9218 default:
9219 *decl = error_mark_node;
9220 return;
9221 }
9222}
9223#endif
5ff904cd 9224
c7e4ee3a 9225/* Do divide operation appropriate to type of operands. */
5ff904cd 9226
c7e4ee3a
CB
9227#if FFECOM_targetCURRENT == FFECOM_targetGCC
9228static tree
9229ffecom_tree_divide_ (tree tree_type, tree left, tree right,
9230 tree dest_tree, ffebld dest, bool *dest_used,
9231 tree hook)
9232{
9233 if ((left == error_mark_node)
9234 || (right == error_mark_node))
9235 return error_mark_node;
a6fa6420 9236
c7e4ee3a
CB
9237 switch (TREE_CODE (tree_type))
9238 {
9239 case INTEGER_TYPE:
9240 return ffecom_2 (TRUNC_DIV_EXPR, tree_type,
9241 left,
9242 right);
a6fa6420 9243
c7e4ee3a 9244 case COMPLEX_TYPE:
c64f913e
CB
9245 if (! optimize_size)
9246 return ffecom_2 (RDIV_EXPR, tree_type,
9247 left,
9248 right);
c7e4ee3a
CB
9249 {
9250 ffecomGfrt ix;
a6fa6420 9251
c7e4ee3a
CB
9252 if (TREE_TYPE (tree_type)
9253 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9254 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */
9255 else
9256 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */
a6fa6420 9257
c7e4ee3a
CB
9258 left = ffecom_1 (ADDR_EXPR,
9259 build_pointer_type (TREE_TYPE (left)),
9260 left);
9261 left = build_tree_list (NULL_TREE, left);
9262 right = ffecom_1 (ADDR_EXPR,
9263 build_pointer_type (TREE_TYPE (right)),
9264 right);
9265 right = build_tree_list (NULL_TREE, right);
9266 TREE_CHAIN (left) = right;
a6fa6420 9267
c7e4ee3a
CB
9268 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9269 ffecom_gfrt_kindtype (ix),
9270 ffe_is_f2c_library (),
9271 tree_type,
9272 left,
9273 dest_tree, dest, dest_used,
9274 NULL_TREE, TRUE, hook);
9275 }
9276 break;
5ff904cd 9277
c7e4ee3a
CB
9278 case RECORD_TYPE:
9279 {
9280 ffecomGfrt ix;
5ff904cd 9281
c7e4ee3a
CB
9282 if (TREE_TYPE (TYPE_FIELDS (tree_type))
9283 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9284 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */
9285 else
9286 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */
5ff904cd 9287
c7e4ee3a
CB
9288 left = ffecom_1 (ADDR_EXPR,
9289 build_pointer_type (TREE_TYPE (left)),
9290 left);
9291 left = build_tree_list (NULL_TREE, left);
9292 right = ffecom_1 (ADDR_EXPR,
9293 build_pointer_type (TREE_TYPE (right)),
9294 right);
9295 right = build_tree_list (NULL_TREE, right);
9296 TREE_CHAIN (left) = right;
a6fa6420 9297
c7e4ee3a
CB
9298 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9299 ffecom_gfrt_kindtype (ix),
9300 ffe_is_f2c_library (),
9301 tree_type,
9302 left,
9303 dest_tree, dest, dest_used,
9304 NULL_TREE, TRUE, hook);
9305 }
9306 break;
5ff904cd 9307
c7e4ee3a
CB
9308 default:
9309 return ffecom_2 (RDIV_EXPR, tree_type,
9310 left,
9311 right);
5ff904cd 9312 }
c7e4ee3a 9313}
5ff904cd 9314
c7e4ee3a
CB
9315#endif
9316/* Build type info for non-dummy variable. */
5ff904cd 9317
c7e4ee3a
CB
9318#if FFECOM_targetCURRENT == FFECOM_targetGCC
9319static tree
9320ffecom_type_localvar_ (ffesymbol s, ffeinfoBasictype bt,
9321 ffeinfoKindtype kt)
9322{
9323 tree type;
9324 ffebld dl;
9325 ffebld dim;
9326 tree lowt;
9327 tree hight;
5ff904cd 9328
c7e4ee3a
CB
9329 type = ffecom_tree_type[bt][kt];
9330 if (bt == FFEINFO_basictypeCHARACTER)
9331 {
9332 hight = build_int_2 (ffesymbol_size (s), 0);
9333 TREE_TYPE (hight) = ffecom_f2c_ftnlen_type_node;
5ff904cd 9334
c7e4ee3a
CB
9335 type
9336 = build_array_type
9337 (type,
9338 build_range_type (ffecom_f2c_ftnlen_type_node,
9339 ffecom_f2c_ftnlen_one_node,
9340 hight));
9341 type = ffecom_check_size_overflow_ (s, type, FALSE);
9342 }
5ff904cd 9343
c7e4ee3a
CB
9344 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
9345 {
9346 if (type == error_mark_node)
9347 break;
5ff904cd 9348
c7e4ee3a
CB
9349 dim = ffebld_head (dl);
9350 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
5ff904cd 9351
c7e4ee3a
CB
9352 if (ffebld_left (dim) == NULL)
9353 lowt = integer_one_node;
9354 else
9355 lowt = ffecom_expr (ffebld_left (dim));
5ff904cd 9356
c7e4ee3a
CB
9357 if (TREE_CODE (lowt) != INTEGER_CST)
9358 lowt = variable_size (lowt);
5ff904cd 9359
c7e4ee3a
CB
9360 assert (ffebld_right (dim) != NULL);
9361 hight = ffecom_expr (ffebld_right (dim));
5ff904cd 9362
c7e4ee3a
CB
9363 if (TREE_CODE (hight) != INTEGER_CST)
9364 hight = variable_size (hight);
5ff904cd 9365
c7e4ee3a
CB
9366 type = build_array_type (type,
9367 build_range_type (ffecom_integer_type_node,
9368 lowt, hight));
9369 type = ffecom_check_size_overflow_ (s, type, FALSE);
9370 }
5ff904cd 9371
c7e4ee3a 9372 return type;
5ff904cd
JL
9373}
9374
9375#endif
c7e4ee3a 9376/* Build Namelist type. */
5ff904cd 9377
c7e4ee3a
CB
9378#if FFECOM_targetCURRENT == FFECOM_targetGCC
9379static tree
9380ffecom_type_namelist_ ()
9381{
9382 static tree type = NULL_TREE;
5ff904cd 9383
c7e4ee3a
CB
9384 if (type == NULL_TREE)
9385 {
9386 static tree namefield, varsfield, nvarsfield;
9387 tree vardesctype;
5ff904cd 9388
c7e4ee3a 9389 vardesctype = ffecom_type_vardesc_ ();
5ff904cd 9390
c7e4ee3a 9391 type = make_node (RECORD_TYPE);
a6fa6420 9392
c7e4ee3a 9393 vardesctype = build_pointer_type (build_pointer_type (vardesctype));
a6fa6420 9394
c7e4ee3a
CB
9395 namefield = ffecom_decl_field (type, NULL_TREE, "name",
9396 string_type_node);
9397 varsfield = ffecom_decl_field (type, namefield, "vars", vardesctype);
9398 nvarsfield = ffecom_decl_field (type, varsfield, "nvars",
9399 integer_type_node);
a6fa6420 9400
c7e4ee3a
CB
9401 TYPE_FIELDS (type) = namefield;
9402 layout_type (type);
a6fa6420 9403
7189a4b0 9404 ggc_add_tree_root (&type, 1);
5ff904cd 9405 }
5ff904cd 9406
c7e4ee3a
CB
9407 return type;
9408}
5ff904cd 9409
c7e4ee3a 9410#endif
5ff904cd 9411
c7e4ee3a 9412/* Build Vardesc type. */
5ff904cd 9413
c7e4ee3a
CB
9414#if FFECOM_targetCURRENT == FFECOM_targetGCC
9415static tree
9416ffecom_type_vardesc_ ()
9417{
9418 static tree type = NULL_TREE;
9419 static tree namefield, addrfield, dimsfield, typefield;
5ff904cd 9420
c7e4ee3a
CB
9421 if (type == NULL_TREE)
9422 {
c7e4ee3a 9423 type = make_node (RECORD_TYPE);
5ff904cd 9424
c7e4ee3a
CB
9425 namefield = ffecom_decl_field (type, NULL_TREE, "name",
9426 string_type_node);
9427 addrfield = ffecom_decl_field (type, namefield, "addr",
9428 string_type_node);
9429 dimsfield = ffecom_decl_field (type, addrfield, "dims",
9430 ffecom_f2c_ptr_to_ftnlen_type_node);
9431 typefield = ffecom_decl_field (type, dimsfield, "type",
9432 integer_type_node);
5ff904cd 9433
c7e4ee3a
CB
9434 TYPE_FIELDS (type) = namefield;
9435 layout_type (type);
9436
7189a4b0 9437 ggc_add_tree_root (&type, 1);
c7e4ee3a
CB
9438 }
9439
9440 return type;
5ff904cd
JL
9441}
9442
9443#endif
5ff904cd
JL
9444
9445#if FFECOM_targetCURRENT == FFECOM_targetGCC
9446static tree
c7e4ee3a 9447ffecom_vardesc_ (ffebld expr)
5ff904cd 9448{
c7e4ee3a 9449 ffesymbol s;
5ff904cd 9450
c7e4ee3a
CB
9451 assert (ffebld_op (expr) == FFEBLD_opSYMTER);
9452 s = ffebld_symter (expr);
5ff904cd 9453
c7e4ee3a
CB
9454 if (ffesymbol_hook (s).vardesc_tree == NULL_TREE)
9455 {
9456 int i;
9457 tree vardesctype = ffecom_type_vardesc_ ();
9458 tree var;
9459 tree nameinit;
9460 tree dimsinit;
9461 tree addrinit;
9462 tree typeinit;
9463 tree field;
9464 tree varinits;
c7e4ee3a 9465 static int mynumber = 0;
5ff904cd 9466
c7e4ee3a
CB
9467 var = build_decl (VAR_DECL,
9468 ffecom_get_invented_identifier ("__g77_vardesc_%d",
14657de8 9469 mynumber++),
c7e4ee3a
CB
9470 vardesctype);
9471 TREE_STATIC (var) = 1;
9472 DECL_INITIAL (var) = error_mark_node;
5ff904cd 9473
c7e4ee3a 9474 var = start_decl (var, FALSE);
5ff904cd 9475
c7e4ee3a 9476 /* Process inits. */
5ff904cd 9477
c7e4ee3a
CB
9478 nameinit = ffecom_build_f2c_string_ ((i = strlen (ffesymbol_text (s)))
9479 + 1,
9480 ffesymbol_text (s));
9481 TREE_TYPE (nameinit)
9482 = build_type_variant
9483 (build_array_type
9484 (char_type_node,
9485 build_range_type (integer_type_node,
9486 integer_one_node,
9487 build_int_2 (i, 0))),
9488 1, 0);
9489 TREE_CONSTANT (nameinit) = 1;
9490 TREE_STATIC (nameinit) = 1;
9491 nameinit = ffecom_1 (ADDR_EXPR,
9492 build_pointer_type (TREE_TYPE (nameinit)),
9493 nameinit);
5ff904cd 9494
c7e4ee3a 9495 addrinit = ffecom_arg_ptr_to_expr (expr, &typeinit);
5ff904cd 9496
c7e4ee3a 9497 dimsinit = ffecom_vardesc_dims_ (s);
5ff904cd 9498
c7e4ee3a
CB
9499 if (typeinit == NULL_TREE)
9500 {
9501 ffeinfoBasictype bt = ffesymbol_basictype (s);
9502 ffeinfoKindtype kt = ffesymbol_kindtype (s);
9503 int tc = ffecom_f2c_typecode (bt, kt);
5ff904cd 9504
c7e4ee3a
CB
9505 assert (tc != -1);
9506 typeinit = build_int_2 (tc, (tc < 0) ? -1 : 0);
9507 }
9508 else
9509 typeinit = ffecom_1 (NEGATE_EXPR, TREE_TYPE (typeinit), typeinit);
5ff904cd 9510
c7e4ee3a
CB
9511 varinits = build_tree_list ((field = TYPE_FIELDS (vardesctype)),
9512 nameinit);
9513 TREE_CHAIN (varinits) = build_tree_list ((field = TREE_CHAIN (field)),
9514 addrinit);
9515 TREE_CHAIN (TREE_CHAIN (varinits))
9516 = build_tree_list ((field = TREE_CHAIN (field)), dimsinit);
9517 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (varinits)))
9518 = build_tree_list ((field = TREE_CHAIN (field)), typeinit);
5ff904cd 9519
c7e4ee3a
CB
9520 varinits = build (CONSTRUCTOR, vardesctype, NULL_TREE, varinits);
9521 TREE_CONSTANT (varinits) = 1;
9522 TREE_STATIC (varinits) = 1;
5ff904cd 9523
c7e4ee3a 9524 finish_decl (var, varinits, FALSE);
5ff904cd 9525
c7e4ee3a 9526 var = ffecom_1 (ADDR_EXPR, build_pointer_type (vardesctype), var);
5ff904cd 9527
c7e4ee3a
CB
9528 ffesymbol_hook (s).vardesc_tree = var;
9529 }
5ff904cd 9530
c7e4ee3a
CB
9531 return ffesymbol_hook (s).vardesc_tree;
9532}
5ff904cd 9533
c7e4ee3a 9534#endif
5ff904cd 9535#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
9536static tree
9537ffecom_vardesc_array_ (ffesymbol s)
5ff904cd 9538{
c7e4ee3a
CB
9539 ffebld b;
9540 tree list;
9541 tree item = NULL_TREE;
9542 tree var;
9543 int i;
c7e4ee3a 9544 static int mynumber = 0;
5ff904cd 9545
c7e4ee3a
CB
9546 for (i = 0, list = NULL_TREE, b = ffesymbol_namelist (s);
9547 b != NULL;
9548 b = ffebld_trail (b), ++i)
9549 {
9550 tree t;
5ff904cd 9551
c7e4ee3a 9552 t = ffecom_vardesc_ (ffebld_head (b));
5ff904cd 9553
c7e4ee3a
CB
9554 if (list == NULL_TREE)
9555 list = item = build_tree_list (NULL_TREE, t);
9556 else
5ff904cd 9557 {
c7e4ee3a
CB
9558 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
9559 item = TREE_CHAIN (item);
5ff904cd 9560 }
5ff904cd 9561 }
5ff904cd 9562
c7e4ee3a
CB
9563 item = build_array_type (build_pointer_type (ffecom_type_vardesc_ ()),
9564 build_range_type (integer_type_node,
9565 integer_one_node,
9566 build_int_2 (i, 0)));
9567 list = build (CONSTRUCTOR, item, NULL_TREE, list);
9568 TREE_CONSTANT (list) = 1;
9569 TREE_STATIC (list) = 1;
5ff904cd 9570
14657de8 9571 var = ffecom_get_invented_identifier ("__g77_vardesc_array_%d", mynumber++);
c7e4ee3a
CB
9572 var = build_decl (VAR_DECL, var, item);
9573 TREE_STATIC (var) = 1;
9574 DECL_INITIAL (var) = error_mark_node;
9575 var = start_decl (var, FALSE);
9576 finish_decl (var, list, FALSE);
5ff904cd 9577
c7e4ee3a
CB
9578 return var;
9579}
5ff904cd 9580
c7e4ee3a
CB
9581#endif
9582#if FFECOM_targetCURRENT == FFECOM_targetGCC
9583static tree
9584ffecom_vardesc_dims_ (ffesymbol s)
9585{
9586 if (ffesymbol_dims (s) == NULL)
9587 return convert (ffecom_f2c_ptr_to_ftnlen_type_node,
9588 integer_zero_node);
5ff904cd 9589
c7e4ee3a
CB
9590 {
9591 ffebld b;
9592 ffebld e;
9593 tree list;
9594 tree backlist;
9595 tree item = NULL_TREE;
9596 tree var;
c7e4ee3a
CB
9597 tree numdim;
9598 tree numelem;
9599 tree baseoff = NULL_TREE;
9600 static int mynumber = 0;
9601
9602 numdim = build_int_2 ((int) ffesymbol_rank (s), 0);
9603 TREE_TYPE (numdim) = ffecom_f2c_ftnlen_type_node;
9604
9605 numelem = ffecom_expr (ffesymbol_arraysize (s));
9606 TREE_TYPE (numelem) = ffecom_f2c_ftnlen_type_node;
9607
9608 list = NULL_TREE;
9609 backlist = NULL_TREE;
9610 for (b = ffesymbol_dims (s), e = ffesymbol_extents (s);
9611 b != NULL;
9612 b = ffebld_trail (b), e = ffebld_trail (e))
5ff904cd 9613 {
c7e4ee3a
CB
9614 tree t;
9615 tree low;
9616 tree back;
5ff904cd 9617
c7e4ee3a
CB
9618 if (ffebld_trail (b) == NULL)
9619 t = NULL_TREE;
9620 else
5ff904cd 9621 {
c7e4ee3a
CB
9622 t = convert (ffecom_f2c_ftnlen_type_node,
9623 ffecom_expr (ffebld_head (e)));
5ff904cd 9624
c7e4ee3a
CB
9625 if (list == NULL_TREE)
9626 list = item = build_tree_list (NULL_TREE, t);
9627 else
9628 {
9629 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
9630 item = TREE_CHAIN (item);
9631 }
9632 }
5ff904cd 9633
c7e4ee3a
CB
9634 if (ffebld_left (ffebld_head (b)) == NULL)
9635 low = ffecom_integer_one_node;
9636 else
9637 low = ffecom_expr (ffebld_left (ffebld_head (b)));
9638 low = convert (ffecom_f2c_ftnlen_type_node, low);
5ff904cd 9639
c7e4ee3a
CB
9640 back = build_tree_list (low, t);
9641 TREE_CHAIN (back) = backlist;
9642 backlist = back;
9643 }
5ff904cd 9644
c7e4ee3a
CB
9645 for (item = backlist; item != NULL_TREE; item = TREE_CHAIN (item))
9646 {
9647 if (TREE_VALUE (item) == NULL_TREE)
9648 baseoff = TREE_PURPOSE (item);
9649 else
9650 baseoff = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
9651 TREE_PURPOSE (item),
9652 ffecom_2 (MULT_EXPR,
9653 ffecom_f2c_ftnlen_type_node,
9654 TREE_VALUE (item),
9655 baseoff));
5ff904cd
JL
9656 }
9657
c7e4ee3a 9658 /* backlist now dead, along with all TREE_PURPOSEs on it. */
5ff904cd 9659
c7e4ee3a
CB
9660 baseoff = build_tree_list (NULL_TREE, baseoff);
9661 TREE_CHAIN (baseoff) = list;
5ff904cd 9662
c7e4ee3a
CB
9663 numelem = build_tree_list (NULL_TREE, numelem);
9664 TREE_CHAIN (numelem) = baseoff;
5ff904cd 9665
c7e4ee3a
CB
9666 numdim = build_tree_list (NULL_TREE, numdim);
9667 TREE_CHAIN (numdim) = numelem;
5ff904cd 9668
c7e4ee3a
CB
9669 item = build_array_type (ffecom_f2c_ftnlen_type_node,
9670 build_range_type (integer_type_node,
9671 integer_zero_node,
9672 build_int_2
9673 ((int) ffesymbol_rank (s)
9674 + 2, 0)));
9675 list = build (CONSTRUCTOR, item, NULL_TREE, numdim);
9676 TREE_CONSTANT (list) = 1;
9677 TREE_STATIC (list) = 1;
9678
14657de8 9679 var = ffecom_get_invented_identifier ("__g77_dims_%d", mynumber++);
c7e4ee3a
CB
9680 var = build_decl (VAR_DECL, var, item);
9681 TREE_STATIC (var) = 1;
9682 DECL_INITIAL (var) = error_mark_node;
9683 var = start_decl (var, FALSE);
9684 finish_decl (var, list, FALSE);
9685
9686 var = ffecom_1 (ADDR_EXPR, build_pointer_type (item), var);
9687
c7e4ee3a
CB
9688 return var;
9689 }
5ff904cd 9690}
c7e4ee3a 9691
5ff904cd 9692#endif
c7e4ee3a
CB
9693/* Essentially does a "fold (build1 (code, type, node))" while checking
9694 for certain housekeeping things.
5ff904cd 9695
c7e4ee3a
CB
9696 NOTE: for building an ADDR_EXPR around a FUNCTION_DECL, use
9697 ffecom_1_fn instead. */
5ff904cd
JL
9698
9699#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
9700tree
9701ffecom_1 (enum tree_code code, tree type, tree node)
5ff904cd 9702{
c7e4ee3a
CB
9703 tree item;
9704
9705 if ((node == error_mark_node)
9706 || (type == error_mark_node))
5ff904cd
JL
9707 return error_mark_node;
9708
c7e4ee3a 9709 if (code == ADDR_EXPR)
5ff904cd 9710 {
c7e4ee3a
CB
9711 if (!mark_addressable (node))
9712 assert ("can't mark_addressable this node!" == NULL);
9713 }
5ff904cd 9714
c7e4ee3a
CB
9715 switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
9716 {
9717 tree realtype;
5ff904cd 9718
c7e4ee3a
CB
9719 case REALPART_EXPR:
9720 item = build (COMPONENT_REF, type, node, TYPE_FIELDS (TREE_TYPE (node)));
5ff904cd
JL
9721 break;
9722
c7e4ee3a
CB
9723 case IMAGPART_EXPR:
9724 item = build (COMPONENT_REF, type, node, TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (node))));
9725 break;
5ff904cd 9726
5ff904cd 9727
c7e4ee3a
CB
9728 case NEGATE_EXPR:
9729 if (TREE_CODE (type) != RECORD_TYPE)
9730 {
9731 item = build1 (code, type, node);
9732 break;
9733 }
9734 node = ffecom_stabilize_aggregate_ (node);
9735 realtype = TREE_TYPE (TYPE_FIELDS (type));
9736 item =
9737 ffecom_2 (COMPLEX_EXPR, type,
9738 ffecom_1 (NEGATE_EXPR, realtype,
9739 ffecom_1 (REALPART_EXPR, realtype,
9740 node)),
9741 ffecom_1 (NEGATE_EXPR, realtype,
9742 ffecom_1 (IMAGPART_EXPR, realtype,
9743 node)));
5ff904cd
JL
9744 break;
9745
9746 default:
c7e4ee3a
CB
9747 item = build1 (code, type, node);
9748 break;
5ff904cd 9749 }
5ff904cd 9750
c7e4ee3a
CB
9751 if (TREE_SIDE_EFFECTS (node))
9752 TREE_SIDE_EFFECTS (item) = 1;
9753 if ((code == ADDR_EXPR) && staticp (node))
9754 TREE_CONSTANT (item) = 1;
9755 return fold (item);
9756}
5ff904cd 9757#endif
5ff904cd 9758
c7e4ee3a
CB
9759/* Like ffecom_1 (ADDR_EXPR, TREE_TYPE (node), node), except
9760 handles TREE_CODE (node) == FUNCTION_DECL. In particular,
9761 does not set TREE_ADDRESSABLE (because calling an inline
9762 function does not mean the function needs to be separately
9763 compiled). */
5ff904cd
JL
9764
9765#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
9766tree
9767ffecom_1_fn (tree node)
5ff904cd 9768{
c7e4ee3a 9769 tree item;
5ff904cd 9770 tree type;
5ff904cd 9771
c7e4ee3a
CB
9772 if (node == error_mark_node)
9773 return error_mark_node;
5ff904cd 9774
c7e4ee3a
CB
9775 type = build_type_variant (TREE_TYPE (node),
9776 TREE_READONLY (node),
9777 TREE_THIS_VOLATILE (node));
9778 item = build1 (ADDR_EXPR,
9779 build_pointer_type (type), node);
9780 if (TREE_SIDE_EFFECTS (node))
9781 TREE_SIDE_EFFECTS (item) = 1;
9782 if (staticp (node))
9783 TREE_CONSTANT (item) = 1;
9784 return fold (item);
5ff904cd 9785}
5ff904cd 9786#endif
c7e4ee3a
CB
9787
9788/* Essentially does a "fold (build (code, type, node1, node2))" while
9789 checking for certain housekeeping things. */
5ff904cd
JL
9790
9791#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
9792tree
9793ffecom_2 (enum tree_code code, tree type, tree node1,
9794 tree node2)
5ff904cd 9795{
c7e4ee3a 9796 tree item;
5ff904cd 9797
c7e4ee3a
CB
9798 if ((node1 == error_mark_node)
9799 || (node2 == error_mark_node)
9800 || (type == error_mark_node))
9801 return error_mark_node;
9802
9803 switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
5ff904cd 9804 {
c7e4ee3a 9805 tree a, b, c, d, realtype;
5ff904cd 9806
c7e4ee3a
CB
9807 case CONJ_EXPR:
9808 assert ("no CONJ_EXPR support yet" == NULL);
9809 return error_mark_node;
5ff904cd 9810
c7e4ee3a
CB
9811 case COMPLEX_EXPR:
9812 item = build_tree_list (TYPE_FIELDS (type), node1);
9813 TREE_CHAIN (item) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), node2);
9814 item = build (CONSTRUCTOR, type, NULL_TREE, item);
9815 break;
5ff904cd 9816
c7e4ee3a
CB
9817 case PLUS_EXPR:
9818 if (TREE_CODE (type) != RECORD_TYPE)
9819 {
9820 item = build (code, type, node1, node2);
9821 break;
9822 }
9823 node1 = ffecom_stabilize_aggregate_ (node1);
9824 node2 = ffecom_stabilize_aggregate_ (node2);
9825 realtype = TREE_TYPE (TYPE_FIELDS (type));
9826 item =
9827 ffecom_2 (COMPLEX_EXPR, type,
9828 ffecom_2 (PLUS_EXPR, realtype,
9829 ffecom_1 (REALPART_EXPR, realtype,
9830 node1),
9831 ffecom_1 (REALPART_EXPR, realtype,
9832 node2)),
9833 ffecom_2 (PLUS_EXPR, realtype,
9834 ffecom_1 (IMAGPART_EXPR, realtype,
9835 node1),
9836 ffecom_1 (IMAGPART_EXPR, realtype,
9837 node2)));
9838 break;
5ff904cd 9839
c7e4ee3a
CB
9840 case MINUS_EXPR:
9841 if (TREE_CODE (type) != RECORD_TYPE)
9842 {
9843 item = build (code, type, node1, node2);
9844 break;
9845 }
9846 node1 = ffecom_stabilize_aggregate_ (node1);
9847 node2 = ffecom_stabilize_aggregate_ (node2);
9848 realtype = TREE_TYPE (TYPE_FIELDS (type));
9849 item =
9850 ffecom_2 (COMPLEX_EXPR, type,
9851 ffecom_2 (MINUS_EXPR, realtype,
9852 ffecom_1 (REALPART_EXPR, realtype,
9853 node1),
9854 ffecom_1 (REALPART_EXPR, realtype,
9855 node2)),
9856 ffecom_2 (MINUS_EXPR, realtype,
9857 ffecom_1 (IMAGPART_EXPR, realtype,
9858 node1),
9859 ffecom_1 (IMAGPART_EXPR, realtype,
9860 node2)));
9861 break;
5ff904cd 9862
c7e4ee3a
CB
9863 case MULT_EXPR:
9864 if (TREE_CODE (type) != RECORD_TYPE)
9865 {
9866 item = build (code, type, node1, node2);
9867 break;
9868 }
9869 node1 = ffecom_stabilize_aggregate_ (node1);
9870 node2 = ffecom_stabilize_aggregate_ (node2);
9871 realtype = TREE_TYPE (TYPE_FIELDS (type));
9872 a = save_expr (ffecom_1 (REALPART_EXPR, realtype,
9873 node1));
9874 b = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
9875 node1));
9876 c = save_expr (ffecom_1 (REALPART_EXPR, realtype,
9877 node2));
9878 d = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
9879 node2));
9880 item =
9881 ffecom_2 (COMPLEX_EXPR, type,
9882 ffecom_2 (MINUS_EXPR, realtype,
9883 ffecom_2 (MULT_EXPR, realtype,
9884 a,
9885 c),
9886 ffecom_2 (MULT_EXPR, realtype,
9887 b,
9888 d)),
9889 ffecom_2 (PLUS_EXPR, realtype,
9890 ffecom_2 (MULT_EXPR, realtype,
9891 a,
9892 d),
9893 ffecom_2 (MULT_EXPR, realtype,
9894 c,
9895 b)));
9896 break;
5ff904cd 9897
c7e4ee3a
CB
9898 case EQ_EXPR:
9899 if ((TREE_CODE (node1) != RECORD_TYPE)
9900 && (TREE_CODE (node2) != RECORD_TYPE))
9901 {
9902 item = build (code, type, node1, node2);
9903 break;
9904 }
9905 assert (TREE_CODE (node1) == RECORD_TYPE);
9906 assert (TREE_CODE (node2) == RECORD_TYPE);
9907 node1 = ffecom_stabilize_aggregate_ (node1);
9908 node2 = ffecom_stabilize_aggregate_ (node2);
9909 realtype = TREE_TYPE (TYPE_FIELDS (type));
9910 item =
9911 ffecom_2 (TRUTH_ANDIF_EXPR, type,
9912 ffecom_2 (code, type,
9913 ffecom_1 (REALPART_EXPR, realtype,
9914 node1),
9915 ffecom_1 (REALPART_EXPR, realtype,
9916 node2)),
9917 ffecom_2 (code, type,
9918 ffecom_1 (IMAGPART_EXPR, realtype,
9919 node1),
9920 ffecom_1 (IMAGPART_EXPR, realtype,
9921 node2)));
9922 break;
9923
9924 case NE_EXPR:
9925 if ((TREE_CODE (node1) != RECORD_TYPE)
9926 && (TREE_CODE (node2) != RECORD_TYPE))
9927 {
9928 item = build (code, type, node1, node2);
9929 break;
9930 }
9931 assert (TREE_CODE (node1) == RECORD_TYPE);
9932 assert (TREE_CODE (node2) == RECORD_TYPE);
9933 node1 = ffecom_stabilize_aggregate_ (node1);
9934 node2 = ffecom_stabilize_aggregate_ (node2);
9935 realtype = TREE_TYPE (TYPE_FIELDS (type));
9936 item =
9937 ffecom_2 (TRUTH_ORIF_EXPR, type,
9938 ffecom_2 (code, type,
9939 ffecom_1 (REALPART_EXPR, realtype,
9940 node1),
9941 ffecom_1 (REALPART_EXPR, realtype,
9942 node2)),
9943 ffecom_2 (code, type,
9944 ffecom_1 (IMAGPART_EXPR, realtype,
9945 node1),
9946 ffecom_1 (IMAGPART_EXPR, realtype,
9947 node2)));
9948 break;
5ff904cd 9949
c7e4ee3a
CB
9950 default:
9951 item = build (code, type, node1, node2);
9952 break;
5ff904cd
JL
9953 }
9954
c7e4ee3a
CB
9955 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2))
9956 TREE_SIDE_EFFECTS (item) = 1;
9957 return fold (item);
5ff904cd
JL
9958}
9959
9960#endif
c7e4ee3a 9961/* ffecom_2pass_advise_entrypoint -- Advise that there's this entrypoint
5ff904cd 9962
c7e4ee3a
CB
9963 ffesymbol s; // the ENTRY point itself
9964 if (ffecom_2pass_advise_entrypoint(s))
9965 // the ENTRY point has been accepted
5ff904cd 9966
c7e4ee3a
CB
9967 Does whatever compiler needs to do when it learns about the entrypoint,
9968 like determine the return type of the master function, count the
9969 number of entrypoints, etc. Returns FALSE if the return type is
9970 not compatible with the return type(s) of other entrypoint(s).
5ff904cd 9971
c7e4ee3a
CB
9972 NOTE: for every call to this fn that returns TRUE, _do_entrypoint must
9973 later (after _finish_progunit) be called with the same entrypoint(s)
9974 as passed to this fn for which TRUE was returned.
5ff904cd 9975
c7e4ee3a
CB
9976 03-Jan-92 JCB 2.0
9977 Return FALSE if the return type conflicts with previous entrypoints. */
5ff904cd
JL
9978
9979#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
9980bool
9981ffecom_2pass_advise_entrypoint (ffesymbol entry)
5ff904cd 9982{
c7e4ee3a
CB
9983 ffebld list; /* opITEM. */
9984 ffebld mlist; /* opITEM. */
9985 ffebld plist; /* opITEM. */
9986 ffebld arg; /* ffebld_head(opITEM). */
9987 ffebld item; /* opITEM. */
9988 ffesymbol s; /* ffebld_symter(arg). */
9989 ffeinfoBasictype bt = ffesymbol_basictype (entry);
9990 ffeinfoKindtype kt = ffesymbol_kindtype (entry);
9991 ffetargetCharacterSize size = ffesymbol_size (entry);
9992 bool ok;
5ff904cd 9993
c7e4ee3a
CB
9994 if (ffecom_num_entrypoints_ == 0)
9995 { /* First entrypoint, make list of main
9996 arglist's dummies. */
9997 assert (ffecom_primary_entry_ != NULL);
5ff904cd 9998
c7e4ee3a
CB
9999 ffecom_master_bt_ = ffesymbol_basictype (ffecom_primary_entry_);
10000 ffecom_master_kt_ = ffesymbol_kindtype (ffecom_primary_entry_);
10001 ffecom_master_size_ = ffesymbol_size (ffecom_primary_entry_);
5ff904cd 10002
c7e4ee3a
CB
10003 for (plist = NULL, list = ffesymbol_dummyargs (ffecom_primary_entry_);
10004 list != NULL;
10005 list = ffebld_trail (list))
10006 {
10007 arg = ffebld_head (list);
10008 if (ffebld_op (arg) != FFEBLD_opSYMTER)
10009 continue; /* Alternate return or some such thing. */
10010 item = ffebld_new_item (arg, NULL);
10011 if (plist == NULL)
10012 ffecom_master_arglist_ = item;
10013 else
10014 ffebld_set_trail (plist, item);
10015 plist = item;
10016 }
5ff904cd
JL
10017 }
10018
c7e4ee3a
CB
10019 /* If necessary, scan entry arglist for alternate returns. Do this scan
10020 apparently redundantly (it's done below to UNIONize the arglists) so
10021 that we don't complain about RETURN 1 if an offending ENTRY is the only
10022 one with an alternate return. */
5ff904cd 10023
c7e4ee3a 10024 if (!ffecom_is_altreturning_)
5ff904cd 10025 {
c7e4ee3a
CB
10026 for (list = ffesymbol_dummyargs (entry);
10027 list != NULL;
10028 list = ffebld_trail (list))
10029 {
10030 arg = ffebld_head (list);
10031 if (ffebld_op (arg) == FFEBLD_opSTAR)
10032 {
10033 ffecom_is_altreturning_ = TRUE;
10034 break;
10035 }
10036 }
10037 }
5ff904cd 10038
c7e4ee3a 10039 /* Now check type compatibility. */
5ff904cd 10040
c7e4ee3a
CB
10041 switch (ffecom_master_bt_)
10042 {
10043 case FFEINFO_basictypeNONE:
10044 ok = (bt != FFEINFO_basictypeCHARACTER);
10045 break;
5ff904cd 10046
c7e4ee3a
CB
10047 case FFEINFO_basictypeCHARACTER:
10048 ok
10049 = (bt == FFEINFO_basictypeCHARACTER)
10050 && (kt == ffecom_master_kt_)
10051 && (size == ffecom_master_size_);
10052 break;
5ff904cd 10053
c7e4ee3a
CB
10054 case FFEINFO_basictypeANY:
10055 return FALSE; /* Just don't bother. */
5ff904cd 10056
c7e4ee3a
CB
10057 default:
10058 if (bt == FFEINFO_basictypeCHARACTER)
5ff904cd 10059 {
c7e4ee3a
CB
10060 ok = FALSE;
10061 break;
5ff904cd 10062 }
c7e4ee3a
CB
10063 ok = TRUE;
10064 if ((bt != ffecom_master_bt_) || (kt != ffecom_master_kt_))
10065 {
10066 ffecom_master_bt_ = FFEINFO_basictypeNONE;
10067 ffecom_master_kt_ = FFEINFO_kindtypeNONE;
10068 }
10069 break;
10070 }
5ff904cd 10071
c7e4ee3a
CB
10072 if (!ok)
10073 {
10074 ffebad_start (FFEBAD_ENTRY_CONFLICTS);
10075 ffest_ffebad_here_current_stmt (0);
10076 ffebad_finish ();
10077 return FALSE; /* Can't handle entrypoint. */
10078 }
5ff904cd 10079
c7e4ee3a 10080 /* Entrypoint type compatible with previous types. */
5ff904cd 10081
c7e4ee3a 10082 ++ffecom_num_entrypoints_;
5ff904cd 10083
c7e4ee3a
CB
10084 /* Master-arg-list = UNION(Master-arg-list,entry-arg-list). */
10085
10086 for (list = ffesymbol_dummyargs (entry);
10087 list != NULL;
10088 list = ffebld_trail (list))
10089 {
10090 arg = ffebld_head (list);
10091 if (ffebld_op (arg) != FFEBLD_opSYMTER)
10092 continue; /* Alternate return or some such thing. */
10093 s = ffebld_symter (arg);
10094 for (plist = NULL, mlist = ffecom_master_arglist_;
10095 mlist != NULL;
10096 plist = mlist, mlist = ffebld_trail (mlist))
10097 { /* plist points to previous item for easy
10098 appending of arg. */
10099 if (ffebld_symter (ffebld_head (mlist)) == s)
10100 break; /* Already have this arg in the master list. */
10101 }
10102 if (mlist != NULL)
10103 continue; /* Already have this arg in the master list. */
5ff904cd 10104
c7e4ee3a 10105 /* Append this arg to the master list. */
5ff904cd 10106
c7e4ee3a
CB
10107 item = ffebld_new_item (arg, NULL);
10108 if (plist == NULL)
10109 ffecom_master_arglist_ = item;
10110 else
10111 ffebld_set_trail (plist, item);
5ff904cd
JL
10112 }
10113
c7e4ee3a 10114 return TRUE;
5ff904cd
JL
10115}
10116
10117#endif
c7e4ee3a
CB
10118/* ffecom_2pass_do_entrypoint -- Do compilation of entrypoint
10119
10120 ffesymbol s; // the ENTRY point itself
10121 ffecom_2pass_do_entrypoint(s);
10122
10123 Does whatever compiler needs to do to make the entrypoint actually
10124 happen. Must be called for each entrypoint after
10125 ffecom_finish_progunit is called. */
10126
5ff904cd 10127#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
10128void
10129ffecom_2pass_do_entrypoint (ffesymbol entry)
5ff904cd 10130{
c7e4ee3a
CB
10131 static int mfn_num = 0;
10132 static int ent_num;
5ff904cd 10133
c7e4ee3a
CB
10134 if (mfn_num != ffecom_num_fns_)
10135 { /* First entrypoint for this program unit. */
10136 ent_num = 1;
10137 mfn_num = ffecom_num_fns_;
10138 ffecom_do_entry_ (ffecom_primary_entry_, 0);
10139 }
10140 else
10141 ++ent_num;
5ff904cd 10142
c7e4ee3a 10143 --ffecom_num_entrypoints_;
5ff904cd 10144
c7e4ee3a
CB
10145 ffecom_do_entry_ (entry, ent_num);
10146}
5ff904cd 10147
c7e4ee3a 10148#endif
5ff904cd 10149
c7e4ee3a
CB
10150/* Essentially does a "fold (build (code, type, node1, node2))" while
10151 checking for certain housekeeping things. Always sets
10152 TREE_SIDE_EFFECTS. */
5ff904cd 10153
c7e4ee3a
CB
10154#if FFECOM_targetCURRENT == FFECOM_targetGCC
10155tree
10156ffecom_2s (enum tree_code code, tree type, tree node1,
10157 tree node2)
10158{
10159 tree item;
5ff904cd 10160
c7e4ee3a
CB
10161 if ((node1 == error_mark_node)
10162 || (node2 == error_mark_node)
10163 || (type == error_mark_node))
10164 return error_mark_node;
5ff904cd 10165
c7e4ee3a
CB
10166 item = build (code, type, node1, node2);
10167 TREE_SIDE_EFFECTS (item) = 1;
10168 return fold (item);
5ff904cd
JL
10169}
10170
10171#endif
c7e4ee3a
CB
10172/* Essentially does a "fold (build (code, type, node1, node2, node3))" while
10173 checking for certain housekeeping things. */
10174
5ff904cd 10175#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
10176tree
10177ffecom_3 (enum tree_code code, tree type, tree node1,
10178 tree node2, tree node3)
5ff904cd 10179{
c7e4ee3a 10180 tree item;
5ff904cd 10181
c7e4ee3a
CB
10182 if ((node1 == error_mark_node)
10183 || (node2 == error_mark_node)
10184 || (node3 == error_mark_node)
10185 || (type == error_mark_node))
10186 return error_mark_node;
5ff904cd 10187
c7e4ee3a
CB
10188 item = build (code, type, node1, node2, node3);
10189 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2)
10190 || (node3 != NULL_TREE && TREE_SIDE_EFFECTS (node3)))
10191 TREE_SIDE_EFFECTS (item) = 1;
10192 return fold (item);
10193}
5ff904cd 10194
c7e4ee3a
CB
10195#endif
10196/* Essentially does a "fold (build (code, type, node1, node2, node3))" while
10197 checking for certain housekeeping things. Always sets
10198 TREE_SIDE_EFFECTS. */
5ff904cd 10199
c7e4ee3a
CB
10200#if FFECOM_targetCURRENT == FFECOM_targetGCC
10201tree
10202ffecom_3s (enum tree_code code, tree type, tree node1,
10203 tree node2, tree node3)
10204{
10205 tree item;
5ff904cd 10206
c7e4ee3a
CB
10207 if ((node1 == error_mark_node)
10208 || (node2 == error_mark_node)
10209 || (node3 == error_mark_node)
10210 || (type == error_mark_node))
10211 return error_mark_node;
5ff904cd 10212
c7e4ee3a
CB
10213 item = build (code, type, node1, node2, node3);
10214 TREE_SIDE_EFFECTS (item) = 1;
10215 return fold (item);
10216}
5ff904cd 10217
c7e4ee3a 10218#endif
5ff904cd 10219
c7e4ee3a 10220/* ffecom_arg_expr -- Transform argument expr into gcc tree
5ff904cd 10221
c7e4ee3a 10222 See use by ffecom_list_expr.
5ff904cd 10223
c7e4ee3a
CB
10224 If expression is NULL, returns an integer zero tree. If it is not
10225 a CHARACTER expression, returns whatever ffecom_expr
10226 returns and sets the length return value to NULL_TREE. Otherwise
10227 generates code to evaluate the character expression, returns the proper
10228 pointer to the result, but does NOT set the length return value to a tree
10229 that specifies the length of the result. (In other words, the length
10230 variable is always set to NULL_TREE, because a length is never passed.)
5ff904cd 10231
c7e4ee3a
CB
10232 21-Dec-91 JCB 1.1
10233 Don't set returned length, since nobody needs it (yet; someday if
10234 we allow CHARACTER*(*) dummies to statement functions, we'll need
10235 it). */
5ff904cd 10236
c7e4ee3a
CB
10237#if FFECOM_targetCURRENT == FFECOM_targetGCC
10238tree
10239ffecom_arg_expr (ffebld expr, tree *length)
10240{
10241 tree ign;
5ff904cd 10242
c7e4ee3a 10243 *length = NULL_TREE;
5ff904cd 10244
c7e4ee3a
CB
10245 if (expr == NULL)
10246 return integer_zero_node;
5ff904cd 10247
c7e4ee3a
CB
10248 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10249 return ffecom_expr (expr);
5ff904cd 10250
c7e4ee3a
CB
10251 return ffecom_arg_ptr_to_expr (expr, &ign);
10252}
10253
10254#endif
10255/* Transform expression into constant argument-pointer-to-expression tree.
10256
10257 If the expression can be transformed into a argument-pointer-to-expression
10258 tree that is constant, that is done, and the tree returned. Else
10259 NULL_TREE is returned.
5ff904cd 10260
c7e4ee3a
CB
10261 That way, a caller can attempt to provide compile-time initialization
10262 of a variable and, if that fails, *then* choose to start a new block
10263 and resort to using temporaries, as appropriate. */
5ff904cd 10264
c7e4ee3a
CB
10265tree
10266ffecom_arg_ptr_to_const_expr (ffebld expr, tree *length)
10267{
10268 if (! expr)
10269 return integer_zero_node;
5ff904cd 10270
c7e4ee3a
CB
10271 if (ffebld_op (expr) == FFEBLD_opANY)
10272 {
10273 if (length)
10274 *length = error_mark_node;
10275 return error_mark_node;
10276 }
10277
10278 if (ffebld_arity (expr) == 0
10279 && (ffebld_op (expr) != FFEBLD_opSYMTER
10280 || ffebld_where (expr) == FFEINFO_whereCOMMON
10281 || ffebld_where (expr) == FFEINFO_whereGLOBAL
10282 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
10283 {
10284 tree t;
10285
10286 t = ffecom_arg_ptr_to_expr (expr, length);
10287 assert (TREE_CONSTANT (t));
10288 assert (! length || TREE_CONSTANT (*length));
10289 return t;
10290 }
10291
10292 if (length
10293 && ffebld_size (expr) != FFETARGET_charactersizeNONE)
10294 *length = build_int_2 (ffebld_size (expr), 0);
10295 else if (length)
10296 *length = NULL_TREE;
10297 return NULL_TREE;
5ff904cd
JL
10298}
10299
c7e4ee3a 10300/* ffecom_arg_ptr_to_expr -- Transform argument expr into gcc tree
5ff904cd 10301
c7e4ee3a
CB
10302 See use by ffecom_list_ptr_to_expr.
10303
10304 If expression is NULL, returns an integer zero tree. If it is not
10305 a CHARACTER expression, returns whatever ffecom_ptr_to_expr
10306 returns and sets the length return value to NULL_TREE. Otherwise
10307 generates code to evaluate the character expression, returns the proper
10308 pointer to the result, AND sets the length return value to a tree that
10309 specifies the length of the result.
10310
10311 If the length argument is NULL, this is a slightly special
10312 case of building a FORMAT expression, that is, an expression that
10313 will be used at run time without regard to length. For the current
10314 implementation, which uses the libf2c library, this means it is nice
10315 to append a null byte to the end of the expression, where feasible,
10316 to make sure any diagnostic about the FORMAT string terminates at
10317 some useful point.
10318
10319 For now, treat %REF(char-expr) as the same as char-expr with a NULL
10320 length argument. This might even be seen as a feature, if a null
10321 byte can always be appended. */
5ff904cd
JL
10322
10323#if FFECOM_targetCURRENT == FFECOM_targetGCC
10324tree
c7e4ee3a 10325ffecom_arg_ptr_to_expr (ffebld expr, tree *length)
5ff904cd
JL
10326{
10327 tree item;
c7e4ee3a
CB
10328 tree ign_length;
10329 ffecomConcatList_ catlist;
5ff904cd 10330
c7e4ee3a
CB
10331 if (length != NULL)
10332 *length = NULL_TREE;
5ff904cd 10333
c7e4ee3a
CB
10334 if (expr == NULL)
10335 return integer_zero_node;
5ff904cd 10336
c7e4ee3a 10337 switch (ffebld_op (expr))
5ff904cd 10338 {
c7e4ee3a
CB
10339 case FFEBLD_opPERCENT_VAL:
10340 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10341 return ffecom_expr (ffebld_left (expr));
10342 {
10343 tree temp_exp;
10344 tree temp_length;
5ff904cd 10345
c7e4ee3a
CB
10346 temp_exp = ffecom_arg_ptr_to_expr (ffebld_left (expr), &temp_length);
10347 if (temp_exp == error_mark_node)
10348 return error_mark_node;
5ff904cd 10349
c7e4ee3a
CB
10350 return ffecom_1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (temp_exp)),
10351 temp_exp);
10352 }
5ff904cd 10353
c7e4ee3a
CB
10354 case FFEBLD_opPERCENT_REF:
10355 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10356 return ffecom_ptr_to_expr (ffebld_left (expr));
10357 if (length != NULL)
10358 {
10359 ign_length = NULL_TREE;
10360 length = &ign_length;
10361 }
10362 expr = ffebld_left (expr);
10363 break;
5ff904cd 10364
c7e4ee3a
CB
10365 case FFEBLD_opPERCENT_DESCR:
10366 switch (ffeinfo_basictype (ffebld_info (expr)))
5ff904cd 10367 {
c7e4ee3a
CB
10368#ifdef PASS_HOLLERITH_BY_DESCRIPTOR
10369 case FFEINFO_basictypeHOLLERITH:
10370#endif
10371 case FFEINFO_basictypeCHARACTER:
10372 break; /* Passed by descriptor anyway. */
10373
10374 default:
10375 item = ffecom_ptr_to_expr (expr);
10376 if (item != error_mark_node)
10377 *length = TYPE_SIZE (TREE_TYPE (TREE_TYPE (item)));
5ff904cd
JL
10378 break;
10379 }
5ff904cd
JL
10380 break;
10381
10382 default:
5ff904cd
JL
10383 break;
10384 }
10385
c7e4ee3a
CB
10386#ifdef PASS_HOLLERITH_BY_DESCRIPTOR
10387 if ((ffeinfo_basictype (ffebld_info (expr)) == FFEINFO_basictypeHOLLERITH)
10388 && (length != NULL))
10389 { /* Pass Hollerith by descriptor. */
10390 ffetargetHollerith h;
10391
10392 assert (ffebld_op (expr) == FFEBLD_opCONTER);
10393 h = ffebld_cu_val_hollerith (ffebld_constant_union
10394 (ffebld_conter (expr)));
10395 *length
10396 = build_int_2 (h.length, 0);
10397 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
10398 }
10399#endif
10400
10401 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10402 return ffecom_ptr_to_expr (expr);
10403
10404 assert (ffeinfo_kindtype (ffebld_info (expr))
10405 == FFEINFO_kindtypeCHARACTER1);
10406
47d98fa2
CB
10407 while (ffebld_op (expr) == FFEBLD_opPAREN)
10408 expr = ffebld_left (expr);
10409
c7e4ee3a
CB
10410 catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
10411 switch (ffecom_concat_list_count_ (catlist))
10412 {
10413 case 0: /* Shouldn't happen, but in case it does... */
10414 if (length != NULL)
10415 {
10416 *length = ffecom_f2c_ftnlen_zero_node;
10417 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
10418 }
10419 ffecom_concat_list_kill_ (catlist);
10420 return null_pointer_node;
10421
10422 case 1: /* The (fairly) easy case. */
10423 if (length == NULL)
10424 ffecom_char_args_with_null_ (&item, &ign_length,
10425 ffecom_concat_list_expr_ (catlist, 0));
10426 else
10427 ffecom_char_args_ (&item, length,
10428 ffecom_concat_list_expr_ (catlist, 0));
10429 ffecom_concat_list_kill_ (catlist);
10430 assert (item != NULL_TREE);
10431 return item;
10432
10433 default: /* Must actually concatenate things. */
10434 break;
10435 }
10436
10437 {
10438 int count = ffecom_concat_list_count_ (catlist);
10439 int i;
10440 tree lengths;
10441 tree items;
10442 tree length_array;
10443 tree item_array;
10444 tree citem;
10445 tree clength;
10446 tree temporary;
10447 tree num;
10448 tree known_length;
10449 ffetargetCharacterSize sz;
10450
10451 sz = ffecom_concat_list_maxlen_ (catlist);
10452 /* ~~Kludge! */
10453 assert (sz != FFETARGET_charactersizeNONE);
10454
10455#ifdef HOHO
10456 length_array
10457 = lengths
10458 = ffecom_push_tempvar (ffecom_f2c_ftnlen_type_node,
10459 FFETARGET_charactersizeNONE, count, TRUE);
10460 item_array
10461 = items
10462 = ffecom_push_tempvar (ffecom_f2c_address_type_node,
10463 FFETARGET_charactersizeNONE, count, TRUE);
10464 temporary = ffecom_push_tempvar (char_type_node,
10465 sz, -1, TRUE);
10466#else
10467 {
10468 tree hook;
10469
10470 hook = ffebld_nonter_hook (expr);
10471 assert (hook);
10472 assert (TREE_CODE (hook) == TREE_VEC);
10473 assert (TREE_VEC_LENGTH (hook) == 3);
10474 length_array = lengths = TREE_VEC_ELT (hook, 0);
10475 item_array = items = TREE_VEC_ELT (hook, 1);
10476 temporary = TREE_VEC_ELT (hook, 2);
10477 }
10478#endif
10479
10480 known_length = ffecom_f2c_ftnlen_zero_node;
10481
10482 for (i = 0; i < count; ++i)
10483 {
10484 if ((i == count)
10485 && (length == NULL))
10486 ffecom_char_args_with_null_ (&citem, &clength,
10487 ffecom_concat_list_expr_ (catlist, i));
10488 else
10489 ffecom_char_args_ (&citem, &clength,
10490 ffecom_concat_list_expr_ (catlist, i));
10491 if ((citem == error_mark_node)
10492 || (clength == error_mark_node))
10493 {
10494 ffecom_concat_list_kill_ (catlist);
10495 *length = error_mark_node;
10496 return error_mark_node;
10497 }
10498
10499 items
10500 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
10501 ffecom_modify (void_type_node,
10502 ffecom_2 (ARRAY_REF,
10503 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
10504 item_array,
10505 build_int_2 (i, 0)),
10506 citem),
10507 items);
10508 clength = ffecom_save_tree (clength);
10509 if (length != NULL)
10510 known_length
10511 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
10512 known_length,
10513 clength);
10514 lengths
10515 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
10516 ffecom_modify (void_type_node,
10517 ffecom_2 (ARRAY_REF,
10518 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
10519 length_array,
10520 build_int_2 (i, 0)),
10521 clength),
10522 lengths);
10523 }
10524
10525 temporary = ffecom_1 (ADDR_EXPR,
10526 build_pointer_type (TREE_TYPE (temporary)),
10527 temporary);
10528
10529 item = build_tree_list (NULL_TREE, temporary);
10530 TREE_CHAIN (item)
10531 = build_tree_list (NULL_TREE,
10532 ffecom_1 (ADDR_EXPR,
10533 build_pointer_type (TREE_TYPE (items)),
10534 items));
10535 TREE_CHAIN (TREE_CHAIN (item))
10536 = build_tree_list (NULL_TREE,
10537 ffecom_1 (ADDR_EXPR,
10538 build_pointer_type (TREE_TYPE (lengths)),
10539 lengths));
10540 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
10541 = build_tree_list
10542 (NULL_TREE,
10543 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
10544 convert (ffecom_f2c_ftnlen_type_node,
10545 build_int_2 (count, 0))));
10546 num = build_int_2 (sz, 0);
10547 TREE_TYPE (num) = ffecom_f2c_ftnlen_type_node;
10548 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item))))
10549 = build_tree_list (NULL_TREE, num);
10550
10551 item = ffecom_call_gfrt (FFECOM_gfrtCAT, item, NULL_TREE);
5ff904cd 10552 TREE_SIDE_EFFECTS (item) = 1;
c7e4ee3a
CB
10553 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (temporary),
10554 item,
10555 temporary);
10556
10557 if (length != NULL)
10558 *length = known_length;
10559 }
10560
10561 ffecom_concat_list_kill_ (catlist);
10562 assert (item != NULL_TREE);
10563 return item;
5ff904cd 10564}
c7e4ee3a 10565
5ff904cd 10566#endif
c7e4ee3a 10567/* Generate call to run-time function.
5ff904cd 10568
c7e4ee3a
CB
10569 The first arg is the GNU Fortran Run-Time function index, the second
10570 arg is the list of arguments to pass to it. Returned is the expression
10571 (WITHOUT TREE_SIDE_EFFECTS set!) that makes the call and returns the
10572 result (which may be void). */
5ff904cd
JL
10573
10574#if FFECOM_targetCURRENT == FFECOM_targetGCC
10575tree
c7e4ee3a 10576ffecom_call_gfrt (ffecomGfrt ix, tree args, tree hook)
5ff904cd 10577{
c7e4ee3a
CB
10578 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
10579 ffecom_gfrt_kindtype (ix),
10580 ffe_is_f2c_library () && ffecom_gfrt_complex_[ix],
10581 NULL_TREE, args, NULL_TREE, NULL,
10582 NULL, NULL_TREE, TRUE, hook);
5ff904cd
JL
10583}
10584#endif
10585
c7e4ee3a 10586/* Transform constant-union to tree. */
5ff904cd
JL
10587
10588#if FFECOM_targetCURRENT == FFECOM_targetGCC
10589tree
c7e4ee3a
CB
10590ffecom_constantunion (ffebldConstantUnion *cu, ffeinfoBasictype bt,
10591 ffeinfoKindtype kt, tree tree_type)
5ff904cd
JL
10592{
10593 tree item;
10594
c7e4ee3a 10595 switch (bt)
5ff904cd 10596 {
c7e4ee3a
CB
10597 case FFEINFO_basictypeINTEGER:
10598 {
10599 int val;
5ff904cd 10600
c7e4ee3a
CB
10601 switch (kt)
10602 {
10603#if FFETARGET_okINTEGER1
10604 case FFEINFO_kindtypeINTEGER1:
10605 val = ffebld_cu_val_integer1 (*cu);
10606 break;
10607#endif
5ff904cd 10608
c7e4ee3a
CB
10609#if FFETARGET_okINTEGER2
10610 case FFEINFO_kindtypeINTEGER2:
10611 val = ffebld_cu_val_integer2 (*cu);
10612 break;
10613#endif
5ff904cd 10614
c7e4ee3a
CB
10615#if FFETARGET_okINTEGER3
10616 case FFEINFO_kindtypeINTEGER3:
10617 val = ffebld_cu_val_integer3 (*cu);
10618 break;
10619#endif
5ff904cd 10620
c7e4ee3a
CB
10621#if FFETARGET_okINTEGER4
10622 case FFEINFO_kindtypeINTEGER4:
10623 val = ffebld_cu_val_integer4 (*cu);
10624 break;
10625#endif
5ff904cd 10626
c7e4ee3a
CB
10627 default:
10628 assert ("bad INTEGER constant kind type" == NULL);
10629 /* Fall through. */
10630 case FFEINFO_kindtypeANY:
10631 return error_mark_node;
10632 }
10633 item = build_int_2 (val, (val < 0) ? -1 : 0);
10634 TREE_TYPE (item) = tree_type;
10635 }
5ff904cd 10636 break;
5ff904cd 10637
c7e4ee3a
CB
10638 case FFEINFO_basictypeLOGICAL:
10639 {
10640 int val;
5ff904cd 10641
c7e4ee3a
CB
10642 switch (kt)
10643 {
10644#if FFETARGET_okLOGICAL1
10645 case FFEINFO_kindtypeLOGICAL1:
10646 val = ffebld_cu_val_logical1 (*cu);
10647 break;
5ff904cd 10648#endif
5ff904cd 10649
c7e4ee3a
CB
10650#if FFETARGET_okLOGICAL2
10651 case FFEINFO_kindtypeLOGICAL2:
10652 val = ffebld_cu_val_logical2 (*cu);
10653 break;
10654#endif
5ff904cd 10655
c7e4ee3a
CB
10656#if FFETARGET_okLOGICAL3
10657 case FFEINFO_kindtypeLOGICAL3:
10658 val = ffebld_cu_val_logical3 (*cu);
10659 break;
10660#endif
5ff904cd 10661
c7e4ee3a
CB
10662#if FFETARGET_okLOGICAL4
10663 case FFEINFO_kindtypeLOGICAL4:
10664 val = ffebld_cu_val_logical4 (*cu);
10665 break;
10666#endif
5ff904cd 10667
c7e4ee3a
CB
10668 default:
10669 assert ("bad LOGICAL constant kind type" == NULL);
10670 /* Fall through. */
10671 case FFEINFO_kindtypeANY:
10672 return error_mark_node;
10673 }
10674 item = build_int_2 (val, (val < 0) ? -1 : 0);
10675 TREE_TYPE (item) = tree_type;
10676 }
10677 break;
5ff904cd 10678
c7e4ee3a
CB
10679 case FFEINFO_basictypeREAL:
10680 {
10681 REAL_VALUE_TYPE val;
5ff904cd 10682
c7e4ee3a
CB
10683 switch (kt)
10684 {
10685#if FFETARGET_okREAL1
10686 case FFEINFO_kindtypeREAL1:
10687 val = ffetarget_value_real1 (ffebld_cu_val_real1 (*cu));
10688 break;
10689#endif
5ff904cd 10690
c7e4ee3a
CB
10691#if FFETARGET_okREAL2
10692 case FFEINFO_kindtypeREAL2:
10693 val = ffetarget_value_real2 (ffebld_cu_val_real2 (*cu));
10694 break;
10695#endif
5ff904cd 10696
c7e4ee3a
CB
10697#if FFETARGET_okREAL3
10698 case FFEINFO_kindtypeREAL3:
10699 val = ffetarget_value_real3 (ffebld_cu_val_real3 (*cu));
10700 break;
10701#endif
5ff904cd 10702
c7e4ee3a
CB
10703#if FFETARGET_okREAL4
10704 case FFEINFO_kindtypeREAL4:
10705 val = ffetarget_value_real4 (ffebld_cu_val_real4 (*cu));
10706 break;
10707#endif
5ff904cd 10708
c7e4ee3a
CB
10709 default:
10710 assert ("bad REAL constant kind type" == NULL);
10711 /* Fall through. */
10712 case FFEINFO_kindtypeANY:
10713 return error_mark_node;
10714 }
10715 item = build_real (tree_type, val);
10716 }
5ff904cd
JL
10717 break;
10718
c7e4ee3a
CB
10719 case FFEINFO_basictypeCOMPLEX:
10720 {
10721 REAL_VALUE_TYPE real;
10722 REAL_VALUE_TYPE imag;
10723 tree el_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
5ff904cd 10724
c7e4ee3a
CB
10725 switch (kt)
10726 {
10727#if FFETARGET_okCOMPLEX1
10728 case FFEINFO_kindtypeREAL1:
10729 real = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).real);
10730 imag = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).imaginary);
10731 break;
10732#endif
5ff904cd 10733
c7e4ee3a
CB
10734#if FFETARGET_okCOMPLEX2
10735 case FFEINFO_kindtypeREAL2:
10736 real = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).real);
10737 imag = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).imaginary);
10738 break;
10739#endif
5ff904cd 10740
c7e4ee3a
CB
10741#if FFETARGET_okCOMPLEX3
10742 case FFEINFO_kindtypeREAL3:
10743 real = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).real);
10744 imag = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).imaginary);
10745 break;
10746#endif
5ff904cd 10747
c7e4ee3a
CB
10748#if FFETARGET_okCOMPLEX4
10749 case FFEINFO_kindtypeREAL4:
10750 real = ffetarget_value_real4 (ffebld_cu_val_complex4 (*cu).real);
10751 imag = ffetarget_value_real4 (ffebld_cu_val_complex4 (*cu).imaginary);
10752 break;
10753#endif
5ff904cd 10754
c7e4ee3a
CB
10755 default:
10756 assert ("bad REAL constant kind type" == NULL);
10757 /* Fall through. */
10758 case FFEINFO_kindtypeANY:
10759 return error_mark_node;
10760 }
10761 item = ffecom_build_complex_constant_ (tree_type,
10762 build_real (el_type, real),
10763 build_real (el_type, imag));
10764 }
10765 break;
5ff904cd 10766
c7e4ee3a
CB
10767 case FFEINFO_basictypeCHARACTER:
10768 { /* Happens only in DATA and similar contexts. */
10769 ffetargetCharacter1 val;
5ff904cd 10770
c7e4ee3a
CB
10771 switch (kt)
10772 {
10773#if FFETARGET_okCHARACTER1
10774 case FFEINFO_kindtypeLOGICAL1:
10775 val = ffebld_cu_val_character1 (*cu);
10776 break;
10777#endif
10778
10779 default:
10780 assert ("bad CHARACTER constant kind type" == NULL);
10781 /* Fall through. */
10782 case FFEINFO_kindtypeANY:
10783 return error_mark_node;
10784 }
10785 item = build_string (ffetarget_length_character1 (val),
10786 ffetarget_text_character1 (val));
10787 TREE_TYPE (item)
10788 = build_type_variant (build_array_type (char_type_node,
10789 build_range_type
10790 (integer_type_node,
10791 integer_one_node,
10792 build_int_2
10793 (ffetarget_length_character1
10794 (val), 0))),
10795 1, 0);
10796 }
10797 break;
5ff904cd 10798
c7e4ee3a
CB
10799 case FFEINFO_basictypeHOLLERITH:
10800 {
10801 ffetargetHollerith h;
5ff904cd 10802
c7e4ee3a 10803 h = ffebld_cu_val_hollerith (*cu);
5ff904cd 10804
c7e4ee3a
CB
10805 /* If not at least as wide as default INTEGER, widen it. */
10806 if (h.length >= FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE)
10807 item = build_string (h.length, h.text);
10808 else
10809 {
10810 char str[FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE];
5ff904cd 10811
c7e4ee3a
CB
10812 memcpy (str, h.text, h.length);
10813 memset (&str[h.length], ' ',
10814 FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE
10815 - h.length);
10816 item = build_string (FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE,
10817 str);
10818 }
10819 TREE_TYPE (item)
10820 = build_type_variant (build_array_type (char_type_node,
10821 build_range_type
10822 (integer_type_node,
10823 integer_one_node,
10824 build_int_2
10825 (h.length, 0))),
10826 1, 0);
10827 }
10828 break;
5ff904cd 10829
c7e4ee3a
CB
10830 case FFEINFO_basictypeTYPELESS:
10831 {
10832 ffetargetInteger1 ival;
10833 ffetargetTypeless tless;
10834 ffebad error;
5ff904cd 10835
c7e4ee3a
CB
10836 tless = ffebld_cu_val_typeless (*cu);
10837 error = ffetarget_convert_integer1_typeless (&ival, tless);
10838 assert (error == FFEBAD);
5ff904cd 10839
c7e4ee3a
CB
10840 item = build_int_2 ((int) ival, 0);
10841 }
10842 break;
5ff904cd 10843
c7e4ee3a
CB
10844 default:
10845 assert ("not yet on constant type" == NULL);
10846 /* Fall through. */
10847 case FFEINFO_basictypeANY:
10848 return error_mark_node;
5ff904cd 10849 }
5ff904cd 10850
c7e4ee3a 10851 TREE_CONSTANT (item) = 1;
5ff904cd 10852
c7e4ee3a 10853 return item;
5ff904cd
JL
10854}
10855
10856#endif
10857
c7e4ee3a
CB
10858/* Transform expression into constant tree.
10859
10860 If the expression can be transformed into a tree that is constant,
10861 that is done, and the tree returned. Else NULL_TREE is returned.
10862
10863 That way, a caller can attempt to provide compile-time initialization
10864 of a variable and, if that fails, *then* choose to start a new block
10865 and resort to using temporaries, as appropriate. */
5ff904cd 10866
5ff904cd 10867tree
c7e4ee3a 10868ffecom_const_expr (ffebld expr)
5ff904cd 10869{
c7e4ee3a
CB
10870 if (! expr)
10871 return integer_zero_node;
5ff904cd 10872
c7e4ee3a 10873 if (ffebld_op (expr) == FFEBLD_opANY)
5ff904cd
JL
10874 return error_mark_node;
10875
c7e4ee3a
CB
10876 if (ffebld_arity (expr) == 0
10877 && (ffebld_op (expr) != FFEBLD_opSYMTER
10878#if NEWCOMMON
10879 /* ~~Enable once common/equivalence is handled properly? */
10880 || ffebld_where (expr) == FFEINFO_whereCOMMON
5ff904cd 10881#endif
c7e4ee3a
CB
10882 || ffebld_where (expr) == FFEINFO_whereGLOBAL
10883 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
10884 {
10885 tree t;
5ff904cd 10886
c7e4ee3a
CB
10887 t = ffecom_expr (expr);
10888 assert (TREE_CONSTANT (t));
10889 return t;
10890 }
5ff904cd 10891
c7e4ee3a 10892 return NULL_TREE;
5ff904cd
JL
10893}
10894
c7e4ee3a 10895/* Handy way to make a field in a struct/union. */
5ff904cd
JL
10896
10897#if FFECOM_targetCURRENT == FFECOM_targetGCC
10898tree
c7e4ee3a
CB
10899ffecom_decl_field (tree context, tree prevfield,
10900 const char *name, tree type)
5ff904cd 10901{
c7e4ee3a 10902 tree field;
5ff904cd 10903
c7e4ee3a
CB
10904 field = build_decl (FIELD_DECL, get_identifier (name), type);
10905 DECL_CONTEXT (field) = context;
8ba77681 10906 DECL_ALIGN (field) = 0;
11cf4d18 10907 DECL_USER_ALIGN (field) = 0;
c7e4ee3a
CB
10908 if (prevfield != NULL_TREE)
10909 TREE_CHAIN (prevfield) = field;
5ff904cd 10910
c7e4ee3a 10911 return field;
5ff904cd
JL
10912}
10913
10914#endif
5ff904cd 10915
c7e4ee3a
CB
10916void
10917ffecom_close_include (FILE *f)
10918{
10919#if FFECOM_GCC_INCLUDE
10920 ffecom_close_include_ (f);
10921#endif
10922}
5ff904cd 10923
c7e4ee3a
CB
10924int
10925ffecom_decode_include_option (char *spec)
10926{
10927#if FFECOM_GCC_INCLUDE
10928 return ffecom_decode_include_option_ (spec);
10929#else
10930 return 1;
10931#endif
10932}
5ff904cd 10933
c7e4ee3a 10934/* End a compound statement (block). */
5ff904cd
JL
10935
10936#if FFECOM_targetCURRENT == FFECOM_targetGCC
10937tree
c7e4ee3a 10938ffecom_end_compstmt (void)
5ff904cd 10939{
c7e4ee3a
CB
10940 return bison_rule_compstmt_ ();
10941}
10942#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
5ff904cd 10943
c7e4ee3a 10944/* ffecom_end_transition -- Perform end transition on all symbols
5ff904cd 10945
c7e4ee3a 10946 ffecom_end_transition();
5ff904cd 10947
c7e4ee3a 10948 Calls ffecom_sym_end_transition for each global and local symbol. */
5ff904cd 10949
c7e4ee3a
CB
10950void
10951ffecom_end_transition ()
10952{
10953#if FFECOM_targetCURRENT == FFECOM_targetGCC
10954 ffebld item;
5ff904cd 10955#endif
5ff904cd 10956
c7e4ee3a
CB
10957 if (ffe_is_ffedebug ())
10958 fprintf (dmpout, "; end_stmt_transition\n");
86fc7a6c 10959
c7e4ee3a
CB
10960#if FFECOM_targetCURRENT == FFECOM_targetGCC
10961 ffecom_list_blockdata_ = NULL;
10962 ffecom_list_common_ = NULL;
10963#endif
86fc7a6c 10964
c7e4ee3a
CB
10965 ffesymbol_drive (ffecom_sym_end_transition);
10966 if (ffe_is_ffedebug ())
10967 {
10968 ffestorag_report ();
10969#if FFECOM_targetCURRENT == FFECOM_targetFFE
10970 ffesymbol_report_all ();
10971#endif
10972 }
5ff904cd
JL
10973
10974#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
10975 ffecom_start_progunit_ ();
10976
10977 for (item = ffecom_list_blockdata_;
10978 item != NULL;
10979 item = ffebld_trail (item))
10980 {
10981 ffebld callee;
10982 ffesymbol s;
10983 tree dt;
10984 tree t;
10985 tree var;
c7e4ee3a
CB
10986 static int number = 0;
10987
10988 callee = ffebld_head (item);
10989 s = ffebld_symter (callee);
10990 t = ffesymbol_hook (s).decl_tree;
10991 if (t == NULL_TREE)
10992 {
10993 s = ffecom_sym_transform_ (s);
10994 t = ffesymbol_hook (s).decl_tree;
10995 }
5ff904cd 10996
c7e4ee3a 10997 dt = build_pointer_type (TREE_TYPE (t));
5ff904cd 10998
c7e4ee3a
CB
10999 var = build_decl (VAR_DECL,
11000 ffecom_get_invented_identifier ("__g77_forceload_%d",
14657de8 11001 number++),
c7e4ee3a
CB
11002 dt);
11003 DECL_EXTERNAL (var) = 0;
11004 TREE_STATIC (var) = 1;
11005 TREE_PUBLIC (var) = 0;
11006 DECL_INITIAL (var) = error_mark_node;
11007 TREE_USED (var) = 1;
5ff904cd 11008
c7e4ee3a 11009 var = start_decl (var, FALSE);
702edf1d 11010
c7e4ee3a 11011 t = ffecom_1 (ADDR_EXPR, dt, t);
5ff904cd 11012
c7e4ee3a 11013 finish_decl (var, t, FALSE);
c7e4ee3a
CB
11014 }
11015
11016 /* This handles any COMMON areas that weren't referenced but have, for
11017 example, important initial data. */
11018
11019 for (item = ffecom_list_common_;
11020 item != NULL;
11021 item = ffebld_trail (item))
11022 ffecom_transform_common_ (ffebld_symter (ffebld_head (item)));
11023
11024 ffecom_list_common_ = NULL;
5ff904cd 11025#endif
c7e4ee3a 11026}
5ff904cd 11027
c7e4ee3a 11028/* ffecom_exec_transition -- Perform exec transition on all symbols
5ff904cd 11029
c7e4ee3a 11030 ffecom_exec_transition();
5ff904cd 11031
c7e4ee3a
CB
11032 Calls ffecom_sym_exec_transition for each global and local symbol.
11033 Make sure error updating not inhibited. */
5ff904cd 11034
c7e4ee3a
CB
11035void
11036ffecom_exec_transition ()
11037{
11038 bool inhibited;
5ff904cd 11039
c7e4ee3a
CB
11040 if (ffe_is_ffedebug ())
11041 fprintf (dmpout, "; exec_stmt_transition\n");
5ff904cd 11042
c7e4ee3a
CB
11043 inhibited = ffebad_inhibit ();
11044 ffebad_set_inhibit (FALSE);
5ff904cd 11045
c7e4ee3a
CB
11046 ffesymbol_drive (ffecom_sym_exec_transition); /* Don't retract! */
11047 ffeequiv_exec_transition (); /* Handle all pending EQUIVALENCEs. */
11048 if (ffe_is_ffedebug ())
5ff904cd 11049 {
c7e4ee3a
CB
11050 ffestorag_report ();
11051#if FFECOM_targetCURRENT == FFECOM_targetFFE
11052 ffesymbol_report_all ();
11053#endif
11054 }
5ff904cd 11055
c7e4ee3a
CB
11056 if (inhibited)
11057 ffebad_set_inhibit (TRUE);
11058}
5ff904cd 11059
c7e4ee3a 11060/* Handle assignment statement.
5ff904cd 11061
c7e4ee3a
CB
11062 Convert dest and source using ffecom_expr, then join them
11063 with an ASSIGN op and pass the whole thing to expand_expr_stmt. */
5ff904cd 11064
c7e4ee3a
CB
11065#if FFECOM_targetCURRENT == FFECOM_targetGCC
11066void
11067ffecom_expand_let_stmt (ffebld dest, ffebld source)
11068{
11069 tree dest_tree;
11070 tree dest_length;
11071 tree source_tree;
11072 tree expr_tree;
5ff904cd 11073
c7e4ee3a
CB
11074 if (ffeinfo_basictype (ffebld_info (dest)) != FFEINFO_basictypeCHARACTER)
11075 {
11076 bool dest_used;
d6cd84e0 11077 tree assign_temp;
5ff904cd 11078
c7e4ee3a
CB
11079 /* This attempts to replicate the test below, but must not be
11080 true when the test below is false. (Always err on the side
11081 of creating unused temporaries, to avoid ICEs.) */
11082 if (ffebld_op (dest) != FFEBLD_opSYMTER
11083 || ((dest_tree = ffesymbol_hook (ffebld_symter (dest)).decl_tree)
11084 && (TREE_CODE (dest_tree) != VAR_DECL
11085 || TREE_ADDRESSABLE (dest_tree))))
11086 {
11087 ffecom_prepare_expr_ (source, dest);
11088 dest_used = TRUE;
11089 }
11090 else
11091 {
11092 ffecom_prepare_expr_ (source, NULL);
11093 dest_used = FALSE;
11094 }
5ff904cd 11095
c7e4ee3a 11096 ffecom_prepare_expr_w (NULL_TREE, dest);
5ff904cd 11097
d6cd84e0
CB
11098 /* For COMPLEX assignment like C1=C2, if partial overlap is possible,
11099 create a temporary through which the assignment is to take place,
11100 since MODIFY_EXPR doesn't handle partial overlap properly. */
11101 if (ffebld_basictype (dest) == FFEINFO_basictypeCOMPLEX
11102 && ffecom_possible_partial_overlap_ (dest, source))
11103 {
11104 assign_temp = ffecom_make_tempvar ("complex_let",
11105 ffecom_tree_type
11106 [ffebld_basictype (dest)]
11107 [ffebld_kindtype (dest)],
11108 FFETARGET_charactersizeNONE,
11109 -1);
11110 }
11111 else
11112 assign_temp = NULL_TREE;
11113
c7e4ee3a 11114 ffecom_prepare_end ();
5ff904cd 11115
c7e4ee3a
CB
11116 dest_tree = ffecom_expr_w (NULL_TREE, dest);
11117 if (dest_tree == error_mark_node)
11118 return;
5ff904cd 11119
c7e4ee3a
CB
11120 if ((TREE_CODE (dest_tree) != VAR_DECL)
11121 || TREE_ADDRESSABLE (dest_tree))
11122 source_tree = ffecom_expr_ (source, dest_tree, dest, &dest_used,
11123 FALSE, FALSE);
11124 else
11125 {
11126 assert (! dest_used);
11127 dest_used = FALSE;
11128 source_tree = ffecom_expr (source);
11129 }
11130 if (source_tree == error_mark_node)
11131 return;
5ff904cd 11132
c7e4ee3a
CB
11133 if (dest_used)
11134 expr_tree = source_tree;
d6cd84e0
CB
11135 else if (assign_temp)
11136 {
11137#ifdef MOVE_EXPR
11138 /* The back end understands a conceptual move (evaluate source;
11139 store into dest), so use that, in case it can determine
11140 that it is going to use, say, two registers as temporaries
11141 anyway. So don't use the temp (and someday avoid generating
11142 it, once this code starts triggering regularly). */
11143 expr_tree = ffecom_2s (MOVE_EXPR, void_type_node,
11144 dest_tree,
11145 source_tree);
11146#else
11147 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11148 assign_temp,
11149 source_tree);
11150 expand_expr_stmt (expr_tree);
11151 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11152 dest_tree,
11153 assign_temp);
11154#endif
11155 }
c7e4ee3a
CB
11156 else
11157 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11158 dest_tree,
11159 source_tree);
5ff904cd 11160
c7e4ee3a
CB
11161 expand_expr_stmt (expr_tree);
11162 return;
11163 }
5ff904cd 11164
c7e4ee3a
CB
11165 ffecom_prepare_let_char_ (ffebld_size_known (dest), source);
11166 ffecom_prepare_expr_w (NULL_TREE, dest);
11167
11168 ffecom_prepare_end ();
11169
11170 ffecom_char_args_ (&dest_tree, &dest_length, dest);
11171 ffecom_let_char_ (dest_tree, dest_length, ffebld_size_known (dest),
11172 source);
5ff904cd
JL
11173}
11174
11175#endif
c7e4ee3a 11176/* ffecom_expr -- Transform expr into gcc tree
5ff904cd 11177
c7e4ee3a
CB
11178 tree t;
11179 ffebld expr; // FFE expression.
11180 tree = ffecom_expr(expr);
5ff904cd 11181
c7e4ee3a
CB
11182 Recursive descent on expr while making corresponding tree nodes and
11183 attaching type info and such. */
5ff904cd
JL
11184
11185#if FFECOM_targetCURRENT == FFECOM_targetGCC
11186tree
c7e4ee3a 11187ffecom_expr (ffebld expr)
5ff904cd 11188{
c7e4ee3a 11189 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, FALSE, FALSE);
5ff904cd 11190}
c7e4ee3a 11191
5ff904cd 11192#endif
c7e4ee3a 11193/* Like ffecom_expr, but return tree usable for assigned GOTO or FORMAT. */
5ff904cd 11194
c7e4ee3a
CB
11195#if FFECOM_targetCURRENT == FFECOM_targetGCC
11196tree
11197ffecom_expr_assign (ffebld expr)
11198{
11199 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE);
11200}
5ff904cd 11201
c7e4ee3a
CB
11202#endif
11203/* Like ffecom_expr_rw, but return tree usable for ASSIGN. */
5ff904cd
JL
11204
11205#if FFECOM_targetCURRENT == FFECOM_targetGCC
11206tree
c7e4ee3a 11207ffecom_expr_assign_w (ffebld expr)
5ff904cd 11208{
c7e4ee3a
CB
11209 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE);
11210}
5ff904cd 11211
5ff904cd 11212#endif
c7e4ee3a
CB
11213/* Transform expr for use as into read/write tree and stabilize the
11214 reference. Not for use on CHARACTER expressions.
5ff904cd 11215
c7e4ee3a
CB
11216 Recursive descent on expr while making corresponding tree nodes and
11217 attaching type info and such. */
5ff904cd 11218
c7e4ee3a
CB
11219#if FFECOM_targetCURRENT == FFECOM_targetGCC
11220tree
11221ffecom_expr_rw (tree type, ffebld expr)
11222{
11223 assert (expr != NULL);
11224 /* Different target types not yet supported. */
11225 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
11226
11227 return stabilize_reference (ffecom_expr (expr));
11228}
5ff904cd 11229
5ff904cd 11230#endif
c7e4ee3a
CB
11231/* Transform expr for use as into write tree and stabilize the
11232 reference. Not for use on CHARACTER expressions.
5ff904cd 11233
c7e4ee3a
CB
11234 Recursive descent on expr while making corresponding tree nodes and
11235 attaching type info and such. */
5ff904cd 11236
c7e4ee3a
CB
11237#if FFECOM_targetCURRENT == FFECOM_targetGCC
11238tree
11239ffecom_expr_w (tree type, ffebld expr)
11240{
11241 assert (expr != NULL);
11242 /* Different target types not yet supported. */
11243 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
11244
11245 return stabilize_reference (ffecom_expr (expr));
11246}
5ff904cd 11247
5ff904cd 11248#endif
c7e4ee3a
CB
11249/* Do global stuff. */
11250
11251#if FFECOM_targetCURRENT == FFECOM_targetGCC
11252void
11253ffecom_finish_compile ()
11254{
11255 assert (ffecom_outer_function_decl_ == NULL_TREE);
11256 assert (current_function_decl == NULL_TREE);
11257
11258 ffeglobal_drive (ffecom_finish_global_);
11259}
5ff904cd 11260
5ff904cd 11261#endif
c7e4ee3a
CB
11262/* Public entry point for front end to access finish_decl. */
11263
11264#if FFECOM_targetCURRENT == FFECOM_targetGCC
11265void
11266ffecom_finish_decl (tree decl, tree init, bool is_top_level)
11267{
11268 assert (!is_top_level);
11269 finish_decl (decl, init, FALSE);
11270}
5ff904cd 11271
5ff904cd 11272#endif
c7e4ee3a
CB
11273/* Finish a program unit. */
11274
11275#if FFECOM_targetCURRENT == FFECOM_targetGCC
11276void
11277ffecom_finish_progunit ()
11278{
11279 ffecom_end_compstmt ();
11280
11281 ffecom_previous_function_decl_ = current_function_decl;
11282 ffecom_which_entrypoint_decl_ = NULL_TREE;
11283
11284 finish_function (0);
11285}
5ff904cd 11286
5ff904cd 11287#endif
14657de8
KG
11288
11289/* Wrapper for get_identifier. pattern is sprintf-like. */
c7e4ee3a
CB
11290
11291#if FFECOM_targetCURRENT == FFECOM_targetGCC
11292tree
14657de8 11293ffecom_get_invented_identifier (const char *pattern, ...)
c7e4ee3a
CB
11294{
11295 tree decl;
11296 char *nam;
14657de8 11297 va_list ap;
c7e4ee3a 11298
14657de8
KG
11299 va_start (ap, pattern);
11300 if (vasprintf (&nam, pattern, ap) == 0)
11301 abort ();
11302 va_end (ap);
c7e4ee3a 11303 decl = get_identifier (nam);
14657de8 11304 free (nam);
c7e4ee3a 11305 IDENTIFIER_INVENTED (decl) = 1;
c7e4ee3a
CB
11306 return decl;
11307}
11308
11309ffeinfoBasictype
11310ffecom_gfrt_basictype (ffecomGfrt gfrt)
11311{
11312 assert (gfrt < FFECOM_gfrt);
11313
11314 switch (ffecom_gfrt_type_[gfrt])
11315 {
11316 case FFECOM_rttypeVOID_:
11317 case FFECOM_rttypeVOIDSTAR_:
11318 return FFEINFO_basictypeNONE;
11319
11320 case FFECOM_rttypeFTNINT_:
11321 return FFEINFO_basictypeINTEGER;
11322
11323 case FFECOM_rttypeINTEGER_:
11324 return FFEINFO_basictypeINTEGER;
11325
11326 case FFECOM_rttypeLONGINT_:
11327 return FFEINFO_basictypeINTEGER;
11328
11329 case FFECOM_rttypeLOGICAL_:
11330 return FFEINFO_basictypeLOGICAL;
11331
11332 case FFECOM_rttypeREAL_F2C_:
11333 case FFECOM_rttypeREAL_GNU_:
11334 return FFEINFO_basictypeREAL;
11335
11336 case FFECOM_rttypeCOMPLEX_F2C_:
11337 case FFECOM_rttypeCOMPLEX_GNU_:
11338 return FFEINFO_basictypeCOMPLEX;
11339
11340 case FFECOM_rttypeDOUBLE_:
11341 case FFECOM_rttypeDOUBLEREAL_:
11342 return FFEINFO_basictypeREAL;
11343
11344 case FFECOM_rttypeDBLCMPLX_F2C_:
11345 case FFECOM_rttypeDBLCMPLX_GNU_:
11346 return FFEINFO_basictypeCOMPLEX;
11347
11348 case FFECOM_rttypeCHARACTER_:
11349 return FFEINFO_basictypeCHARACTER;
11350
11351 default:
11352 return FFEINFO_basictypeANY;
11353 }
11354}
11355
11356ffeinfoKindtype
11357ffecom_gfrt_kindtype (ffecomGfrt gfrt)
11358{
11359 assert (gfrt < FFECOM_gfrt);
11360
11361 switch (ffecom_gfrt_type_[gfrt])
11362 {
11363 case FFECOM_rttypeVOID_:
11364 case FFECOM_rttypeVOIDSTAR_:
11365 return FFEINFO_kindtypeNONE;
5ff904cd 11366
c7e4ee3a
CB
11367 case FFECOM_rttypeFTNINT_:
11368 return FFEINFO_kindtypeINTEGER1;
5ff904cd 11369
c7e4ee3a
CB
11370 case FFECOM_rttypeINTEGER_:
11371 return FFEINFO_kindtypeINTEGER1;
5ff904cd 11372
c7e4ee3a
CB
11373 case FFECOM_rttypeLONGINT_:
11374 return FFEINFO_kindtypeINTEGER4;
5ff904cd 11375
c7e4ee3a
CB
11376 case FFECOM_rttypeLOGICAL_:
11377 return FFEINFO_kindtypeLOGICAL1;
5ff904cd 11378
c7e4ee3a
CB
11379 case FFECOM_rttypeREAL_F2C_:
11380 case FFECOM_rttypeREAL_GNU_:
11381 return FFEINFO_kindtypeREAL1;
5ff904cd 11382
c7e4ee3a
CB
11383 case FFECOM_rttypeCOMPLEX_F2C_:
11384 case FFECOM_rttypeCOMPLEX_GNU_:
11385 return FFEINFO_kindtypeREAL1;
5ff904cd 11386
c7e4ee3a
CB
11387 case FFECOM_rttypeDOUBLE_:
11388 case FFECOM_rttypeDOUBLEREAL_:
11389 return FFEINFO_kindtypeREAL2;
5ff904cd 11390
c7e4ee3a
CB
11391 case FFECOM_rttypeDBLCMPLX_F2C_:
11392 case FFECOM_rttypeDBLCMPLX_GNU_:
11393 return FFEINFO_kindtypeREAL2;
5ff904cd 11394
c7e4ee3a
CB
11395 case FFECOM_rttypeCHARACTER_:
11396 return FFEINFO_kindtypeCHARACTER1;
5ff904cd 11397
c7e4ee3a
CB
11398 default:
11399 return FFEINFO_kindtypeANY;
11400 }
11401}
5ff904cd 11402
c7e4ee3a
CB
11403void
11404ffecom_init_0 ()
11405{
11406 tree endlink;
11407 int i;
11408 int j;
11409 tree t;
11410 tree field;
11411 ffetype type;
11412 ffetype base_type;
7189a4b0
GK
11413 tree double_ftype_double;
11414 tree float_ftype_float;
11415 tree ldouble_ftype_ldouble;
11416 tree ffecom_tree_ptr_to_fun_type_void;
5ff904cd 11417
c7e4ee3a
CB
11418 /* This block of code comes from the now-obsolete cktyps.c. It checks
11419 whether the compiler environment is buggy in known ways, some of which
11420 would, if not explicitly checked here, result in subtle bugs in g77. */
5ff904cd 11421
c7e4ee3a
CB
11422 if (ffe_is_do_internal_checks ())
11423 {
11424 static char names[][12]
11425 =
11426 {"bar", "bletch", "foo", "foobar"};
11427 char *name;
11428 unsigned long ul;
11429 double fl;
5ff904cd 11430
c7e4ee3a 11431 name = bsearch ("foo", &names[0], ARRAY_SIZE (names), sizeof (names[0]),
b0791fa9 11432 (int (*)(const void *, const void *)) strcmp);
c7e4ee3a
CB
11433 if (name != (char *) &names[2])
11434 {
11435 assert ("bsearch doesn't work, #define FFEPROJ_BSEARCH 0 in proj.h"
11436 == NULL);
11437 abort ();
11438 }
5ff904cd 11439
c7e4ee3a
CB
11440 ul = strtoul ("123456789", NULL, 10);
11441 if (ul != 123456789L)
11442 {
11443 assert ("strtoul doesn't have enough range, #define FFEPROJ_STRTOUL 0\
11444 in proj.h" == NULL);
11445 abort ();
11446 }
5ff904cd 11447
c7e4ee3a
CB
11448 fl = atof ("56.789");
11449 if ((fl < 56.788) || (fl > 56.79))
11450 {
11451 assert ("atof not type double, fix your #include <stdio.h>"
11452 == NULL);
11453 abort ();
11454 }
11455 }
5ff904cd 11456
c7e4ee3a
CB
11457#if FFECOM_GCC_INCLUDE
11458 ffecom_initialize_char_syntax_ ();
11459#endif
5ff904cd 11460
c7e4ee3a
CB
11461 ffecom_outer_function_decl_ = NULL_TREE;
11462 current_function_decl = NULL_TREE;
11463 named_labels = NULL_TREE;
11464 current_binding_level = NULL_BINDING_LEVEL;
11465 free_binding_level = NULL_BINDING_LEVEL;
11466 /* Make the binding_level structure for global names. */
11467 pushlevel (0);
11468 global_binding_level = current_binding_level;
11469 current_binding_level->prep_state = 2;
5ff904cd 11470
81b3411c 11471 build_common_tree_nodes (1);
5ff904cd 11472
81b3411c 11473 /* Define `int' and `char' first so that dbx will output them first. */
c7e4ee3a
CB
11474 pushdecl (build_decl (TYPE_DECL, get_identifier ("int"),
11475 integer_type_node));
c7e4ee3a
CB
11476 pushdecl (build_decl (TYPE_DECL, get_identifier ("char"),
11477 char_type_node));
c7e4ee3a
CB
11478 pushdecl (build_decl (TYPE_DECL, get_identifier ("long int"),
11479 long_integer_type_node));
c7e4ee3a
CB
11480 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned int"),
11481 unsigned_type_node));
c7e4ee3a
CB
11482 pushdecl (build_decl (TYPE_DECL, get_identifier ("long unsigned int"),
11483 long_unsigned_type_node));
c7e4ee3a
CB
11484 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long int"),
11485 long_long_integer_type_node));
c7e4ee3a
CB
11486 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long unsigned int"),
11487 long_long_unsigned_type_node));
c7e4ee3a
CB
11488 pushdecl (build_decl (TYPE_DECL, get_identifier ("short int"),
11489 short_integer_type_node));
c7e4ee3a
CB
11490 pushdecl (build_decl (TYPE_DECL, get_identifier ("short unsigned int"),
11491 short_unsigned_type_node));
5ff904cd 11492
ff852b44
CB
11493 /* Set the sizetype before we make other types. This *should* be the
11494 first type we create. */
11495
11496 set_sizetype
11497 (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE))));
11498 ffecom_typesize_pointer_
11499 = TREE_INT_CST_LOW (TYPE_SIZE (sizetype)) / BITS_PER_UNIT;
11500
81b3411c 11501 build_common_tree_nodes_2 (0);
ff852b44 11502
c7e4ee3a 11503 /* Define both `signed char' and `unsigned char'. */
c7e4ee3a
CB
11504 pushdecl (build_decl (TYPE_DECL, get_identifier ("signed char"),
11505 signed_char_type_node));
5ff904cd 11506
c7e4ee3a
CB
11507 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned char"),
11508 unsigned_char_type_node));
5ff904cd 11509
c7e4ee3a
CB
11510 pushdecl (build_decl (TYPE_DECL, get_identifier ("float"),
11511 float_type_node));
c7e4ee3a
CB
11512 pushdecl (build_decl (TYPE_DECL, get_identifier ("double"),
11513 double_type_node));
c7e4ee3a
CB
11514 pushdecl (build_decl (TYPE_DECL, get_identifier ("long double"),
11515 long_double_type_node));
5ff904cd 11516
81b3411c 11517 /* For now, override what build_common_tree_nodes has done. */
c7e4ee3a 11518 complex_integer_type_node = ffecom_make_complex_type_ (integer_type_node);
81b3411c
BS
11519 complex_float_type_node = ffecom_make_complex_type_ (float_type_node);
11520 complex_double_type_node = ffecom_make_complex_type_ (double_type_node);
11521 complex_long_double_type_node
11522 = ffecom_make_complex_type_ (long_double_type_node);
11523
c7e4ee3a
CB
11524 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex int"),
11525 complex_integer_type_node));
c7e4ee3a
CB
11526 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex float"),
11527 complex_float_type_node));
c7e4ee3a
CB
11528 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex double"),
11529 complex_double_type_node));
c7e4ee3a
CB
11530 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex long double"),
11531 complex_long_double_type_node));
5ff904cd 11532
c7e4ee3a
CB
11533 pushdecl (build_decl (TYPE_DECL, get_identifier ("void"),
11534 void_type_node));
c7e4ee3a
CB
11535 /* We are not going to have real types in C with less than byte alignment,
11536 so we might as well not have any types that claim to have it. */
11537 TYPE_ALIGN (void_type_node) = BITS_PER_UNIT;
11cf4d18 11538 TYPE_USER_ALIGN (void_type_node) = 0;
5ff904cd 11539
c7e4ee3a 11540 string_type_node = build_pointer_type (char_type_node);
5ff904cd 11541
c7e4ee3a
CB
11542 ffecom_tree_fun_type_void
11543 = build_function_type (void_type_node, NULL_TREE);
5ff904cd 11544
c7e4ee3a
CB
11545 ffecom_tree_ptr_to_fun_type_void
11546 = build_pointer_type (ffecom_tree_fun_type_void);
5ff904cd 11547
c7e4ee3a 11548 endlink = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
5ff904cd 11549
c7e4ee3a
CB
11550 float_ftype_float
11551 = build_function_type (float_type_node,
11552 tree_cons (NULL_TREE, float_type_node, endlink));
5ff904cd 11553
c7e4ee3a
CB
11554 double_ftype_double
11555 = build_function_type (double_type_node,
11556 tree_cons (NULL_TREE, double_type_node, endlink));
5ff904cd 11557
c7e4ee3a
CB
11558 ldouble_ftype_ldouble
11559 = build_function_type (long_double_type_node,
11560 tree_cons (NULL_TREE, long_double_type_node,
11561 endlink));
5ff904cd 11562
c7e4ee3a
CB
11563 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11564 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11565 {
11566 ffecom_tree_type[i][j] = NULL_TREE;
11567 ffecom_tree_fun_type[i][j] = NULL_TREE;
11568 ffecom_tree_ptr_to_fun_type[i][j] = NULL_TREE;
11569 ffecom_f2c_typecode_[i][j] = -1;
11570 }
5ff904cd 11571
c7e4ee3a
CB
11572 /* Set up standard g77 types. Note that INTEGER and LOGICAL are set
11573 to size FLOAT_TYPE_SIZE because they have to be the same size as
11574 REAL, which also is FLOAT_TYPE_SIZE, according to the standard.
11575 Compiler options and other such stuff that change the ways these
11576 types are set should not affect this particular setup. */
5ff904cd 11577
c7e4ee3a
CB
11578 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1]
11579 = t = make_signed_type (FLOAT_TYPE_SIZE);
11580 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer"),
11581 t));
11582 type = ffetype_new ();
11583 base_type = type;
11584 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER1,
11585 type);
11586 ffetype_set_ams (type,
11587 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11588 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11589 ffetype_set_star (base_type,
11590 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11591 type);
11592 ffetype_set_kind (base_type, 1, type);
ff852b44 11593 ffecom_typesize_integer1_ = ffetype_size (type);
c7e4ee3a 11594 assert (ffetype_size (type) == sizeof (ffetargetInteger1));
5ff904cd 11595
c7e4ee3a
CB
11596 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER1]
11597 = t = make_unsigned_type (FLOAT_TYPE_SIZE); /* HOLLERITH means unsigned. */
11598 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned"),
11599 t));
5ff904cd 11600
c7e4ee3a
CB
11601 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER2]
11602 = t = make_signed_type (CHAR_TYPE_SIZE);
11603 pushdecl (build_decl (TYPE_DECL, get_identifier ("byte"),
11604 t));
11605 type = ffetype_new ();
11606 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER2,
11607 type);
11608 ffetype_set_ams (type,
11609 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11610 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11611 ffetype_set_star (base_type,
11612 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11613 type);
11614 ffetype_set_kind (base_type, 3, type);
11615 assert (ffetype_size (type) == sizeof (ffetargetInteger2));
5ff904cd 11616
c7e4ee3a
CB
11617 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER2]
11618 = t = make_unsigned_type (CHAR_TYPE_SIZE);
11619 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned byte"),
11620 t));
11621
11622 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER3]
11623 = t = make_signed_type (CHAR_TYPE_SIZE * 2);
11624 pushdecl (build_decl (TYPE_DECL, get_identifier ("word"),
11625 t));
11626 type = ffetype_new ();
11627 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER3,
11628 type);
11629 ffetype_set_ams (type,
11630 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11631 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11632 ffetype_set_star (base_type,
11633 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11634 type);
11635 ffetype_set_kind (base_type, 6, type);
11636 assert (ffetype_size (type) == sizeof (ffetargetInteger3));
5ff904cd 11637
c7e4ee3a
CB
11638 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER3]
11639 = t = make_unsigned_type (CHAR_TYPE_SIZE * 2);
11640 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned word"),
11641 t));
5ff904cd 11642
c7e4ee3a
CB
11643 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER4]
11644 = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
11645 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer4"),
11646 t));
11647 type = ffetype_new ();
11648 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER4,
11649 type);
11650 ffetype_set_ams (type,
11651 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11652 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11653 ffetype_set_star (base_type,
11654 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11655 type);
11656 ffetype_set_kind (base_type, 2, type);
11657 assert (ffetype_size (type) == sizeof (ffetargetInteger4));
5ff904cd 11658
c7e4ee3a
CB
11659 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER4]
11660 = t = make_unsigned_type (FLOAT_TYPE_SIZE * 2);
11661 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned4"),
11662 t));
5ff904cd 11663
c7e4ee3a
CB
11664#if 0
11665 if (ffe_is_do_internal_checks ()
11666 && LONG_TYPE_SIZE != FLOAT_TYPE_SIZE
11667 && LONG_TYPE_SIZE != CHAR_TYPE_SIZE
11668 && LONG_TYPE_SIZE != SHORT_TYPE_SIZE
11669 && LONG_TYPE_SIZE != LONG_LONG_TYPE_SIZE)
5ff904cd 11670 {
c7e4ee3a
CB
11671 fprintf (stderr, "Sorry, no g77 support for LONG_TYPE_SIZE (%d bits) yet.\n",
11672 LONG_TYPE_SIZE);
5ff904cd 11673 }
c7e4ee3a 11674#endif
5ff904cd 11675
c7e4ee3a
CB
11676 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL1]
11677 = t = make_signed_type (FLOAT_TYPE_SIZE);
11678 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical"),
11679 t));
11680 type = ffetype_new ();
11681 base_type = type;
11682 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL1,
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, 1, type);
11691 assert (ffetype_size (type) == sizeof (ffetargetLogical1));
5ff904cd 11692
c7e4ee3a
CB
11693 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL2]
11694 = t = make_signed_type (CHAR_TYPE_SIZE);
11695 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical2"),
11696 t));
11697 type = ffetype_new ();
11698 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL2,
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, 3, type);
11707 assert (ffetype_size (type) == sizeof (ffetargetLogical2));
5ff904cd 11708
c7e4ee3a
CB
11709 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL3]
11710 = t = make_signed_type (CHAR_TYPE_SIZE * 2);
11711 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical3"),
11712 t));
11713 type = ffetype_new ();
11714 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL3,
11715 type);
11716 ffetype_set_ams (type,
11717 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11718 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11719 ffetype_set_star (base_type,
11720 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11721 type);
11722 ffetype_set_kind (base_type, 6, type);
11723 assert (ffetype_size (type) == sizeof (ffetargetLogical3));
5ff904cd 11724
c7e4ee3a
CB
11725 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL4]
11726 = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
11727 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical4"),
11728 t));
11729 type = ffetype_new ();
11730 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL4,
11731 type);
11732 ffetype_set_ams (type,
11733 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11734 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11735 ffetype_set_star (base_type,
11736 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11737 type);
11738 ffetype_set_kind (base_type, 2, type);
11739 assert (ffetype_size (type) == sizeof (ffetargetLogical4));
5ff904cd 11740
c7e4ee3a
CB
11741 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
11742 = t = make_node (REAL_TYPE);
11743 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE;
11744 pushdecl (build_decl (TYPE_DECL, get_identifier ("real"),
11745 t));
11746 layout_type (t);
11747 type = ffetype_new ();
11748 base_type = type;
11749 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREAL1,
11750 type);
11751 ffetype_set_ams (type,
11752 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11753 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11754 ffetype_set_star (base_type,
11755 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11756 type);
11757 ffetype_set_kind (base_type, 1, type);
11758 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
11759 = FFETARGET_f2cTYREAL;
11760 assert (ffetype_size (type) == sizeof (ffetargetReal1));
5ff904cd 11761
c7e4ee3a
CB
11762 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREALDOUBLE]
11763 = t = make_node (REAL_TYPE);
11764 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE * 2; /* Always twice REAL. */
11765 pushdecl (build_decl (TYPE_DECL, get_identifier ("double precision"),
11766 t));
11767 layout_type (t);
11768 type = ffetype_new ();
11769 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREALDOUBLE,
11770 type);
11771 ffetype_set_ams (type,
11772 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11773 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11774 ffetype_set_star (base_type,
11775 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11776 type);
11777 ffetype_set_kind (base_type, 2, type);
11778 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]
11779 = FFETARGET_f2cTYDREAL;
11780 assert (ffetype_size (type) == sizeof (ffetargetReal2));
5ff904cd 11781
c7e4ee3a
CB
11782 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
11783 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]);
11784 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex"),
11785 t));
11786 type = ffetype_new ();
11787 base_type = type;
11788 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREAL1,
11789 type);
11790 ffetype_set_ams (type,
11791 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11792 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11793 ffetype_set_star (base_type,
11794 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11795 type);
11796 ffetype_set_kind (base_type, 1, type);
11797 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
11798 = FFETARGET_f2cTYCOMPLEX;
11799 assert (ffetype_size (type) == sizeof (ffetargetComplex1));
5ff904cd 11800
c7e4ee3a
CB
11801 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREALDOUBLE]
11802 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]);
11803 pushdecl (build_decl (TYPE_DECL, get_identifier ("double complex"),
11804 t));
11805 type = ffetype_new ();
11806 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREALDOUBLE,
11807 type);
11808 ffetype_set_ams (type,
11809 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11810 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11811 ffetype_set_star (base_type,
11812 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11813 type);
11814 ffetype_set_kind (base_type, 2,
11815 type);
11816 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL2]
11817 = FFETARGET_f2cTYDCOMPLEX;
11818 assert (ffetype_size (type) == sizeof (ffetargetComplex2));
5ff904cd 11819
c7e4ee3a 11820 /* Make function and ptr-to-function types for non-CHARACTER types. */
5ff904cd 11821
c7e4ee3a
CB
11822 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11823 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11824 {
11825 if ((t = ffecom_tree_type[i][j]) != NULL_TREE)
11826 {
11827 if (i == FFEINFO_basictypeINTEGER)
11828 {
11829 /* Figure out the smallest INTEGER type that can hold
11830 a pointer on this machine. */
11831 if (GET_MODE_SIZE (TYPE_MODE (t))
11832 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
11833 {
11834 if ((ffecom_pointer_kind_ == FFEINFO_kindtypeNONE)
11835 || (GET_MODE_SIZE (TYPE_MODE (ffecom_tree_type[i][ffecom_pointer_kind_]))
11836 > GET_MODE_SIZE (TYPE_MODE (t))))
11837 ffecom_pointer_kind_ = j;
11838 }
11839 }
11840 else if (i == FFEINFO_basictypeCOMPLEX)
11841 t = void_type_node;
11842 /* For f2c compatibility, REAL functions are really
11843 implemented as DOUBLE PRECISION. */
11844 else if ((i == FFEINFO_basictypeREAL)
11845 && (j == FFEINFO_kindtypeREAL1))
11846 t = ffecom_tree_type
11847 [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2];
5ff904cd 11848
c7e4ee3a
CB
11849 t = ffecom_tree_fun_type[i][j] = build_function_type (t,
11850 NULL_TREE);
11851 ffecom_tree_ptr_to_fun_type[i][j] = build_pointer_type (t);
11852 }
11853 }
5ff904cd 11854
c7e4ee3a 11855 /* Set up pointer types. */
5ff904cd 11856
c7e4ee3a 11857 if (ffecom_pointer_kind_ == FFEINFO_basictypeNONE)
400500c4 11858 fatal_error ("no INTEGER type can hold a pointer on this configuration");
c7e4ee3a
CB
11859 else if (0 && ffe_is_do_internal_checks ())
11860 fprintf (stderr, "Pointer type kt=%d\n", ffecom_pointer_kind_);
11861 ffetype_set_kind (ffeinfo_type (FFEINFO_basictypeINTEGER,
11862 FFEINFO_kindtypeINTEGERDEFAULT),
11863 7,
11864 ffeinfo_type (FFEINFO_basictypeINTEGER,
11865 ffecom_pointer_kind_));
5ff904cd 11866
c7e4ee3a
CB
11867 if (ffe_is_ugly_assign ())
11868 ffecom_label_kind_ = ffecom_pointer_kind_; /* Require ASSIGN etc to this. */
11869 else
11870 ffecom_label_kind_ = FFEINFO_kindtypeINTEGERDEFAULT;
11871 if (0 && ffe_is_do_internal_checks ())
11872 fprintf (stderr, "Label type kt=%d\n", ffecom_label_kind_);
5ff904cd 11873
c7e4ee3a
CB
11874 ffecom_integer_type_node
11875 = ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1];
11876 ffecom_integer_zero_node = convert (ffecom_integer_type_node,
11877 integer_zero_node);
11878 ffecom_integer_one_node = convert (ffecom_integer_type_node,
11879 integer_one_node);
5ff904cd 11880
c7e4ee3a
CB
11881 /* Yes, the "FLOAT_TYPE_SIZE" references below are intentional.
11882 Turns out that by TYLONG, runtime/libI77/lio.h really means
11883 "whatever size an ftnint is". For consistency and sanity,
11884 com.h and runtime/f2c.h.in agree that flag, ftnint, and ftlen
11885 all are INTEGER, which we also make out of whatever back-end
11886 integer type is FLOAT_TYPE_SIZE bits wide. This change, from
11887 LONG_TYPE_SIZE, for TYLONG and TYLOGICAL, was necessary to
11888 accommodate machines like the Alpha. Note that this suggests
11889 f2c and libf2c are missing a distinction perhaps needed on
11890 some machines between "int" and "long int". -- burley 0.5.5 950215 */
5ff904cd 11891
c7e4ee3a
CB
11892 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, FLOAT_TYPE_SIZE,
11893 FFETARGET_f2cTYLONG);
11894 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, SHORT_TYPE_SIZE,
11895 FFETARGET_f2cTYSHORT);
11896 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, CHAR_TYPE_SIZE,
11897 FFETARGET_f2cTYINT1);
11898 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, LONG_LONG_TYPE_SIZE,
11899 FFETARGET_f2cTYQUAD);
11900 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, FLOAT_TYPE_SIZE,
11901 FFETARGET_f2cTYLOGICAL);
11902 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, SHORT_TYPE_SIZE,
11903 FFETARGET_f2cTYLOGICAL2);
11904 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, CHAR_TYPE_SIZE,
11905 FFETARGET_f2cTYLOGICAL1);
11906 /* ~~~Not really such a type in libf2c, e.g. I/O support? */
11907 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, LONG_LONG_TYPE_SIZE,
11908 FFETARGET_f2cTYQUAD);
5ff904cd 11909
c7e4ee3a
CB
11910 /* CHARACTER stuff is all special-cased, so it is not handled in the above
11911 loop. CHARACTER items are built as arrays of unsigned char. */
5ff904cd 11912
c7e4ee3a
CB
11913 ffecom_tree_type[FFEINFO_basictypeCHARACTER]
11914 [FFEINFO_kindtypeCHARACTER1] = t = char_type_node;
11915 type = ffetype_new ();
11916 base_type = type;
11917 ffeinfo_set_type (FFEINFO_basictypeCHARACTER,
11918 FFEINFO_kindtypeCHARACTER1,
11919 type);
11920 ffetype_set_ams (type,
11921 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11922 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11923 ffetype_set_kind (base_type, 1, type);
11924 assert (ffetype_size (type)
11925 == sizeof (((ffetargetCharacter1) { 0, NULL }).text[0]));
5ff904cd 11926
c7e4ee3a
CB
11927 ffecom_tree_fun_type[FFEINFO_basictypeCHARACTER]
11928 [FFEINFO_kindtypeCHARACTER1] = ffecom_tree_fun_type_void;
11929 ffecom_tree_ptr_to_fun_type[FFEINFO_basictypeCHARACTER]
11930 [FFEINFO_kindtypeCHARACTER1]
11931 = ffecom_tree_ptr_to_fun_type_void;
11932 ffecom_f2c_typecode_[FFEINFO_basictypeCHARACTER][FFEINFO_kindtypeCHARACTER1]
11933 = FFETARGET_f2cTYCHAR;
5ff904cd 11934
c7e4ee3a
CB
11935 ffecom_f2c_typecode_[FFEINFO_basictypeANY][FFEINFO_kindtypeANY]
11936 = 0;
5ff904cd 11937
c7e4ee3a 11938 /* Make multi-return-value type and fields. */
5ff904cd 11939
c7e4ee3a 11940 ffecom_multi_type_node_ = make_node (UNION_TYPE);
5ff904cd 11941
c7e4ee3a 11942 field = NULL_TREE;
5ff904cd 11943
c7e4ee3a
CB
11944 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11945 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11946 {
11947 char name[30];
5ff904cd 11948
c7e4ee3a
CB
11949 if (ffecom_tree_type[i][j] == NULL_TREE)
11950 continue; /* Not supported. */
11951 sprintf (&name[0], "bt_%s_kt_%s",
11952 ffeinfo_basictype_string ((ffeinfoBasictype) i),
11953 ffeinfo_kindtype_string ((ffeinfoKindtype) j));
11954 ffecom_multi_fields_[i][j] = build_decl (FIELD_DECL,
11955 get_identifier (name),
11956 ffecom_tree_type[i][j]);
11957 DECL_CONTEXT (ffecom_multi_fields_[i][j])
11958 = ffecom_multi_type_node_;
8ba77681 11959 DECL_ALIGN (ffecom_multi_fields_[i][j]) = 0;
11cf4d18 11960 DECL_USER_ALIGN (ffecom_multi_fields_[i][j]) = 0;
c7e4ee3a
CB
11961 TREE_CHAIN (ffecom_multi_fields_[i][j]) = field;
11962 field = ffecom_multi_fields_[i][j];
11963 }
5ff904cd 11964
c7e4ee3a
CB
11965 TYPE_FIELDS (ffecom_multi_type_node_) = field;
11966 layout_type (ffecom_multi_type_node_);
5ff904cd 11967
c7e4ee3a
CB
11968 /* Subroutines usually return integer because they might have alternate
11969 returns. */
5ff904cd 11970
c7e4ee3a
CB
11971 ffecom_tree_subr_type
11972 = build_function_type (integer_type_node, NULL_TREE);
11973 ffecom_tree_ptr_to_subr_type
11974 = build_pointer_type (ffecom_tree_subr_type);
11975 ffecom_tree_blockdata_type
11976 = build_function_type (void_type_node, NULL_TREE);
5ff904cd 11977
c7e4ee3a 11978 builtin_function ("__builtin_sqrtf", float_ftype_float,
26db82d8 11979 BUILT_IN_FSQRT, BUILT_IN_NORMAL, "sqrtf");
c7e4ee3a 11980 builtin_function ("__builtin_fsqrt", double_ftype_double,
26db82d8 11981 BUILT_IN_FSQRT, BUILT_IN_NORMAL, "sqrt");
c7e4ee3a 11982 builtin_function ("__builtin_sqrtl", ldouble_ftype_ldouble,
26db82d8 11983 BUILT_IN_FSQRT, BUILT_IN_NORMAL, "sqrtl");
c7e4ee3a 11984 builtin_function ("__builtin_sinf", float_ftype_float,
26db82d8 11985 BUILT_IN_SIN, BUILT_IN_NORMAL, "sinf");
c7e4ee3a 11986 builtin_function ("__builtin_sin", double_ftype_double,
26db82d8 11987 BUILT_IN_SIN, BUILT_IN_NORMAL, "sin");
c7e4ee3a 11988 builtin_function ("__builtin_sinl", ldouble_ftype_ldouble,
26db82d8 11989 BUILT_IN_SIN, BUILT_IN_NORMAL, "sinl");
c7e4ee3a 11990 builtin_function ("__builtin_cosf", float_ftype_float,
26db82d8 11991 BUILT_IN_COS, BUILT_IN_NORMAL, "cosf");
c7e4ee3a 11992 builtin_function ("__builtin_cos", double_ftype_double,
26db82d8 11993 BUILT_IN_COS, BUILT_IN_NORMAL, "cos");
c7e4ee3a 11994 builtin_function ("__builtin_cosl", ldouble_ftype_ldouble,
26db82d8 11995 BUILT_IN_COS, BUILT_IN_NORMAL, "cosl");
5ff904cd 11996
c7e4ee3a
CB
11997#if BUILT_FOR_270
11998 pedantic_lvalues = FALSE;
5ff904cd 11999#endif
5ff904cd 12000
c7e4ee3a
CB
12001 ffecom_f2c_make_type_ (&ffecom_f2c_integer_type_node,
12002 FFECOM_f2cINTEGER,
12003 "integer");
12004 ffecom_f2c_make_type_ (&ffecom_f2c_address_type_node,
12005 FFECOM_f2cADDRESS,
12006 "address");
12007 ffecom_f2c_make_type_ (&ffecom_f2c_real_type_node,
12008 FFECOM_f2cREAL,
12009 "real");
12010 ffecom_f2c_make_type_ (&ffecom_f2c_doublereal_type_node,
12011 FFECOM_f2cDOUBLEREAL,
12012 "doublereal");
12013 ffecom_f2c_make_type_ (&ffecom_f2c_complex_type_node,
12014 FFECOM_f2cCOMPLEX,
12015 "complex");
12016 ffecom_f2c_make_type_ (&ffecom_f2c_doublecomplex_type_node,
12017 FFECOM_f2cDOUBLECOMPLEX,
12018 "doublecomplex");
12019 ffecom_f2c_make_type_ (&ffecom_f2c_longint_type_node,
12020 FFECOM_f2cLONGINT,
12021 "longint");
12022 ffecom_f2c_make_type_ (&ffecom_f2c_logical_type_node,
12023 FFECOM_f2cLOGICAL,
12024 "logical");
12025 ffecom_f2c_make_type_ (&ffecom_f2c_flag_type_node,
12026 FFECOM_f2cFLAG,
12027 "flag");
12028 ffecom_f2c_make_type_ (&ffecom_f2c_ftnlen_type_node,
12029 FFECOM_f2cFTNLEN,
12030 "ftnlen");
12031 ffecom_f2c_make_type_ (&ffecom_f2c_ftnint_type_node,
12032 FFECOM_f2cFTNINT,
12033 "ftnint");
5ff904cd 12034
c7e4ee3a
CB
12035 ffecom_f2c_ftnlen_zero_node
12036 = convert (ffecom_f2c_ftnlen_type_node, integer_zero_node);
5ff904cd 12037
c7e4ee3a
CB
12038 ffecom_f2c_ftnlen_one_node
12039 = convert (ffecom_f2c_ftnlen_type_node, integer_one_node);
5ff904cd 12040
c7e4ee3a
CB
12041 ffecom_f2c_ftnlen_two_node = build_int_2 (2, 0);
12042 TREE_TYPE (ffecom_f2c_ftnlen_two_node) = ffecom_integer_type_node;
5ff904cd 12043
c7e4ee3a
CB
12044 ffecom_f2c_ptr_to_ftnlen_type_node
12045 = build_pointer_type (ffecom_f2c_ftnlen_type_node);
5ff904cd 12046
c7e4ee3a
CB
12047 ffecom_f2c_ptr_to_ftnint_type_node
12048 = build_pointer_type (ffecom_f2c_ftnint_type_node);
5ff904cd 12049
c7e4ee3a
CB
12050 ffecom_f2c_ptr_to_integer_type_node
12051 = build_pointer_type (ffecom_f2c_integer_type_node);
5ff904cd 12052
c7e4ee3a
CB
12053 ffecom_f2c_ptr_to_real_type_node
12054 = build_pointer_type (ffecom_f2c_real_type_node);
5ff904cd 12055
c7e4ee3a
CB
12056 ffecom_float_zero_ = build_real (float_type_node, dconst0);
12057 ffecom_double_zero_ = build_real (double_type_node, dconst0);
12058 {
12059 REAL_VALUE_TYPE point_5;
5ff904cd 12060
c7e4ee3a
CB
12061#ifdef REAL_ARITHMETIC
12062 REAL_ARITHMETIC (point_5, RDIV_EXPR, dconst1, dconst2);
12063#else
12064 point_5 = .5;
12065#endif
12066 ffecom_float_half_ = build_real (float_type_node, point_5);
12067 ffecom_double_half_ = build_real (double_type_node, point_5);
12068 }
5ff904cd 12069
c7e4ee3a 12070 /* Do "extern int xargc;". */
5ff904cd 12071
c7e4ee3a
CB
12072 ffecom_tree_xargc_ = build_decl (VAR_DECL,
12073 get_identifier ("f__xargc"),
12074 integer_type_node);
12075 DECL_EXTERNAL (ffecom_tree_xargc_) = 1;
12076 TREE_STATIC (ffecom_tree_xargc_) = 1;
12077 TREE_PUBLIC (ffecom_tree_xargc_) = 1;
12078 ffecom_tree_xargc_ = start_decl (ffecom_tree_xargc_, FALSE);
12079 finish_decl (ffecom_tree_xargc_, NULL_TREE, FALSE);
5ff904cd 12080
c7e4ee3a
CB
12081#if 0 /* This is being fixed, and seems to be working now. */
12082 if ((FLOAT_TYPE_SIZE != 32)
12083 || (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))) != 32))
5ff904cd 12084 {
c7e4ee3a
CB
12085 warning ("configuration: REAL, INTEGER, and LOGICAL are %d bits wide,",
12086 (int) FLOAT_TYPE_SIZE);
12087 warning ("and pointers are %d bits wide, but g77 doesn't yet work",
12088 (int) TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))));
12089 warning ("properly unless they all are 32 bits wide.");
12090 warning ("Please keep this in mind before you report bugs. g77 should");
12091 warning ("support non-32-bit machines better as of version 0.6.");
12092 }
12093#endif
5ff904cd 12094
c7e4ee3a
CB
12095#if 0 /* Code in ste.c that would crash has been commented out. */
12096 if (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)
12097 < TYPE_PRECISION (string_type_node))
12098 /* I/O will probably crash. */
12099 warning ("configuration: char * holds %d bits, but ftnlen only %d",
12100 TYPE_PRECISION (string_type_node),
12101 TYPE_PRECISION (ffecom_f2c_ftnlen_type_node));
12102#endif
5ff904cd 12103
c7e4ee3a
CB
12104#if 0 /* ASSIGN-related stuff has been changed to accommodate this. */
12105 if (TYPE_PRECISION (ffecom_integer_type_node)
12106 < TYPE_PRECISION (string_type_node))
12107 /* ASSIGN 10 TO I will crash. */
12108 warning ("configuration: char * holds %d bits, but INTEGER only %d --\n\
12109 ASSIGN statement might fail",
12110 TYPE_PRECISION (string_type_node),
12111 TYPE_PRECISION (ffecom_integer_type_node));
12112#endif
12113}
5ff904cd 12114
c7e4ee3a
CB
12115#endif
12116/* ffecom_init_2 -- Initialize
5ff904cd 12117
c7e4ee3a 12118 ffecom_init_2(); */
5ff904cd 12119
c7e4ee3a
CB
12120#if FFECOM_targetCURRENT == FFECOM_targetGCC
12121void
12122ffecom_init_2 ()
12123{
12124 assert (ffecom_outer_function_decl_ == NULL_TREE);
12125 assert (current_function_decl == NULL_TREE);
12126 assert (ffecom_which_entrypoint_decl_ == NULL_TREE);
5ff904cd 12127
c7e4ee3a
CB
12128 ffecom_master_arglist_ = NULL;
12129 ++ffecom_num_fns_;
12130 ffecom_primary_entry_ = NULL;
12131 ffecom_is_altreturning_ = FALSE;
12132 ffecom_func_result_ = NULL_TREE;
12133 ffecom_multi_retval_ = NULL_TREE;
12134}
5ff904cd 12135
c7e4ee3a
CB
12136#endif
12137/* ffecom_list_expr -- Transform list of exprs into gcc tree
5ff904cd 12138
c7e4ee3a
CB
12139 tree t;
12140 ffebld expr; // FFE opITEM list.
12141 tree = ffecom_list_expr(expr);
5ff904cd 12142
c7e4ee3a 12143 List of actual args is transformed into corresponding gcc backend list. */
5ff904cd 12144
c7e4ee3a
CB
12145#if FFECOM_targetCURRENT == FFECOM_targetGCC
12146tree
12147ffecom_list_expr (ffebld expr)
5ff904cd 12148{
c7e4ee3a
CB
12149 tree list;
12150 tree *plist = &list;
12151 tree trail = NULL_TREE; /* Append char length args here. */
12152 tree *ptrail = &trail;
12153 tree length;
5ff904cd 12154
c7e4ee3a 12155 while (expr != NULL)
5ff904cd 12156 {
c7e4ee3a 12157 tree texpr = ffecom_arg_expr (ffebld_head (expr), &length);
5ff904cd 12158
c7e4ee3a
CB
12159 if (texpr == error_mark_node)
12160 return error_mark_node;
5ff904cd 12161
c7e4ee3a
CB
12162 *plist = build_tree_list (NULL_TREE, texpr);
12163 plist = &TREE_CHAIN (*plist);
12164 expr = ffebld_trail (expr);
12165 if (length != NULL_TREE)
5ff904cd 12166 {
c7e4ee3a
CB
12167 *ptrail = build_tree_list (NULL_TREE, length);
12168 ptrail = &TREE_CHAIN (*ptrail);
5ff904cd
JL
12169 }
12170 }
12171
c7e4ee3a 12172 *plist = trail;
5ff904cd 12173
c7e4ee3a
CB
12174 return list;
12175}
5ff904cd 12176
c7e4ee3a
CB
12177#endif
12178/* ffecom_list_ptr_to_expr -- Transform list of exprs into gcc tree
5ff904cd 12179
c7e4ee3a
CB
12180 tree t;
12181 ffebld expr; // FFE opITEM list.
12182 tree = ffecom_list_ptr_to_expr(expr);
5ff904cd 12183
c7e4ee3a
CB
12184 List of actual args is transformed into corresponding gcc backend list for
12185 use in calling an external procedure (vs. a statement function). */
5ff904cd 12186
c7e4ee3a
CB
12187#if FFECOM_targetCURRENT == FFECOM_targetGCC
12188tree
12189ffecom_list_ptr_to_expr (ffebld expr)
12190{
12191 tree list;
12192 tree *plist = &list;
12193 tree trail = NULL_TREE; /* Append char length args here. */
12194 tree *ptrail = &trail;
12195 tree length;
5ff904cd 12196
c7e4ee3a
CB
12197 while (expr != NULL)
12198 {
12199 tree texpr = ffecom_arg_ptr_to_expr (ffebld_head (expr), &length);
5ff904cd 12200
c7e4ee3a
CB
12201 if (texpr == error_mark_node)
12202 return error_mark_node;
5ff904cd 12203
c7e4ee3a
CB
12204 *plist = build_tree_list (NULL_TREE, texpr);
12205 plist = &TREE_CHAIN (*plist);
12206 expr = ffebld_trail (expr);
12207 if (length != NULL_TREE)
12208 {
12209 *ptrail = build_tree_list (NULL_TREE, length);
12210 ptrail = &TREE_CHAIN (*ptrail);
12211 }
12212 }
5ff904cd 12213
c7e4ee3a 12214 *plist = trail;
5ff904cd 12215
c7e4ee3a
CB
12216 return list;
12217}
5ff904cd 12218
c7e4ee3a
CB
12219#endif
12220/* Obtain gcc's LABEL_DECL tree for label. */
5ff904cd 12221
c7e4ee3a
CB
12222#if FFECOM_targetCURRENT == FFECOM_targetGCC
12223tree
12224ffecom_lookup_label (ffelab label)
12225{
12226 tree glabel;
5ff904cd 12227
c7e4ee3a
CB
12228 if (ffelab_hook (label) == NULL_TREE)
12229 {
12230 char labelname[16];
5ff904cd 12231
c7e4ee3a
CB
12232 switch (ffelab_type (label))
12233 {
12234 case FFELAB_typeLOOPEND:
12235 case FFELAB_typeNOTLOOP:
12236 case FFELAB_typeENDIF:
12237 sprintf (labelname, "%" ffelabValue_f "u", ffelab_value (label));
12238 glabel = build_decl (LABEL_DECL, get_identifier (labelname),
12239 void_type_node);
12240 DECL_CONTEXT (glabel) = current_function_decl;
12241 DECL_MODE (glabel) = VOIDmode;
12242 break;
5ff904cd 12243
c7e4ee3a 12244 case FFELAB_typeFORMAT:
c7e4ee3a
CB
12245 glabel = build_decl (VAR_DECL,
12246 ffecom_get_invented_identifier
14657de8 12247 ("__g77_format_%d", (int) ffelab_value (label)),
c7e4ee3a
CB
12248 build_type_variant (build_array_type
12249 (char_type_node,
12250 NULL_TREE),
12251 1, 0));
12252 TREE_CONSTANT (glabel) = 1;
12253 TREE_STATIC (glabel) = 1;
611081b2 12254 DECL_CONTEXT (glabel) = current_function_decl;
c7e4ee3a 12255 DECL_INITIAL (glabel) = NULL;
6c418184 12256 make_decl_rtl (glabel, NULL);
c7e4ee3a 12257 expand_decl (glabel);
5ff904cd 12258
7189a4b0 12259 ffecom_save_tree_forever (glabel);
5ff904cd 12260
c7e4ee3a 12261 break;
5ff904cd 12262
c7e4ee3a
CB
12263 case FFELAB_typeANY:
12264 glabel = error_mark_node;
12265 break;
5ff904cd 12266
c7e4ee3a
CB
12267 default:
12268 assert ("bad label type" == NULL);
12269 glabel = NULL;
12270 break;
12271 }
12272 ffelab_set_hook (label, glabel);
12273 }
12274 else
12275 {
12276 glabel = ffelab_hook (label);
12277 }
5ff904cd 12278
c7e4ee3a
CB
12279 return glabel;
12280}
5ff904cd 12281
c7e4ee3a
CB
12282#endif
12283/* Stabilizes the arguments. Don't use this if the lhs and rhs come from
12284 a single source specification (as in the fourth argument of MVBITS).
12285 If the type is NULL_TREE, the type of lhs is used to make the type of
12286 the MODIFY_EXPR. */
5ff904cd 12287
c7e4ee3a
CB
12288#if FFECOM_targetCURRENT == FFECOM_targetGCC
12289tree
12290ffecom_modify (tree newtype, tree lhs,
12291 tree rhs)
12292{
12293 if (lhs == error_mark_node || rhs == error_mark_node)
12294 return error_mark_node;
5ff904cd 12295
c7e4ee3a
CB
12296 if (newtype == NULL_TREE)
12297 newtype = TREE_TYPE (lhs);
5ff904cd 12298
c7e4ee3a
CB
12299 if (TREE_SIDE_EFFECTS (lhs))
12300 lhs = stabilize_reference (lhs);
5ff904cd 12301
c7e4ee3a
CB
12302 return ffecom_2s (MODIFY_EXPR, newtype, lhs, rhs);
12303}
5ff904cd 12304
c7e4ee3a 12305#endif
5ff904cd 12306
c7e4ee3a 12307/* Register source file name. */
5ff904cd 12308
c7e4ee3a 12309void
b0791fa9 12310ffecom_file (const char *name)
c7e4ee3a
CB
12311{
12312#if FFECOM_GCC_INCLUDE
12313 ffecom_file_ (name);
12314#endif
12315}
5ff904cd 12316
c7e4ee3a 12317/* ffecom_notify_init_storage -- An aggregate storage is now fully init'ed
5ff904cd 12318
c7e4ee3a
CB
12319 ffestorag st;
12320 ffecom_notify_init_storage(st);
5ff904cd 12321
c7e4ee3a
CB
12322 Gets called when all possible units in an aggregate storage area (a LOCAL
12323 with equivalences or a COMMON) have been initialized. The initialization
12324 info either is in ffestorag_init or, if that is NULL,
12325 ffestorag_accretion:
5ff904cd 12326
c7e4ee3a
CB
12327 ffestorag_init may contain an opCONTER or opARRTER. opCONTER may occur
12328 even for an array if the array is one element in length!
5ff904cd 12329
c7e4ee3a
CB
12330 ffestorag_accretion will contain an opACCTER. It is much like an
12331 opARRTER except it has an ffebit object in it instead of just a size.
12332 The back end can use the info in the ffebit object, if it wants, to
12333 reduce the amount of actual initialization, but in any case it should
12334 kill the ffebit object when done. Also, set accretion to NULL but
12335 init to a non-NULL value.
5ff904cd 12336
c7e4ee3a
CB
12337 After performing initialization, DO NOT set init to NULL, because that'll
12338 tell the front end it is ok for more initialization to happen. Instead,
12339 set init to an opANY expression or some such thing that you can use to
12340 tell that you've already initialized the object.
5ff904cd 12341
c7e4ee3a
CB
12342 27-Oct-91 JCB 1.1
12343 Support two-pass FFE. */
5ff904cd 12344
c7e4ee3a
CB
12345void
12346ffecom_notify_init_storage (ffestorag st)
12347{
12348 ffebld init; /* The initialization expression. */
12349#if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12350 ffetargetOffset size; /* The size of the entity. */
12351 ffetargetAlign pad; /* Its initial padding. */
12352#endif
12353
12354 if (ffestorag_init (st) == NULL)
5ff904cd 12355 {
c7e4ee3a
CB
12356 init = ffestorag_accretion (st);
12357 assert (init != NULL);
12358 ffestorag_set_accretion (st, NULL);
12359 ffestorag_set_accretes (st, 0);
12360
12361#if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12362 /* For GNU backend, just turn ACCTER into ARRTER and proceed. */
12363 size = ffebld_accter_size (init);
12364 pad = ffebld_accter_pad (init);
12365 ffebit_kill (ffebld_accter_bits (init));
12366 ffebld_set_op (init, FFEBLD_opARRTER);
12367 ffebld_set_arrter (init, ffebld_accter (init));
12368 ffebld_arrter_set_size (init, size);
12369 ffebld_arrter_set_pad (init, size);
12370#endif
12371
12372#if FFECOM_TWOPASS
12373 ffestorag_set_init (st, init);
12374#endif
5ff904cd 12375 }
c7e4ee3a
CB
12376#if FFECOM_ONEPASS
12377 else
12378 init = ffestorag_init (st);
5ff904cd
JL
12379#endif
12380
c7e4ee3a
CB
12381#if FFECOM_ONEPASS /* Process the inits, wipe 'em out. */
12382 ffestorag_set_init (st, ffebld_new_any ());
5ff904cd 12383
c7e4ee3a
CB
12384 if (ffebld_op (init) == FFEBLD_opANY)
12385 return; /* Oh, we already did this! */
5ff904cd 12386
c7e4ee3a
CB
12387#if FFECOM_targetCURRENT == FFECOM_targetFFE
12388 {
12389 ffesymbol s;
5ff904cd 12390
c7e4ee3a
CB
12391 if (ffestorag_symbol (st) != NULL)
12392 s = ffestorag_symbol (st);
12393 else
12394 s = ffestorag_typesymbol (st);
5ff904cd 12395
c7e4ee3a
CB
12396 fprintf (dmpout, "= initialize_storage \"%s\" ",
12397 (s != NULL) ? ffesymbol_text (s) : "(unnamed)");
12398 ffebld_dump (init);
12399 fputc ('\n', dmpout);
12400 }
12401#endif
5ff904cd 12402
c7e4ee3a
CB
12403#endif /* if FFECOM_ONEPASS */
12404}
5ff904cd 12405
c7e4ee3a 12406/* ffecom_notify_init_symbol -- A symbol is now fully init'ed
5ff904cd 12407
c7e4ee3a
CB
12408 ffesymbol s;
12409 ffecom_notify_init_symbol(s);
5ff904cd 12410
c7e4ee3a
CB
12411 Gets called when all possible units in a symbol (not placed in COMMON
12412 or involved in EQUIVALENCE, unless it as yet has no ffestorag object)
12413 have been initialized. The initialization info either is in
12414 ffesymbol_init or, if that is NULL, ffesymbol_accretion:
5ff904cd 12415
c7e4ee3a
CB
12416 ffesymbol_init may contain an opCONTER or opARRTER. opCONTER may occur
12417 even for an array if the array is one element in length!
5ff904cd 12418
c7e4ee3a
CB
12419 ffesymbol_accretion will contain an opACCTER. It is much like an
12420 opARRTER except it has an ffebit object in it instead of just a size.
12421 The back end can use the info in the ffebit object, if it wants, to
12422 reduce the amount of actual initialization, but in any case it should
12423 kill the ffebit object when done. Also, set accretion to NULL but
12424 init to a non-NULL value.
5ff904cd 12425
c7e4ee3a
CB
12426 After performing initialization, DO NOT set init to NULL, because that'll
12427 tell the front end it is ok for more initialization to happen. Instead,
12428 set init to an opANY expression or some such thing that you can use to
12429 tell that you've already initialized the object.
5ff904cd 12430
c7e4ee3a
CB
12431 27-Oct-91 JCB 1.1
12432 Support two-pass FFE. */
5ff904cd 12433
c7e4ee3a
CB
12434void
12435ffecom_notify_init_symbol (ffesymbol s)
12436{
12437 ffebld init; /* The initialization expression. */
12438#if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12439 ffetargetOffset size; /* The size of the entity. */
12440 ffetargetAlign pad; /* Its initial padding. */
12441#endif
5ff904cd 12442
c7e4ee3a
CB
12443 if (ffesymbol_storage (s) == NULL)
12444 return; /* Do nothing until COMMON/EQUIVALENCE
12445 possibilities checked. */
5ff904cd 12446
c7e4ee3a
CB
12447 if ((ffesymbol_init (s) == NULL)
12448 && ((init = ffesymbol_accretion (s)) != NULL))
12449 {
12450 ffesymbol_set_accretion (s, NULL);
12451 ffesymbol_set_accretes (s, 0);
5ff904cd 12452
c7e4ee3a
CB
12453#if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12454 /* For GNU backend, just turn ACCTER into ARRTER and proceed. */
12455 size = ffebld_accter_size (init);
12456 pad = ffebld_accter_pad (init);
12457 ffebit_kill (ffebld_accter_bits (init));
12458 ffebld_set_op (init, FFEBLD_opARRTER);
12459 ffebld_set_arrter (init, ffebld_accter (init));
12460 ffebld_arrter_set_size (init, size);
12461 ffebld_arrter_set_pad (init, size);
12462#endif
5ff904cd 12463
c7e4ee3a
CB
12464#if FFECOM_TWOPASS
12465 ffesymbol_set_init (s, init);
12466#endif
12467 }
12468#if FFECOM_ONEPASS
12469 else
12470 init = ffesymbol_init (s);
12471#endif
5ff904cd 12472
c7e4ee3a
CB
12473#if FFECOM_ONEPASS
12474 ffesymbol_set_init (s, ffebld_new_any ());
5ff904cd 12475
c7e4ee3a
CB
12476 if (ffebld_op (init) == FFEBLD_opANY)
12477 return; /* Oh, we already did this! */
5ff904cd 12478
c7e4ee3a
CB
12479#if FFECOM_targetCURRENT == FFECOM_targetFFE
12480 fprintf (dmpout, "= initialize_symbol \"%s\" ", ffesymbol_text (s));
12481 ffebld_dump (init);
12482 fputc ('\n', dmpout);
12483#endif
5ff904cd 12484
c7e4ee3a
CB
12485#endif /* if FFECOM_ONEPASS */
12486}
5ff904cd 12487
c7e4ee3a 12488/* ffecom_notify_primary_entry -- Learn which is the primary entry point
5ff904cd 12489
c7e4ee3a
CB
12490 ffesymbol s;
12491 ffecom_notify_primary_entry(s);
5ff904cd 12492
c7e4ee3a
CB
12493 Gets called when implicit or explicit PROGRAM statement seen or when
12494 FUNCTION, SUBROUTINE, or BLOCK DATA statement seen, with the primary
12495 global symbol that serves as the entry point. */
5ff904cd 12496
c7e4ee3a
CB
12497void
12498ffecom_notify_primary_entry (ffesymbol s)
12499{
12500 ffecom_primary_entry_ = s;
12501 ffecom_primary_entry_kind_ = ffesymbol_kind (s);
5ff904cd 12502
c7e4ee3a
CB
12503 if ((ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
12504 || (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE))
12505 ffecom_primary_entry_is_proc_ = TRUE;
12506 else
12507 ffecom_primary_entry_is_proc_ = FALSE;
5ff904cd 12508
c7e4ee3a
CB
12509 if (!ffe_is_silent ())
12510 {
12511 if (ffecom_primary_entry_kind_ == FFEINFO_kindPROGRAM)
12512 fprintf (stderr, "%s:\n", ffesymbol_text (s));
12513 else
12514 fprintf (stderr, " %s:\n", ffesymbol_text (s));
12515 }
5ff904cd 12516
c7e4ee3a
CB
12517#if FFECOM_targetCURRENT == FFECOM_targetGCC
12518 if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
12519 {
12520 ffebld list;
12521 ffebld arg;
5ff904cd 12522
c7e4ee3a
CB
12523 for (list = ffesymbol_dummyargs (s);
12524 list != NULL;
12525 list = ffebld_trail (list))
12526 {
12527 arg = ffebld_head (list);
12528 if (ffebld_op (arg) == FFEBLD_opSTAR)
12529 {
12530 ffecom_is_altreturning_ = TRUE;
12531 break;
12532 }
12533 }
12534 }
12535#endif
12536}
5ff904cd 12537
c7e4ee3a
CB
12538FILE *
12539ffecom_open_include (char *name, ffewhereLine l, ffewhereColumn c)
12540{
12541#if FFECOM_GCC_INCLUDE
12542 return ffecom_open_include_ (name, l, c);
12543#else
12544 return fopen (name, "r");
5ff904cd 12545#endif
c7e4ee3a 12546}
5ff904cd 12547
c7e4ee3a 12548/* ffecom_ptr_to_expr -- Transform expr into gcc tree with & in front
5ff904cd 12549
c7e4ee3a
CB
12550 tree t;
12551 ffebld expr; // FFE expression.
12552 tree = ffecom_ptr_to_expr(expr);
5ff904cd 12553
c7e4ee3a 12554 Like ffecom_expr, but sticks address-of in front of most things. */
5ff904cd 12555
c7e4ee3a
CB
12556#if FFECOM_targetCURRENT == FFECOM_targetGCC
12557tree
12558ffecom_ptr_to_expr (ffebld expr)
12559{
12560 tree item;
12561 ffeinfoBasictype bt;
12562 ffeinfoKindtype kt;
12563 ffesymbol s;
5ff904cd 12564
c7e4ee3a 12565 assert (expr != NULL);
5ff904cd 12566
c7e4ee3a
CB
12567 switch (ffebld_op (expr))
12568 {
12569 case FFEBLD_opSYMTER:
12570 s = ffebld_symter (expr);
12571 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
12572 {
12573 ffecomGfrt ix;
5ff904cd 12574
c7e4ee3a
CB
12575 ix = ffeintrin_gfrt_indirect (ffebld_symter_implementation (expr));
12576 assert (ix != FFECOM_gfrt);
12577 if ((item = ffecom_gfrt_[ix]) == NULL_TREE)
12578 {
12579 ffecom_make_gfrt_ (ix);
12580 item = ffecom_gfrt_[ix];
12581 }
12582 }
12583 else
12584 {
12585 item = ffesymbol_hook (s).decl_tree;
12586 if (item == NULL_TREE)
12587 {
12588 s = ffecom_sym_transform_ (s);
12589 item = ffesymbol_hook (s).decl_tree;
12590 }
12591 }
12592 assert (item != NULL);
12593 if (item == error_mark_node)
12594 return item;
12595 if (!ffesymbol_hook (s).addr)
12596 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12597 item);
12598 return item;
5ff904cd 12599
c7e4ee3a 12600 case FFEBLD_opARRAYREF:
ff852b44 12601 return ffecom_arrayref_ (NULL_TREE, expr, 1);
5ff904cd 12602
c7e4ee3a 12603 case FFEBLD_opCONTER:
5ff904cd 12604
c7e4ee3a
CB
12605 bt = ffeinfo_basictype (ffebld_info (expr));
12606 kt = ffeinfo_kindtype (ffebld_info (expr));
5ff904cd 12607
c7e4ee3a
CB
12608 item = ffecom_constantunion (&ffebld_constant_union
12609 (ffebld_conter (expr)), bt, kt,
12610 ffecom_tree_type[bt][kt]);
12611 if (item == error_mark_node)
12612 return error_mark_node;
12613 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12614 item);
12615 return item;
5ff904cd 12616
c7e4ee3a
CB
12617 case FFEBLD_opANY:
12618 return error_mark_node;
5ff904cd 12619
c7e4ee3a
CB
12620 default:
12621 bt = ffeinfo_basictype (ffebld_info (expr));
12622 kt = ffeinfo_kindtype (ffebld_info (expr));
12623
12624 item = ffecom_expr (expr);
12625 if (item == error_mark_node)
12626 return error_mark_node;
12627
12628 /* The back end currently optimizes a bit too zealously for us, in that
12629 we fail JCB001 if the following block of code is omitted. It checks
12630 to see if the transformed expression is a symbol or array reference,
12631 and encloses it in a SAVE_EXPR if that is the case. */
12632
12633 STRIP_NOPS (item);
12634 if ((TREE_CODE (item) == VAR_DECL)
12635 || (TREE_CODE (item) == PARM_DECL)
12636 || (TREE_CODE (item) == RESULT_DECL)
12637 || (TREE_CODE (item) == INDIRECT_REF)
12638 || (TREE_CODE (item) == ARRAY_REF)
12639 || (TREE_CODE (item) == COMPONENT_REF)
12640#ifdef OFFSET_REF
12641 || (TREE_CODE (item) == OFFSET_REF)
12642#endif
12643 || (TREE_CODE (item) == BUFFER_REF)
12644 || (TREE_CODE (item) == REALPART_EXPR)
12645 || (TREE_CODE (item) == IMAGPART_EXPR))
12646 {
12647 item = ffecom_save_tree (item);
12648 }
12649
12650 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12651 item);
12652 return item;
12653 }
12654
12655 assert ("fall-through error" == NULL);
12656 return error_mark_node;
5ff904cd
JL
12657}
12658
12659#endif
c7e4ee3a 12660/* Obtain a temp var with given data type.
5ff904cd 12661
c7e4ee3a
CB
12662 size is FFETARGET_charactersizeNONE for a non-CHARACTER type
12663 or >= 0 for a CHARACTER type.
5ff904cd 12664
c7e4ee3a 12665 elements is -1 for a scalar or > 0 for an array of type. */
5ff904cd
JL
12666
12667#if FFECOM_targetCURRENT == FFECOM_targetGCC
12668tree
c7e4ee3a
CB
12669ffecom_make_tempvar (const char *commentary, tree type,
12670 ffetargetCharacterSize size, int elements)
5ff904cd 12671{
c7e4ee3a
CB
12672 tree t;
12673 static int mynumber;
5ff904cd 12674
c7e4ee3a 12675 assert (current_binding_level->prep_state < 2);
702edf1d 12676
c7e4ee3a
CB
12677 if (type == error_mark_node)
12678 return error_mark_node;
702edf1d 12679
c7e4ee3a
CB
12680 if (size != FFETARGET_charactersizeNONE)
12681 type = build_array_type (type,
12682 build_range_type (ffecom_f2c_ftnlen_type_node,
12683 ffecom_f2c_ftnlen_one_node,
12684 build_int_2 (size, 0)));
12685 if (elements != -1)
12686 type = build_array_type (type,
12687 build_range_type (integer_type_node,
12688 integer_zero_node,
12689 build_int_2 (elements - 1,
12690 0)));
12691 t = build_decl (VAR_DECL,
12692 ffecom_get_invented_identifier ("__g77_%s_%d",
12693 commentary,
12694 mynumber++),
12695 type);
5ff904cd 12696
c7e4ee3a
CB
12697 t = start_decl (t, FALSE);
12698 finish_decl (t, NULL_TREE, FALSE);
12699
c7e4ee3a
CB
12700 return t;
12701}
5ff904cd 12702#endif
5ff904cd 12703
c7e4ee3a 12704/* Prepare argument pointer to expression.
5ff904cd 12705
c7e4ee3a
CB
12706 Like ffecom_prepare_expr, except for expressions to be evaluated
12707 via ffecom_arg_ptr_to_expr. */
5ff904cd 12708
c7e4ee3a
CB
12709void
12710ffecom_prepare_arg_ptr_to_expr (ffebld expr)
5ff904cd 12711{
c7e4ee3a
CB
12712 /* ~~For now, it seems to be the same thing. */
12713 ffecom_prepare_expr (expr);
12714 return;
12715}
702edf1d 12716
c7e4ee3a 12717/* End of preparations. */
702edf1d 12718
c7e4ee3a
CB
12719bool
12720ffecom_prepare_end (void)
12721{
12722 int prep_state = current_binding_level->prep_state;
5ff904cd 12723
c7e4ee3a
CB
12724 assert (prep_state < 2);
12725 current_binding_level->prep_state = 2;
5ff904cd 12726
c7e4ee3a 12727 return (prep_state == 1) ? TRUE : FALSE;
5ff904cd
JL
12728}
12729
c7e4ee3a 12730/* Prepare expression.
5ff904cd 12731
c7e4ee3a
CB
12732 This is called before any code is generated for the current block.
12733 It scans the expression, declares any temporaries that might be needed
12734 during evaluation of the expression, and stores those temporaries in
12735 the appropriate "hook" fields of the expression. `dest', if not NULL,
12736 specifies the destination that ffecom_expr_ will see, in case that
12737 helps avoid generating unused temporaries.
12738
12739 ~~Improve to avoid allocating unused temporaries by taking `dest'
12740 into account vis-a-vis aliasing requirements of complex/character
12741 functions. */
12742
12743void
12744ffecom_prepare_expr_ (ffebld expr, ffebld dest UNUSED)
5ff904cd 12745{
c7e4ee3a
CB
12746 ffeinfoBasictype bt;
12747 ffeinfoKindtype kt;
12748 ffetargetCharacterSize sz;
12749 tree tempvar = NULL_TREE;
5ff904cd 12750
c7e4ee3a
CB
12751 assert (current_binding_level->prep_state < 2);
12752
12753 if (! expr)
12754 return;
12755
12756 bt = ffeinfo_basictype (ffebld_info (expr));
12757 kt = ffeinfo_kindtype (ffebld_info (expr));
12758 sz = ffeinfo_size (ffebld_info (expr));
12759
12760 /* Generate whatever temporaries are needed to represent the result
12761 of the expression. */
12762
47d98fa2
CB
12763 if (bt == FFEINFO_basictypeCHARACTER)
12764 {
12765 while (ffebld_op (expr) == FFEBLD_opPAREN)
12766 expr = ffebld_left (expr);
12767 }
12768
c7e4ee3a 12769 switch (ffebld_op (expr))
5ff904cd 12770 {
c7e4ee3a
CB
12771 default:
12772 /* Don't make temps for SYMTER, CONTER, etc. */
12773 if (ffebld_arity (expr) == 0)
12774 break;
5ff904cd 12775
c7e4ee3a 12776 switch (bt)
5ff904cd 12777 {
c7e4ee3a
CB
12778 case FFEINFO_basictypeCOMPLEX:
12779 if (ffebld_op (expr) == FFEBLD_opFUNCREF)
12780 {
12781 ffesymbol s;
5ff904cd 12782
c7e4ee3a
CB
12783 if (ffebld_op (ffebld_left (expr)) != FFEBLD_opSYMTER)
12784 break;
5ff904cd 12785
c7e4ee3a
CB
12786 s = ffebld_symter (ffebld_left (expr));
12787 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT
68779408
CB
12788 || (ffesymbol_where (s) != FFEINFO_whereINTRINSIC
12789 && ! ffesymbol_is_f2c (s))
12790 || (ffesymbol_where (s) == FFEINFO_whereINTRINSIC
12791 && ! ffe_is_f2c_library ()))
c7e4ee3a
CB
12792 break;
12793 }
12794 else if (ffebld_op (expr) == FFEBLD_opPOWER)
12795 {
12796 /* Requires special treatment. There's no POW_CC function
12797 in libg2c, so POW_ZZ is used, which means we always
12798 need a double-complex temp, not a single-complex. */
12799 kt = FFEINFO_kindtypeREAL2;
12800 }
12801 else if (ffebld_op (expr) != FFEBLD_opDIVIDE)
12802 /* The other ops don't need temps for complex operands. */
12803 break;
5ff904cd 12804
c7e4ee3a
CB
12805 /* ~~~Avoid making temps for some intrinsics, such as AIMAG(C),
12806 REAL(C). See 19990325-0.f, routine `check', for cases. */
12807 tempvar = ffecom_make_tempvar ("complex",
12808 ffecom_tree_type
12809 [FFEINFO_basictypeCOMPLEX][kt],
12810 FFETARGET_charactersizeNONE,
12811 -1);
5ff904cd
JL
12812 break;
12813
c7e4ee3a
CB
12814 case FFEINFO_basictypeCHARACTER:
12815 if (ffebld_op (expr) != FFEBLD_opFUNCREF)
12816 break;
12817
12818 if (sz == FFETARGET_charactersizeNONE)
12819 /* ~~Kludge alert! This should someday be fixed. */
12820 sz = 24;
12821
12822 tempvar = ffecom_make_tempvar ("char", char_type_node, sz, -1);
5ff904cd
JL
12823 break;
12824
12825 default:
5ff904cd
JL
12826 break;
12827 }
c7e4ee3a 12828 break;
5ff904cd 12829
c7e4ee3a
CB
12830#ifdef HAHA
12831 case FFEBLD_opPOWER:
12832 {
12833 tree rtype, ltype;
12834 tree rtmp, ltmp, result;
5ff904cd 12835
c7e4ee3a
CB
12836 ltype = ffecom_type_expr (ffebld_left (expr));
12837 rtype = ffecom_type_expr (ffebld_right (expr));
5ff904cd 12838
c7e4ee3a
CB
12839 rtmp = ffecom_make_tempvar (rtype, FFETARGET_charactersizeNONE, -1);
12840 ltmp = ffecom_make_tempvar (ltype, FFETARGET_charactersizeNONE, -1);
12841 result = ffecom_make_tempvar (ltype, FFETARGET_charactersizeNONE, -1);
5ff904cd 12842
c7e4ee3a
CB
12843 tempvar = make_tree_vec (3);
12844 TREE_VEC_ELT (tempvar, 0) = rtmp;
12845 TREE_VEC_ELT (tempvar, 1) = ltmp;
12846 TREE_VEC_ELT (tempvar, 2) = result;
12847 }
12848 break;
12849#endif /* HAHA */
5ff904cd 12850
c7e4ee3a
CB
12851 case FFEBLD_opCONCATENATE:
12852 {
12853 /* This gets special handling, because only one set of temps
12854 is needed for a tree of these -- the tree is treated as
12855 a flattened list of concatenations when generating code. */
5ff904cd 12856
c7e4ee3a
CB
12857 ffecomConcatList_ catlist;
12858 tree ltmp, itmp, result;
12859 int count;
12860 int i;
5ff904cd 12861
c7e4ee3a
CB
12862 catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
12863 count = ffecom_concat_list_count_ (catlist);
5ff904cd 12864
c7e4ee3a
CB
12865 if (count >= 2)
12866 {
12867 ltmp
12868 = ffecom_make_tempvar ("concat_len",
12869 ffecom_f2c_ftnlen_type_node,
12870 FFETARGET_charactersizeNONE, count);
12871 itmp
12872 = ffecom_make_tempvar ("concat_item",
12873 ffecom_f2c_address_type_node,
12874 FFETARGET_charactersizeNONE, count);
12875 result
12876 = ffecom_make_tempvar ("concat_res",
12877 char_type_node,
12878 ffecom_concat_list_maxlen_ (catlist),
12879 -1);
12880
12881 tempvar = make_tree_vec (3);
12882 TREE_VEC_ELT (tempvar, 0) = ltmp;
12883 TREE_VEC_ELT (tempvar, 1) = itmp;
12884 TREE_VEC_ELT (tempvar, 2) = result;
12885 }
5ff904cd 12886
c7e4ee3a
CB
12887 for (i = 0; i < count; ++i)
12888 ffecom_prepare_arg_ptr_to_expr (ffecom_concat_list_expr_ (catlist,
12889 i));
5ff904cd 12890
c7e4ee3a 12891 ffecom_concat_list_kill_ (catlist);
5ff904cd 12892
c7e4ee3a
CB
12893 if (tempvar)
12894 {
12895 ffebld_nonter_set_hook (expr, tempvar);
12896 current_binding_level->prep_state = 1;
12897 }
12898 }
12899 return;
5ff904cd 12900
c7e4ee3a
CB
12901 case FFEBLD_opCONVERT:
12902 if (bt == FFEINFO_basictypeCHARACTER
12903 && ((ffebld_size_known (ffebld_left (expr))
12904 == FFETARGET_charactersizeNONE)
12905 || (ffebld_size_known (ffebld_left (expr)) >= sz)))
12906 tempvar = ffecom_make_tempvar ("convert", char_type_node, sz, -1);
12907 break;
12908 }
5ff904cd 12909
c7e4ee3a
CB
12910 if (tempvar)
12911 {
12912 ffebld_nonter_set_hook (expr, tempvar);
12913 current_binding_level->prep_state = 1;
12914 }
5ff904cd 12915
c7e4ee3a 12916 /* Prepare subexpressions for this expr. */
5ff904cd 12917
c7e4ee3a 12918 switch (ffebld_op (expr))
5ff904cd 12919 {
c7e4ee3a
CB
12920 case FFEBLD_opPERCENT_LOC:
12921 ffecom_prepare_ptr_to_expr (ffebld_left (expr));
12922 break;
5ff904cd 12923
c7e4ee3a
CB
12924 case FFEBLD_opPERCENT_VAL:
12925 case FFEBLD_opPERCENT_REF:
12926 ffecom_prepare_expr (ffebld_left (expr));
12927 break;
5ff904cd 12928
c7e4ee3a
CB
12929 case FFEBLD_opPERCENT_DESCR:
12930 ffecom_prepare_arg_ptr_to_expr (ffebld_left (expr));
12931 break;
5ff904cd 12932
c7e4ee3a
CB
12933 case FFEBLD_opITEM:
12934 {
12935 ffebld item;
5ff904cd 12936
c7e4ee3a
CB
12937 for (item = expr;
12938 item != NULL;
12939 item = ffebld_trail (item))
12940 if (ffebld_head (item) != NULL)
12941 ffecom_prepare_expr (ffebld_head (item));
12942 }
12943 break;
5ff904cd 12944
c7e4ee3a
CB
12945 default:
12946 /* Need to handle character conversion specially. */
12947 switch (ffebld_arity (expr))
12948 {
12949 case 2:
12950 ffecom_prepare_expr (ffebld_left (expr));
12951 ffecom_prepare_expr (ffebld_right (expr));
12952 break;
5ff904cd 12953
c7e4ee3a
CB
12954 case 1:
12955 ffecom_prepare_expr (ffebld_left (expr));
12956 break;
5ff904cd 12957
c7e4ee3a
CB
12958 default:
12959 break;
12960 }
12961 }
5ff904cd 12962
c7e4ee3a 12963 return;
5ff904cd
JL
12964}
12965
c7e4ee3a 12966/* Prepare expression for reading and writing.
5ff904cd 12967
c7e4ee3a
CB
12968 Like ffecom_prepare_expr, except for expressions to be evaluated
12969 via ffecom_expr_rw. */
5ff904cd 12970
c7e4ee3a
CB
12971void
12972ffecom_prepare_expr_rw (tree type, ffebld expr)
12973{
12974 /* This is all we support for now. */
12975 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
5ff904cd 12976
c7e4ee3a
CB
12977 /* ~~For now, it seems to be the same thing. */
12978 ffecom_prepare_expr (expr);
12979 return;
12980}
5ff904cd 12981
c7e4ee3a 12982/* Prepare expression for writing.
5ff904cd 12983
c7e4ee3a
CB
12984 Like ffecom_prepare_expr, except for expressions to be evaluated
12985 via ffecom_expr_w. */
5ff904cd
JL
12986
12987void
c7e4ee3a 12988ffecom_prepare_expr_w (tree type, ffebld expr)
5ff904cd 12989{
c7e4ee3a
CB
12990 /* This is all we support for now. */
12991 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
5ff904cd 12992
c7e4ee3a
CB
12993 /* ~~For now, it seems to be the same thing. */
12994 ffecom_prepare_expr (expr);
12995 return;
12996}
5ff904cd 12997
c7e4ee3a 12998/* Prepare expression for returning.
5ff904cd 12999
c7e4ee3a
CB
13000 Like ffecom_prepare_expr, except for expressions to be evaluated
13001 via ffecom_return_expr. */
5ff904cd 13002
c7e4ee3a
CB
13003void
13004ffecom_prepare_return_expr (ffebld expr)
13005{
13006 assert (current_binding_level->prep_state < 2);
5ff904cd 13007
c7e4ee3a
CB
13008 if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE
13009 && ffecom_is_altreturning_
13010 && expr != NULL)
13011 ffecom_prepare_expr (expr);
13012}
5ff904cd 13013
c7e4ee3a 13014/* Prepare pointer to expression.
5ff904cd 13015
c7e4ee3a
CB
13016 Like ffecom_prepare_expr, except for expressions to be evaluated
13017 via ffecom_ptr_to_expr. */
5ff904cd 13018
c7e4ee3a
CB
13019void
13020ffecom_prepare_ptr_to_expr (ffebld expr)
13021{
13022 /* ~~For now, it seems to be the same thing. */
13023 ffecom_prepare_expr (expr);
13024 return;
5ff904cd
JL
13025}
13026
c7e4ee3a 13027/* Transform expression into constant pointer-to-expression tree.
5ff904cd 13028
c7e4ee3a
CB
13029 If the expression can be transformed into a pointer-to-expression tree
13030 that is constant, that is done, and the tree returned. Else NULL_TREE
13031 is returned.
5ff904cd 13032
c7e4ee3a
CB
13033 That way, a caller can attempt to provide compile-time initialization
13034 of a variable and, if that fails, *then* choose to start a new block
13035 and resort to using temporaries, as appropriate. */
5ff904cd 13036
c7e4ee3a
CB
13037tree
13038ffecom_ptr_to_const_expr (ffebld expr)
5ff904cd 13039{
c7e4ee3a
CB
13040 if (! expr)
13041 return integer_zero_node;
5ff904cd 13042
c7e4ee3a
CB
13043 if (ffebld_op (expr) == FFEBLD_opANY)
13044 return error_mark_node;
5ff904cd 13045
c7e4ee3a
CB
13046 if (ffebld_arity (expr) == 0
13047 && (ffebld_op (expr) != FFEBLD_opSYMTER
13048 || ffebld_where (expr) == FFEINFO_whereCOMMON
13049 || ffebld_where (expr) == FFEINFO_whereGLOBAL
13050 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
5ff904cd 13051 {
c7e4ee3a
CB
13052 tree t;
13053
13054 t = ffecom_ptr_to_expr (expr);
13055 assert (TREE_CONSTANT (t));
13056 return t;
5ff904cd
JL
13057 }
13058
c7e4ee3a
CB
13059 return NULL_TREE;
13060}
13061
13062/* ffecom_return_expr -- Returns return-value expr given alt return expr
13063
13064 tree rtn; // NULL_TREE means use expand_null_return()
13065 ffebld expr; // NULL if no alt return expr to RETURN stmt
13066 rtn = ffecom_return_expr(expr);
13067
13068 Based on the program unit type and other info (like return function
13069 type, return master function type when alternate ENTRY points,
13070 whether subroutine has any alternate RETURN points, etc), returns the
13071 appropriate expression to be returned to the caller, or NULL_TREE
13072 meaning no return value or the caller expects it to be returned somewhere
13073 else (which is handled by other parts of this module). */
13074
5ff904cd 13075#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
13076tree
13077ffecom_return_expr (ffebld expr)
13078{
13079 tree rtn;
13080
13081 switch (ffecom_primary_entry_kind_)
5ff904cd 13082 {
c7e4ee3a
CB
13083 case FFEINFO_kindPROGRAM:
13084 case FFEINFO_kindBLOCKDATA:
13085 rtn = NULL_TREE;
13086 break;
5ff904cd 13087
c7e4ee3a
CB
13088 case FFEINFO_kindSUBROUTINE:
13089 if (!ffecom_is_altreturning_)
13090 rtn = NULL_TREE; /* No alt returns, never an expr. */
13091 else if (expr == NULL)
13092 rtn = integer_zero_node;
13093 else
13094 rtn = ffecom_expr (expr);
13095 break;
13096
13097 case FFEINFO_kindFUNCTION:
13098 if ((ffecom_multi_retval_ != NULL_TREE)
13099 || (ffesymbol_basictype (ffecom_primary_entry_)
13100 == FFEINFO_basictypeCHARACTER)
13101 || ((ffesymbol_basictype (ffecom_primary_entry_)
13102 == FFEINFO_basictypeCOMPLEX)
13103 && (ffecom_num_entrypoints_ == 0)
13104 && ffesymbol_is_f2c (ffecom_primary_entry_)))
13105 { /* Value is returned by direct assignment
13106 into (implicit) dummy. */
13107 rtn = NULL_TREE;
13108 break;
5ff904cd 13109 }
c7e4ee3a
CB
13110 rtn = ffecom_func_result_;
13111#if 0
13112 /* Spurious error if RETURN happens before first reference! So elide
13113 this code. In particular, for debugging registry, rtn should always
13114 be non-null after all, but TREE_USED won't be set until we encounter
13115 a reference in the code. Perfectly okay (but weird) code that,
13116 e.g., has "GOTO 20;10 RETURN;20 RTN=0;GOTO 10", would result in
13117 this diagnostic for no reason. Have people use -O -Wuninitialized
13118 and leave it to the back end to find obviously weird cases. */
5ff904cd 13119
c7e4ee3a
CB
13120 /* Used to "assert(rtn != NULL_TREE);" here, but it's kind of a valid
13121 situation; if the return value has never been referenced, it won't
13122 have a tree under 2pass mode. */
13123 if ((rtn == NULL_TREE)
13124 || !TREE_USED (rtn))
13125 {
13126 ffebad_start (FFEBAD_RETURN_VALUE_UNSET);
13127 ffebad_here (0, ffesymbol_where_line (ffecom_primary_entry_),
13128 ffesymbol_where_column (ffecom_primary_entry_));
13129 ffebad_string (ffesymbol_text (ffesymbol_funcresult
13130 (ffecom_primary_entry_)));
13131 ffebad_finish ();
13132 }
5ff904cd 13133#endif
c7e4ee3a 13134 break;
5ff904cd 13135
c7e4ee3a
CB
13136 default:
13137 assert ("bad unit kind" == NULL);
13138 case FFEINFO_kindANY:
13139 rtn = error_mark_node;
13140 break;
13141 }
5ff904cd 13142
c7e4ee3a
CB
13143 return rtn;
13144}
5ff904cd 13145
c7e4ee3a
CB
13146#endif
13147/* Do save_expr only if tree is not error_mark_node. */
5ff904cd
JL
13148
13149#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
13150tree
13151ffecom_save_tree (tree t)
5ff904cd 13152{
c7e4ee3a 13153 return save_expr (t);
5ff904cd 13154}
5ff904cd 13155#endif
c7e4ee3a
CB
13156
13157/* Start a compound statement (block). */
5ff904cd
JL
13158
13159#if FFECOM_targetCURRENT == FFECOM_targetGCC
13160void
c7e4ee3a 13161ffecom_start_compstmt (void)
5ff904cd 13162{
c7e4ee3a 13163 bison_rule_pushlevel_ ();
5ff904cd 13164}
c7e4ee3a 13165#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
5ff904cd 13166
c7e4ee3a 13167/* Public entry point for front end to access start_decl. */
5ff904cd
JL
13168
13169#if FFECOM_targetCURRENT == FFECOM_targetGCC
13170tree
c7e4ee3a 13171ffecom_start_decl (tree decl, bool is_initialized)
5ff904cd 13172{
c7e4ee3a
CB
13173 DECL_INITIAL (decl) = is_initialized ? error_mark_node : NULL_TREE;
13174 return start_decl (decl, FALSE);
13175}
5ff904cd 13176
c7e4ee3a
CB
13177#endif
13178/* ffecom_sym_commit -- Symbol's state being committed to reality
5ff904cd 13179
c7e4ee3a
CB
13180 ffesymbol s;
13181 ffecom_sym_commit(s);
5ff904cd 13182
c7e4ee3a
CB
13183 Does whatever the backend needs when a symbol is committed after having
13184 been backtrackable for a period of time. */
5ff904cd 13185
c7e4ee3a
CB
13186#if FFECOM_targetCURRENT == FFECOM_targetGCC
13187void
13188ffecom_sym_commit (ffesymbol s UNUSED)
13189{
13190 assert (!ffesymbol_retractable ());
13191}
5ff904cd 13192
c7e4ee3a
CB
13193#endif
13194/* ffecom_sym_end_transition -- Perform end transition on all symbols
5ff904cd 13195
c7e4ee3a 13196 ffecom_sym_end_transition();
5ff904cd 13197
c7e4ee3a
CB
13198 Does backend-specific stuff and also calls ffest_sym_end_transition
13199 to do the necessary FFE stuff.
5ff904cd 13200
c7e4ee3a
CB
13201 Backtracking is never enabled when this fn is called, so don't worry
13202 about it. */
5ff904cd 13203
c7e4ee3a
CB
13204ffesymbol
13205ffecom_sym_end_transition (ffesymbol s)
13206{
13207 ffestorag st;
5ff904cd 13208
c7e4ee3a 13209 assert (!ffesymbol_retractable ());
5ff904cd 13210
c7e4ee3a 13211 s = ffest_sym_end_transition (s);
5ff904cd 13212
c7e4ee3a
CB
13213#if FFECOM_targetCURRENT == FFECOM_targetGCC
13214 if ((ffesymbol_kind (s) == FFEINFO_kindBLOCKDATA)
13215 && (ffesymbol_where (s) == FFEINFO_whereGLOBAL))
13216 {
13217 ffecom_list_blockdata_
13218 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
13219 FFEINTRIN_specNONE,
13220 FFEINTRIN_impNONE),
13221 ffecom_list_blockdata_);
5ff904cd 13222 }
5ff904cd 13223#endif
5ff904cd 13224
c7e4ee3a
CB
13225 /* This is where we finally notice that a symbol has partial initialization
13226 and finalize it. */
5ff904cd 13227
c7e4ee3a
CB
13228 if (ffesymbol_accretion (s) != NULL)
13229 {
13230 assert (ffesymbol_init (s) == NULL);
13231 ffecom_notify_init_symbol (s);
13232 }
13233 else if (((st = ffesymbol_storage (s)) != NULL)
13234 && ((st = ffestorag_parent (st)) != NULL)
13235 && (ffestorag_accretion (st) != NULL))
13236 {
13237 assert (ffestorag_init (st) == NULL);
13238 ffecom_notify_init_storage (st);
13239 }
5ff904cd
JL
13240
13241#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
13242 if ((ffesymbol_kind (s) == FFEINFO_kindCOMMON)
13243 && (ffesymbol_where (s) == FFEINFO_whereLOCAL)
13244 && (ffesymbol_storage (s) != NULL))
13245 {
13246 ffecom_list_common_
13247 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
13248 FFEINTRIN_specNONE,
13249 FFEINTRIN_impNONE),
13250 ffecom_list_common_);
13251 }
13252#endif
5ff904cd 13253
c7e4ee3a
CB
13254 return s;
13255}
5ff904cd 13256
c7e4ee3a 13257/* ffecom_sym_exec_transition -- Perform exec transition on all symbols
5ff904cd 13258
c7e4ee3a 13259 ffecom_sym_exec_transition();
5ff904cd 13260
c7e4ee3a
CB
13261 Does backend-specific stuff and also calls ffest_sym_exec_transition
13262 to do the necessary FFE stuff.
5ff904cd 13263
c7e4ee3a
CB
13264 See the long-winded description in ffecom_sym_learned for info
13265 on handling the situation where backtracking is inhibited. */
5ff904cd 13266
c7e4ee3a
CB
13267ffesymbol
13268ffecom_sym_exec_transition (ffesymbol s)
13269{
13270 s = ffest_sym_exec_transition (s);
5ff904cd 13271
c7e4ee3a
CB
13272 return s;
13273}
5ff904cd 13274
c7e4ee3a 13275/* ffecom_sym_learned -- Initial or more info gained on symbol after exec
5ff904cd 13276
c7e4ee3a
CB
13277 ffesymbol s;
13278 s = ffecom_sym_learned(s);
5ff904cd 13279
c7e4ee3a
CB
13280 Called when a new symbol is seen after the exec transition or when more
13281 info (perhaps) is gained for an UNCERTAIN symbol. The symbol state when
13282 it arrives here is that all its latest info is updated already, so its
13283 state may be UNCERTAIN or UNDERSTOOD, it might already have the hook
13284 field filled in if its gone through here or exec_transition first, and
13285 so on.
5ff904cd 13286
c7e4ee3a
CB
13287 The backend probably wants to check ffesymbol_retractable() to see if
13288 backtracking is in effect. If so, the FFE's changes to the symbol may
13289 be retracted (undone) or committed (ratified), at which time the
13290 appropriate ffecom_sym_retract or _commit function will be called
13291 for that function.
5ff904cd 13292
c7e4ee3a
CB
13293 If the backend has its own backtracking mechanism, great, use it so that
13294 committal is a simple operation. Though it doesn't make much difference,
13295 I suppose: the reason for tentative symbol evolution in the FFE is to
13296 enable error detection in weird incorrect statements early and to disable
13297 incorrect error detection on a correct statement. The backend is not
13298 likely to introduce any information that'll get involved in these
13299 considerations, so it is probably just fine that the implementation
13300 model for this fn and for _exec_transition is to not do anything
13301 (besides the required FFE stuff) if ffesymbol_retractable() returns TRUE
13302 and instead wait until ffecom_sym_commit is called (which it never
13303 will be as long as we're using ambiguity-detecting statement analysis in
13304 the FFE, which we are initially to shake out the code, but don't depend
13305 on this), otherwise go ahead and do whatever is needed.
5ff904cd 13306
c7e4ee3a
CB
13307 In essence, then, when this fn and _exec_transition get called while
13308 backtracking is enabled, a general mechanism would be to flag which (or
13309 both) of these were called (and in what order? neat question as to what
13310 might happen that I'm too lame to think through right now) and then when
13311 _commit is called reproduce the original calling sequence, if any, for
13312 the two fns (at which point backtracking will, of course, be disabled). */
5ff904cd 13313
c7e4ee3a
CB
13314ffesymbol
13315ffecom_sym_learned (ffesymbol s)
13316{
13317 ffestorag_exec_layout (s);
5ff904cd 13318
c7e4ee3a 13319 return s;
5ff904cd
JL
13320}
13321
c7e4ee3a 13322/* ffecom_sym_retract -- Symbol's state being retracted from reality
5ff904cd 13323
c7e4ee3a
CB
13324 ffesymbol s;
13325 ffecom_sym_retract(s);
5ff904cd 13326
c7e4ee3a
CB
13327 Does whatever the backend needs when a symbol is retracted after having
13328 been backtrackable for a period of time. */
5ff904cd
JL
13329
13330#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
13331void
13332ffecom_sym_retract (ffesymbol s UNUSED)
5ff904cd 13333{
c7e4ee3a 13334 assert (!ffesymbol_retractable ());
5ff904cd 13335
c7e4ee3a
CB
13336#if 0 /* GCC doesn't commit any backtrackable sins,
13337 so nothing needed here. */
13338 switch (ffesymbol_hook (s).state)
5ff904cd 13339 {
c7e4ee3a 13340 case 0: /* nothing happened yet. */
5ff904cd
JL
13341 break;
13342
c7e4ee3a 13343 case 1: /* exec transition happened. */
5ff904cd
JL
13344 break;
13345
c7e4ee3a
CB
13346 case 2: /* learned happened. */
13347 break;
5ff904cd 13348
c7e4ee3a
CB
13349 case 3: /* learned then exec. */
13350 break;
13351
13352 case 4: /* exec then learned. */
5ff904cd
JL
13353 break;
13354
13355 default:
c7e4ee3a 13356 assert ("bad hook state" == NULL);
5ff904cd
JL
13357 break;
13358 }
c7e4ee3a
CB
13359#endif
13360}
5ff904cd 13361
c7e4ee3a
CB
13362#endif
13363/* Create temporary gcc label. */
13364
13365#if FFECOM_targetCURRENT == FFECOM_targetGCC
13366tree
13367ffecom_temp_label ()
13368{
13369 tree glabel;
13370 static int mynumber = 0;
13371
13372 glabel = build_decl (LABEL_DECL,
13373 ffecom_get_invented_identifier ("__g77_label_%d",
c7e4ee3a
CB
13374 mynumber++),
13375 void_type_node);
13376 DECL_CONTEXT (glabel) = current_function_decl;
13377 DECL_MODE (glabel) = VOIDmode;
13378
13379 return glabel;
5ff904cd
JL
13380}
13381
13382#endif
c7e4ee3a
CB
13383/* Return an expression that is usable as an arg in a conditional context
13384 (IF, DO WHILE, .NOT., and so on).
13385
13386 Use the one provided for the back end as of >2.6.0. */
5ff904cd
JL
13387
13388#if FFECOM_targetCURRENT == FFECOM_targetGCC
a2977d2d 13389tree
c7e4ee3a 13390ffecom_truth_value (tree expr)
5ff904cd 13391{
c7e4ee3a 13392 return truthvalue_conversion (expr);
5ff904cd 13393}
c7e4ee3a 13394
5ff904cd 13395#endif
c7e4ee3a
CB
13396/* Return the inversion of a truth value (the inversion of what
13397 ffecom_truth_value builds).
5ff904cd 13398
c7e4ee3a
CB
13399 Apparently invert_truthvalue, which is properly in the back end, is
13400 enough for now, so just use it. */
5ff904cd
JL
13401
13402#if FFECOM_targetCURRENT == FFECOM_targetGCC
13403tree
c7e4ee3a 13404ffecom_truth_value_invert (tree expr)
5ff904cd 13405{
c7e4ee3a 13406 return invert_truthvalue (ffecom_truth_value (expr));
5ff904cd
JL
13407}
13408
13409#endif
5ff904cd 13410
c7e4ee3a
CB
13411/* Return the tree that is the type of the expression, as would be
13412 returned in TREE_TYPE(ffecom_expr(expr)), without otherwise
13413 transforming the expression, generating temporaries, etc. */
5ff904cd 13414
c7e4ee3a
CB
13415tree
13416ffecom_type_expr (ffebld expr)
13417{
13418 ffeinfoBasictype bt;
13419 ffeinfoKindtype kt;
13420 tree tree_type;
13421
13422 assert (expr != NULL);
13423
13424 bt = ffeinfo_basictype (ffebld_info (expr));
13425 kt = ffeinfo_kindtype (ffebld_info (expr));
13426 tree_type = ffecom_tree_type[bt][kt];
13427
13428 switch (ffebld_op (expr))
13429 {
13430 case FFEBLD_opCONTER:
13431 case FFEBLD_opSYMTER:
13432 case FFEBLD_opARRAYREF:
13433 case FFEBLD_opUPLUS:
13434 case FFEBLD_opPAREN:
13435 case FFEBLD_opUMINUS:
13436 case FFEBLD_opADD:
13437 case FFEBLD_opSUBTRACT:
13438 case FFEBLD_opMULTIPLY:
13439 case FFEBLD_opDIVIDE:
13440 case FFEBLD_opPOWER:
13441 case FFEBLD_opNOT:
13442 case FFEBLD_opFUNCREF:
13443 case FFEBLD_opSUBRREF:
13444 case FFEBLD_opAND:
13445 case FFEBLD_opOR:
13446 case FFEBLD_opXOR:
13447 case FFEBLD_opNEQV:
13448 case FFEBLD_opEQV:
13449 case FFEBLD_opCONVERT:
13450 case FFEBLD_opLT:
13451 case FFEBLD_opLE:
13452 case FFEBLD_opEQ:
13453 case FFEBLD_opNE:
13454 case FFEBLD_opGT:
13455 case FFEBLD_opGE:
13456 case FFEBLD_opPERCENT_LOC:
13457 return tree_type;
13458
13459 case FFEBLD_opACCTER:
13460 case FFEBLD_opARRTER:
13461 case FFEBLD_opITEM:
13462 case FFEBLD_opSTAR:
13463 case FFEBLD_opBOUNDS:
13464 case FFEBLD_opREPEAT:
13465 case FFEBLD_opLABTER:
13466 case FFEBLD_opLABTOK:
13467 case FFEBLD_opIMPDO:
13468 case FFEBLD_opCONCATENATE:
13469 case FFEBLD_opSUBSTR:
13470 default:
13471 assert ("bad op for ffecom_type_expr" == NULL);
13472 /* Fall through. */
13473 case FFEBLD_opANY:
13474 return error_mark_node;
13475 }
13476}
13477
13478/* Return PARM_DECL for arg#1 of master fn containing alternate ENTRY points
13479
13480 If the PARM_DECL already exists, return it, else create it. It's an
13481 integer_type_node argument for the master function that implements a
13482 subroutine or function with more than one entrypoint and is bound at
13483 run time with the entrypoint number (0 for SUBROUTINE/FUNCTION, 1 for
13484 first ENTRY statement, and so on). */
5ff904cd
JL
13485
13486#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
13487tree
13488ffecom_which_entrypoint_decl ()
5ff904cd 13489{
c7e4ee3a
CB
13490 assert (ffecom_which_entrypoint_decl_ != NULL_TREE);
13491
13492 return ffecom_which_entrypoint_decl_;
5ff904cd
JL
13493}
13494
13495#endif
c7e4ee3a
CB
13496\f
13497/* The following sections consists of private and public functions
13498 that have the same names and perform roughly the same functions
13499 as counterparts in the C front end. Changes in the C front end
13500 might affect how things should be done here. Only functions
13501 needed by the back end should be public here; the rest should
13502 be private (static in the C sense). Functions needed by other
13503 g77 front-end modules should be accessed by them via public
13504 ffecom_* names, which should themselves call private versions
13505 in this section so the private versions are easy to recognize
13506 when upgrading to a new gcc and finding interesting changes
13507 in the front end.
5ff904cd 13508
c7e4ee3a
CB
13509 Functions named after rule "foo:" in c-parse.y are named
13510 "bison_rule_foo_" so they are easy to find. */
5ff904cd 13511
c7e4ee3a 13512#if FFECOM_targetCURRENT == FFECOM_targetGCC
5ff904cd 13513
c7e4ee3a
CB
13514static void
13515bison_rule_pushlevel_ ()
13516{
13517 emit_line_note (input_filename, lineno);
13518 pushlevel (0);
13519 clear_last_expr ();
c7e4ee3a
CB
13520 expand_start_bindings (0);
13521}
5ff904cd 13522
c7e4ee3a
CB
13523static tree
13524bison_rule_compstmt_ ()
5ff904cd 13525{
c7e4ee3a
CB
13526 tree t;
13527 int keep = kept_level_p ();
5ff904cd 13528
c7e4ee3a
CB
13529 /* Make the temps go away. */
13530 if (! keep)
13531 current_binding_level->names = NULL_TREE;
5ff904cd 13532
c7e4ee3a
CB
13533 emit_line_note (input_filename, lineno);
13534 expand_end_bindings (getdecls (), keep, 0);
13535 t = poplevel (keep, 1, 0);
5ff904cd 13536
c7e4ee3a
CB
13537 return t;
13538}
5ff904cd 13539
c7e4ee3a
CB
13540/* Return a definition for a builtin function named NAME and whose data type
13541 is TYPE. TYPE should be a function type with argument types.
13542 FUNCTION_CODE tells later passes how to compile calls to this function.
13543 See tree.h for its possible values.
5ff904cd 13544
c7e4ee3a
CB
13545 If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME,
13546 the name to be called if we can't opencode the function. */
5ff904cd 13547
26db82d8
BS
13548tree
13549builtin_function (const char *name, tree type, int function_code,
13550 enum built_in_class class,
c7e4ee3a
CB
13551 const char *library_name)
13552{
13553 tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
13554 DECL_EXTERNAL (decl) = 1;
13555 TREE_PUBLIC (decl) = 1;
13556 if (library_name)
13557 DECL_ASSEMBLER_NAME (decl) = get_identifier (library_name);
6c418184 13558 make_decl_rtl (decl, NULL_PTR);
c7e4ee3a 13559 pushdecl (decl);
26db82d8
BS
13560 DECL_BUILT_IN_CLASS (decl) = class;
13561 DECL_FUNCTION_CODE (decl) = function_code;
5ff904cd 13562
c7e4ee3a 13563 return decl;
5ff904cd
JL
13564}
13565
c7e4ee3a
CB
13566/* Handle when a new declaration NEWDECL
13567 has the same name as an old one OLDDECL
13568 in the same binding contour.
13569 Prints an error message if appropriate.
5ff904cd 13570
c7e4ee3a
CB
13571 If safely possible, alter OLDDECL to look like NEWDECL, and return 1.
13572 Otherwise, return 0. */
5ff904cd 13573
c7e4ee3a
CB
13574static int
13575duplicate_decls (tree newdecl, tree olddecl)
5ff904cd 13576{
c7e4ee3a
CB
13577 int types_match = 1;
13578 int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
13579 && DECL_INITIAL (newdecl) != 0);
13580 tree oldtype = TREE_TYPE (olddecl);
13581 tree newtype = TREE_TYPE (newdecl);
5ff904cd 13582
c7e4ee3a
CB
13583 if (olddecl == newdecl)
13584 return 1;
5ff904cd 13585
c7e4ee3a
CB
13586 if (TREE_CODE (newtype) == ERROR_MARK
13587 || TREE_CODE (oldtype) == ERROR_MARK)
13588 types_match = 0;
5ff904cd 13589
c7e4ee3a
CB
13590 /* New decl is completely inconsistent with the old one =>
13591 tell caller to replace the old one.
13592 This is always an error except in the case of shadowing a builtin. */
13593 if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
13594 return 0;
5ff904cd 13595
c7e4ee3a
CB
13596 /* For real parm decl following a forward decl,
13597 return 1 so old decl will be reused. */
13598 if (types_match && TREE_CODE (newdecl) == PARM_DECL
13599 && TREE_ASM_WRITTEN (olddecl) && ! TREE_ASM_WRITTEN (newdecl))
13600 return 1;
5ff904cd 13601
c7e4ee3a
CB
13602 /* The new declaration is the same kind of object as the old one.
13603 The declarations may partially match. Print warnings if they don't
13604 match enough. Ultimately, copy most of the information from the new
13605 decl to the old one, and keep using the old one. */
5ff904cd 13606
c7e4ee3a
CB
13607 if (TREE_CODE (olddecl) == FUNCTION_DECL
13608 && DECL_BUILT_IN (olddecl))
13609 {
13610 /* A function declaration for a built-in function. */
13611 if (!TREE_PUBLIC (newdecl))
13612 return 0;
13613 else if (!types_match)
13614 {
13615 /* Accept the return type of the new declaration if same modes. */
13616 tree oldreturntype = TREE_TYPE (TREE_TYPE (olddecl));
13617 tree newreturntype = TREE_TYPE (TREE_TYPE (newdecl));
5ff904cd 13618
c7e4ee3a
CB
13619 if (TYPE_MODE (oldreturntype) == TYPE_MODE (newreturntype))
13620 {
13621 /* Function types may be shared, so we can't just modify
13622 the return type of olddecl's function type. */
13623 tree newtype
13624 = build_function_type (newreturntype,
13625 TYPE_ARG_TYPES (TREE_TYPE (olddecl)));
5ff904cd 13626
c7e4ee3a
CB
13627 types_match = 1;
13628 if (types_match)
13629 TREE_TYPE (olddecl) = newtype;
13630 }
c7e4ee3a
CB
13631 }
13632 if (!types_match)
13633 return 0;
13634 }
13635 else if (TREE_CODE (olddecl) == FUNCTION_DECL
13636 && DECL_SOURCE_LINE (olddecl) == 0)
5ff904cd 13637 {
c7e4ee3a
CB
13638 /* A function declaration for a predeclared function
13639 that isn't actually built in. */
13640 if (!TREE_PUBLIC (newdecl))
13641 return 0;
13642 else if (!types_match)
13643 {
13644 /* If the types don't match, preserve volatility indication.
13645 Later on, we will discard everything else about the
13646 default declaration. */
13647 TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
13648 }
13649 }
5ff904cd 13650
c7e4ee3a
CB
13651 /* Copy all the DECL_... slots specified in the new decl
13652 except for any that we copy here from the old type.
5ff904cd 13653
c7e4ee3a
CB
13654 Past this point, we don't change OLDTYPE and NEWTYPE
13655 even if we change the types of NEWDECL and OLDDECL. */
5ff904cd 13656
c7e4ee3a
CB
13657 if (types_match)
13658 {
c7e4ee3a
CB
13659 /* Merge the data types specified in the two decls. */
13660 if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl))
13661 TREE_TYPE (newdecl)
13662 = TREE_TYPE (olddecl)
13663 = TREE_TYPE (newdecl);
5ff904cd 13664
c7e4ee3a
CB
13665 /* Lay the type out, unless already done. */
13666 if (oldtype != TREE_TYPE (newdecl))
13667 {
13668 if (TREE_TYPE (newdecl) != error_mark_node)
13669 layout_type (TREE_TYPE (newdecl));
13670 if (TREE_CODE (newdecl) != FUNCTION_DECL
13671 && TREE_CODE (newdecl) != TYPE_DECL
13672 && TREE_CODE (newdecl) != CONST_DECL)
13673 layout_decl (newdecl, 0);
13674 }
13675 else
13676 {
13677 /* Since the type is OLDDECL's, make OLDDECL's size go with. */
13678 DECL_SIZE (newdecl) = DECL_SIZE (olddecl);
06ceef4e 13679 DECL_SIZE_UNIT (newdecl) = DECL_SIZE_UNIT (olddecl);
c7e4ee3a
CB
13680 if (TREE_CODE (olddecl) != FUNCTION_DECL)
13681 if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
11cf4d18
JJ
13682 {
13683 DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
13684 DECL_USER_ALIGN (newdecl) |= DECL_USER_ALIGN (olddecl);
13685 }
c7e4ee3a 13686 }
5ff904cd 13687
c7e4ee3a
CB
13688 /* Keep the old rtl since we can safely use it. */
13689 DECL_RTL (newdecl) = DECL_RTL (olddecl);
5ff904cd 13690
c7e4ee3a
CB
13691 /* Merge the type qualifiers. */
13692 if (DECL_BUILT_IN_NONANSI (olddecl) && TREE_THIS_VOLATILE (olddecl)
13693 && !TREE_THIS_VOLATILE (newdecl))
13694 TREE_THIS_VOLATILE (olddecl) = 0;
13695 if (TREE_READONLY (newdecl))
13696 TREE_READONLY (olddecl) = 1;
13697 if (TREE_THIS_VOLATILE (newdecl))
13698 {
13699 TREE_THIS_VOLATILE (olddecl) = 1;
13700 if (TREE_CODE (newdecl) == VAR_DECL)
13701 make_var_volatile (newdecl);
13702 }
5ff904cd 13703
c7e4ee3a
CB
13704 /* Keep source location of definition rather than declaration.
13705 Likewise, keep decl at outer scope. */
13706 if ((DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0)
13707 || (DECL_CONTEXT (newdecl) != 0 && DECL_CONTEXT (olddecl) == 0))
13708 {
13709 DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl);
13710 DECL_SOURCE_FILE (newdecl) = DECL_SOURCE_FILE (olddecl);
5ff904cd 13711
c7e4ee3a
CB
13712 if (DECL_CONTEXT (olddecl) == 0
13713 && TREE_CODE (newdecl) != FUNCTION_DECL)
13714 DECL_CONTEXT (newdecl) = 0;
13715 }
5ff904cd 13716
c7e4ee3a
CB
13717 /* Merge the unused-warning information. */
13718 if (DECL_IN_SYSTEM_HEADER (olddecl))
13719 DECL_IN_SYSTEM_HEADER (newdecl) = 1;
13720 else if (DECL_IN_SYSTEM_HEADER (newdecl))
13721 DECL_IN_SYSTEM_HEADER (olddecl) = 1;
5ff904cd 13722
c7e4ee3a
CB
13723 /* Merge the initialization information. */
13724 if (DECL_INITIAL (newdecl) == 0)
13725 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
5ff904cd 13726
c7e4ee3a
CB
13727 /* Merge the section attribute.
13728 We want to issue an error if the sections conflict but that must be
13729 done later in decl_attributes since we are called before attributes
13730 are assigned. */
13731 if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
13732 DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
5ff904cd 13733
c7e4ee3a
CB
13734#if BUILT_FOR_270
13735 if (TREE_CODE (newdecl) == FUNCTION_DECL)
13736 {
13737 DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
13738 DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
13739 }
5ff904cd 13740#endif
c7e4ee3a
CB
13741 }
13742 /* If cannot merge, then use the new type and qualifiers,
13743 and don't preserve the old rtl. */
13744 else
13745 {
13746 TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
13747 TREE_READONLY (olddecl) = TREE_READONLY (newdecl);
13748 TREE_THIS_VOLATILE (olddecl) = TREE_THIS_VOLATILE (newdecl);
13749 TREE_SIDE_EFFECTS (olddecl) = TREE_SIDE_EFFECTS (newdecl);
13750 }
5ff904cd 13751
c7e4ee3a
CB
13752 /* Merge the storage class information. */
13753 /* For functions, static overrides non-static. */
13754 if (TREE_CODE (newdecl) == FUNCTION_DECL)
13755 {
13756 TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl);
13757 /* This is since we don't automatically
13758 copy the attributes of NEWDECL into OLDDECL. */
13759 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
13760 /* If this clears `static', clear it in the identifier too. */
13761 if (! TREE_PUBLIC (olddecl))
13762 TREE_PUBLIC (DECL_NAME (olddecl)) = 0;
13763 }
13764 if (DECL_EXTERNAL (newdecl))
13765 {
13766 TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
13767 DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
13768 /* An extern decl does not override previous storage class. */
13769 TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
13770 }
13771 else
13772 {
13773 TREE_STATIC (olddecl) = TREE_STATIC (newdecl);
13774 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
13775 }
5ff904cd 13776
c7e4ee3a
CB
13777 /* If either decl says `inline', this fn is inline,
13778 unless its definition was passed already. */
13779 if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == 0)
13780 DECL_INLINE (olddecl) = 1;
13781 DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
5ff904cd 13782
c7e4ee3a
CB
13783 /* Get rid of any built-in function if new arg types don't match it
13784 or if we have a function definition. */
13785 if (TREE_CODE (newdecl) == FUNCTION_DECL
13786 && DECL_BUILT_IN (olddecl)
13787 && (!types_match || new_is_definition))
13788 {
13789 TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
26db82d8 13790 DECL_BUILT_IN_CLASS (olddecl) = NOT_BUILT_IN;
c7e4ee3a 13791 }
5ff904cd 13792
c7e4ee3a
CB
13793 /* If redeclaring a builtin function, and not a definition,
13794 it stays built in.
13795 Also preserve various other info from the definition. */
13796 if (TREE_CODE (newdecl) == FUNCTION_DECL && !new_is_definition)
13797 {
13798 if (DECL_BUILT_IN (olddecl))
13799 {
26db82d8 13800 DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
c7e4ee3a
CB
13801 DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
13802 }
13803 else
13804 DECL_FRAME_SIZE (newdecl) = DECL_FRAME_SIZE (olddecl);
5ff904cd 13805
c7e4ee3a
CB
13806 DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
13807 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
13808 DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
13809 DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
13810 }
5ff904cd 13811
c7e4ee3a
CB
13812 /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
13813 But preserve olddecl's DECL_UID. */
13814 {
13815 register unsigned olddecl_uid = DECL_UID (olddecl);
5ff904cd 13816
c7e4ee3a
CB
13817 memcpy ((char *) olddecl + sizeof (struct tree_common),
13818 (char *) newdecl + sizeof (struct tree_common),
13819 sizeof (struct tree_decl) - sizeof (struct tree_common));
13820 DECL_UID (olddecl) = olddecl_uid;
13821 }
5ff904cd 13822
c7e4ee3a 13823 return 1;
5ff904cd
JL
13824}
13825
c7e4ee3a
CB
13826/* Finish processing of a declaration;
13827 install its initial value.
13828 If the length of an array type is not known before,
13829 it must be determined now, from the initial value, or it is an error. */
13830
5ff904cd 13831static void
c7e4ee3a 13832finish_decl (tree decl, tree init, bool is_top_level)
5ff904cd 13833{
c7e4ee3a
CB
13834 register tree type = TREE_TYPE (decl);
13835 int was_incomplete = (DECL_SIZE (decl) == 0);
c7e4ee3a
CB
13836 bool at_top_level = (current_binding_level == global_binding_level);
13837 bool top_level = is_top_level || at_top_level;
5ff904cd 13838
c7e4ee3a
CB
13839 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
13840 level anyway. */
13841 assert (!is_top_level || !at_top_level);
5ff904cd 13842
c7e4ee3a
CB
13843 if (TREE_CODE (decl) == PARM_DECL)
13844 assert (init == NULL_TREE);
13845 /* Remember that PARM_DECL doesn't have a DECL_INITIAL field per se -- it
13846 overlaps DECL_ARG_TYPE. */
13847 else if (init == NULL_TREE)
13848 assert (DECL_INITIAL (decl) == NULL_TREE);
13849 else
13850 assert (DECL_INITIAL (decl) == error_mark_node);
5ff904cd 13851
c7e4ee3a 13852 if (init != NULL_TREE)
5ff904cd 13853 {
c7e4ee3a
CB
13854 if (TREE_CODE (decl) != TYPE_DECL)
13855 DECL_INITIAL (decl) = init;
13856 else
13857 {
13858 /* typedef foo = bar; store the type of bar as the type of foo. */
13859 TREE_TYPE (decl) = TREE_TYPE (init);
13860 DECL_INITIAL (decl) = init = 0;
13861 }
5ff904cd
JL
13862 }
13863
c7e4ee3a 13864 /* Deduce size of array from initialization, if not already known */
5ff904cd 13865
c7e4ee3a
CB
13866 if (TREE_CODE (type) == ARRAY_TYPE
13867 && TYPE_DOMAIN (type) == 0
13868 && TREE_CODE (decl) != TYPE_DECL)
13869 {
13870 assert (top_level);
13871 assert (was_incomplete);
5ff904cd 13872
c7e4ee3a
CB
13873 layout_decl (decl, 0);
13874 }
5ff904cd 13875
c7e4ee3a
CB
13876 if (TREE_CODE (decl) == VAR_DECL)
13877 {
13878 if (DECL_SIZE (decl) == NULL_TREE
13879 && TYPE_SIZE (TREE_TYPE (decl)) != NULL_TREE)
13880 layout_decl (decl, 0);
5ff904cd 13881
c7e4ee3a
CB
13882 if (DECL_SIZE (decl) == NULL_TREE
13883 && (TREE_STATIC (decl)
13884 ?
13885 /* A static variable with an incomplete type is an error if it is
13886 initialized. Also if it is not file scope. Otherwise, let it
13887 through, but if it is not `extern' then it may cause an error
13888 message later. */
13889 (DECL_INITIAL (decl) != 0 || DECL_CONTEXT (decl) != 0)
13890 :
13891 /* An automatic variable with an incomplete type is an error. */
13892 !DECL_EXTERNAL (decl)))
13893 {
13894 assert ("storage size not known" == NULL);
13895 abort ();
13896 }
5ff904cd 13897
c7e4ee3a
CB
13898 if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
13899 && (DECL_SIZE (decl) != 0)
13900 && (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST))
13901 {
13902 assert ("storage size not constant" == NULL);
13903 abort ();
13904 }
13905 }
5ff904cd 13906
c7e4ee3a
CB
13907 /* Output the assembler code and/or RTL code for variables and functions,
13908 unless the type is an undefined structure or union. If not, it will get
13909 done when the type is completed. */
5ff904cd 13910
c7e4ee3a 13911 if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
5ff904cd 13912 {
c7e4ee3a
CB
13913 rest_of_decl_compilation (decl, NULL,
13914 DECL_CONTEXT (decl) == 0,
13915 0);
5ff904cd 13916
c7e4ee3a
CB
13917 if (DECL_CONTEXT (decl) != 0)
13918 {
13919 /* Recompute the RTL of a local array now if it used to be an
13920 incomplete type. */
13921 if (was_incomplete
13922 && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
5ff904cd 13923 {
c7e4ee3a
CB
13924 /* If we used it already as memory, it must stay in memory. */
13925 TREE_ADDRESSABLE (decl) = TREE_USED (decl);
13926 /* If it's still incomplete now, no init will save it. */
13927 if (DECL_SIZE (decl) == 0)
13928 DECL_INITIAL (decl) = 0;
13929 expand_decl (decl);
5ff904cd 13930 }
c7e4ee3a
CB
13931 /* Compute and store the initial value. */
13932 if (TREE_CODE (decl) != FUNCTION_DECL)
13933 expand_decl_init (decl);
13934 }
13935 }
13936 else if (TREE_CODE (decl) == TYPE_DECL)
13937 {
13938 rest_of_decl_compilation (decl, NULL_PTR,
13939 DECL_CONTEXT (decl) == 0,
13940 0);
13941 }
5ff904cd 13942
c7e4ee3a
CB
13943 /* At the end of a declaration, throw away any variable type sizes of types
13944 defined inside that declaration. There is no use computing them in the
13945 following function definition. */
13946 if (current_binding_level == global_binding_level)
13947 get_pending_sizes ();
13948}
5ff904cd 13949
c7e4ee3a
CB
13950/* Finish up a function declaration and compile that function
13951 all the way to assembler language output. The free the storage
13952 for the function definition.
5ff904cd 13953
c7e4ee3a 13954 This is called after parsing the body of the function definition.
5ff904cd 13955
c7e4ee3a
CB
13956 NESTED is nonzero if the function being finished is nested in another. */
13957
13958static void
13959finish_function (int nested)
13960{
13961 register tree fndecl = current_function_decl;
13962
13963 assert (fndecl != NULL_TREE);
13964 if (TREE_CODE (fndecl) != ERROR_MARK)
13965 {
13966 if (nested)
13967 assert (DECL_CONTEXT (fndecl) != NULL_TREE);
5ff904cd 13968 else
c7e4ee3a
CB
13969 assert (DECL_CONTEXT (fndecl) == NULL_TREE);
13970 }
5ff904cd 13971
c7e4ee3a
CB
13972/* TREE_READONLY (fndecl) = 1;
13973 This caused &foo to be of type ptr-to-const-function
13974 which then got a warning when stored in a ptr-to-function variable. */
5ff904cd 13975
c7e4ee3a 13976 poplevel (1, 0, 1);
5ff904cd 13977
c7e4ee3a
CB
13978 if (TREE_CODE (fndecl) != ERROR_MARK)
13979 {
13980 BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
5ff904cd 13981
c7e4ee3a 13982 /* Must mark the RESULT_DECL as being in this function. */
5ff904cd 13983
c7e4ee3a 13984 DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
5ff904cd 13985
c7e4ee3a
CB
13986 /* Obey `register' declarations if `setjmp' is called in this fn. */
13987 /* Generate rtl for function exit. */
13988 expand_function_end (input_filename, lineno, 0);
5ff904cd 13989
7189a4b0
GK
13990 /* If this is a nested function, protect the local variables in the stack
13991 above us from being collected while we're compiling this function. */
1f8f4a0b 13992 if (nested)
7189a4b0
GK
13993 ggc_push_context ();
13994
c7e4ee3a
CB
13995 /* Run the optimizers and output the assembler code for this function. */
13996 rest_of_compilation (fndecl);
7189a4b0
GK
13997
13998 /* Undo the GC context switch. */
1f8f4a0b 13999 if (nested)
7189a4b0 14000 ggc_pop_context ();
c7e4ee3a 14001 }
5ff904cd 14002
c7e4ee3a
CB
14003 if (TREE_CODE (fndecl) != ERROR_MARK
14004 && !nested
14005 && DECL_SAVED_INSNS (fndecl) == 0)
14006 {
14007 /* Stop pointing to the local nodes about to be freed. */
14008 /* But DECL_INITIAL must remain nonzero so we know this was an actual
14009 function definition. */
14010 /* For a nested function, this is done in pop_f_function_context. */
14011 /* If rest_of_compilation set this to 0, leave it 0. */
14012 if (DECL_INITIAL (fndecl) != 0)
14013 DECL_INITIAL (fndecl) = error_mark_node;
14014 DECL_ARGUMENTS (fndecl) = 0;
5ff904cd 14015 }
c7e4ee3a
CB
14016
14017 if (!nested)
5ff904cd 14018 {
c7e4ee3a
CB
14019 /* Let the error reporting routines know that we're outside a function.
14020 For a nested function, this value is used in pop_c_function_context
14021 and then reset via pop_function_context. */
14022 ffecom_outer_function_decl_ = current_function_decl = NULL;
5ff904cd 14023 }
c7e4ee3a 14024}
5ff904cd 14025
c7e4ee3a
CB
14026/* Plug-in replacement for identifying the name of a decl and, for a
14027 function, what we call it in diagnostics. For now, "program unit"
14028 should suffice, since it's a bit of a hassle to figure out which
14029 of several kinds of things it is. Note that it could conceivably
14030 be a statement function, which probably isn't really a program unit
14031 per se, but if that comes up, it should be easy to check (being a
14032 nested function and all). */
14033
4b731ffa 14034static const char *
c7e4ee3a
CB
14035lang_printable_name (tree decl, int v)
14036{
14037 /* Just to keep GCC quiet about the unused variable.
14038 In theory, differing values of V should produce different
14039 output. */
14040 switch (v)
5ff904cd 14041 {
c7e4ee3a
CB
14042 default:
14043 if (TREE_CODE (decl) == ERROR_MARK)
14044 return "erroneous code";
14045 return IDENTIFIER_POINTER (DECL_NAME (decl));
5ff904cd 14046 }
c7e4ee3a
CB
14047}
14048
14049/* g77's function to print out name of current function that caused
14050 an error. */
14051
14052#if BUILT_FOR_270
b0791fa9
KG
14053static void
14054lang_print_error_function (const char *file)
c7e4ee3a
CB
14055{
14056 static ffeglobal last_g = NULL;
14057 static ffesymbol last_s = NULL;
14058 ffeglobal g;
14059 ffesymbol s;
14060 const char *kind;
14061
14062 if ((ffecom_primary_entry_ == NULL)
14063 || (ffesymbol_global (ffecom_primary_entry_) == NULL))
5ff904cd 14064 {
c7e4ee3a
CB
14065 g = NULL;
14066 s = NULL;
14067 kind = NULL;
5ff904cd
JL
14068 }
14069 else
14070 {
c7e4ee3a
CB
14071 g = ffesymbol_global (ffecom_primary_entry_);
14072 if (ffecom_nested_entry_ == NULL)
14073 {
14074 s = ffecom_primary_entry_;
14075 switch (ffesymbol_kind (s))
14076 {
14077 case FFEINFO_kindFUNCTION:
14078 kind = "function";
14079 break;
5ff904cd 14080
c7e4ee3a
CB
14081 case FFEINFO_kindSUBROUTINE:
14082 kind = "subroutine";
14083 break;
5ff904cd 14084
c7e4ee3a
CB
14085 case FFEINFO_kindPROGRAM:
14086 kind = "program";
14087 break;
14088
14089 case FFEINFO_kindBLOCKDATA:
14090 kind = "block-data";
14091 break;
14092
14093 default:
14094 kind = ffeinfo_kind_message (ffesymbol_kind (s));
14095 break;
14096 }
14097 }
14098 else
14099 {
14100 s = ffecom_nested_entry_;
14101 kind = "statement function";
14102 }
5ff904cd
JL
14103 }
14104
c7e4ee3a 14105 if ((last_g != g) || (last_s != s))
5ff904cd 14106 {
c7e4ee3a
CB
14107 if (file)
14108 fprintf (stderr, "%s: ", file);
14109
14110 if (s == NULL)
14111 fprintf (stderr, "Outside of any program unit:\n");
14112 else
5ff904cd 14113 {
c7e4ee3a
CB
14114 const char *name = ffesymbol_text (s);
14115
14116 fprintf (stderr, "In %s `%s':\n", kind, name);
5ff904cd 14117 }
5ff904cd 14118
c7e4ee3a
CB
14119 last_g = g;
14120 last_s = s;
5ff904cd 14121 }
c7e4ee3a
CB
14122}
14123#endif
5ff904cd 14124
c7e4ee3a 14125/* Similar to `lookup_name' but look only at current binding level. */
5ff904cd 14126
c7e4ee3a
CB
14127static tree
14128lookup_name_current_level (tree name)
14129{
14130 register tree t;
5ff904cd 14131
c7e4ee3a
CB
14132 if (current_binding_level == global_binding_level)
14133 return IDENTIFIER_GLOBAL_VALUE (name);
14134
14135 if (IDENTIFIER_LOCAL_VALUE (name) == 0)
14136 return 0;
14137
14138 for (t = current_binding_level->names; t; t = TREE_CHAIN (t))
14139 if (DECL_NAME (t) == name)
14140 break;
14141
14142 return t;
5ff904cd
JL
14143}
14144
c7e4ee3a 14145/* Create a new `struct binding_level'. */
5ff904cd 14146
c7e4ee3a
CB
14147static struct binding_level *
14148make_binding_level ()
5ff904cd 14149{
c7e4ee3a
CB
14150 /* NOSTRICT */
14151 return (struct binding_level *) xmalloc (sizeof (struct binding_level));
14152}
5ff904cd 14153
c7e4ee3a
CB
14154/* Save and restore the variables in this file and elsewhere
14155 that keep track of the progress of compilation of the current function.
14156 Used for nested functions. */
5ff904cd 14157
c7e4ee3a
CB
14158struct f_function
14159{
14160 struct f_function *next;
14161 tree named_labels;
14162 tree shadowed_labels;
14163 struct binding_level *binding_level;
14164};
5ff904cd 14165
c7e4ee3a 14166struct f_function *f_function_chain;
5ff904cd 14167
c7e4ee3a 14168/* Restore the variables used during compilation of a C function. */
5ff904cd 14169
c7e4ee3a
CB
14170static void
14171pop_f_function_context ()
14172{
14173 struct f_function *p = f_function_chain;
14174 tree link;
5ff904cd 14175
c7e4ee3a
CB
14176 /* Bring back all the labels that were shadowed. */
14177 for (link = shadowed_labels; link; link = TREE_CHAIN (link))
14178 if (DECL_NAME (TREE_VALUE (link)) != 0)
14179 IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)))
14180 = TREE_VALUE (link);
5ff904cd 14181
c7e4ee3a
CB
14182 if (current_function_decl != error_mark_node
14183 && DECL_SAVED_INSNS (current_function_decl) == 0)
14184 {
14185 /* Stop pointing to the local nodes about to be freed. */
14186 /* But DECL_INITIAL must remain nonzero so we know this was an actual
14187 function definition. */
14188 DECL_INITIAL (current_function_decl) = error_mark_node;
14189 DECL_ARGUMENTS (current_function_decl) = 0;
5ff904cd
JL
14190 }
14191
c7e4ee3a 14192 pop_function_context ();
5ff904cd 14193
c7e4ee3a 14194 f_function_chain = p->next;
5ff904cd 14195
c7e4ee3a
CB
14196 named_labels = p->named_labels;
14197 shadowed_labels = p->shadowed_labels;
14198 current_binding_level = p->binding_level;
5ff904cd 14199
c7e4ee3a
CB
14200 free (p);
14201}
5ff904cd 14202
c7e4ee3a
CB
14203/* Save and reinitialize the variables
14204 used during compilation of a C function. */
5ff904cd 14205
c7e4ee3a
CB
14206static void
14207push_f_function_context ()
14208{
14209 struct f_function *p
14210 = (struct f_function *) xmalloc (sizeof (struct f_function));
5ff904cd 14211
c7e4ee3a
CB
14212 push_function_context ();
14213
14214 p->next = f_function_chain;
14215 f_function_chain = p;
14216
14217 p->named_labels = named_labels;
14218 p->shadowed_labels = shadowed_labels;
14219 p->binding_level = current_binding_level;
14220}
5ff904cd 14221
c7e4ee3a
CB
14222static void
14223push_parm_decl (tree parm)
14224{
14225 int old_immediate_size_expand = immediate_size_expand;
5ff904cd 14226
c7e4ee3a 14227 /* Don't try computing parm sizes now -- wait till fn is called. */
5ff904cd 14228
c7e4ee3a 14229 immediate_size_expand = 0;
5ff904cd 14230
c7e4ee3a 14231 /* Fill in arg stuff. */
5ff904cd 14232
c7e4ee3a
CB
14233 DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
14234 DECL_ARG_TYPE_AS_WRITTEN (parm) = TREE_TYPE (parm);
14235 TREE_READONLY (parm) = 1; /* All implementation args are read-only. */
5ff904cd 14236
c7e4ee3a
CB
14237 parm = pushdecl (parm);
14238
14239 immediate_size_expand = old_immediate_size_expand;
14240
14241 finish_decl (parm, NULL_TREE, FALSE);
5ff904cd
JL
14242}
14243
c7e4ee3a 14244/* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL, if appropriate. */
5ff904cd 14245
c7e4ee3a
CB
14246static tree
14247pushdecl_top_level (x)
14248 tree x;
14249{
14250 register tree t;
14251 register struct binding_level *b = current_binding_level;
14252 register tree f = current_function_decl;
5ff904cd 14253
c7e4ee3a
CB
14254 current_binding_level = global_binding_level;
14255 current_function_decl = NULL_TREE;
14256 t = pushdecl (x);
14257 current_binding_level = b;
14258 current_function_decl = f;
14259 return t;
14260}
14261
14262/* Store the list of declarations of the current level.
14263 This is done for the parameter declarations of a function being defined,
14264 after they are modified in the light of any missing parameters. */
14265
14266static tree
14267storedecls (decls)
14268 tree decls;
14269{
14270 return current_binding_level->names = decls;
14271}
14272
14273/* Store the parameter declarations into the current function declaration.
14274 This is called after parsing the parameter declarations, before
14275 digesting the body of the function.
14276
14277 For an old-style definition, modify the function's type
14278 to specify at least the number of arguments. */
5ff904cd
JL
14279
14280static void
c7e4ee3a 14281store_parm_decls (int is_main_program UNUSED)
5ff904cd
JL
14282{
14283 register tree fndecl = current_function_decl;
14284
c7e4ee3a
CB
14285 if (fndecl == error_mark_node)
14286 return;
5ff904cd 14287
c7e4ee3a
CB
14288 /* This is a chain of PARM_DECLs from old-style parm declarations. */
14289 DECL_ARGUMENTS (fndecl) = storedecls (nreverse (getdecls ()));
5ff904cd 14290
c7e4ee3a 14291 /* Initialize the RTL code for the function. */
5ff904cd 14292
c7e4ee3a 14293 init_function_start (fndecl, input_filename, lineno);
56a0044b 14294
c7e4ee3a 14295 /* Set up parameters and prepare for return, for the function. */
5ff904cd 14296
c7e4ee3a
CB
14297 expand_function_start (fndecl, 0);
14298}
5ff904cd 14299
c7e4ee3a
CB
14300static tree
14301start_decl (tree decl, bool is_top_level)
14302{
14303 register tree tem;
14304 bool at_top_level = (current_binding_level == global_binding_level);
14305 bool top_level = is_top_level || at_top_level;
5ff904cd 14306
c7e4ee3a
CB
14307 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
14308 level anyway. */
14309 assert (!is_top_level || !at_top_level);
5ff904cd 14310
c7e4ee3a
CB
14311 if (DECL_INITIAL (decl) != NULL_TREE)
14312 {
14313 assert (DECL_INITIAL (decl) == error_mark_node);
14314 assert (!DECL_EXTERNAL (decl));
56a0044b 14315 }
c7e4ee3a
CB
14316 else if (top_level)
14317 assert ((TREE_STATIC (decl) == 1) || DECL_EXTERNAL (decl) == 1);
5ff904cd 14318
c7e4ee3a
CB
14319 /* For Fortran, we by default put things in .common when possible. */
14320 DECL_COMMON (decl) = 1;
5ff904cd 14321
c7e4ee3a
CB
14322 /* Add this decl to the current binding level. TEM may equal DECL or it may
14323 be a previous decl of the same name. */
14324 if (is_top_level)
14325 tem = pushdecl_top_level (decl);
14326 else
14327 tem = pushdecl (decl);
14328
14329 /* For a local variable, define the RTL now. */
14330 if (!top_level
14331 /* But not if this is a duplicate decl and we preserved the rtl from the
14332 previous one (which may or may not happen). */
14333 && DECL_RTL (tem) == 0)
5ff904cd 14334 {
c7e4ee3a
CB
14335 if (TYPE_SIZE (TREE_TYPE (tem)) != 0)
14336 expand_decl (tem);
14337 else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
14338 && DECL_INITIAL (tem) != 0)
14339 expand_decl (tem);
5ff904cd
JL
14340 }
14341
c7e4ee3a 14342 return tem;
5ff904cd
JL
14343}
14344
c7e4ee3a
CB
14345/* Create the FUNCTION_DECL for a function definition.
14346 DECLSPECS and DECLARATOR are the parts of the declaration;
14347 they describe the function's name and the type it returns,
14348 but twisted together in a fashion that parallels the syntax of C.
5ff904cd 14349
c7e4ee3a
CB
14350 This function creates a binding context for the function body
14351 as well as setting up the FUNCTION_DECL in current_function_decl.
5ff904cd 14352
c7e4ee3a
CB
14353 Returns 1 on success. If the DECLARATOR is not suitable for a function
14354 (it defines a datum instead), we return 0, which tells
14355 yyparse to report a parse error.
5ff904cd 14356
c7e4ee3a
CB
14357 NESTED is nonzero for a function nested within another function. */
14358
14359static void
14360start_function (tree name, tree type, int nested, int public)
5ff904cd 14361{
c7e4ee3a
CB
14362 tree decl1;
14363 tree restype;
14364 int old_immediate_size_expand = immediate_size_expand;
5ff904cd 14365
c7e4ee3a
CB
14366 named_labels = 0;
14367 shadowed_labels = 0;
14368
14369 /* Don't expand any sizes in the return type of the function. */
14370 immediate_size_expand = 0;
14371
14372 if (nested)
5ff904cd 14373 {
c7e4ee3a
CB
14374 assert (!public);
14375 assert (current_function_decl != NULL_TREE);
14376 assert (DECL_CONTEXT (current_function_decl) == NULL_TREE);
14377 }
14378 else
14379 {
14380 assert (current_function_decl == NULL_TREE);
5ff904cd 14381 }
c7e4ee3a
CB
14382
14383 if (TREE_CODE (type) == ERROR_MARK)
14384 decl1 = current_function_decl = error_mark_node;
56a0044b 14385 else
5ff904cd 14386 {
c7e4ee3a
CB
14387 decl1 = build_decl (FUNCTION_DECL,
14388 name,
14389 type);
14390 TREE_PUBLIC (decl1) = public ? 1 : 0;
14391 if (nested)
14392 DECL_INLINE (decl1) = 1;
14393 TREE_STATIC (decl1) = 1;
14394 DECL_EXTERNAL (decl1) = 0;
5ff904cd 14395
c7e4ee3a 14396 announce_function (decl1);
5ff904cd 14397
c7e4ee3a
CB
14398 /* Make the init_value nonzero so pushdecl knows this is not tentative.
14399 error_mark_node is replaced below (in poplevel) with the BLOCK. */
14400 DECL_INITIAL (decl1) = error_mark_node;
5ff904cd 14401
c7e4ee3a
CB
14402 /* Record the decl so that the function name is defined. If we already have
14403 a decl for this name, and it is a FUNCTION_DECL, use the old decl. */
5ff904cd 14404
c7e4ee3a 14405 current_function_decl = pushdecl (decl1);
5ff904cd
JL
14406 }
14407
c7e4ee3a
CB
14408 if (!nested)
14409 ffecom_outer_function_decl_ = current_function_decl;
5ff904cd 14410
c7e4ee3a
CB
14411 pushlevel (0);
14412 current_binding_level->prep_state = 2;
5ff904cd 14413
c7e4ee3a
CB
14414 if (TREE_CODE (current_function_decl) != ERROR_MARK)
14415 {
6c418184 14416 make_decl_rtl (current_function_decl, NULL);
5ff904cd 14417
c7e4ee3a
CB
14418 restype = TREE_TYPE (TREE_TYPE (current_function_decl));
14419 DECL_RESULT (current_function_decl)
14420 = build_decl (RESULT_DECL, NULL_TREE, restype);
5ff904cd 14421 }
5ff904cd 14422
c7e4ee3a
CB
14423 if (!nested && (TREE_CODE (current_function_decl) != ERROR_MARK))
14424 TREE_ADDRESSABLE (current_function_decl) = 1;
14425
14426 immediate_size_expand = old_immediate_size_expand;
14427}
14428\f
14429/* Here are the public functions the GNU back end needs. */
14430
14431tree
14432convert (type, expr)
14433 tree type, expr;
5ff904cd 14434{
c7e4ee3a
CB
14435 register tree e = expr;
14436 register enum tree_code code = TREE_CODE (type);
5ff904cd 14437
c7e4ee3a
CB
14438 if (type == TREE_TYPE (e)
14439 || TREE_CODE (e) == ERROR_MARK)
14440 return e;
14441 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
14442 return fold (build1 (NOP_EXPR, type, e));
14443 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
14444 || code == ERROR_MARK)
14445 return error_mark_node;
14446 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
14447 {
14448 assert ("void value not ignored as it ought to be" == NULL);
14449 return error_mark_node;
14450 }
14451 if (code == VOID_TYPE)
14452 return build1 (CONVERT_EXPR, type, e);
14453 if ((code != RECORD_TYPE)
14454 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
14455 e = ffecom_1 (REALPART_EXPR, TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e))),
14456 e);
14457 if (code == INTEGER_TYPE || code == ENUMERAL_TYPE)
14458 return fold (convert_to_integer (type, e));
14459 if (code == POINTER_TYPE)
14460 return fold (convert_to_pointer (type, e));
14461 if (code == REAL_TYPE)
14462 return fold (convert_to_real (type, e));
14463 if (code == COMPLEX_TYPE)
14464 return fold (convert_to_complex (type, e));
14465 if (code == RECORD_TYPE)
14466 return fold (ffecom_convert_to_complex_ (type, e));
5ff904cd 14467
c7e4ee3a
CB
14468 assert ("conversion to non-scalar type requested" == NULL);
14469 return error_mark_node;
14470}
5ff904cd 14471
c7e4ee3a
CB
14472/* integrate_decl_tree calls this function, but since we don't use the
14473 DECL_LANG_SPECIFIC field, this is a no-op. */
5ff904cd 14474
c7e4ee3a
CB
14475void
14476copy_lang_decl (node)
14477 tree node UNUSED;
14478{
5ff904cd
JL
14479}
14480
c7e4ee3a
CB
14481/* Return the list of declarations of the current level.
14482 Note that this list is in reverse order unless/until
14483 you nreverse it; and when you do nreverse it, you must
14484 store the result back using `storedecls' or you will lose. */
5ff904cd 14485
c7e4ee3a
CB
14486tree
14487getdecls ()
5ff904cd 14488{
c7e4ee3a 14489 return current_binding_level->names;
5ff904cd
JL
14490}
14491
c7e4ee3a 14492/* Nonzero if we are currently in the global binding level. */
5ff904cd 14493
c7e4ee3a
CB
14494int
14495global_bindings_p ()
5ff904cd 14496{
c7e4ee3a
CB
14497 return current_binding_level == global_binding_level;
14498}
5ff904cd 14499
c7e4ee3a
CB
14500/* Print an error message for invalid use of an incomplete type.
14501 VALUE is the expression that was used (or 0 if that isn't known)
14502 and TYPE is the type that was invalid. */
5ff904cd 14503
c7e4ee3a
CB
14504void
14505incomplete_type_error (value, type)
14506 tree value UNUSED;
14507 tree type;
14508{
14509 if (TREE_CODE (type) == ERROR_MARK)
14510 return;
5ff904cd 14511
c7e4ee3a
CB
14512 assert ("incomplete type?!?" == NULL);
14513}
14514
7189a4b0
GK
14515/* Mark ARG for GC. */
14516static void
54551044 14517mark_binding_level (void *arg)
7189a4b0
GK
14518{
14519 struct binding_level *level = *(struct binding_level **) arg;
14520
14521 while (level)
14522 {
14523 ggc_mark_tree (level->names);
14524 ggc_mark_tree (level->blocks);
14525 ggc_mark_tree (level->this_block);
14526 level = level->level_chain;
14527 }
14528}
14529
c7e4ee3a
CB
14530void
14531init_decl_processing ()
5ff904cd 14532{
7189a4b0
GK
14533 static tree *const tree_roots[] = {
14534 &current_function_decl,
14535 &string_type_node,
14536 &ffecom_tree_fun_type_void,
14537 &ffecom_integer_zero_node,
14538 &ffecom_integer_one_node,
14539 &ffecom_tree_subr_type,
14540 &ffecom_tree_ptr_to_subr_type,
14541 &ffecom_tree_blockdata_type,
14542 &ffecom_tree_xargc_,
14543 &ffecom_f2c_integer_type_node,
14544 &ffecom_f2c_ptr_to_integer_type_node,
14545 &ffecom_f2c_address_type_node,
14546 &ffecom_f2c_real_type_node,
14547 &ffecom_f2c_ptr_to_real_type_node,
14548 &ffecom_f2c_doublereal_type_node,
14549 &ffecom_f2c_complex_type_node,
14550 &ffecom_f2c_doublecomplex_type_node,
14551 &ffecom_f2c_longint_type_node,
14552 &ffecom_f2c_logical_type_node,
14553 &ffecom_f2c_flag_type_node,
14554 &ffecom_f2c_ftnlen_type_node,
14555 &ffecom_f2c_ftnlen_zero_node,
14556 &ffecom_f2c_ftnlen_one_node,
14557 &ffecom_f2c_ftnlen_two_node,
14558 &ffecom_f2c_ptr_to_ftnlen_type_node,
14559 &ffecom_f2c_ftnint_type_node,
14560 &ffecom_f2c_ptr_to_ftnint_type_node,
14561 &ffecom_outer_function_decl_,
14562 &ffecom_previous_function_decl_,
14563 &ffecom_which_entrypoint_decl_,
14564 &ffecom_float_zero_,
14565 &ffecom_float_half_,
14566 &ffecom_double_zero_,
14567 &ffecom_double_half_,
14568 &ffecom_func_result_,
14569 &ffecom_func_length_,
14570 &ffecom_multi_type_node_,
14571 &ffecom_multi_retval_,
14572 &named_labels,
14573 &shadowed_labels
14574 };
14575 size_t i;
14576
c7e4ee3a 14577 malloc_init ();
7189a4b0
GK
14578
14579 /* Record our roots. */
75ff2ca7 14580 for (i = 0; i < ARRAY_SIZE (tree_roots); i++)
7189a4b0
GK
14581 ggc_add_tree_root (tree_roots[i], 1);
14582 ggc_add_tree_root (&ffecom_tree_type[0][0],
14583 FFEINFO_basictype*FFEINFO_kindtype);
14584 ggc_add_tree_root (&ffecom_tree_fun_type[0][0],
14585 FFEINFO_basictype*FFEINFO_kindtype);
14586 ggc_add_tree_root (&ffecom_tree_ptr_to_fun_type[0][0],
14587 FFEINFO_basictype*FFEINFO_kindtype);
14588 ggc_add_tree_root (ffecom_gfrt_, FFECOM_gfrt);
14589 ggc_add_root (&current_binding_level, 1, sizeof current_binding_level,
14590 mark_binding_level);
14591 ggc_add_root (&free_binding_level, 1, sizeof current_binding_level,
14592 mark_binding_level);
14593 ggc_add_root (&tracker_head, 1, sizeof tracker_head, mark_tracker_head);
14594
c7e4ee3a
CB
14595 ffe_init_0 ();
14596}
5ff904cd 14597
3b304f5b 14598const char *
c7e4ee3a 14599init_parse (filename)
3b304f5b 14600 const char *filename;
c7e4ee3a 14601{
c7e4ee3a
CB
14602 /* Open input file. */
14603 if (filename == 0 || !strcmp (filename, "-"))
5ff904cd 14604 {
c7e4ee3a
CB
14605 finput = stdin;
14606 filename = "stdin";
5ff904cd 14607 }
c7e4ee3a
CB
14608 else
14609 finput = fopen (filename, "r");
14610 if (finput == 0)
400500c4 14611 fatal_io_error ("can't open %s", filename);
5ff904cd 14612
c7e4ee3a
CB
14613#ifdef IO_BUFFER_SIZE
14614 setvbuf (finput, (char *) xmalloc (IO_BUFFER_SIZE), _IOFBF, IO_BUFFER_SIZE);
14615#endif
5ff904cd 14616
c7e4ee3a
CB
14617 /* Make identifier nodes long enough for the language-specific slots. */
14618 set_identifier_size (sizeof (struct lang_identifier));
14619 decl_printable_name = lang_printable_name;
14620#if BUILT_FOR_270
14621 print_error_function = lang_print_error_function;
14622#endif
5ff904cd 14623
c7e4ee3a
CB
14624 return filename;
14625}
5ff904cd 14626
c7e4ee3a
CB
14627void
14628finish_parse ()
14629{
14630 fclose (finput);
14631}
14632
14633/* Delete the node BLOCK from the current binding level.
14634 This is used for the block inside a stmt expr ({...})
14635 so that the block can be reinserted where appropriate. */
14636
14637static void
14638delete_block (block)
14639 tree block;
14640{
14641 tree t;
14642 if (current_binding_level->blocks == block)
14643 current_binding_level->blocks = TREE_CHAIN (block);
14644 for (t = current_binding_level->blocks; t;)
14645 {
14646 if (TREE_CHAIN (t) == block)
14647 TREE_CHAIN (t) = TREE_CHAIN (block);
14648 else
14649 t = TREE_CHAIN (t);
14650 }
14651 TREE_CHAIN (block) = NULL;
14652 /* Clear TREE_USED which is always set by poplevel.
14653 The flag is set again if insert_block is called. */
14654 TREE_USED (block) = 0;
14655}
14656
14657void
14658insert_block (block)
14659 tree block;
14660{
14661 TREE_USED (block) = 1;
14662 current_binding_level->blocks
14663 = chainon (current_binding_level->blocks, block);
14664}
14665
cd2a3ba2 14666/* Each front end provides its own. */
ee811cfd
NB
14667static void ffe_init PARAMS ((void));
14668static void ffe_finish PARAMS ((void));
14669static void ffe_init_options PARAMS ((void));
14670
14671struct lang_hooks lang_hooks = {ffe_init,
14672 ffe_finish,
14673 ffe_init_options,
14674 ffe_decode_option,
13c61421 14675 NULL /* post_options */};
cd2a3ba2 14676
c7e4ee3a 14677/* used by print-tree.c */
5ff904cd 14678
c7e4ee3a
CB
14679void
14680lang_print_xnode (file, node, indent)
14681 FILE *file UNUSED;
14682 tree node UNUSED;
14683 int indent UNUSED;
5ff904cd 14684{
c7e4ee3a 14685}
5ff904cd 14686
13c61421 14687static void
ee811cfd 14688ffe_finish ()
c7e4ee3a
CB
14689{
14690 ffe_terminate_0 ();
5ff904cd 14691
c7e4ee3a
CB
14692 if (ffe_is_ffedebug ())
14693 malloc_pool_display (malloc_pool_image ());
5ff904cd
JL
14694}
14695
dafbd854 14696const char *
c7e4ee3a 14697lang_identify ()
5ff904cd 14698{
c7e4ee3a
CB
14699 return "f77";
14700}
5ff904cd 14701
2e761e49
RH
14702/* Return the typed-based alias set for T, which may be an expression
14703 or a type. Return -1 if we don't do anything special. */
14704
14705HOST_WIDE_INT
14706lang_get_alias_set (t)
5ac9118e 14707 tree t ATTRIBUTE_UNUSED;
2e761e49
RH
14708{
14709 /* We do not wish to use alias-set based aliasing at all. Used in the
14710 extreme (every object with its own set, with equivalences recorded)
14711 it might be helpful, but there are problems when it comes to inlining.
14712 We get on ok with flag_argument_noalias, and alias-set aliasing does
14713 currently limit how stack slots can be reused, which is a lose. */
14714 return 0;
14715}
14716
ee811cfd
NB
14717static void
14718ffe_init_options ()
c7e4ee3a
CB
14719{
14720 /* Set default options for Fortran. */
14721 flag_move_all_movables = 1;
14722 flag_reduce_all_givs = 1;
14723 flag_argument_noalias = 2;
41af162c 14724 flag_errno_math = 0;
c64f913e 14725 flag_complex_divide_method = 1;
c7e4ee3a 14726}
5ff904cd 14727
13c61421 14728static void
ee811cfd 14729ffe_init ()
c7e4ee3a
CB
14730{
14731 /* If the file is output from cpp, it should contain a first line
14732 `# 1 "real-filename"', and the current design of gcc (toplev.c
14733 in particular and the way it sets up information relied on by
14734 INCLUDE) requires that we read this now, and store the
14735 "real-filename" info in master_input_filename. Ask the lexer
14736 to try doing this. */
14737 ffelex_hash_kludge (finput);
14738}
5ff904cd 14739
c7e4ee3a
CB
14740int
14741mark_addressable (exp)
14742 tree exp;
14743{
14744 register tree x = exp;
14745 while (1)
14746 switch (TREE_CODE (x))
14747 {
14748 case ADDR_EXPR:
14749 case COMPONENT_REF:
14750 case ARRAY_REF:
14751 x = TREE_OPERAND (x, 0);
14752 break;
5ff904cd 14753
c7e4ee3a
CB
14754 case CONSTRUCTOR:
14755 TREE_ADDRESSABLE (x) = 1;
14756 return 1;
5ff904cd 14757
c7e4ee3a
CB
14758 case VAR_DECL:
14759 case CONST_DECL:
14760 case PARM_DECL:
14761 case RESULT_DECL:
14762 if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x)
14763 && DECL_NONLOCAL (x))
14764 {
14765 if (TREE_PUBLIC (x))
14766 {
14767 assert ("address of global register var requested" == NULL);
14768 return 0;
14769 }
14770 assert ("address of register variable requested" == NULL);
14771 }
14772 else if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x))
14773 {
14774 if (TREE_PUBLIC (x))
14775 {
14776 assert ("address of global register var requested" == NULL);
14777 return 0;
14778 }
14779 assert ("address of register var requested" == NULL);
14780 }
14781 put_var_into_stack (x);
5ff904cd 14782
c7e4ee3a
CB
14783 /* drops in */
14784 case FUNCTION_DECL:
14785 TREE_ADDRESSABLE (x) = 1;
14786#if 0 /* poplevel deals with this now. */
14787 if (DECL_CONTEXT (x) == 0)
14788 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;
14789#endif
5ff904cd 14790
c7e4ee3a
CB
14791 default:
14792 return 1;
14793 }
5ff904cd
JL
14794}
14795
c7e4ee3a
CB
14796/* If DECL has a cleanup, build and return that cleanup here.
14797 This is a callback called by expand_expr. */
5ff904cd 14798
c7e4ee3a
CB
14799tree
14800maybe_build_cleanup (decl)
14801 tree decl UNUSED;
5ff904cd 14802{
c7e4ee3a
CB
14803 /* There are no cleanups in Fortran. */
14804 return NULL_TREE;
5ff904cd
JL
14805}
14806
c7e4ee3a
CB
14807/* Exit a binding level.
14808 Pop the level off, and restore the state of the identifier-decl mappings
14809 that were in effect when this level was entered.
5ff904cd 14810
c7e4ee3a
CB
14811 If KEEP is nonzero, this level had explicit declarations, so
14812 and create a "block" (a BLOCK node) for the level
14813 to record its declarations and subblocks for symbol table output.
5ff904cd 14814
c7e4ee3a
CB
14815 If FUNCTIONBODY is nonzero, this level is the body of a function,
14816 so create a block as if KEEP were set and also clear out all
14817 label names.
5ff904cd 14818
c7e4ee3a
CB
14819 If REVERSE is nonzero, reverse the order of decls before putting
14820 them into the BLOCK. */
5ff904cd 14821
c7e4ee3a
CB
14822tree
14823poplevel (keep, reverse, functionbody)
14824 int keep;
14825 int reverse;
14826 int functionbody;
5ff904cd 14827{
c7e4ee3a
CB
14828 register tree link;
14829 /* The chain of decls was accumulated in reverse order.
14830 Put it into forward order, just for cleanliness. */
14831 tree decls;
14832 tree subblocks = current_binding_level->blocks;
14833 tree block = 0;
14834 tree decl;
14835 int block_previously_created;
5ff904cd 14836
c7e4ee3a
CB
14837 /* Get the decls in the order they were written.
14838 Usually current_binding_level->names is in reverse order.
14839 But parameter decls were previously put in forward order. */
702edf1d 14840
c7e4ee3a
CB
14841 if (reverse)
14842 current_binding_level->names
14843 = decls = nreverse (current_binding_level->names);
14844 else
14845 decls = current_binding_level->names;
5ff904cd 14846
c7e4ee3a
CB
14847 /* Output any nested inline functions within this block
14848 if they weren't already output. */
5ff904cd 14849
c7e4ee3a
CB
14850 for (decl = decls; decl; decl = TREE_CHAIN (decl))
14851 if (TREE_CODE (decl) == FUNCTION_DECL
14852 && ! TREE_ASM_WRITTEN (decl)
14853 && DECL_INITIAL (decl) != 0
14854 && TREE_ADDRESSABLE (decl))
14855 {
14856 /* If this decl was copied from a file-scope decl
14857 on account of a block-scope extern decl,
14858 propagate TREE_ADDRESSABLE to the file-scope decl.
14859
14860 DECL_ABSTRACT_ORIGIN can be set to itself if warn_return_type is
14861 true, since then the decl goes through save_for_inline_copying. */
14862 if (DECL_ABSTRACT_ORIGIN (decl) != 0
14863 && DECL_ABSTRACT_ORIGIN (decl) != decl)
14864 TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
14865 else if (DECL_SAVED_INSNS (decl) != 0)
14866 {
14867 push_function_context ();
14868 output_inline_function (decl);
14869 pop_function_context ();
14870 }
14871 }
5ff904cd 14872
c7e4ee3a
CB
14873 /* If there were any declarations or structure tags in that level,
14874 or if this level is a function body,
14875 create a BLOCK to record them for the life of this function. */
5ff904cd 14876
c7e4ee3a
CB
14877 block = 0;
14878 block_previously_created = (current_binding_level->this_block != 0);
14879 if (block_previously_created)
14880 block = current_binding_level->this_block;
14881 else if (keep || functionbody)
14882 block = make_node (BLOCK);
14883 if (block != 0)
14884 {
14885 BLOCK_VARS (block) = decls;
14886 BLOCK_SUBBLOCKS (block) = subblocks;
c7e4ee3a 14887 }
5ff904cd 14888
c7e4ee3a 14889 /* In each subblock, record that this is its superior. */
5ff904cd 14890
c7e4ee3a
CB
14891 for (link = subblocks; link; link = TREE_CHAIN (link))
14892 BLOCK_SUPERCONTEXT (link) = block;
5ff904cd 14893
c7e4ee3a 14894 /* Clear out the meanings of the local variables of this level. */
5ff904cd 14895
c7e4ee3a 14896 for (link = decls; link; link = TREE_CHAIN (link))
5ff904cd 14897 {
c7e4ee3a
CB
14898 if (DECL_NAME (link) != 0)
14899 {
14900 /* If the ident. was used or addressed via a local extern decl,
14901 don't forget that fact. */
14902 if (DECL_EXTERNAL (link))
14903 {
14904 if (TREE_USED (link))
14905 TREE_USED (DECL_NAME (link)) = 1;
14906 if (TREE_ADDRESSABLE (link))
14907 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1;
14908 }
14909 IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = 0;
14910 }
5ff904cd 14911 }
5ff904cd 14912
c7e4ee3a
CB
14913 /* If the level being exited is the top level of a function,
14914 check over all the labels, and clear out the current
14915 (function local) meanings of their names. */
5ff904cd 14916
c7e4ee3a 14917 if (functionbody)
5ff904cd 14918 {
c7e4ee3a
CB
14919 /* If this is the top level block of a function,
14920 the vars are the function's parameters.
14921 Don't leave them in the BLOCK because they are
14922 found in the FUNCTION_DECL instead. */
14923
14924 BLOCK_VARS (block) = 0;
5ff904cd
JL
14925 }
14926
c7e4ee3a
CB
14927 /* Pop the current level, and free the structure for reuse. */
14928
14929 {
14930 register struct binding_level *level = current_binding_level;
14931 current_binding_level = current_binding_level->level_chain;
14932
14933 level->level_chain = free_binding_level;
14934 free_binding_level = level;
14935 }
14936
14937 /* Dispose of the block that we just made inside some higher level. */
14938 if (functionbody
14939 && current_function_decl != error_mark_node)
14940 DECL_INITIAL (current_function_decl) = block;
14941 else if (block)
5ff904cd 14942 {
c7e4ee3a
CB
14943 if (!block_previously_created)
14944 current_binding_level->blocks
14945 = chainon (current_binding_level->blocks, block);
5ff904cd 14946 }
c7e4ee3a
CB
14947 /* If we did not make a block for the level just exited,
14948 any blocks made for inner levels
14949 (since they cannot be recorded as subblocks in that level)
14950 must be carried forward so they will later become subblocks
14951 of something else. */
14952 else if (subblocks)
14953 current_binding_level->blocks
14954 = chainon (current_binding_level->blocks, subblocks);
5ff904cd 14955
c7e4ee3a
CB
14956 if (block)
14957 TREE_USED (block) = 1;
14958 return block;
5ff904cd
JL
14959}
14960
c7e4ee3a
CB
14961void
14962print_lang_decl (file, node, indent)
14963 FILE *file UNUSED;
14964 tree node UNUSED;
14965 int indent UNUSED;
14966{
14967}
5ff904cd 14968
c7e4ee3a
CB
14969void
14970print_lang_identifier (file, node, indent)
14971 FILE *file;
14972 tree node;
14973 int indent;
14974{
14975 print_node (file, "global", IDENTIFIER_GLOBAL_VALUE (node), indent + 4);
14976 print_node (file, "local", IDENTIFIER_LOCAL_VALUE (node), indent + 4);
14977}
5ff904cd 14978
c7e4ee3a
CB
14979void
14980print_lang_statistics ()
14981{
14982}
5ff904cd 14983
c7e4ee3a
CB
14984void
14985print_lang_type (file, node, indent)
14986 FILE *file UNUSED;
14987 tree node UNUSED;
14988 int indent UNUSED;
5ff904cd 14989{
c7e4ee3a 14990}
5ff904cd 14991
c7e4ee3a
CB
14992/* Record a decl-node X as belonging to the current lexical scope.
14993 Check for errors (such as an incompatible declaration for the same
14994 name already seen in the same scope).
5ff904cd 14995
c7e4ee3a
CB
14996 Returns either X or an old decl for the same name.
14997 If an old decl is returned, it may have been smashed
14998 to agree with what X says. */
5ff904cd 14999
c7e4ee3a
CB
15000tree
15001pushdecl (x)
15002 tree x;
15003{
15004 register tree t;
15005 register tree name = DECL_NAME (x);
15006 register struct binding_level *b = current_binding_level;
5ff904cd 15007
c7e4ee3a
CB
15008 if ((TREE_CODE (x) == FUNCTION_DECL)
15009 && (DECL_INITIAL (x) == 0)
15010 && DECL_EXTERNAL (x))
15011 DECL_CONTEXT (x) = NULL_TREE;
56a0044b 15012 else
c7e4ee3a
CB
15013 DECL_CONTEXT (x) = current_function_decl;
15014
15015 if (name)
56a0044b 15016 {
c7e4ee3a
CB
15017 if (IDENTIFIER_INVENTED (name))
15018 {
15019#if BUILT_FOR_270
15020 DECL_ARTIFICIAL (x) = 1;
15021#endif
15022 DECL_IN_SYSTEM_HEADER (x) = 1;
15023 }
5ff904cd 15024
c7e4ee3a 15025 t = lookup_name_current_level (name);
5ff904cd 15026
c7e4ee3a 15027 assert ((t == NULL_TREE) || (DECL_CONTEXT (x) == NULL_TREE));
5ff904cd 15028
c7e4ee3a
CB
15029 /* Don't push non-parms onto list for parms until we understand
15030 why we're doing this and whether it works. */
56a0044b 15031
c7e4ee3a
CB
15032 assert ((b == global_binding_level)
15033 || !ffecom_transform_only_dummies_
15034 || TREE_CODE (x) == PARM_DECL);
5ff904cd 15035
c7e4ee3a
CB
15036 if ((t != NULL_TREE) && duplicate_decls (x, t))
15037 return t;
5ff904cd 15038
c7e4ee3a
CB
15039 /* If we are processing a typedef statement, generate a whole new
15040 ..._TYPE node (which will be just an variant of the existing
15041 ..._TYPE node with identical properties) and then install the
15042 TYPE_DECL node generated to represent the typedef name as the
15043 TYPE_NAME of this brand new (duplicate) ..._TYPE node.
5ff904cd 15044
c7e4ee3a
CB
15045 The whole point here is to end up with a situation where each and every
15046 ..._TYPE node the compiler creates will be uniquely associated with
15047 AT MOST one node representing a typedef name. This way, even though
15048 the compiler substitutes corresponding ..._TYPE nodes for TYPE_DECL
15049 (i.e. "typedef name") nodes very early on, later parts of the
15050 compiler can always do the reverse translation and get back the
15051 corresponding typedef name. For example, given:
5ff904cd 15052
c7e4ee3a 15053 typedef struct S MY_TYPE; MY_TYPE object;
5ff904cd 15054
c7e4ee3a
CB
15055 Later parts of the compiler might only know that `object' was of type
15056 `struct S' if it were not for code just below. With this code
15057 however, later parts of the compiler see something like:
5ff904cd 15058
c7e4ee3a 15059 struct S' == struct S typedef struct S' MY_TYPE; struct S' object;
5ff904cd 15060
c7e4ee3a
CB
15061 And they can then deduce (from the node for type struct S') that the
15062 original object declaration was:
5ff904cd 15063
c7e4ee3a 15064 MY_TYPE object;
5ff904cd 15065
c7e4ee3a
CB
15066 Being able to do this is important for proper support of protoize, and
15067 also for generating precise symbolic debugging information which
15068 takes full account of the programmer's (typedef) vocabulary.
5ff904cd 15069
c7e4ee3a
CB
15070 Obviously, we don't want to generate a duplicate ..._TYPE node if the
15071 TYPE_DECL node that we are now processing really represents a
15072 standard built-in type.
5ff904cd 15073
c7e4ee3a
CB
15074 Since all standard types are effectively declared at line zero in the
15075 source file, we can easily check to see if we are working on a
15076 standard type by checking the current value of lineno. */
15077
15078 if (TREE_CODE (x) == TYPE_DECL)
15079 {
15080 if (DECL_SOURCE_LINE (x) == 0)
15081 {
15082 if (TYPE_NAME (TREE_TYPE (x)) == 0)
15083 TYPE_NAME (TREE_TYPE (x)) = x;
15084 }
15085 else if (TREE_TYPE (x) != error_mark_node)
15086 {
15087 tree tt = TREE_TYPE (x);
15088
15089 tt = build_type_copy (tt);
15090 TYPE_NAME (tt) = x;
15091 TREE_TYPE (x) = tt;
15092 }
15093 }
5ff904cd 15094
c7e4ee3a
CB
15095 /* This name is new in its binding level. Install the new declaration
15096 and return it. */
15097 if (b == global_binding_level)
15098 IDENTIFIER_GLOBAL_VALUE (name) = x;
15099 else
15100 IDENTIFIER_LOCAL_VALUE (name) = x;
15101 }
5ff904cd 15102
c7e4ee3a
CB
15103 /* Put decls on list in reverse order. We will reverse them later if
15104 necessary. */
15105 TREE_CHAIN (x) = b->names;
15106 b->names = x;
5ff904cd 15107
c7e4ee3a 15108 return x;
5ff904cd
JL
15109}
15110
c7e4ee3a 15111/* Nonzero if the current level needs to have a BLOCK made. */
5ff904cd 15112
c7e4ee3a
CB
15113static int
15114kept_level_p ()
5ff904cd 15115{
c7e4ee3a
CB
15116 tree decl;
15117
15118 for (decl = current_binding_level->names;
15119 decl;
15120 decl = TREE_CHAIN (decl))
15121 {
15122 if (TREE_USED (decl) || TREE_CODE (decl) != VAR_DECL
15123 || (DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl)))
15124 /* Currently, there aren't supposed to be non-artificial names
15125 at other than the top block for a function -- they're
15126 believed to always be temps. But it's wise to check anyway. */
15127 return 1;
15128 }
15129 return 0;
5ff904cd
JL
15130}
15131
c7e4ee3a
CB
15132/* Enter a new binding level.
15133 If TAG_TRANSPARENT is nonzero, do so only for the name space of variables,
15134 not for that of tags. */
5ff904cd
JL
15135
15136void
c7e4ee3a
CB
15137pushlevel (tag_transparent)
15138 int tag_transparent;
5ff904cd 15139{
c7e4ee3a 15140 register struct binding_level *newlevel = NULL_BINDING_LEVEL;
5ff904cd 15141
c7e4ee3a 15142 assert (! tag_transparent);
5ff904cd 15143
c7e4ee3a
CB
15144 if (current_binding_level == global_binding_level)
15145 {
15146 named_labels = 0;
15147 }
5ff904cd 15148
c7e4ee3a 15149 /* Reuse or create a struct for this binding level. */
5ff904cd 15150
c7e4ee3a 15151 if (free_binding_level)
77f77701 15152 {
c7e4ee3a
CB
15153 newlevel = free_binding_level;
15154 free_binding_level = free_binding_level->level_chain;
77f77701
DB
15155 }
15156 else
c7e4ee3a
CB
15157 {
15158 newlevel = make_binding_level ();
15159 }
77f77701 15160
c7e4ee3a
CB
15161 /* Add this level to the front of the chain (stack) of levels that
15162 are active. */
71b5e532 15163
c7e4ee3a
CB
15164 *newlevel = clear_binding_level;
15165 newlevel->level_chain = current_binding_level;
15166 current_binding_level = newlevel;
5ff904cd
JL
15167}
15168
c7e4ee3a
CB
15169/* Set the BLOCK node for the innermost scope
15170 (the one we are currently in). */
77f77701 15171
5ff904cd 15172void
c7e4ee3a
CB
15173set_block (block)
15174 register tree block;
5ff904cd 15175{
c7e4ee3a 15176 current_binding_level->this_block = block;
5ff904cd
JL
15177}
15178
c7e4ee3a 15179/* ~~gcc/tree.h *should* declare this, because toplev.c references it. */
5ff904cd 15180
c7e4ee3a 15181/* Can't 'yydebug' a front end not generated by yacc/bison! */
bc289659
ML
15182
15183void
c7e4ee3a
CB
15184set_yydebug (value)
15185 int value;
bc289659 15186{
c7e4ee3a
CB
15187 if (value)
15188 fprintf (stderr, "warning: no yacc/bison-generated output to debug!\n");
bc289659
ML
15189}
15190
c7e4ee3a
CB
15191tree
15192signed_or_unsigned_type (unsignedp, type)
15193 int unsignedp;
15194 tree type;
5ff904cd 15195{
c7e4ee3a 15196 tree type2;
5ff904cd 15197
c7e4ee3a
CB
15198 if (! INTEGRAL_TYPE_P (type))
15199 return type;
15200 if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node))
15201 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15202 if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
15203 return unsignedp ? unsigned_type_node : integer_type_node;
15204 if (TYPE_PRECISION (type) == TYPE_PRECISION (short_integer_type_node))
15205 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15206 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_integer_type_node))
15207 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15208 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_long_integer_type_node))
15209 return (unsignedp ? long_long_unsigned_type_node
15210 : long_long_integer_type_node);
5ff904cd 15211
c7e4ee3a
CB
15212 type2 = type_for_size (TYPE_PRECISION (type), unsignedp);
15213 if (type2 == NULL_TREE)
15214 return type;
f84639ba 15215
c7e4ee3a 15216 return type2;
5ff904cd
JL
15217}
15218
c7e4ee3a
CB
15219tree
15220signed_type (type)
15221 tree type;
5ff904cd 15222{
c7e4ee3a
CB
15223 tree type1 = TYPE_MAIN_VARIANT (type);
15224 ffeinfoKindtype kt;
15225 tree type2;
5ff904cd 15226
c7e4ee3a
CB
15227 if (type1 == unsigned_char_type_node || type1 == char_type_node)
15228 return signed_char_type_node;
15229 if (type1 == unsigned_type_node)
15230 return integer_type_node;
15231 if (type1 == short_unsigned_type_node)
15232 return short_integer_type_node;
15233 if (type1 == long_unsigned_type_node)
15234 return long_integer_type_node;
15235 if (type1 == long_long_unsigned_type_node)
15236 return long_long_integer_type_node;
15237#if 0 /* gcc/c-* files only */
15238 if (type1 == unsigned_intDI_type_node)
15239 return intDI_type_node;
15240 if (type1 == unsigned_intSI_type_node)
15241 return intSI_type_node;
15242 if (type1 == unsigned_intHI_type_node)
15243 return intHI_type_node;
15244 if (type1 == unsigned_intQI_type_node)
15245 return intQI_type_node;
15246#endif
5ff904cd 15247
c7e4ee3a
CB
15248 type2 = type_for_size (TYPE_PRECISION (type1), 0);
15249 if (type2 != NULL_TREE)
15250 return type2;
5ff904cd 15251
c7e4ee3a
CB
15252 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15253 {
15254 type2 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
5ff904cd 15255
c7e4ee3a
CB
15256 if (type1 == type2)
15257 return ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15258 }
15259
15260 return type;
5ff904cd
JL
15261}
15262
c7e4ee3a
CB
15263/* Prepare expr to be an argument of a TRUTH_NOT_EXPR,
15264 or validate its data type for an `if' or `while' statement or ?..: exp.
15265
15266 This preparation consists of taking the ordinary
15267 representation of an expression expr and producing a valid tree
15268 boolean expression describing whether expr is nonzero. We could
15269 simply always do build_binary_op (NE_EXPR, expr, integer_zero_node, 1),
15270 but we optimize comparisons, &&, ||, and !.
15271
15272 The resulting type should always be `integer_type_node'. */
5ff904cd
JL
15273
15274tree
c7e4ee3a
CB
15275truthvalue_conversion (expr)
15276 tree expr;
5ff904cd 15277{
c7e4ee3a
CB
15278 if (TREE_CODE (expr) == ERROR_MARK)
15279 return expr;
5ff904cd 15280
c7e4ee3a
CB
15281#if 0 /* This appears to be wrong for C++. */
15282 /* These really should return error_mark_node after 2.4 is stable.
15283 But not all callers handle ERROR_MARK properly. */
15284 switch (TREE_CODE (TREE_TYPE (expr)))
15285 {
15286 case RECORD_TYPE:
15287 error ("struct type value used where scalar is required");
15288 return integer_zero_node;
5ff904cd 15289
c7e4ee3a
CB
15290 case UNION_TYPE:
15291 error ("union type value used where scalar is required");
15292 return integer_zero_node;
5ff904cd 15293
c7e4ee3a
CB
15294 case ARRAY_TYPE:
15295 error ("array type value used where scalar is required");
15296 return integer_zero_node;
5ff904cd 15297
c7e4ee3a
CB
15298 default:
15299 break;
15300 }
15301#endif /* 0 */
5ff904cd 15302
c7e4ee3a
CB
15303 switch (TREE_CODE (expr))
15304 {
15305 /* It is simpler and generates better code to have only TRUTH_*_EXPR
15306 or comparison expressions as truth values at this level. */
15307#if 0
15308 case COMPONENT_REF:
15309 /* A one-bit unsigned bit-field is already acceptable. */
15310 if (1 == TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (expr, 1)))
15311 && TREE_UNSIGNED (TREE_OPERAND (expr, 1)))
15312 return expr;
15313 break;
15314#endif
15315
15316 case EQ_EXPR:
15317 /* It is simpler and generates better code to have only TRUTH_*_EXPR
15318 or comparison expressions as truth values at this level. */
15319#if 0
15320 if (integer_zerop (TREE_OPERAND (expr, 1)))
15321 return build_unary_op (TRUTH_NOT_EXPR, TREE_OPERAND (expr, 0), 0);
15322#endif
15323 case NE_EXPR: case LE_EXPR: case GE_EXPR: case LT_EXPR: case GT_EXPR:
15324 case TRUTH_ANDIF_EXPR:
15325 case TRUTH_ORIF_EXPR:
15326 case TRUTH_AND_EXPR:
15327 case TRUTH_OR_EXPR:
15328 case TRUTH_XOR_EXPR:
15329 TREE_TYPE (expr) = integer_type_node;
15330 return expr;
5ff904cd 15331
c7e4ee3a
CB
15332 case ERROR_MARK:
15333 return expr;
5ff904cd 15334
c7e4ee3a
CB
15335 case INTEGER_CST:
15336 return integer_zerop (expr) ? integer_zero_node : integer_one_node;
5ff904cd 15337
c7e4ee3a
CB
15338 case REAL_CST:
15339 return real_zerop (expr) ? integer_zero_node : integer_one_node;
5ff904cd 15340
c7e4ee3a
CB
15341 case ADDR_EXPR:
15342 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 0)))
15343 return build (COMPOUND_EXPR, integer_type_node,
15344 TREE_OPERAND (expr, 0), integer_one_node);
15345 else
15346 return integer_one_node;
5ff904cd 15347
c7e4ee3a
CB
15348 case COMPLEX_EXPR:
15349 return ffecom_2 ((TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
15350 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
15351 integer_type_node,
15352 truthvalue_conversion (TREE_OPERAND (expr, 0)),
15353 truthvalue_conversion (TREE_OPERAND (expr, 1)));
5ff904cd 15354
c7e4ee3a
CB
15355 case NEGATE_EXPR:
15356 case ABS_EXPR:
15357 case FLOAT_EXPR:
15358 case FFS_EXPR:
15359 /* These don't change whether an object is non-zero or zero. */
15360 return truthvalue_conversion (TREE_OPERAND (expr, 0));
5ff904cd 15361
c7e4ee3a
CB
15362 case LROTATE_EXPR:
15363 case RROTATE_EXPR:
15364 /* These don't change whether an object is zero or non-zero, but
15365 we can't ignore them if their second arg has side-effects. */
15366 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
15367 return build (COMPOUND_EXPR, integer_type_node, TREE_OPERAND (expr, 1),
15368 truthvalue_conversion (TREE_OPERAND (expr, 0)));
15369 else
15370 return truthvalue_conversion (TREE_OPERAND (expr, 0));
5ff904cd 15371
c7e4ee3a
CB
15372 case COND_EXPR:
15373 /* Distribute the conversion into the arms of a COND_EXPR. */
15374 return fold (build (COND_EXPR, integer_type_node, TREE_OPERAND (expr, 0),
15375 truthvalue_conversion (TREE_OPERAND (expr, 1)),
15376 truthvalue_conversion (TREE_OPERAND (expr, 2))));
5ff904cd 15377
c7e4ee3a
CB
15378 case CONVERT_EXPR:
15379 /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
15380 since that affects how `default_conversion' will behave. */
15381 if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE
15382 || TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE)
15383 break;
15384 /* fall through... */
15385 case NOP_EXPR:
15386 /* If this is widening the argument, we can ignore it. */
15387 if (TYPE_PRECISION (TREE_TYPE (expr))
15388 >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))
15389 return truthvalue_conversion (TREE_OPERAND (expr, 0));
15390 break;
5ff904cd 15391
c7e4ee3a
CB
15392 case MINUS_EXPR:
15393 /* With IEEE arithmetic, x - x may not equal 0, so we can't optimize
15394 this case. */
15395 if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
15396 && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE)
15397 break;
15398 /* fall through... */
15399 case BIT_XOR_EXPR:
15400 /* This and MINUS_EXPR can be changed into a comparison of the
15401 two objects. */
15402 if (TREE_TYPE (TREE_OPERAND (expr, 0))
15403 == TREE_TYPE (TREE_OPERAND (expr, 1)))
15404 return ffecom_2 (NE_EXPR, integer_type_node,
15405 TREE_OPERAND (expr, 0),
15406 TREE_OPERAND (expr, 1));
15407 return ffecom_2 (NE_EXPR, integer_type_node,
15408 TREE_OPERAND (expr, 0),
15409 fold (build1 (NOP_EXPR,
15410 TREE_TYPE (TREE_OPERAND (expr, 0)),
15411 TREE_OPERAND (expr, 1))));
15412
15413 case BIT_AND_EXPR:
15414 if (integer_onep (TREE_OPERAND (expr, 1)))
15415 return expr;
15416 break;
15417
15418 case MODIFY_EXPR:
15419#if 0 /* No such thing in Fortran. */
15420 if (warn_parentheses && C_EXP_ORIGINAL_CODE (expr) == MODIFY_EXPR)
15421 warning ("suggest parentheses around assignment used as truth value");
15422#endif
15423 break;
15424
15425 default:
15426 break;
5ff904cd
JL
15427 }
15428
c7e4ee3a
CB
15429 if (TREE_CODE (TREE_TYPE (expr)) == COMPLEX_TYPE)
15430 return (ffecom_2
15431 ((TREE_SIDE_EFFECTS (expr)
15432 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
15433 integer_type_node,
15434 truthvalue_conversion (ffecom_1 (REALPART_EXPR,
15435 TREE_TYPE (TREE_TYPE (expr)),
15436 expr)),
15437 truthvalue_conversion (ffecom_1 (IMAGPART_EXPR,
15438 TREE_TYPE (TREE_TYPE (expr)),
15439 expr))));
15440
15441 return ffecom_2 (NE_EXPR, integer_type_node,
15442 expr,
15443 convert (TREE_TYPE (expr), integer_zero_node));
15444}
15445
15446tree
15447type_for_mode (mode, unsignedp)
15448 enum machine_mode mode;
15449 int unsignedp;
15450{
15451 int i;
15452 int j;
15453 tree t;
5ff904cd 15454
c7e4ee3a
CB
15455 if (mode == TYPE_MODE (integer_type_node))
15456 return unsignedp ? unsigned_type_node : integer_type_node;
5ff904cd 15457
c7e4ee3a
CB
15458 if (mode == TYPE_MODE (signed_char_type_node))
15459 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
5ff904cd 15460
c7e4ee3a
CB
15461 if (mode == TYPE_MODE (short_integer_type_node))
15462 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
5ff904cd 15463
c7e4ee3a
CB
15464 if (mode == TYPE_MODE (long_integer_type_node))
15465 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
5ff904cd 15466
c7e4ee3a
CB
15467 if (mode == TYPE_MODE (long_long_integer_type_node))
15468 return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
5ff904cd 15469
fed3cef0
RK
15470#if HOST_BITS_PER_WIDE_INT >= 64
15471 if (mode == TYPE_MODE (intTI_type_node))
15472 return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
15473#endif
15474
c7e4ee3a
CB
15475 if (mode == TYPE_MODE (float_type_node))
15476 return float_type_node;
5ff904cd 15477
c7e4ee3a
CB
15478 if (mode == TYPE_MODE (double_type_node))
15479 return double_type_node;
5ff904cd 15480
c7e4ee3a
CB
15481 if (mode == TYPE_MODE (build_pointer_type (char_type_node)))
15482 return build_pointer_type (char_type_node);
5ff904cd 15483
c7e4ee3a
CB
15484 if (mode == TYPE_MODE (build_pointer_type (integer_type_node)))
15485 return build_pointer_type (integer_type_node);
5ff904cd 15486
c7e4ee3a
CB
15487 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
15488 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
15489 {
15490 if (((t = ffecom_tree_type[i][j]) != NULL_TREE)
15491 && (mode == TYPE_MODE (t)))
15492 {
15493 if ((i == FFEINFO_basictypeINTEGER) && unsignedp)
15494 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][j];
15495 else
15496 return t;
15497 }
15498 }
5ff904cd 15499
c7e4ee3a 15500 return 0;
5ff904cd
JL
15501}
15502
c7e4ee3a
CB
15503tree
15504type_for_size (bits, unsignedp)
15505 unsigned bits;
15506 int unsignedp;
5ff904cd 15507{
c7e4ee3a
CB
15508 ffeinfoKindtype kt;
15509 tree type_node;
5ff904cd 15510
c7e4ee3a
CB
15511 if (bits == TYPE_PRECISION (integer_type_node))
15512 return unsignedp ? unsigned_type_node : integer_type_node;
5ff904cd 15513
c7e4ee3a
CB
15514 if (bits == TYPE_PRECISION (signed_char_type_node))
15515 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
5ff904cd 15516
c7e4ee3a
CB
15517 if (bits == TYPE_PRECISION (short_integer_type_node))
15518 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
5ff904cd 15519
c7e4ee3a
CB
15520 if (bits == TYPE_PRECISION (long_integer_type_node))
15521 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
5ff904cd 15522
c7e4ee3a
CB
15523 if (bits == TYPE_PRECISION (long_long_integer_type_node))
15524 return (unsignedp ? long_long_unsigned_type_node
15525 : long_long_integer_type_node);
5ff904cd 15526
c7e4ee3a 15527 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
5ff904cd 15528 {
c7e4ee3a 15529 type_node = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
5ff904cd 15530
c7e4ee3a
CB
15531 if ((type_node != NULL_TREE) && (bits == TYPE_PRECISION (type_node)))
15532 return unsignedp ? ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt]
15533 : type_node;
15534 }
5ff904cd 15535
c7e4ee3a
CB
15536 return 0;
15537}
5ff904cd 15538
c7e4ee3a
CB
15539tree
15540unsigned_type (type)
15541 tree type;
15542{
15543 tree type1 = TYPE_MAIN_VARIANT (type);
15544 ffeinfoKindtype kt;
15545 tree type2;
5ff904cd 15546
c7e4ee3a
CB
15547 if (type1 == signed_char_type_node || type1 == char_type_node)
15548 return unsigned_char_type_node;
15549 if (type1 == integer_type_node)
15550 return unsigned_type_node;
15551 if (type1 == short_integer_type_node)
15552 return short_unsigned_type_node;
15553 if (type1 == long_integer_type_node)
15554 return long_unsigned_type_node;
15555 if (type1 == long_long_integer_type_node)
15556 return long_long_unsigned_type_node;
15557#if 0 /* gcc/c-* files only */
15558 if (type1 == intDI_type_node)
15559 return unsigned_intDI_type_node;
15560 if (type1 == intSI_type_node)
15561 return unsigned_intSI_type_node;
15562 if (type1 == intHI_type_node)
15563 return unsigned_intHI_type_node;
15564 if (type1 == intQI_type_node)
15565 return unsigned_intQI_type_node;
15566#endif
5ff904cd 15567
c7e4ee3a
CB
15568 type2 = type_for_size (TYPE_PRECISION (type1), 1);
15569 if (type2 != NULL_TREE)
15570 return type2;
5ff904cd 15571
c7e4ee3a
CB
15572 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15573 {
15574 type2 = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
5ff904cd 15575
c7e4ee3a
CB
15576 if (type1 == type2)
15577 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
15578 }
5ff904cd 15579
c7e4ee3a
CB
15580 return type;
15581}
5ff904cd 15582
7189a4b0
GK
15583void
15584lang_mark_tree (t)
15585 union tree_node *t ATTRIBUTE_UNUSED;
15586{
15587 if (TREE_CODE (t) == IDENTIFIER_NODE)
15588 {
15589 struct lang_identifier *i = (struct lang_identifier *) t;
15590 ggc_mark_tree (IDENTIFIER_GLOBAL_VALUE (i));
15591 ggc_mark_tree (IDENTIFIER_LOCAL_VALUE (i));
15592 ggc_mark_tree (IDENTIFIER_LABEL_VALUE (i));
15593 }
15594 else if (TYPE_P (t) && TYPE_LANG_SPECIFIC (t))
15595 ggc_mark (TYPE_LANG_SPECIFIC (t));
15596}
15597
c7e4ee3a
CB
15598#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
15599\f
15600#if FFECOM_GCC_INCLUDE
5ff904cd 15601
c7e4ee3a 15602/* From gcc/cccp.c, the code to handle -I. */
5ff904cd 15603
c7e4ee3a
CB
15604/* Skip leading "./" from a directory name.
15605 This may yield the empty string, which represents the current directory. */
5ff904cd 15606
c7e4ee3a
CB
15607static const char *
15608skip_redundant_dir_prefix (const char *dir)
15609{
15610 while (dir[0] == '.' && dir[1] == '/')
15611 for (dir += 2; *dir == '/'; dir++)
15612 continue;
15613 if (dir[0] == '.' && !dir[1])
15614 dir++;
15615 return dir;
15616}
5ff904cd 15617
c7e4ee3a
CB
15618/* The file_name_map structure holds a mapping of file names for a
15619 particular directory. This mapping is read from the file named
15620 FILE_NAME_MAP_FILE in that directory. Such a file can be used to
15621 map filenames on a file system with severe filename restrictions,
15622 such as DOS. The format of the file name map file is just a series
15623 of lines with two tokens on each line. The first token is the name
15624 to map, and the second token is the actual name to use. */
5ff904cd 15625
c7e4ee3a
CB
15626struct file_name_map
15627{
15628 struct file_name_map *map_next;
15629 char *map_from;
15630 char *map_to;
15631};
5ff904cd 15632
c7e4ee3a 15633#define FILE_NAME_MAP_FILE "header.gcc"
5ff904cd 15634
c7e4ee3a
CB
15635/* Current maximum length of directory names in the search path
15636 for include files. (Altered as we get more of them.) */
5ff904cd 15637
c7e4ee3a 15638static int max_include_len = 0;
5ff904cd 15639
c7e4ee3a
CB
15640struct file_name_list
15641 {
15642 struct file_name_list *next;
15643 char *fname;
15644 /* Mapping of file names for this directory. */
15645 struct file_name_map *name_map;
15646 /* Non-zero if name_map is valid. */
15647 int got_name_map;
15648 };
5ff904cd 15649
c7e4ee3a
CB
15650static struct file_name_list *include = NULL; /* First dir to search */
15651static struct file_name_list *last_include = NULL; /* Last in chain */
5ff904cd 15652
c7e4ee3a
CB
15653/* I/O buffer structure.
15654 The `fname' field is nonzero for source files and #include files
15655 and for the dummy text used for -D and -U.
15656 It is zero for rescanning results of macro expansion
15657 and for expanding macro arguments. */
15658#define INPUT_STACK_MAX 400
15659static struct file_buf {
b0791fa9 15660 const char *fname;
c7e4ee3a 15661 /* Filename specified with #line command. */
b0791fa9 15662 const char *nominal_fname;
c7e4ee3a
CB
15663 /* Record where in the search path this file was found.
15664 For #include_next. */
15665 struct file_name_list *dir;
15666 ffewhereLine line;
15667 ffewhereColumn column;
15668} instack[INPUT_STACK_MAX];
5ff904cd 15669
c7e4ee3a
CB
15670static int last_error_tick = 0; /* Incremented each time we print it. */
15671static int input_file_stack_tick = 0; /* Incremented when status changes. */
5ff904cd 15672
c7e4ee3a
CB
15673/* Current nesting level of input sources.
15674 `instack[indepth]' is the level currently being read. */
15675static int indepth = -1;
5ff904cd 15676
c7e4ee3a 15677typedef struct file_buf FILE_BUF;
5ff904cd 15678
c7e4ee3a 15679typedef unsigned char U_CHAR;
5ff904cd 15680
c7e4ee3a
CB
15681/* table to tell if char can be part of a C identifier. */
15682U_CHAR is_idchar[256];
15683/* table to tell if char can be first char of a c identifier. */
15684U_CHAR is_idstart[256];
15685/* table to tell if c is horizontal space. */
15686U_CHAR is_hor_space[256];
15687/* table to tell if c is horizontal or vertical space. */
15688static U_CHAR is_space[256];
5ff904cd 15689
c7e4ee3a
CB
15690#define SKIP_WHITE_SPACE(p) do { while (is_hor_space[*p]) p++; } while (0)
15691#define SKIP_ALL_WHITE_SPACE(p) do { while (is_space[*p]) p++; } while (0)
5ff904cd 15692
c7e4ee3a
CB
15693/* Nonzero means -I- has been seen,
15694 so don't look for #include "foo" the source-file directory. */
15695static int ignore_srcdir;
5ff904cd 15696
c7e4ee3a
CB
15697#ifndef INCLUDE_LEN_FUDGE
15698#define INCLUDE_LEN_FUDGE 0
15699#endif
5ff904cd 15700
c7e4ee3a
CB
15701static void append_include_chain (struct file_name_list *first,
15702 struct file_name_list *last);
15703static FILE *open_include_file (char *filename,
15704 struct file_name_list *searchptr);
15705static void print_containing_files (ffebadSeverity sev);
15706static const char *skip_redundant_dir_prefix (const char *);
15707static char *read_filename_string (int ch, FILE *f);
15708static struct file_name_map *read_name_map (const char *dirname);
5ff904cd 15709
c7e4ee3a
CB
15710/* Append a chain of `struct file_name_list's
15711 to the end of the main include chain.
15712 FIRST is the beginning of the chain to append, and LAST is the end. */
5ff904cd 15713
c7e4ee3a
CB
15714static void
15715append_include_chain (first, last)
15716 struct file_name_list *first, *last;
5ff904cd 15717{
c7e4ee3a 15718 struct file_name_list *dir;
5ff904cd 15719
c7e4ee3a
CB
15720 if (!first || !last)
15721 return;
5ff904cd 15722
c7e4ee3a
CB
15723 if (include == 0)
15724 include = first;
15725 else
15726 last_include->next = first;
5ff904cd 15727
c7e4ee3a
CB
15728 for (dir = first; ; dir = dir->next) {
15729 int len = strlen (dir->fname) + INCLUDE_LEN_FUDGE;
15730 if (len > max_include_len)
15731 max_include_len = len;
15732 if (dir == last)
15733 break;
15734 }
15735
15736 last->next = NULL;
15737 last_include = last;
5ff904cd
JL
15738}
15739
c7e4ee3a
CB
15740/* Try to open include file FILENAME. SEARCHPTR is the directory
15741 being tried from the include file search path. This function maps
15742 filenames on file systems based on information read by
15743 read_name_map. */
15744
15745static FILE *
15746open_include_file (filename, searchptr)
15747 char *filename;
15748 struct file_name_list *searchptr;
5ff904cd 15749{
c7e4ee3a
CB
15750 register struct file_name_map *map;
15751 register char *from;
15752 char *p, *dir;
5ff904cd 15753
c7e4ee3a
CB
15754 if (searchptr && ! searchptr->got_name_map)
15755 {
15756 searchptr->name_map = read_name_map (searchptr->fname
15757 ? searchptr->fname : ".");
15758 searchptr->got_name_map = 1;
15759 }
5ff904cd 15760
c7e4ee3a
CB
15761 /* First check the mapping for the directory we are using. */
15762 if (searchptr && searchptr->name_map)
15763 {
15764 from = filename;
15765 if (searchptr->fname)
15766 from += strlen (searchptr->fname) + 1;
15767 for (map = searchptr->name_map; map; map = map->map_next)
15768 {
15769 if (! strcmp (map->map_from, from))
15770 {
15771 /* Found a match. */
15772 return fopen (map->map_to, "r");
15773 }
15774 }
15775 }
5ff904cd 15776
c7e4ee3a
CB
15777 /* Try to find a mapping file for the particular directory we are
15778 looking in. Thus #include <sys/types.h> will look up sys/types.h
15779 in /usr/include/header.gcc and look up types.h in
15780 /usr/include/sys/header.gcc. */
9473c522 15781 p = strrchr (filename, '/');
c7e4ee3a 15782#ifdef DIR_SEPARATOR
9473c522 15783 if (! p) p = strrchr (filename, DIR_SEPARATOR);
c7e4ee3a 15784 else {
9473c522 15785 char *tmp = strrchr (filename, DIR_SEPARATOR);
c7e4ee3a
CB
15786 if (tmp != NULL && tmp > p) p = tmp;
15787 }
15788#endif
15789 if (! p)
15790 p = filename;
15791 if (searchptr
15792 && searchptr->fname
15793 && strlen (searchptr->fname) == (size_t) (p - filename)
15794 && ! strncmp (searchptr->fname, filename, (int) (p - filename)))
15795 {
15796 /* FILENAME is in SEARCHPTR, which we've already checked. */
15797 return fopen (filename, "r");
15798 }
15799
15800 if (p == filename)
15801 {
15802 from = filename;
15803 map = read_name_map (".");
15804 }
15805 else
5ff904cd 15806 {
c7e4ee3a
CB
15807 dir = (char *) xmalloc (p - filename + 1);
15808 memcpy (dir, filename, p - filename);
15809 dir[p - filename] = '\0';
15810 from = p + 1;
15811 map = read_name_map (dir);
15812 free (dir);
5ff904cd 15813 }
c7e4ee3a
CB
15814 for (; map; map = map->map_next)
15815 if (! strcmp (map->map_from, from))
15816 return fopen (map->map_to, "r");
5ff904cd 15817
c7e4ee3a 15818 return fopen (filename, "r");
5ff904cd
JL
15819}
15820
c7e4ee3a
CB
15821/* Print the file names and line numbers of the #include
15822 commands which led to the current file. */
5ff904cd 15823
c7e4ee3a
CB
15824static void
15825print_containing_files (ffebadSeverity sev)
15826{
15827 FILE_BUF *ip = NULL;
15828 int i;
15829 int first = 1;
15830 const char *str1;
15831 const char *str2;
5ff904cd 15832
c7e4ee3a
CB
15833 /* If stack of files hasn't changed since we last printed
15834 this info, don't repeat it. */
15835 if (last_error_tick == input_file_stack_tick)
15836 return;
5ff904cd 15837
c7e4ee3a
CB
15838 for (i = indepth; i >= 0; i--)
15839 if (instack[i].fname != NULL) {
15840 ip = &instack[i];
15841 break;
15842 }
5ff904cd 15843
c7e4ee3a
CB
15844 /* Give up if we don't find a source file. */
15845 if (ip == NULL)
15846 return;
5ff904cd 15847
c7e4ee3a
CB
15848 /* Find the other, outer source files. */
15849 for (i--; i >= 0; i--)
15850 if (instack[i].fname != NULL)
15851 {
15852 ip = &instack[i];
15853 if (first)
15854 {
15855 first = 0;
15856 str1 = "In file included";
15857 }
15858 else
15859 {
15860 str1 = "... ...";
15861 }
5ff904cd 15862
c7e4ee3a
CB
15863 if (i == 1)
15864 str2 = ":";
15865 else
15866 str2 = "";
5ff904cd 15867
c7e4ee3a
CB
15868 ffebad_start_msg ("%A from %B at %0%C", sev);
15869 ffebad_here (0, ip->line, ip->column);
15870 ffebad_string (str1);
15871 ffebad_string (ip->nominal_fname);
15872 ffebad_string (str2);
15873 ffebad_finish ();
15874 }
5ff904cd 15875
c7e4ee3a
CB
15876 /* Record we have printed the status as of this time. */
15877 last_error_tick = input_file_stack_tick;
15878}
5ff904cd 15879
c7e4ee3a
CB
15880/* Read a space delimited string of unlimited length from a stdio
15881 file. */
5ff904cd 15882
c7e4ee3a
CB
15883static char *
15884read_filename_string (ch, f)
15885 int ch;
15886 FILE *f;
15887{
15888 char *alloc, *set;
15889 int len;
5ff904cd 15890
c7e4ee3a
CB
15891 len = 20;
15892 set = alloc = xmalloc (len + 1);
15893 if (! is_space[ch])
15894 {
15895 *set++ = ch;
15896 while ((ch = getc (f)) != EOF && ! is_space[ch])
15897 {
15898 if (set - alloc == len)
15899 {
15900 len *= 2;
15901 alloc = xrealloc (alloc, len + 1);
15902 set = alloc + len / 2;
15903 }
15904 *set++ = ch;
15905 }
15906 }
15907 *set = '\0';
15908 ungetc (ch, f);
15909 return alloc;
15910}
5ff904cd 15911
c7e4ee3a 15912/* Read the file name map file for DIRNAME. */
5ff904cd 15913
c7e4ee3a
CB
15914static struct file_name_map *
15915read_name_map (dirname)
15916 const char *dirname;
15917{
15918 /* This structure holds a linked list of file name maps, one per
15919 directory. */
15920 struct file_name_map_list
15921 {
15922 struct file_name_map_list *map_list_next;
15923 char *map_list_name;
15924 struct file_name_map *map_list_map;
15925 };
15926 static struct file_name_map_list *map_list;
15927 register struct file_name_map_list *map_list_ptr;
15928 char *name;
15929 FILE *f;
15930 size_t dirlen;
15931 int separator_needed;
5ff904cd 15932
c7e4ee3a 15933 dirname = skip_redundant_dir_prefix (dirname);
5ff904cd 15934
c7e4ee3a
CB
15935 for (map_list_ptr = map_list; map_list_ptr;
15936 map_list_ptr = map_list_ptr->map_list_next)
15937 if (! strcmp (map_list_ptr->map_list_name, dirname))
15938 return map_list_ptr->map_list_map;
5ff904cd 15939
c7e4ee3a
CB
15940 map_list_ptr = ((struct file_name_map_list *)
15941 xmalloc (sizeof (struct file_name_map_list)));
15942 map_list_ptr->map_list_name = xstrdup (dirname);
15943 map_list_ptr->map_list_map = NULL;
5ff904cd 15944
c7e4ee3a
CB
15945 dirlen = strlen (dirname);
15946 separator_needed = dirlen != 0 && dirname[dirlen - 1] != '/';
15947 name = (char *) xmalloc (dirlen + strlen (FILE_NAME_MAP_FILE) + 2);
15948 strcpy (name, dirname);
15949 name[dirlen] = '/';
15950 strcpy (name + dirlen + separator_needed, FILE_NAME_MAP_FILE);
15951 f = fopen (name, "r");
15952 free (name);
15953 if (!f)
15954 map_list_ptr->map_list_map = NULL;
15955 else
15956 {
15957 int ch;
5ff904cd 15958
c7e4ee3a
CB
15959 while ((ch = getc (f)) != EOF)
15960 {
15961 char *from, *to;
15962 struct file_name_map *ptr;
15963
15964 if (is_space[ch])
15965 continue;
15966 from = read_filename_string (ch, f);
15967 while ((ch = getc (f)) != EOF && is_hor_space[ch])
15968 ;
15969 to = read_filename_string (ch, f);
5ff904cd 15970
c7e4ee3a
CB
15971 ptr = ((struct file_name_map *)
15972 xmalloc (sizeof (struct file_name_map)));
15973 ptr->map_from = from;
5ff904cd 15974
c7e4ee3a
CB
15975 /* Make the real filename absolute. */
15976 if (*to == '/')
15977 ptr->map_to = to;
15978 else
15979 {
15980 ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
15981 strcpy (ptr->map_to, dirname);
15982 ptr->map_to[dirlen] = '/';
15983 strcpy (ptr->map_to + dirlen + separator_needed, to);
15984 free (to);
15985 }
5ff904cd 15986
c7e4ee3a
CB
15987 ptr->map_next = map_list_ptr->map_list_map;
15988 map_list_ptr->map_list_map = ptr;
5ff904cd 15989
c7e4ee3a
CB
15990 while ((ch = getc (f)) != '\n')
15991 if (ch == EOF)
15992 break;
15993 }
15994 fclose (f);
5ff904cd
JL
15995 }
15996
c7e4ee3a
CB
15997 map_list_ptr->map_list_next = map_list;
15998 map_list = map_list_ptr;
5ff904cd 15999
c7e4ee3a 16000 return map_list_ptr->map_list_map;
5ff904cd
JL
16001}
16002
c7e4ee3a 16003static void
b0791fa9 16004ffecom_file_ (const char *name)
5ff904cd 16005{
c7e4ee3a 16006 FILE_BUF *fp;
5ff904cd 16007
c7e4ee3a
CB
16008 /* Do partial setup of input buffer for the sake of generating
16009 early #line directives (when -g is in effect). */
5ff904cd 16010
c7e4ee3a
CB
16011 fp = &instack[++indepth];
16012 memset ((char *) fp, 0, sizeof (FILE_BUF));
16013 if (name == NULL)
16014 name = "";
16015 fp->nominal_fname = fp->fname = name;
16016}
5ff904cd 16017
c7e4ee3a 16018/* Initialize syntactic classifications of characters. */
5ff904cd 16019
c7e4ee3a
CB
16020static void
16021ffecom_initialize_char_syntax_ ()
16022{
16023 register int i;
5ff904cd 16024
c7e4ee3a
CB
16025 /*
16026 * Set up is_idchar and is_idstart tables. These should be
16027 * faster than saying (is_alpha (c) || c == '_'), etc.
16028 * Set up these things before calling any routines tthat
16029 * refer to them.
16030 */
16031 for (i = 'a'; i <= 'z'; i++) {
16032 is_idchar[i - 'a' + 'A'] = 1;
16033 is_idchar[i] = 1;
16034 is_idstart[i - 'a' + 'A'] = 1;
16035 is_idstart[i] = 1;
16036 }
16037 for (i = '0'; i <= '9'; i++)
16038 is_idchar[i] = 1;
16039 is_idchar['_'] = 1;
16040 is_idstart['_'] = 1;
5ff904cd 16041
c7e4ee3a
CB
16042 /* horizontal space table */
16043 is_hor_space[' '] = 1;
16044 is_hor_space['\t'] = 1;
16045 is_hor_space['\v'] = 1;
16046 is_hor_space['\f'] = 1;
16047 is_hor_space['\r'] = 1;
5ff904cd 16048
c7e4ee3a
CB
16049 is_space[' '] = 1;
16050 is_space['\t'] = 1;
16051 is_space['\v'] = 1;
16052 is_space['\f'] = 1;
16053 is_space['\n'] = 1;
16054 is_space['\r'] = 1;
16055}
5ff904cd 16056
c7e4ee3a
CB
16057static void
16058ffecom_close_include_ (FILE *f)
16059{
16060 fclose (f);
5ff904cd 16061
c7e4ee3a
CB
16062 indepth--;
16063 input_file_stack_tick++;
5ff904cd 16064
c7e4ee3a
CB
16065 ffewhere_line_kill (instack[indepth].line);
16066 ffewhere_column_kill (instack[indepth].column);
16067}
5ff904cd 16068
c7e4ee3a
CB
16069static int
16070ffecom_decode_include_option_ (char *spec)
16071{
16072 struct file_name_list *dirtmp;
16073
16074 if (! ignore_srcdir && !strcmp (spec, "-"))
16075 ignore_srcdir = 1;
16076 else
16077 {
16078 dirtmp = (struct file_name_list *)
16079 xmalloc (sizeof (struct file_name_list));
16080 dirtmp->next = 0; /* New one goes on the end */
400500c4 16081 dirtmp->fname = spec;
c7e4ee3a 16082 dirtmp->got_name_map = 0;
400500c4
RK
16083 if (spec[0] == 0)
16084 error ("Directory name must immediately follow -I");
16085 else
16086 append_include_chain (dirtmp, dirtmp);
c7e4ee3a
CB
16087 }
16088 return 1;
5ff904cd
JL
16089}
16090
c7e4ee3a
CB
16091/* Open INCLUDEd file. */
16092
16093static FILE *
16094ffecom_open_include_ (char *name, ffewhereLine l, ffewhereColumn c)
5ff904cd 16095{
c7e4ee3a
CB
16096 char *fbeg = name;
16097 size_t flen = strlen (fbeg);
16098 struct file_name_list *search_start = include; /* Chain of dirs to search */
16099 struct file_name_list dsp[1]; /* First in chain, if #include "..." */
16100 struct file_name_list *searchptr = 0;
16101 char *fname; /* Dynamically allocated fname buffer */
16102 FILE *f;
16103 FILE_BUF *fp;
5ff904cd 16104
c7e4ee3a
CB
16105 if (flen == 0)
16106 return NULL;
5ff904cd 16107
c7e4ee3a 16108 dsp[0].fname = NULL;
5ff904cd 16109
c7e4ee3a
CB
16110 /* If -I- was specified, don't search current dir, only spec'd ones. */
16111 if (!ignore_srcdir)
16112 {
16113 for (fp = &instack[indepth]; fp >= instack; fp--)
16114 {
16115 int n;
16116 char *ep;
b0791fa9 16117 const char *nam;
5ff904cd 16118
c7e4ee3a
CB
16119 if ((nam = fp->nominal_fname) != NULL)
16120 {
16121 /* Found a named file. Figure out dir of the file,
16122 and put it in front of the search list. */
16123 dsp[0].next = search_start;
16124 search_start = dsp;
16125#ifndef VMS
9473c522 16126 ep = strrchr (nam, '/');
c7e4ee3a 16127#ifdef DIR_SEPARATOR
9473c522 16128 if (ep == NULL) ep = strrchr (nam, DIR_SEPARATOR);
c7e4ee3a 16129 else {
9473c522 16130 char *tmp = strrchr (nam, DIR_SEPARATOR);
c7e4ee3a
CB
16131 if (tmp != NULL && tmp > ep) ep = tmp;
16132 }
16133#endif
16134#else /* VMS */
9473c522
JM
16135 ep = strrchr (nam, ']');
16136 if (ep == NULL) ep = strrchr (nam, '>');
16137 if (ep == NULL) ep = strrchr (nam, ':');
c7e4ee3a
CB
16138 if (ep != NULL) ep++;
16139#endif /* VMS */
16140 if (ep != NULL)
16141 {
16142 n = ep - nam;
16143 dsp[0].fname = (char *) xmalloc (n + 1);
16144 strncpy (dsp[0].fname, nam, n);
16145 dsp[0].fname[n] = '\0';
16146 if (n + INCLUDE_LEN_FUDGE > max_include_len)
16147 max_include_len = n + INCLUDE_LEN_FUDGE;
16148 }
16149 else
16150 dsp[0].fname = NULL; /* Current directory */
16151 dsp[0].got_name_map = 0;
16152 break;
16153 }
16154 }
16155 }
5ff904cd 16156
c7e4ee3a
CB
16157 /* Allocate this permanently, because it gets stored in the definitions
16158 of macros. */
16159 fname = xmalloc (max_include_len + flen + 4);
16160 /* + 2 above for slash and terminating null. */
16161 /* + 2 added for '.h' on VMS (to support '#include filename') (NOT USED
16162 for g77 yet). */
5ff904cd 16163
c7e4ee3a 16164 /* If specified file name is absolute, just open it. */
5ff904cd 16165
c7e4ee3a
CB
16166 if (*fbeg == '/'
16167#ifdef DIR_SEPARATOR
16168 || *fbeg == DIR_SEPARATOR
16169#endif
16170 )
16171 {
16172 strncpy (fname, (char *) fbeg, flen);
16173 fname[flen] = 0;
16174 f = open_include_file (fname, NULL_PTR);
5ff904cd 16175 }
c7e4ee3a
CB
16176 else
16177 {
16178 f = NULL;
5ff904cd 16179
c7e4ee3a
CB
16180 /* Search directory path, trying to open the file.
16181 Copy each filename tried into FNAME. */
5ff904cd 16182
c7e4ee3a
CB
16183 for (searchptr = search_start; searchptr; searchptr = searchptr->next)
16184 {
16185 if (searchptr->fname)
16186 {
16187 /* The empty string in a search path is ignored.
16188 This makes it possible to turn off entirely
16189 a standard piece of the list. */
16190 if (searchptr->fname[0] == 0)
16191 continue;
16192 strcpy (fname, skip_redundant_dir_prefix (searchptr->fname));
16193 if (fname[0] && fname[strlen (fname) - 1] != '/')
16194 strcat (fname, "/");
16195 fname[strlen (fname) + flen] = 0;
16196 }
16197 else
16198 fname[0] = 0;
5ff904cd 16199
c7e4ee3a
CB
16200 strncat (fname, fbeg, flen);
16201#ifdef VMS
16202 /* Change this 1/2 Unix 1/2 VMS file specification into a
16203 full VMS file specification */
16204 if (searchptr->fname && (searchptr->fname[0] != 0))
16205 {
16206 /* Fix up the filename */
16207 hack_vms_include_specification (fname);
16208 }
16209 else
16210 {
16211 /* This is a normal VMS filespec, so use it unchanged. */
16212 strncpy (fname, (char *) fbeg, flen);
16213 fname[flen] = 0;
16214#if 0 /* Not for g77. */
16215 /* if it's '#include filename', add the missing .h */
9473c522 16216 if (strchr (fname, '.') == NULL)
c7e4ee3a 16217 strcat (fname, ".h");
5ff904cd 16218#endif
c7e4ee3a
CB
16219 }
16220#endif /* VMS */
16221 f = open_include_file (fname, searchptr);
16222#ifdef EACCES
16223 if (f == NULL && errno == EACCES)
16224 {
16225 print_containing_files (FFEBAD_severityWARNING);
16226 ffebad_start_msg ("At %0, INCLUDE file %A exists, but is not readable",
16227 FFEBAD_severityWARNING);
16228 ffebad_string (fname);
16229 ffebad_here (0, l, c);
16230 ffebad_finish ();
16231 }
16232#endif
16233 if (f != NULL)
16234 break;
16235 }
16236 }
5ff904cd 16237
c7e4ee3a 16238 if (f == NULL)
5ff904cd 16239 {
c7e4ee3a 16240 /* A file that was not found. */
5ff904cd 16241
c7e4ee3a
CB
16242 strncpy (fname, (char *) fbeg, flen);
16243 fname[flen] = 0;
16244 print_containing_files (ffebad_severity (FFEBAD_OPEN_INCLUDE));
16245 ffebad_start (FFEBAD_OPEN_INCLUDE);
16246 ffebad_here (0, l, c);
16247 ffebad_string (fname);
16248 ffebad_finish ();
5ff904cd
JL
16249 }
16250
c7e4ee3a
CB
16251 if (dsp[0].fname != NULL)
16252 free (dsp[0].fname);
5ff904cd 16253
c7e4ee3a
CB
16254 if (f == NULL)
16255 return NULL;
5ff904cd 16256
c7e4ee3a
CB
16257 if (indepth >= (INPUT_STACK_MAX - 1))
16258 {
16259 print_containing_files (FFEBAD_severityFATAL);
16260 ffebad_start_msg ("At %0, INCLUDE nesting too deep",
16261 FFEBAD_severityFATAL);
16262 ffebad_string (fname);
16263 ffebad_here (0, l, c);
16264 ffebad_finish ();
16265 return NULL;
16266 }
5ff904cd 16267
c7e4ee3a
CB
16268 instack[indepth].line = ffewhere_line_use (l);
16269 instack[indepth].column = ffewhere_column_use (c);
5ff904cd 16270
c7e4ee3a
CB
16271 fp = &instack[indepth + 1];
16272 memset ((char *) fp, 0, sizeof (FILE_BUF));
16273 fp->nominal_fname = fp->fname = fname;
16274 fp->dir = searchptr;
5ff904cd 16275
c7e4ee3a
CB
16276 indepth++;
16277 input_file_stack_tick++;
5ff904cd 16278
c7e4ee3a
CB
16279 return f;
16280}
16281#endif /* FFECOM_GCC_INCLUDE */
5ff904cd 16282
c7e4ee3a
CB
16283/**INDENT* (Do not reformat this comment even with -fca option.)
16284 Data-gathering files: Given the source file listed below, compiled with
16285 f2c I obtained the output file listed after that, and from the output
16286 file I derived the above code.
5ff904cd 16287
c7e4ee3a
CB
16288-------- (begin input file to f2c)
16289 implicit none
16290 character*10 A1,A2
16291 complex C1,C2
16292 integer I1,I2
16293 real R1,R2
16294 double precision D1,D2
16295C
16296 call getem(A1,A2,C1,C2,I1,I2,R1,R2,D1,D2)
16297c /
16298 call fooI(I1/I2)
16299 call fooR(R1/I1)
16300 call fooD(D1/I1)
16301 call fooC(C1/I1)
16302 call fooR(R1/R2)
16303 call fooD(R1/D1)
16304 call fooD(D1/D2)
16305 call fooD(D1/R1)
16306 call fooC(C1/C2)
16307 call fooC(C1/R1)
16308 call fooZ(C1/D1)
16309c **
16310 call fooI(I1**I2)
16311 call fooR(R1**I1)
16312 call fooD(D1**I1)
16313 call fooC(C1**I1)
16314 call fooR(R1**R2)
16315 call fooD(R1**D1)
16316 call fooD(D1**D2)
16317 call fooD(D1**R1)
16318 call fooC(C1**C2)
16319 call fooC(C1**R1)
16320 call fooZ(C1**D1)
16321c FFEINTRIN_impABS
16322 call fooR(ABS(R1))
16323c FFEINTRIN_impACOS
16324 call fooR(ACOS(R1))
16325c FFEINTRIN_impAIMAG
16326 call fooR(AIMAG(C1))
16327c FFEINTRIN_impAINT
16328 call fooR(AINT(R1))
16329c FFEINTRIN_impALOG
16330 call fooR(ALOG(R1))
16331c FFEINTRIN_impALOG10
16332 call fooR(ALOG10(R1))
16333c FFEINTRIN_impAMAX0
16334 call fooR(AMAX0(I1,I2))
16335c FFEINTRIN_impAMAX1
16336 call fooR(AMAX1(R1,R2))
16337c FFEINTRIN_impAMIN0
16338 call fooR(AMIN0(I1,I2))
16339c FFEINTRIN_impAMIN1
16340 call fooR(AMIN1(R1,R2))
16341c FFEINTRIN_impAMOD
16342 call fooR(AMOD(R1,R2))
16343c FFEINTRIN_impANINT
16344 call fooR(ANINT(R1))
16345c FFEINTRIN_impASIN
16346 call fooR(ASIN(R1))
16347c FFEINTRIN_impATAN
16348 call fooR(ATAN(R1))
16349c FFEINTRIN_impATAN2
16350 call fooR(ATAN2(R1,R2))
16351c FFEINTRIN_impCABS
16352 call fooR(CABS(C1))
16353c FFEINTRIN_impCCOS
16354 call fooC(CCOS(C1))
16355c FFEINTRIN_impCEXP
16356 call fooC(CEXP(C1))
16357c FFEINTRIN_impCHAR
16358 call fooA(CHAR(I1))
16359c FFEINTRIN_impCLOG
16360 call fooC(CLOG(C1))
16361c FFEINTRIN_impCONJG
16362 call fooC(CONJG(C1))
16363c FFEINTRIN_impCOS
16364 call fooR(COS(R1))
16365c FFEINTRIN_impCOSH
16366 call fooR(COSH(R1))
16367c FFEINTRIN_impCSIN
16368 call fooC(CSIN(C1))
16369c FFEINTRIN_impCSQRT
16370 call fooC(CSQRT(C1))
16371c FFEINTRIN_impDABS
16372 call fooD(DABS(D1))
16373c FFEINTRIN_impDACOS
16374 call fooD(DACOS(D1))
16375c FFEINTRIN_impDASIN
16376 call fooD(DASIN(D1))
16377c FFEINTRIN_impDATAN
16378 call fooD(DATAN(D1))
16379c FFEINTRIN_impDATAN2
16380 call fooD(DATAN2(D1,D2))
16381c FFEINTRIN_impDCOS
16382 call fooD(DCOS(D1))
16383c FFEINTRIN_impDCOSH
16384 call fooD(DCOSH(D1))
16385c FFEINTRIN_impDDIM
16386 call fooD(DDIM(D1,D2))
16387c FFEINTRIN_impDEXP
16388 call fooD(DEXP(D1))
16389c FFEINTRIN_impDIM
16390 call fooR(DIM(R1,R2))
16391c FFEINTRIN_impDINT
16392 call fooD(DINT(D1))
16393c FFEINTRIN_impDLOG
16394 call fooD(DLOG(D1))
16395c FFEINTRIN_impDLOG10
16396 call fooD(DLOG10(D1))
16397c FFEINTRIN_impDMAX1
16398 call fooD(DMAX1(D1,D2))
16399c FFEINTRIN_impDMIN1
16400 call fooD(DMIN1(D1,D2))
16401c FFEINTRIN_impDMOD
16402 call fooD(DMOD(D1,D2))
16403c FFEINTRIN_impDNINT
16404 call fooD(DNINT(D1))
16405c FFEINTRIN_impDPROD
16406 call fooD(DPROD(R1,R2))
16407c FFEINTRIN_impDSIGN
16408 call fooD(DSIGN(D1,D2))
16409c FFEINTRIN_impDSIN
16410 call fooD(DSIN(D1))
16411c FFEINTRIN_impDSINH
16412 call fooD(DSINH(D1))
16413c FFEINTRIN_impDSQRT
16414 call fooD(DSQRT(D1))
16415c FFEINTRIN_impDTAN
16416 call fooD(DTAN(D1))
16417c FFEINTRIN_impDTANH
16418 call fooD(DTANH(D1))
16419c FFEINTRIN_impEXP
16420 call fooR(EXP(R1))
16421c FFEINTRIN_impIABS
16422 call fooI(IABS(I1))
16423c FFEINTRIN_impICHAR
16424 call fooI(ICHAR(A1))
16425c FFEINTRIN_impIDIM
16426 call fooI(IDIM(I1,I2))
16427c FFEINTRIN_impIDNINT
16428 call fooI(IDNINT(D1))
16429c FFEINTRIN_impINDEX
16430 call fooI(INDEX(A1,A2))
16431c FFEINTRIN_impISIGN
16432 call fooI(ISIGN(I1,I2))
16433c FFEINTRIN_impLEN
16434 call fooI(LEN(A1))
16435c FFEINTRIN_impLGE
16436 call fooL(LGE(A1,A2))
16437c FFEINTRIN_impLGT
16438 call fooL(LGT(A1,A2))
16439c FFEINTRIN_impLLE
16440 call fooL(LLE(A1,A2))
16441c FFEINTRIN_impLLT
16442 call fooL(LLT(A1,A2))
16443c FFEINTRIN_impMAX0
16444 call fooI(MAX0(I1,I2))
16445c FFEINTRIN_impMAX1
16446 call fooI(MAX1(R1,R2))
16447c FFEINTRIN_impMIN0
16448 call fooI(MIN0(I1,I2))
16449c FFEINTRIN_impMIN1
16450 call fooI(MIN1(R1,R2))
16451c FFEINTRIN_impMOD
16452 call fooI(MOD(I1,I2))
16453c FFEINTRIN_impNINT
16454 call fooI(NINT(R1))
16455c FFEINTRIN_impSIGN
16456 call fooR(SIGN(R1,R2))
16457c FFEINTRIN_impSIN
16458 call fooR(SIN(R1))
16459c FFEINTRIN_impSINH
16460 call fooR(SINH(R1))
16461c FFEINTRIN_impSQRT
16462 call fooR(SQRT(R1))
16463c FFEINTRIN_impTAN
16464 call fooR(TAN(R1))
16465c FFEINTRIN_impTANH
16466 call fooR(TANH(R1))
16467c FFEINTRIN_imp_CMPLX_C
16468 call fooC(cmplx(C1,C2))
16469c FFEINTRIN_imp_CMPLX_D
16470 call fooZ(cmplx(D1,D2))
16471c FFEINTRIN_imp_CMPLX_I
16472 call fooC(cmplx(I1,I2))
16473c FFEINTRIN_imp_CMPLX_R
16474 call fooC(cmplx(R1,R2))
16475c FFEINTRIN_imp_DBLE_C
16476 call fooD(dble(C1))
16477c FFEINTRIN_imp_DBLE_D
16478 call fooD(dble(D1))
16479c FFEINTRIN_imp_DBLE_I
16480 call fooD(dble(I1))
16481c FFEINTRIN_imp_DBLE_R
16482 call fooD(dble(R1))
16483c FFEINTRIN_imp_INT_C
16484 call fooI(int(C1))
16485c FFEINTRIN_imp_INT_D
16486 call fooI(int(D1))
16487c FFEINTRIN_imp_INT_I
16488 call fooI(int(I1))
16489c FFEINTRIN_imp_INT_R
16490 call fooI(int(R1))
16491c FFEINTRIN_imp_REAL_C
16492 call fooR(real(C1))
16493c FFEINTRIN_imp_REAL_D
16494 call fooR(real(D1))
16495c FFEINTRIN_imp_REAL_I
16496 call fooR(real(I1))
16497c FFEINTRIN_imp_REAL_R
16498 call fooR(real(R1))
16499c
16500c FFEINTRIN_imp_INT_D:
16501c
16502c FFEINTRIN_specIDINT
16503 call fooI(IDINT(D1))
16504c
16505c FFEINTRIN_imp_INT_R:
16506c
16507c FFEINTRIN_specIFIX
16508 call fooI(IFIX(R1))
16509c FFEINTRIN_specINT
16510 call fooI(INT(R1))
16511c
16512c FFEINTRIN_imp_REAL_D:
16513c
16514c FFEINTRIN_specSNGL
16515 call fooR(SNGL(D1))
16516c
16517c FFEINTRIN_imp_REAL_I:
16518c
16519c FFEINTRIN_specFLOAT
16520 call fooR(FLOAT(I1))
16521c FFEINTRIN_specREAL
16522 call fooR(REAL(I1))
16523c
16524 end
16525-------- (end input file to f2c)
5ff904cd 16526
c7e4ee3a
CB
16527-------- (begin output from providing above input file as input to:
16528-------- `f2c | gcc -E -C - | sed -e "s:/[*]*://:g" -e "s:[*]*[/]://:g" \
16529-------- -e "s:^#.*$::g"')
5ff904cd 16530
c7e4ee3a
CB
16531// -- translated by f2c (version 19950223).
16532 You must link the resulting object file with the libraries:
16533 -lf2c -lm (in that order)
16534//
5ff904cd 16535
5ff904cd 16536
c7e4ee3a 16537// f2c.h -- Standard Fortran to C header file //
5ff904cd 16538
c7e4ee3a 16539/// barf [ba:rf] 2. "He suggested using FORTRAN, and everybody barfed."
5ff904cd 16540
c7e4ee3a 16541 - From The Shogakukan DICTIONARY OF NEW ENGLISH (Second edition) //
5ff904cd 16542
5ff904cd 16543
5ff904cd 16544
5ff904cd 16545
c7e4ee3a
CB
16546// F2C_INTEGER will normally be `int' but would be `long' on 16-bit systems //
16547// we assume short, float are OK //
16548typedef long int // long int // integer;
16549typedef char *address;
16550typedef short int shortint;
16551typedef float real;
16552typedef double doublereal;
16553typedef struct { real r, i; } complex;
16554typedef struct { doublereal r, i; } doublecomplex;
16555typedef long int // long int // logical;
16556typedef short int shortlogical;
16557typedef char logical1;
16558typedef char integer1;
16559// typedef long long longint; // // system-dependent //
5ff904cd 16560
5ff904cd 16561
5ff904cd 16562
5ff904cd 16563
c7e4ee3a 16564// Extern is for use with -E //
5ff904cd 16565
5ff904cd 16566
5ff904cd 16567
5ff904cd 16568
c7e4ee3a 16569// I/O stuff //
5ff904cd 16570
5ff904cd 16571
5ff904cd 16572
5ff904cd 16573
5ff904cd 16574
5ff904cd 16575
5ff904cd 16576
5ff904cd 16577
c7e4ee3a
CB
16578typedef long int // int or long int // flag;
16579typedef long int // int or long int // ftnlen;
16580typedef long int // int or long int // ftnint;
5ff904cd 16581
5ff904cd 16582
c7e4ee3a
CB
16583//external read, write//
16584typedef struct
16585{ flag cierr;
16586 ftnint ciunit;
16587 flag ciend;
16588 char *cifmt;
16589 ftnint cirec;
16590} cilist;
5ff904cd 16591
c7e4ee3a
CB
16592//internal read, write//
16593typedef struct
16594{ flag icierr;
16595 char *iciunit;
16596 flag iciend;
16597 char *icifmt;
16598 ftnint icirlen;
16599 ftnint icirnum;
16600} icilist;
5ff904cd 16601
c7e4ee3a
CB
16602//open//
16603typedef struct
16604{ flag oerr;
16605 ftnint ounit;
16606 char *ofnm;
16607 ftnlen ofnmlen;
16608 char *osta;
16609 char *oacc;
16610 char *ofm;
16611 ftnint orl;
16612 char *oblnk;
16613} olist;
5ff904cd 16614
c7e4ee3a
CB
16615//close//
16616typedef struct
16617{ flag cerr;
16618 ftnint cunit;
16619 char *csta;
16620} cllist;
5ff904cd 16621
c7e4ee3a
CB
16622//rewind, backspace, endfile//
16623typedef struct
16624{ flag aerr;
16625 ftnint aunit;
16626} alist;
5ff904cd 16627
c7e4ee3a
CB
16628// inquire //
16629typedef struct
16630{ flag inerr;
16631 ftnint inunit;
16632 char *infile;
16633 ftnlen infilen;
16634 ftnint *inex; //parameters in standard's order//
16635 ftnint *inopen;
16636 ftnint *innum;
16637 ftnint *innamed;
16638 char *inname;
16639 ftnlen innamlen;
16640 char *inacc;
16641 ftnlen inacclen;
16642 char *inseq;
16643 ftnlen inseqlen;
16644 char *indir;
16645 ftnlen indirlen;
16646 char *infmt;
16647 ftnlen infmtlen;
16648 char *inform;
16649 ftnint informlen;
16650 char *inunf;
16651 ftnlen inunflen;
16652 ftnint *inrecl;
16653 ftnint *innrec;
16654 char *inblank;
16655 ftnlen inblanklen;
16656} inlist;
5ff904cd 16657
5ff904cd 16658
5ff904cd 16659
c7e4ee3a
CB
16660union Multitype { // for multiple entry points //
16661 integer1 g;
16662 shortint h;
16663 integer i;
16664 // longint j; //
16665 real r;
16666 doublereal d;
16667 complex c;
16668 doublecomplex z;
16669 };
16670
16671typedef union Multitype Multitype;
5ff904cd 16672
c7e4ee3a 16673typedef long Long; // No longer used; formerly in Namelist //
5ff904cd 16674
c7e4ee3a
CB
16675struct Vardesc { // for Namelist //
16676 char *name;
16677 char *addr;
16678 ftnlen *dims;
16679 int type;
16680 };
16681typedef struct Vardesc Vardesc;
5ff904cd 16682
c7e4ee3a
CB
16683struct Namelist {
16684 char *name;
16685 Vardesc **vars;
16686 int nvars;
16687 };
16688typedef struct Namelist Namelist;
5ff904cd 16689
5ff904cd 16690
5ff904cd 16691
5ff904cd 16692
5ff904cd 16693
5ff904cd 16694
5ff904cd 16695
5ff904cd 16696
c7e4ee3a 16697// procedure parameter types for -A and -C++ //
5ff904cd 16698
5ff904cd 16699
5ff904cd 16700
5ff904cd 16701
c7e4ee3a
CB
16702typedef int // Unknown procedure type // (*U_fp)();
16703typedef shortint (*J_fp)();
16704typedef integer (*I_fp)();
16705typedef real (*R_fp)();
16706typedef doublereal (*D_fp)(), (*E_fp)();
16707typedef // Complex // void (*C_fp)();
16708typedef // Double Complex // void (*Z_fp)();
16709typedef logical (*L_fp)();
16710typedef shortlogical (*K_fp)();
16711typedef // Character // void (*H_fp)();
16712typedef // Subroutine // int (*S_fp)();
5ff904cd 16713
c7e4ee3a
CB
16714// E_fp is for real functions when -R is not specified //
16715typedef void C_f; // complex function //
16716typedef void H_f; // character function //
16717typedef void Z_f; // double complex function //
16718typedef doublereal E_f; // real function with -R not specified //
5ff904cd 16719
c7e4ee3a 16720// undef any lower-case symbols that your C compiler predefines, e.g.: //
5ff904cd 16721
5ff904cd 16722
c7e4ee3a
CB
16723// (No such symbols should be defined in a strict ANSI C compiler.
16724 We can avoid trouble with f2c-translated code by using
16725 gcc -ansi [-traditional].) //
16726
5ff904cd 16727
5ff904cd 16728
5ff904cd 16729
5ff904cd 16730
5ff904cd 16731
5ff904cd 16732
5ff904cd 16733
5ff904cd 16734
5ff904cd 16735
5ff904cd 16736
5ff904cd 16737
5ff904cd 16738
5ff904cd 16739
5ff904cd 16740
5ff904cd 16741
5ff904cd 16742
5ff904cd 16743
5ff904cd 16744
5ff904cd 16745
5ff904cd 16746
5ff904cd 16747
5ff904cd 16748
c7e4ee3a
CB
16749// Main program // MAIN__()
16750{
16751 // System generated locals //
16752 integer i__1;
16753 real r__1, r__2;
16754 doublereal d__1, d__2;
16755 complex q__1;
16756 doublecomplex z__1, z__2, z__3;
16757 logical L__1;
16758 char ch__1[1];
16759
16760 // Builtin functions //
16761 void c_div();
16762 integer pow_ii();
16763 double pow_ri(), pow_di();
16764 void pow_ci();
16765 double pow_dd();
16766 void pow_zz();
16767 double acos(), r_imag(), r_int(), log(), r_lg10(), r_mod(), r_nint(),
16768 asin(), atan(), atan2(), c_abs();
16769 void c_cos(), c_exp(), c_log(), r_cnjg();
16770 double cos(), cosh();
16771 void c_sin(), c_sqrt();
16772 double d_dim(), exp(), r_dim(), d_int(), d_lg10(), d_mod(), d_nint(),
16773 d_sign(), sin(), sinh(), sqrt(), tan(), tanh();
16774 integer i_dim(), i_dnnt(), i_indx(), i_sign(), i_len();
16775 logical l_ge(), l_gt(), l_le(), l_lt();
16776 integer i_nint();
16777 double r_sign();
16778
16779 // Local variables //
16780 extern // Subroutine // int fooa_(), fooc_(), food_(), fooi_(), foor_(),
16781 fool_(), fooz_(), getem_();
16782 static char a1[10], a2[10];
16783 static complex c1, c2;
16784 static doublereal d1, d2;
16785 static integer i1, i2;
16786 static real r1, r2;
16787
16788
16789 getem_(a1, a2, &c1, &c2, &i1, &i2, &r1, &r2, &d1, &d2, 10L, 10L);
16790// / //
16791 i__1 = i1 / i2;
16792 fooi_(&i__1);
16793 r__1 = r1 / i1;
16794 foor_(&r__1);
16795 d__1 = d1 / i1;
16796 food_(&d__1);
16797 d__1 = (doublereal) i1;
16798 q__1.r = c1.r / d__1, q__1.i = c1.i / d__1;
16799 fooc_(&q__1);
16800 r__1 = r1 / r2;
16801 foor_(&r__1);
16802 d__1 = r1 / d1;
16803 food_(&d__1);
16804 d__1 = d1 / d2;
16805 food_(&d__1);
16806 d__1 = d1 / r1;
16807 food_(&d__1);
16808 c_div(&q__1, &c1, &c2);
16809 fooc_(&q__1);
16810 q__1.r = c1.r / r1, q__1.i = c1.i / r1;
16811 fooc_(&q__1);
16812 z__1.r = c1.r / d1, z__1.i = c1.i / d1;
16813 fooz_(&z__1);
16814// ** //
16815 i__1 = pow_ii(&i1, &i2);
16816 fooi_(&i__1);
16817 r__1 = pow_ri(&r1, &i1);
16818 foor_(&r__1);
16819 d__1 = pow_di(&d1, &i1);
16820 food_(&d__1);
16821 pow_ci(&q__1, &c1, &i1);
16822 fooc_(&q__1);
16823 d__1 = (doublereal) r1;
16824 d__2 = (doublereal) r2;
16825 r__1 = pow_dd(&d__1, &d__2);
16826 foor_(&r__1);
16827 d__2 = (doublereal) r1;
16828 d__1 = pow_dd(&d__2, &d1);
16829 food_(&d__1);
16830 d__1 = pow_dd(&d1, &d2);
16831 food_(&d__1);
16832 d__2 = (doublereal) r1;
16833 d__1 = pow_dd(&d1, &d__2);
16834 food_(&d__1);
16835 z__2.r = c1.r, z__2.i = c1.i;
16836 z__3.r = c2.r, z__3.i = c2.i;
16837 pow_zz(&z__1, &z__2, &z__3);
16838 q__1.r = z__1.r, q__1.i = z__1.i;
16839 fooc_(&q__1);
16840 z__2.r = c1.r, z__2.i = c1.i;
16841 z__3.r = r1, z__3.i = 0.;
16842 pow_zz(&z__1, &z__2, &z__3);
16843 q__1.r = z__1.r, q__1.i = z__1.i;
16844 fooc_(&q__1);
16845 z__2.r = c1.r, z__2.i = c1.i;
16846 z__3.r = d1, z__3.i = 0.;
16847 pow_zz(&z__1, &z__2, &z__3);
16848 fooz_(&z__1);
16849// FFEINTRIN_impABS //
16850 r__1 = (doublereal)(( r1 ) >= 0 ? ( r1 ) : -( r1 )) ;
16851 foor_(&r__1);
16852// FFEINTRIN_impACOS //
16853 r__1 = acos(r1);
16854 foor_(&r__1);
16855// FFEINTRIN_impAIMAG //
16856 r__1 = r_imag(&c1);
16857 foor_(&r__1);
16858// FFEINTRIN_impAINT //
16859 r__1 = r_int(&r1);
16860 foor_(&r__1);
16861// FFEINTRIN_impALOG //
16862 r__1 = log(r1);
16863 foor_(&r__1);
16864// FFEINTRIN_impALOG10 //
16865 r__1 = r_lg10(&r1);
16866 foor_(&r__1);
16867// FFEINTRIN_impAMAX0 //
16868 r__1 = (real) (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
16869 foor_(&r__1);
16870// FFEINTRIN_impAMAX1 //
16871 r__1 = (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
16872 foor_(&r__1);
16873// FFEINTRIN_impAMIN0 //
16874 r__1 = (real) (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
16875 foor_(&r__1);
16876// FFEINTRIN_impAMIN1 //
16877 r__1 = (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
16878 foor_(&r__1);
16879// FFEINTRIN_impAMOD //
16880 r__1 = r_mod(&r1, &r2);
16881 foor_(&r__1);
16882// FFEINTRIN_impANINT //
16883 r__1 = r_nint(&r1);
16884 foor_(&r__1);
16885// FFEINTRIN_impASIN //
16886 r__1 = asin(r1);
16887 foor_(&r__1);
16888// FFEINTRIN_impATAN //
16889 r__1 = atan(r1);
16890 foor_(&r__1);
16891// FFEINTRIN_impATAN2 //
16892 r__1 = atan2(r1, r2);
16893 foor_(&r__1);
16894// FFEINTRIN_impCABS //
16895 r__1 = c_abs(&c1);
16896 foor_(&r__1);
16897// FFEINTRIN_impCCOS //
16898 c_cos(&q__1, &c1);
16899 fooc_(&q__1);
16900// FFEINTRIN_impCEXP //
16901 c_exp(&q__1, &c1);
16902 fooc_(&q__1);
16903// FFEINTRIN_impCHAR //
16904 *(unsigned char *)&ch__1[0] = i1;
16905 fooa_(ch__1, 1L);
16906// FFEINTRIN_impCLOG //
16907 c_log(&q__1, &c1);
16908 fooc_(&q__1);
16909// FFEINTRIN_impCONJG //
16910 r_cnjg(&q__1, &c1);
16911 fooc_(&q__1);
16912// FFEINTRIN_impCOS //
16913 r__1 = cos(r1);
16914 foor_(&r__1);
16915// FFEINTRIN_impCOSH //
16916 r__1 = cosh(r1);
16917 foor_(&r__1);
16918// FFEINTRIN_impCSIN //
16919 c_sin(&q__1, &c1);
16920 fooc_(&q__1);
16921// FFEINTRIN_impCSQRT //
16922 c_sqrt(&q__1, &c1);
16923 fooc_(&q__1);
16924// FFEINTRIN_impDABS //
16925 d__1 = (( d1 ) >= 0 ? ( d1 ) : -( d1 )) ;
16926 food_(&d__1);
16927// FFEINTRIN_impDACOS //
16928 d__1 = acos(d1);
16929 food_(&d__1);
16930// FFEINTRIN_impDASIN //
16931 d__1 = asin(d1);
16932 food_(&d__1);
16933// FFEINTRIN_impDATAN //
16934 d__1 = atan(d1);
16935 food_(&d__1);
16936// FFEINTRIN_impDATAN2 //
16937 d__1 = atan2(d1, d2);
16938 food_(&d__1);
16939// FFEINTRIN_impDCOS //
16940 d__1 = cos(d1);
16941 food_(&d__1);
16942// FFEINTRIN_impDCOSH //
16943 d__1 = cosh(d1);
16944 food_(&d__1);
16945// FFEINTRIN_impDDIM //
16946 d__1 = d_dim(&d1, &d2);
16947 food_(&d__1);
16948// FFEINTRIN_impDEXP //
16949 d__1 = exp(d1);
16950 food_(&d__1);
16951// FFEINTRIN_impDIM //
16952 r__1 = r_dim(&r1, &r2);
16953 foor_(&r__1);
16954// FFEINTRIN_impDINT //
16955 d__1 = d_int(&d1);
16956 food_(&d__1);
16957// FFEINTRIN_impDLOG //
16958 d__1 = log(d1);
16959 food_(&d__1);
16960// FFEINTRIN_impDLOG10 //
16961 d__1 = d_lg10(&d1);
16962 food_(&d__1);
16963// FFEINTRIN_impDMAX1 //
16964 d__1 = (( d1 ) >= ( d2 ) ? ( d1 ) : ( d2 )) ;
16965 food_(&d__1);
16966// FFEINTRIN_impDMIN1 //
16967 d__1 = (( d1 ) <= ( d2 ) ? ( d1 ) : ( d2 )) ;
16968 food_(&d__1);
16969// FFEINTRIN_impDMOD //
16970 d__1 = d_mod(&d1, &d2);
16971 food_(&d__1);
16972// FFEINTRIN_impDNINT //
16973 d__1 = d_nint(&d1);
16974 food_(&d__1);
16975// FFEINTRIN_impDPROD //
16976 d__1 = (doublereal) r1 * r2;
16977 food_(&d__1);
16978// FFEINTRIN_impDSIGN //
16979 d__1 = d_sign(&d1, &d2);
16980 food_(&d__1);
16981// FFEINTRIN_impDSIN //
16982 d__1 = sin(d1);
16983 food_(&d__1);
16984// FFEINTRIN_impDSINH //
16985 d__1 = sinh(d1);
16986 food_(&d__1);
16987// FFEINTRIN_impDSQRT //
16988 d__1 = sqrt(d1);
16989 food_(&d__1);
16990// FFEINTRIN_impDTAN //
16991 d__1 = tan(d1);
16992 food_(&d__1);
16993// FFEINTRIN_impDTANH //
16994 d__1 = tanh(d1);
16995 food_(&d__1);
16996// FFEINTRIN_impEXP //
16997 r__1 = exp(r1);
16998 foor_(&r__1);
16999// FFEINTRIN_impIABS //
17000 i__1 = (( i1 ) >= 0 ? ( i1 ) : -( i1 )) ;
17001 fooi_(&i__1);
17002// FFEINTRIN_impICHAR //
17003 i__1 = *(unsigned char *)a1;
17004 fooi_(&i__1);
17005// FFEINTRIN_impIDIM //
17006 i__1 = i_dim(&i1, &i2);
17007 fooi_(&i__1);
17008// FFEINTRIN_impIDNINT //
17009 i__1 = i_dnnt(&d1);
17010 fooi_(&i__1);
17011// FFEINTRIN_impINDEX //
17012 i__1 = i_indx(a1, a2, 10L, 10L);
17013 fooi_(&i__1);
17014// FFEINTRIN_impISIGN //
17015 i__1 = i_sign(&i1, &i2);
17016 fooi_(&i__1);
17017// FFEINTRIN_impLEN //
17018 i__1 = i_len(a1, 10L);
17019 fooi_(&i__1);
17020// FFEINTRIN_impLGE //
17021 L__1 = l_ge(a1, a2, 10L, 10L);
17022 fool_(&L__1);
17023// FFEINTRIN_impLGT //
17024 L__1 = l_gt(a1, a2, 10L, 10L);
17025 fool_(&L__1);
17026// FFEINTRIN_impLLE //
17027 L__1 = l_le(a1, a2, 10L, 10L);
17028 fool_(&L__1);
17029// FFEINTRIN_impLLT //
17030 L__1 = l_lt(a1, a2, 10L, 10L);
17031 fool_(&L__1);
17032// FFEINTRIN_impMAX0 //
17033 i__1 = (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
17034 fooi_(&i__1);
17035// FFEINTRIN_impMAX1 //
17036 i__1 = (integer) (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
17037 fooi_(&i__1);
17038// FFEINTRIN_impMIN0 //
17039 i__1 = (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
17040 fooi_(&i__1);
17041// FFEINTRIN_impMIN1 //
17042 i__1 = (integer) (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
17043 fooi_(&i__1);
17044// FFEINTRIN_impMOD //
17045 i__1 = i1 % i2;
17046 fooi_(&i__1);
17047// FFEINTRIN_impNINT //
17048 i__1 = i_nint(&r1);
17049 fooi_(&i__1);
17050// FFEINTRIN_impSIGN //
17051 r__1 = r_sign(&r1, &r2);
17052 foor_(&r__1);
17053// FFEINTRIN_impSIN //
17054 r__1 = sin(r1);
17055 foor_(&r__1);
17056// FFEINTRIN_impSINH //
17057 r__1 = sinh(r1);
17058 foor_(&r__1);
17059// FFEINTRIN_impSQRT //
17060 r__1 = sqrt(r1);
17061 foor_(&r__1);
17062// FFEINTRIN_impTAN //
17063 r__1 = tan(r1);
17064 foor_(&r__1);
17065// FFEINTRIN_impTANH //
17066 r__1 = tanh(r1);
17067 foor_(&r__1);
17068// FFEINTRIN_imp_CMPLX_C //
17069 r__1 = c1.r;
17070 r__2 = c2.r;
17071 q__1.r = r__1, q__1.i = r__2;
17072 fooc_(&q__1);
17073// FFEINTRIN_imp_CMPLX_D //
17074 z__1.r = d1, z__1.i = d2;
17075 fooz_(&z__1);
17076// FFEINTRIN_imp_CMPLX_I //
17077 r__1 = (real) i1;
17078 r__2 = (real) i2;
17079 q__1.r = r__1, q__1.i = r__2;
17080 fooc_(&q__1);
17081// FFEINTRIN_imp_CMPLX_R //
17082 q__1.r = r1, q__1.i = r2;
17083 fooc_(&q__1);
17084// FFEINTRIN_imp_DBLE_C //
17085 d__1 = (doublereal) c1.r;
17086 food_(&d__1);
17087// FFEINTRIN_imp_DBLE_D //
17088 d__1 = d1;
17089 food_(&d__1);
17090// FFEINTRIN_imp_DBLE_I //
17091 d__1 = (doublereal) i1;
17092 food_(&d__1);
17093// FFEINTRIN_imp_DBLE_R //
17094 d__1 = (doublereal) r1;
17095 food_(&d__1);
17096// FFEINTRIN_imp_INT_C //
17097 i__1 = (integer) c1.r;
17098 fooi_(&i__1);
17099// FFEINTRIN_imp_INT_D //
17100 i__1 = (integer) d1;
17101 fooi_(&i__1);
17102// FFEINTRIN_imp_INT_I //
17103 i__1 = i1;
17104 fooi_(&i__1);
17105// FFEINTRIN_imp_INT_R //
17106 i__1 = (integer) r1;
17107 fooi_(&i__1);
17108// FFEINTRIN_imp_REAL_C //
17109 r__1 = c1.r;
17110 foor_(&r__1);
17111// FFEINTRIN_imp_REAL_D //
17112 r__1 = (real) d1;
17113 foor_(&r__1);
17114// FFEINTRIN_imp_REAL_I //
17115 r__1 = (real) i1;
17116 foor_(&r__1);
17117// FFEINTRIN_imp_REAL_R //
17118 r__1 = r1;
17119 foor_(&r__1);
17120
17121// FFEINTRIN_imp_INT_D: //
17122
17123// FFEINTRIN_specIDINT //
17124 i__1 = (integer) d1;
17125 fooi_(&i__1);
17126
17127// FFEINTRIN_imp_INT_R: //
17128
17129// FFEINTRIN_specIFIX //
17130 i__1 = (integer) r1;
17131 fooi_(&i__1);
17132// FFEINTRIN_specINT //
17133 i__1 = (integer) r1;
17134 fooi_(&i__1);
17135
17136// FFEINTRIN_imp_REAL_D: //
5ff904cd 17137
c7e4ee3a
CB
17138// FFEINTRIN_specSNGL //
17139 r__1 = (real) d1;
17140 foor_(&r__1);
5ff904cd 17141
c7e4ee3a 17142// FFEINTRIN_imp_REAL_I: //
5ff904cd 17143
c7e4ee3a
CB
17144// FFEINTRIN_specFLOAT //
17145 r__1 = (real) i1;
17146 foor_(&r__1);
17147// FFEINTRIN_specREAL //
17148 r__1 = (real) i1;
17149 foor_(&r__1);
5ff904cd 17150
c7e4ee3a 17151} // MAIN__ //
5ff904cd 17152
c7e4ee3a 17153-------- (end output file from f2c)
5ff904cd 17154
c7e4ee3a 17155*/
This page took 2.801669 seconds and 5 git commands to generate.