]> gcc.gnu.org Git - gcc.git/blame - gcc/f/com.c
Makefile.in (SPLAY_TREE_H): New macro.
[gcc.git] / gcc / f / com.c
CommitLineData
5ff904cd 1/* com.c -- Implementation File (module.c template V1.0)
06ceef4e
RK
2 Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000
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):
57 int yes;
58 yes = suspend_momentary ();
59 if (is_nested) push_f_function_context ();
60 start_function (get_identifier ("function_name"), function_type,
61 is_nested, is_public);
62 // for each arg, build PARM_DECL and call push_parm_decl (decl) with it;
63 store_parm_decls (is_main_program);
c7e4ee3a 64 ffecom_start_compstmt ();
5ff904cd 65 // for stmts and decls inside function, do appropriate things;
c7e4ee3a 66 ffecom_end_compstmt ();
5ff904cd
JL
67 finish_function (is_nested);
68 if (is_nested) pop_f_function_context ();
69 if (is_nested) resume_momentary (yes);
70
71 Everything Else:
72 int yes;
73 tree d;
74 tree init;
75 yes = suspend_momentary ();
76 // fill in external, public, static, &c for decl, and
77 // set DECL_INITIAL to error_mark_node if going to initialize
78 // set is_top_level TRUE only if not at top level and decl
79 // must go in top level (i.e. not within current function decl context)
80 d = start_decl (decl, is_top_level);
81 init = ...; // if have initializer
82 finish_decl (d, init, is_top_level);
83 resume_momentary (yes);
84
85*/
86
87/* Include files. */
88
95a1b676 89#include "proj.h"
5ff904cd 90#if FFECOM_targetCURRENT == FFECOM_targetGCC
5ff904cd
JL
91#include "flags.j"
92#include "rtl.j"
8b45da67 93#include "toplev.j"
5ff904cd 94#include "tree.j"
95a1b676 95#include "output.j" /* Must follow tree.j so TREE_CODE is defined! */
5ff904cd 96#include "convert.j"
7189a4b0 97#include "ggc.j"
5ff904cd
JL
98#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
99
100#define FFECOM_GCC_INCLUDE 1 /* Enable -I. */
101
102/* BEGIN stuff from gcc/cccp.c. */
103
104/* The following symbols should be autoconfigured:
105 HAVE_FCNTL_H
106 HAVE_STDLIB_H
107 HAVE_SYS_TIME_H
108 HAVE_UNISTD_H
109 STDC_HEADERS
110 TIME_WITH_SYS_TIME
111 In the mean time, we'll get by with approximations based
112 on existing GCC configuration symbols. */
113
114#ifdef POSIX
115# ifndef HAVE_STDLIB_H
116# define HAVE_STDLIB_H 1
117# endif
118# ifndef HAVE_UNISTD_H
119# define HAVE_UNISTD_H 1
120# endif
121# ifndef STDC_HEADERS
122# define STDC_HEADERS 1
123# endif
124#endif /* defined (POSIX) */
125
126#if defined (POSIX) || (defined (USG) && !defined (VMS))
127# ifndef HAVE_FCNTL_H
128# define HAVE_FCNTL_H 1
129# endif
130#endif
131
132#ifndef RLIMIT_STACK
133# include <time.h>
134#else
135# if TIME_WITH_SYS_TIME
136# include <sys/time.h>
137# include <time.h>
138# else
139# if HAVE_SYS_TIME_H
140# include <sys/time.h>
141# else
142# include <time.h>
143# endif
144# endif
145# include <sys/resource.h>
146#endif
147
148#if HAVE_FCNTL_H
149# include <fcntl.h>
150#endif
151
152/* This defines "errno" properly for VMS, and gives us EACCES. */
153#include <errno.h>
154
155#if HAVE_STDLIB_H
156# include <stdlib.h>
157#else
158char *getenv ();
159#endif
160
5ff904cd
JL
161#if HAVE_UNISTD_H
162# include <unistd.h>
163#endif
164
165/* VMS-specific definitions */
166#ifdef VMS
167#include <descrip.h>
168#define O_RDONLY 0 /* Open arg for Read/Only */
169#define O_WRONLY 1 /* Open arg for Write/Only */
170#define read(fd,buf,size) VMS_read (fd,buf,size)
171#define write(fd,buf,size) VMS_write (fd,buf,size)
172#define open(fname,mode,prot) VMS_open (fname,mode,prot)
173#define fopen(fname,mode) VMS_fopen (fname,mode)
174#define freopen(fname,mode,ofile) VMS_freopen (fname,mode,ofile)
175#define strncat(dst,src,cnt) VMS_strncat (dst,src,cnt)
176#define fstat(fd,stbuf) VMS_fstat (fd,stbuf)
177static int VMS_fstat (), VMS_stat ();
178static char * VMS_strncat ();
179static int VMS_read ();
180static int VMS_write ();
181static int VMS_open ();
182static FILE * VMS_fopen ();
183static FILE * VMS_freopen ();
184static void hack_vms_include_specification ();
185typedef struct { unsigned :16, :16, :16; } vms_ino_t;
186#define ino_t vms_ino_t
187#define INCLUDE_LEN_FUDGE 10 /* leave room for VMS syntax conversion */
188#ifdef __GNUC__
189#define BSTRING /* VMS/GCC supplies the bstring routines */
190#endif /* __GNUC__ */
191#endif /* VMS */
192
193#ifndef O_RDONLY
194#define O_RDONLY 0
195#endif
196
197/* END stuff from gcc/cccp.c. */
198
5ff904cd
JL
199#define FFECOM_DETERMINE_TYPES 1 /* for com.h */
200#include "com.h"
201#include "bad.h"
202#include "bld.h"
203#include "equiv.h"
204#include "expr.h"
205#include "implic.h"
206#include "info.h"
207#include "malloc.h"
208#include "src.h"
209#include "st.h"
210#include "storag.h"
211#include "symbol.h"
212#include "target.h"
213#include "top.h"
214#include "type.h"
215
216/* Externals defined here. */
217
5ff904cd
JL
218#if FFECOM_targetCURRENT == FFECOM_targetGCC
219
c7e4ee3a
CB
220/* ~~gcc/tree.h *should* declare this, because toplev.c and dwarfout.c
221 reference it. */
5ff904cd 222
f425a887 223const char * const language_string = "GNU F77";
5ff904cd 224
77f77701
DB
225/* Stream for reading from the input file. */
226FILE *finput;
227
5ff904cd
JL
228/* These definitions parallel those in c-decl.c so that code from that
229 module can be used pretty much as is. Much of these defs aren't
230 otherwise used, i.e. by g77 code per se, except some of them are used
231 to build some of them that are. The ones that are global (i.e. not
232 "static") are those that ste.c and such might use (directly
233 or by using com macros that reference them in their definitions). */
234
5ff904cd
JL
235tree string_type_node;
236
5ff904cd
JL
237/* The rest of these are inventions for g77, though there might be
238 similar things in the C front end. As they are found, these
239 inventions should be renamed to be canonical. Note that only
240 the ones currently required to be global are so. */
241
242static tree ffecom_tree_fun_type_void;
5ff904cd
JL
243
244tree ffecom_integer_type_node; /* Abbrev for _tree_type[blah][blah]. */
245tree ffecom_integer_zero_node; /* Like *_*_* with g77's integer type. */
246tree ffecom_integer_one_node; /* " */
247tree ffecom_tree_type[FFEINFO_basictype][FFEINFO_kindtype];
248
249/* _fun_type things are the f2c-specific versions. For -fno-f2c,
250 just use build_function_type and build_pointer_type on the
251 appropriate _tree_type array element. */
252
253static tree ffecom_tree_fun_type[FFEINFO_basictype][FFEINFO_kindtype];
254static tree ffecom_tree_ptr_to_fun_type[FFEINFO_basictype][FFEINFO_kindtype];
255static tree ffecom_tree_subr_type;
256static tree ffecom_tree_ptr_to_subr_type;
257static tree ffecom_tree_blockdata_type;
258
259static tree ffecom_tree_xargc_;
260
261ffecomSymbol ffecom_symbol_null_
262=
263{
264 NULL_TREE,
265 NULL_TREE,
266 NULL_TREE,
0816ebdd
KG
267 NULL_TREE,
268 false
5ff904cd
JL
269};
270ffeinfoKindtype ffecom_pointer_kind_ = FFEINFO_basictypeNONE;
271ffeinfoKindtype ffecom_label_kind_ = FFEINFO_basictypeNONE;
272
273int ffecom_f2c_typecode_[FFEINFO_basictype][FFEINFO_kindtype];
274tree ffecom_f2c_integer_type_node;
275tree ffecom_f2c_ptr_to_integer_type_node;
276tree ffecom_f2c_address_type_node;
277tree ffecom_f2c_real_type_node;
278tree ffecom_f2c_ptr_to_real_type_node;
279tree ffecom_f2c_doublereal_type_node;
280tree ffecom_f2c_complex_type_node;
281tree ffecom_f2c_doublecomplex_type_node;
282tree ffecom_f2c_longint_type_node;
283tree ffecom_f2c_logical_type_node;
284tree ffecom_f2c_flag_type_node;
285tree ffecom_f2c_ftnlen_type_node;
286tree ffecom_f2c_ftnlen_zero_node;
287tree ffecom_f2c_ftnlen_one_node;
288tree ffecom_f2c_ftnlen_two_node;
289tree ffecom_f2c_ptr_to_ftnlen_type_node;
290tree ffecom_f2c_ftnint_type_node;
291tree ffecom_f2c_ptr_to_ftnint_type_node;
292#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
293
294/* Simple definitions and enumerations. */
295
296#ifndef FFECOM_sizeMAXSTACKITEM
297#define FFECOM_sizeMAXSTACKITEM 32*1024 /* Keep user-declared things
298 larger than this # bytes
299 off stack if possible. */
300#endif
301
302/* For systems that have large enough stacks, they should define
303 this to 0, and here, for ease of use later on, we just undefine
304 it if it is 0. */
305
306#if FFECOM_sizeMAXSTACKITEM == 0
307#undef FFECOM_sizeMAXSTACKITEM
308#endif
309
310typedef enum
311 {
312 FFECOM_rttypeVOID_,
6d433196 313 FFECOM_rttypeVOIDSTAR_, /* C's `void *' type. */
795232f7
JL
314 FFECOM_rttypeFTNINT_, /* f2c's `ftnint' type. */
315 FFECOM_rttypeINTEGER_, /* f2c's `integer' type. */
316 FFECOM_rttypeLONGINT_, /* f2c's `longint' type. */
317 FFECOM_rttypeLOGICAL_, /* f2c's `logical' type. */
318 FFECOM_rttypeREAL_F2C_, /* f2c's `real' returned as `double'. */
319 FFECOM_rttypeREAL_GNU_, /* `real' returned as such. */
5ff904cd 320 FFECOM_rttypeCOMPLEX_F2C_, /* f2c's `complex' returned via 1st arg. */
795232f7 321 FFECOM_rttypeCOMPLEX_GNU_, /* f2c's `complex' returned directly. */
5ff904cd 322 FFECOM_rttypeDOUBLE_, /* C's `double' type. */
795232f7 323 FFECOM_rttypeDOUBLEREAL_, /* f2c's `doublereal' type. */
5ff904cd 324 FFECOM_rttypeDBLCMPLX_F2C_, /* f2c's `doublecomplex' returned via 1st arg. */
795232f7 325 FFECOM_rttypeDBLCMPLX_GNU_, /* f2c's `doublecomplex' returned directly. */
5ff904cd
JL
326 FFECOM_rttypeCHARACTER_, /* f2c `char *'/`ftnlen' pair. */
327 FFECOM_rttype_
328 } ffecomRttype_;
329
330/* Internal typedefs. */
331
332#if FFECOM_targetCURRENT == FFECOM_targetGCC
333typedef struct _ffecom_concat_list_ ffecomConcatList_;
5ff904cd
JL
334#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
335
336/* Private include files. */
337
338
339/* Internal structure definitions. */
340
341#if FFECOM_targetCURRENT == FFECOM_targetGCC
342struct _ffecom_concat_list_
343 {
344 ffebld *exprs;
345 int count;
346 int max;
347 ffetargetCharacterSize minlen;
348 ffetargetCharacterSize maxlen;
349 };
5ff904cd
JL
350#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
351
352/* Static functions (internal). */
353
354#if FFECOM_targetCURRENT == FFECOM_targetGCC
26f096f9 355static tree ffecom_arglist_expr_ (const char *argstring, ffebld args);
5ff904cd
JL
356static tree ffecom_widest_expr_type_ (ffebld list);
357static bool ffecom_overlap_ (tree dest_decl, tree dest_offset,
358 tree dest_size, tree source_tree,
359 ffebld source, bool scalar_arg);
360static bool ffecom_args_overlapping_ (tree dest_tree, ffebld dest,
361 tree args, tree callee_commons,
362 bool scalar_args);
26f096f9 363static tree ffecom_build_f2c_string_ (int i, const char *s);
5ff904cd
JL
364static tree ffecom_call_ (tree fn, ffeinfoKindtype kt,
365 bool is_f2c_complex, tree type,
366 tree args, tree dest_tree,
367 ffebld dest, bool *dest_used,
c7e4ee3a 368 tree callee_commons, bool scalar_args, tree hook);
5ff904cd
JL
369static tree ffecom_call_binop_ (tree fn, ffeinfoKindtype kt,
370 bool is_f2c_complex, tree type,
371 ffebld left, ffebld right,
372 tree dest_tree, ffebld dest,
373 bool *dest_used, tree callee_commons,
c7e4ee3a 374 bool scalar_args, tree hook);
86fc7a6c
CB
375static void ffecom_char_args_x_ (tree *xitem, tree *length,
376 ffebld expr, bool with_null);
5ff904cd
JL
377static tree ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy);
378static tree ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s);
379static ffecomConcatList_
380 ffecom_concat_list_gather_ (ffecomConcatList_ catlist,
381 ffebld expr,
382 ffetargetCharacterSize max);
383static void ffecom_concat_list_kill_ (ffecomConcatList_ catlist);
384static ffecomConcatList_ ffecom_concat_list_new_ (ffebld expr,
385 ffetargetCharacterSize max);
26f096f9
KG
386static void ffecom_debug_kludge_ (tree aggr, const char *aggr_type,
387 ffesymbol member, tree member_type,
388 ffetargetOffset offset);
5ff904cd 389static void ffecom_do_entry_ (ffesymbol fn, int entrynum);
092a4ef8
RH
390static tree ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
391 bool *dest_used, bool assignp, bool widenp);
5ff904cd
JL
392static tree ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
393 ffebld dest, bool *dest_used);
c7e4ee3a 394static tree ffecom_expr_power_integer_ (ffebld expr);
5ff904cd 395static void ffecom_expr_transform_ (ffebld expr);
26f096f9 396static void ffecom_f2c_make_type_ (tree *type, int tcode, const char *name);
5ff904cd
JL
397static void ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size,
398 int code);
399static ffeglobal ffecom_finish_global_ (ffeglobal global);
400static ffesymbol ffecom_finish_symbol_transform_ (ffesymbol s);
26f096f9 401static tree ffecom_get_appended_identifier_ (char us, const char *text);
5ff904cd 402static tree ffecom_get_external_identifier_ (ffesymbol s);
26f096f9 403static tree ffecom_get_identifier_ (const char *text);
5ff904cd
JL
404static tree ffecom_gen_sfuncdef_ (ffesymbol s,
405 ffeinfoBasictype bt,
406 ffeinfoKindtype kt);
26f096f9 407static const char *ffecom_gfrt_args_ (ffecomGfrt ix);
5ff904cd
JL
408static tree ffecom_gfrt_tree_ (ffecomGfrt ix);
409static tree ffecom_init_zero_ (tree decl);
410static tree ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg,
411 tree *maybe_tree);
412static tree ffecom_intrinsic_len_ (ffebld expr);
413static void ffecom_let_char_ (tree dest_tree,
414 tree dest_length,
415 ffetargetCharacterSize dest_size,
416 ffebld source);
417static void ffecom_make_gfrt_ (ffecomGfrt ix);
418static void ffecom_member_phase1_ (ffestorag mst, ffestorag st);
5ff904cd 419static void ffecom_member_phase2_ (ffestorag mst, ffestorag st);
c7e4ee3a
CB
420static void ffecom_prepare_let_char_ (ffetargetCharacterSize dest_size,
421 ffebld source);
5ff904cd
JL
422static void ffecom_push_dummy_decls_ (ffebld dumlist,
423 bool stmtfunc);
424static void ffecom_start_progunit_ (void);
425static ffesymbol ffecom_sym_transform_ (ffesymbol s);
426static ffesymbol ffecom_sym_transform_assign_ (ffesymbol s);
427static void ffecom_transform_common_ (ffesymbol s);
428static void ffecom_transform_equiv_ (ffestorag st);
429static tree ffecom_transform_namelist_ (ffesymbol s);
430static void ffecom_tree_canonize_ptr_ (tree *decl, tree *offset,
431 tree t);
432static void ffecom_tree_canonize_ref_ (tree *decl, tree *offset,
433 tree *size, tree tree);
434static tree ffecom_tree_divide_ (tree tree_type, tree left, tree right,
435 tree dest_tree, ffebld dest,
c7e4ee3a 436 bool *dest_used, tree hook);
5ff904cd
JL
437static tree ffecom_type_localvar_ (ffesymbol s,
438 ffeinfoBasictype bt,
439 ffeinfoKindtype kt);
440static tree ffecom_type_namelist_ (void);
5ff904cd
JL
441static tree ffecom_type_vardesc_ (void);
442static tree ffecom_vardesc_ (ffebld expr);
443static tree ffecom_vardesc_array_ (ffesymbol s);
444static tree ffecom_vardesc_dims_ (ffesymbol s);
26f096f9
KG
445static tree ffecom_convert_narrow_ (tree type, tree expr);
446static tree ffecom_convert_widen_ (tree type, tree expr);
5ff904cd
JL
447#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
448
449/* These are static functions that parallel those found in the C front
450 end and thus have the same names. */
451
452#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a 453static tree bison_rule_compstmt_ (void);
5ff904cd 454static void bison_rule_pushlevel_ (void);
c7e4ee3a 455static void delete_block (tree block);
5ff904cd
JL
456static int duplicate_decls (tree newdecl, tree olddecl);
457static void finish_decl (tree decl, tree init, bool is_top_level);
458static void finish_function (int nested);
4b731ffa 459static const char *lang_printable_name (tree decl, int v);
5ff904cd
JL
460static tree lookup_name_current_level (tree name);
461static struct binding_level *make_binding_level (void);
462static void pop_f_function_context (void);
463static void push_f_function_context (void);
464static void push_parm_decl (tree parm);
465static tree pushdecl_top_level (tree decl);
c7e4ee3a 466static int kept_level_p (void);
5ff904cd
JL
467static tree storedecls (tree decls);
468static void store_parm_decls (int is_main_program);
469static tree start_decl (tree decl, bool is_top_level);
470static void start_function (tree name, tree type, int nested, int public);
471#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
472#if FFECOM_GCC_INCLUDE
b0791fa9 473static void ffecom_file_ (const char *name);
5ff904cd
JL
474static void ffecom_initialize_char_syntax_ (void);
475static void ffecom_close_include_ (FILE *f);
476static int ffecom_decode_include_option_ (char *spec);
477static FILE *ffecom_open_include_ (char *name, ffewhereLine l,
478 ffewhereColumn c);
479#endif /* FFECOM_GCC_INCLUDE */
480
481/* Static objects accessed by functions in this module. */
482
483static ffesymbol ffecom_primary_entry_ = NULL;
484static ffesymbol ffecom_nested_entry_ = NULL;
485static ffeinfoKind ffecom_primary_entry_kind_;
486static bool ffecom_primary_entry_is_proc_;
487#if FFECOM_targetCURRENT == FFECOM_targetGCC
488static tree ffecom_outer_function_decl_;
489static tree ffecom_previous_function_decl_;
490static tree ffecom_which_entrypoint_decl_;
5ff904cd
JL
491static tree ffecom_float_zero_ = NULL_TREE;
492static tree ffecom_float_half_ = NULL_TREE;
493static tree ffecom_double_zero_ = NULL_TREE;
494static tree ffecom_double_half_ = NULL_TREE;
495static tree ffecom_func_result_;/* For functions. */
496static tree ffecom_func_length_;/* For CHARACTER fns. */
497static ffebld ffecom_list_blockdata_;
498static ffebld ffecom_list_common_;
499static ffebld ffecom_master_arglist_;
500static ffeinfoBasictype ffecom_master_bt_;
501static ffeinfoKindtype ffecom_master_kt_;
502static ffetargetCharacterSize ffecom_master_size_;
503static int ffecom_num_fns_ = 0;
504static int ffecom_num_entrypoints_ = 0;
505static bool ffecom_is_altreturning_ = FALSE;
506static tree ffecom_multi_type_node_;
507static tree ffecom_multi_retval_;
508static tree
509 ffecom_multi_fields_[FFEINFO_basictype][FFEINFO_kindtype];
510static bool ffecom_member_namelisted_; /* _member_phase1_ namelisted? */
511static bool ffecom_doing_entry_ = FALSE;
512static bool ffecom_transform_only_dummies_ = FALSE;
ff852b44
CB
513static int ffecom_typesize_pointer_;
514static int ffecom_typesize_integer1_;
5ff904cd
JL
515
516/* Holds pointer-to-function expressions. */
517
518static tree ffecom_gfrt_[FFECOM_gfrt]
519=
520{
521#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) NULL_TREE,
522#include "com-rt.def"
523#undef DEFGFRT
524};
525
526/* Holds the external names of the functions. */
527
26f096f9 528static const char *ffecom_gfrt_name_[FFECOM_gfrt]
5ff904cd
JL
529=
530{
531#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) NAME,
532#include "com-rt.def"
533#undef DEFGFRT
534};
535
536/* Whether the function returns. */
537
538static bool ffecom_gfrt_volatile_[FFECOM_gfrt]
539=
540{
541#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) VOLATILE,
542#include "com-rt.def"
543#undef DEFGFRT
544};
545
546/* Whether the function returns type complex. */
547
548static bool ffecom_gfrt_complex_[FFECOM_gfrt]
549=
550{
551#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) COMPLEX,
552#include "com-rt.def"
553#undef DEFGFRT
554};
555
556/* Type code for the function return value. */
557
558static ffecomRttype_ ffecom_gfrt_type_[FFECOM_gfrt]
559=
560{
561#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) TYPE,
562#include "com-rt.def"
563#undef DEFGFRT
564};
565
566/* String of codes for the function's arguments. */
567
26f096f9 568static const char *ffecom_gfrt_argstring_[FFECOM_gfrt]
5ff904cd
JL
569=
570{
571#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) ARGS,
572#include "com-rt.def"
573#undef DEFGFRT
574};
575#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
576
577/* Internal macros. */
578
579#if FFECOM_targetCURRENT == FFECOM_targetGCC
580
581/* We let tm.h override the types used here, to handle trivial differences
582 such as the choice of unsigned int or long unsigned int for size_t.
583 When machines start needing nontrivial differences in the size type,
584 it would be best to do something here to figure out automatically
585 from other information what type to use. */
586
ff852b44
CB
587#ifndef SIZE_TYPE
588#define SIZE_TYPE "long unsigned int"
589#endif
5ff904cd 590
5ff904cd
JL
591#define ffecom_concat_list_count_(catlist) ((catlist).count)
592#define ffecom_concat_list_expr_(catlist,i) ((catlist).exprs[(i)])
593#define ffecom_concat_list_maxlen_(catlist) ((catlist).maxlen)
594#define ffecom_concat_list_minlen_(catlist) ((catlist).minlen)
595
86fc7a6c
CB
596#define ffecom_char_args_(i,l,e) ffecom_char_args_x_((i),(l),(e),FALSE)
597#define ffecom_char_args_with_null_(i,l,e) ffecom_char_args_x_((i),(l),(e),TRUE)
598
5ff904cd
JL
599/* For each binding contour we allocate a binding_level structure
600 * which records the names defined in that contour.
601 * Contours include:
602 * 0) the global one
603 * 1) one for each function definition,
604 * where internal declarations of the parameters appear.
605 *
606 * The current meaning of a name can be found by searching the levels from
607 * the current one out to the global one.
608 */
609
610/* Note that the information in the `names' component of the global contour
611 is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers. */
612
613struct binding_level
614 {
c7e4ee3a
CB
615 /* A chain of _DECL nodes for all variables, constants, functions,
616 and typedef types. These are in the reverse of the order supplied.
617 */
5ff904cd
JL
618 tree names;
619
c7e4ee3a
CB
620 /* For each level (except not the global one),
621 a chain of BLOCK nodes for all the levels
622 that were entered and exited one level down. */
5ff904cd
JL
623 tree blocks;
624
c7e4ee3a
CB
625 /* The BLOCK node for this level, if one has been preallocated.
626 If 0, the BLOCK is allocated (if needed) when the level is popped. */
5ff904cd
JL
627 tree this_block;
628
629 /* The binding level which this one is contained in (inherits from). */
630 struct binding_level *level_chain;
c7e4ee3a
CB
631
632 /* 0: no ffecom_prepare_* functions called at this level yet;
633 1: ffecom_prepare* functions called, except not ffecom_prepare_end;
634 2: ffecom_prepare_end called. */
635 int prep_state;
5ff904cd
JL
636 };
637
638#define NULL_BINDING_LEVEL (struct binding_level *) NULL
639
640/* The binding level currently in effect. */
641
642static struct binding_level *current_binding_level;
643
644/* A chain of binding_level structures awaiting reuse. */
645
646static struct binding_level *free_binding_level;
647
648/* The outermost binding level, for names of file scope.
649 This is created when the compiler is started and exists
650 through the entire run. */
651
652static struct binding_level *global_binding_level;
653
654/* Binding level structures are initialized by copying this one. */
655
656static struct binding_level clear_binding_level
657=
c7e4ee3a 658{NULL, NULL, NULL, NULL_BINDING_LEVEL, 0};
5ff904cd
JL
659
660/* Language-dependent contents of an identifier. */
661
662struct lang_identifier
663 {
664 struct tree_identifier ignore;
665 tree global_value, local_value, label_value;
666 bool invented;
667 };
668
669/* Macros for access to language-specific slots in an identifier. */
670/* Each of these slots contains a DECL node or null. */
671
672/* This represents the value which the identifier has in the
673 file-scope namespace. */
674#define IDENTIFIER_GLOBAL_VALUE(NODE) \
675 (((struct lang_identifier *)(NODE))->global_value)
676/* This represents the value which the identifier has in the current
677 scope. */
678#define IDENTIFIER_LOCAL_VALUE(NODE) \
679 (((struct lang_identifier *)(NODE))->local_value)
680/* This represents the value which the identifier has as a label in
681 the current label scope. */
682#define IDENTIFIER_LABEL_VALUE(NODE) \
683 (((struct lang_identifier *)(NODE))->label_value)
684/* This is nonzero if the identifier was "made up" by g77 code. */
685#define IDENTIFIER_INVENTED(NODE) \
686 (((struct lang_identifier *)(NODE))->invented)
687
688/* In identifiers, C uses the following fields in a special way:
689 TREE_PUBLIC to record that there was a previous local extern decl.
690 TREE_USED to record that such a decl was used.
691 TREE_ADDRESSABLE to record that the address of such a decl was used. */
692
693/* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
694 that have names. Here so we can clear out their names' definitions
695 at the end of the function. */
696
697static tree named_labels;
698
699/* A list of LABEL_DECLs from outer contexts that are currently shadowed. */
700
701static tree shadowed_labels;
702
703#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
704\f
6b55276e
CB
705/* Return the subscript expression, modified to do range-checking.
706
707 `array' is the array to be checked against.
708 `element' is the subscript expression to check.
709 `dim' is the dimension number (starting at 0).
710 `total_dims' is the total number of dimensions (0 for CHARACTER substring).
711*/
712
713static tree
714ffecom_subscript_check_ (tree array, tree element, int dim, int total_dims,
3b304f5b 715 const char *array_name)
6b55276e
CB
716{
717 tree low = TYPE_MIN_VALUE (TYPE_DOMAIN (array));
718 tree high = TYPE_MAX_VALUE (TYPE_DOMAIN (array));
719 tree cond;
720 tree die;
721 tree args;
722
723 if (element == error_mark_node)
724 return element;
725
ff852b44
CB
726 if (TREE_TYPE (low) != TREE_TYPE (element))
727 {
728 if (TYPE_PRECISION (TREE_TYPE (low))
729 > TYPE_PRECISION (TREE_TYPE (element)))
730 element = convert (TREE_TYPE (low), element);
731 else
732 {
733 low = convert (TREE_TYPE (element), low);
734 if (high)
735 high = convert (TREE_TYPE (element), high);
736 }
737 }
738
6b55276e
CB
739 element = ffecom_save_tree (element);
740 cond = ffecom_2 (LE_EXPR, integer_type_node,
741 low,
742 element);
743 if (high)
744 {
745 cond = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
746 cond,
747 ffecom_2 (LE_EXPR, integer_type_node,
748 element,
749 high));
750 }
751
752 {
753 int len;
754 char *proc;
755 char *var;
756 tree arg3;
757 tree arg2;
758 tree arg1;
759 tree arg4;
760
761 switch (total_dims)
762 {
763 case 0:
764 var = xmalloc (strlen (array_name) + 20);
3b304f5b 765 sprintf (var, "%s[%s-substring]",
6b55276e
CB
766 array_name,
767 dim ? "end" : "start");
768 len = strlen (var) + 1;
3b304f5b
ZW
769 arg1 = build_string (len, var);
770 free (var);
6b55276e
CB
771 break;
772
773 case 1:
774 len = strlen (array_name) + 1;
3b304f5b 775 arg1 = build_string (len, array_name);
6b55276e
CB
776 break;
777
778 default:
779 var = xmalloc (strlen (array_name) + 40);
3b304f5b 780 sprintf (var, "%s[subscript-%d-of-%d]",
6b55276e
CB
781 array_name,
782 dim + 1, total_dims);
783 len = strlen (var) + 1;
3b304f5b
ZW
784 arg1 = build_string (len, var);
785 free (var);
6b55276e
CB
786 break;
787 }
788
6b55276e
CB
789 TREE_TYPE (arg1)
790 = build_type_variant (build_array_type (char_type_node,
791 build_range_type
792 (integer_type_node,
793 integer_one_node,
794 build_int_2 (len, 0))),
795 1, 0);
796 TREE_CONSTANT (arg1) = 1;
797 TREE_STATIC (arg1) = 1;
798 arg1 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg1)),
799 arg1);
800
801 /* s_rnge adds one to the element to print it, so bias against
802 that -- want to print a faithful *subscript* value. */
803 arg2 = convert (ffecom_f2c_ftnint_type_node,
804 ffecom_2 (MINUS_EXPR,
805 TREE_TYPE (element),
806 element,
807 convert (TREE_TYPE (element),
808 integer_one_node)));
809
810 proc = xmalloc ((len = strlen (input_filename)
811 + IDENTIFIER_LENGTH (DECL_NAME (current_function_decl))
812 + 2));
813
814 sprintf (&proc[0], "%s/%s",
815 input_filename,
816 IDENTIFIER_POINTER (DECL_NAME (current_function_decl)));
817 arg3 = build_string (len, proc);
818
819 free (proc);
820
821 TREE_TYPE (arg3)
822 = build_type_variant (build_array_type (char_type_node,
823 build_range_type
824 (integer_type_node,
825 integer_one_node,
826 build_int_2 (len, 0))),
827 1, 0);
828 TREE_CONSTANT (arg3) = 1;
829 TREE_STATIC (arg3) = 1;
830 arg3 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg3)),
831 arg3);
832
833 arg4 = convert (ffecom_f2c_ftnint_type_node,
834 build_int_2 (lineno, 0));
835
836 arg1 = build_tree_list (NULL_TREE, arg1);
837 arg2 = build_tree_list (NULL_TREE, arg2);
838 arg3 = build_tree_list (NULL_TREE, arg3);
839 arg4 = build_tree_list (NULL_TREE, arg4);
840 TREE_CHAIN (arg3) = arg4;
841 TREE_CHAIN (arg2) = arg3;
842 TREE_CHAIN (arg1) = arg2;
843
844 args = arg1;
845 }
846 die = ffecom_call_gfrt (FFECOM_gfrtRANGE,
847 args, NULL_TREE);
848 TREE_SIDE_EFFECTS (die) = 1;
849
850 element = ffecom_3 (COND_EXPR,
851 TREE_TYPE (element),
852 cond,
853 element,
854 die);
855
856 return element;
857}
858
859/* Return the computed element of an array reference.
860
ff852b44
CB
861 `item' is NULL_TREE, or the transformed pointer to the array.
862 `expr' is the original opARRAYREF expression, which is transformed
863 if `item' is NULL_TREE.
864 `want_ptr' is non-zero if a pointer to the element, instead of
6b55276e
CB
865 the element itself, is to be returned. */
866
867static tree
868ffecom_arrayref_ (tree item, ffebld expr, int want_ptr)
869{
870 ffebld dims[FFECOM_dimensionsMAX];
871 int i;
872 int total_dims;
ff852b44
CB
873 int flatten = ffe_is_flatten_arrays ();
874 int need_ptr;
6b55276e
CB
875 tree array;
876 tree element;
ff852b44
CB
877 tree tree_type;
878 tree tree_type_x;
3b304f5b 879 const char *array_name;
ff852b44
CB
880 ffetype type;
881 ffebld list;
6b55276e
CB
882
883 if (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER)
884 array_name = ffesymbol_text (ffebld_symter (ffebld_left (expr)));
885 else
886 array_name = "[expr?]";
887
888 /* Build up ARRAY_REFs in reverse order (since we're column major
889 here in Fortran land). */
890
ff852b44
CB
891 for (i = 0, list = ffebld_right (expr);
892 list != NULL;
893 ++i, list = ffebld_trail (list))
894 {
895 dims[i] = ffebld_head (list);
896 type = ffeinfo_type (ffebld_basictype (dims[i]),
897 ffebld_kindtype (dims[i]));
898 if (! flatten
899 && ffecom_typesize_pointer_ > ffecom_typesize_integer1_
900 && ffetype_size (type) > ffecom_typesize_integer1_)
901 /* E.g. ARRAY(INDEX), given INTEGER*8 INDEX, on a system with 64-bit
902 pointers and 32-bit integers. Do the full 64-bit pointer
903 arithmetic, for codes using arrays for nonstandard heap-like
904 work. */
905 flatten = 1;
906 }
6b55276e
CB
907
908 total_dims = i;
909
ff852b44
CB
910 need_ptr = want_ptr || flatten;
911
912 if (! item)
913 {
914 if (need_ptr)
915 item = ffecom_ptr_to_expr (ffebld_left (expr));
916 else
917 item = ffecom_expr (ffebld_left (expr));
918
919 if (item == error_mark_node)
920 return item;
921
922 if (ffeinfo_where (ffebld_info (expr)) == FFEINFO_whereFLEETING
923 && ! mark_addressable (item))
924 return error_mark_node;
925 }
926
927 if (item == error_mark_node)
928 return item;
929
6b55276e
CB
930 if (need_ptr)
931 {
ff852b44
CB
932 tree min;
933
6b55276e
CB
934 for (--i, array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
935 i >= 0;
936 --i, array = TYPE_MAIN_VARIANT (TREE_TYPE (array)))
937 {
ff852b44
CB
938 min = TYPE_MIN_VALUE (TYPE_DOMAIN (array));
939 element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
02f06e64 940 if (flag_bounds_check)
6b55276e
CB
941 element = ffecom_subscript_check_ (array, element, i, total_dims,
942 array_name);
ff852b44
CB
943 if (element == error_mark_node)
944 return element;
945
946 /* Widen integral arithmetic as desired while preserving
947 signedness. */
948 tree_type = TREE_TYPE (element);
949 tree_type_x = tree_type;
950 if (tree_type
951 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
952 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
953 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
954
955 if (TREE_TYPE (min) != tree_type_x)
956 min = convert (tree_type_x, min);
957 if (TREE_TYPE (element) != tree_type_x)
958 element = convert (tree_type_x, element);
959
6b55276e
CB
960 item = ffecom_2 (PLUS_EXPR,
961 build_pointer_type (TREE_TYPE (array)),
962 item,
963 size_binop (MULT_EXPR,
964 size_in_bytes (TREE_TYPE (array)),
fed3cef0
RK
965 convert (sizetype,
966 fold (build (MINUS_EXPR,
967 tree_type_x,
968 element, min)))));
6b55276e
CB
969 }
970 if (! want_ptr)
971 {
972 item = ffecom_1 (INDIRECT_REF,
973 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))),
974 item);
975 }
976 }
977 else
978 {
979 for (--i;
980 i >= 0;
981 --i)
982 {
983 array = TYPE_MAIN_VARIANT (TREE_TYPE (item));
984
985 element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
02f06e64 986 if (flag_bounds_check)
6b55276e
CB
987 element = ffecom_subscript_check_ (array, element, i, total_dims,
988 array_name);
ff852b44
CB
989 if (element == error_mark_node)
990 return element;
991
992 /* Widen integral arithmetic as desired while preserving
993 signedness. */
994 tree_type = TREE_TYPE (element);
995 tree_type_x = tree_type;
996 if (tree_type
997 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
998 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
999 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
1000
1001 element = convert (tree_type_x, element);
1002
6b55276e
CB
1003 item = ffecom_2 (ARRAY_REF,
1004 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))),
1005 item,
1006 element);
1007 }
1008 }
1009
1010 return item;
1011}
1012
5ff904cd
JL
1013/* This is like gcc's stabilize_reference -- in fact, most of the code
1014 comes from that -- but it handles the situation where the reference
1015 is going to have its subparts picked at, and it shouldn't change
1016 (or trigger extra invocations of functions in the subtrees) due to
1017 this. save_expr is a bit overzealous, because we don't need the
1018 entire thing calculated and saved like a temp. So, for DECLs, no
1019 change is needed, because these are stable aggregates, and ARRAY_REF
1020 and such might well be stable too, but for things like calculations,
1021 we do need to calculate a snapshot of a value before picking at it. */
1022
1023#if FFECOM_targetCURRENT == FFECOM_targetGCC
1024static tree
1025ffecom_stabilize_aggregate_ (tree ref)
1026{
1027 tree result;
1028 enum tree_code code = TREE_CODE (ref);
1029
1030 switch (code)
1031 {
1032 case VAR_DECL:
1033 case PARM_DECL:
1034 case RESULT_DECL:
1035 /* No action is needed in this case. */
1036 return ref;
1037
1038 case NOP_EXPR:
1039 case CONVERT_EXPR:
1040 case FLOAT_EXPR:
1041 case FIX_TRUNC_EXPR:
1042 case FIX_FLOOR_EXPR:
1043 case FIX_ROUND_EXPR:
1044 case FIX_CEIL_EXPR:
1045 result = build_nt (code, stabilize_reference (TREE_OPERAND (ref, 0)));
1046 break;
1047
1048 case INDIRECT_REF:
1049 result = build_nt (INDIRECT_REF,
1050 stabilize_reference_1 (TREE_OPERAND (ref, 0)));
1051 break;
1052
1053 case COMPONENT_REF:
1054 result = build_nt (COMPONENT_REF,
1055 stabilize_reference (TREE_OPERAND (ref, 0)),
1056 TREE_OPERAND (ref, 1));
1057 break;
1058
1059 case BIT_FIELD_REF:
1060 result = build_nt (BIT_FIELD_REF,
1061 stabilize_reference (TREE_OPERAND (ref, 0)),
1062 stabilize_reference_1 (TREE_OPERAND (ref, 1)),
1063 stabilize_reference_1 (TREE_OPERAND (ref, 2)));
1064 break;
1065
1066 case ARRAY_REF:
1067 result = build_nt (ARRAY_REF,
1068 stabilize_reference (TREE_OPERAND (ref, 0)),
1069 stabilize_reference_1 (TREE_OPERAND (ref, 1)));
1070 break;
1071
1072 case COMPOUND_EXPR:
1073 result = build_nt (COMPOUND_EXPR,
1074 stabilize_reference_1 (TREE_OPERAND (ref, 0)),
1075 stabilize_reference (TREE_OPERAND (ref, 1)));
1076 break;
1077
1078 case RTL_EXPR:
1079 result = build1 (INDIRECT_REF, TREE_TYPE (ref),
1080 save_expr (build1 (ADDR_EXPR,
1081 build_pointer_type (TREE_TYPE (ref)),
1082 ref)));
1083 break;
1084
1085
1086 default:
1087 return save_expr (ref);
1088
1089 case ERROR_MARK:
1090 return error_mark_node;
1091 }
1092
1093 TREE_TYPE (result) = TREE_TYPE (ref);
1094 TREE_READONLY (result) = TREE_READONLY (ref);
1095 TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (ref);
1096 TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (ref);
5ff904cd
JL
1097
1098 return result;
1099}
1100#endif
1101
1102/* A rip-off of gcc's convert.c convert_to_complex function,
1103 reworked to handle complex implemented as C structures
1104 (RECORD_TYPE with two fields, real and imaginary `r' and `i'). */
1105
1106#if FFECOM_targetCURRENT == FFECOM_targetGCC
1107static tree
1108ffecom_convert_to_complex_ (tree type, tree expr)
1109{
1110 register enum tree_code form = TREE_CODE (TREE_TYPE (expr));
1111 tree subtype;
1112
1113 assert (TREE_CODE (type) == RECORD_TYPE);
1114
1115 subtype = TREE_TYPE (TYPE_FIELDS (type));
1116
1117 if (form == REAL_TYPE || form == INTEGER_TYPE || form == ENUMERAL_TYPE)
1118 {
1119 expr = convert (subtype, expr);
1120 return ffecom_2 (COMPLEX_EXPR, type, expr,
1121 convert (subtype, integer_zero_node));
1122 }
1123
1124 if (form == RECORD_TYPE)
1125 {
1126 tree elt_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr)));
1127 if (TYPE_MAIN_VARIANT (elt_type) == TYPE_MAIN_VARIANT (subtype))
1128 return expr;
1129 else
1130 {
1131 expr = save_expr (expr);
1132 return ffecom_2 (COMPLEX_EXPR,
1133 type,
1134 convert (subtype,
1135 ffecom_1 (REALPART_EXPR,
1136 TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))),
1137 expr)),
1138 convert (subtype,
1139 ffecom_1 (IMAGPART_EXPR,
1140 TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))),
1141 expr)));
1142 }
1143 }
1144
1145 if (form == POINTER_TYPE || form == REFERENCE_TYPE)
1146 error ("pointer value used where a complex was expected");
1147 else
1148 error ("aggregate value used where a complex was expected");
1149
1150 return ffecom_2 (COMPLEX_EXPR, type,
1151 convert (subtype, integer_zero_node),
1152 convert (subtype, integer_zero_node));
1153}
1154#endif
1155
1156/* Like gcc's convert(), but crashes if widening might happen. */
1157
1158#if FFECOM_targetCURRENT == FFECOM_targetGCC
1159static tree
1160ffecom_convert_narrow_ (type, expr)
1161 tree type, expr;
1162{
1163 register tree e = expr;
1164 register enum tree_code code = TREE_CODE (type);
1165
1166 if (type == TREE_TYPE (e)
1167 || TREE_CODE (e) == ERROR_MARK)
1168 return e;
1169 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
1170 return fold (build1 (NOP_EXPR, type, e));
1171 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
1172 || code == ERROR_MARK)
1173 return error_mark_node;
1174 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
1175 {
1176 assert ("void value not ignored as it ought to be" == NULL);
1177 return error_mark_node;
1178 }
1179 assert (code != VOID_TYPE);
1180 if ((code != RECORD_TYPE)
1181 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
1182 assert ("converting COMPLEX to REAL" == NULL);
1183 assert (code != ENUMERAL_TYPE);
1184 if (code == INTEGER_TYPE)
1185 {
a74de6ea
CB
1186 assert ((TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE
1187 && TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)))
1188 || (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
1189 && (TYPE_PRECISION (type)
1190 == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (e))))));
5ff904cd
JL
1191 return fold (convert_to_integer (type, e));
1192 }
1193 if (code == POINTER_TYPE)
1194 {
1195 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
1196 return fold (convert_to_pointer (type, e));
1197 }
1198 if (code == REAL_TYPE)
1199 {
1200 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
1201 assert (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)));
1202 return fold (convert_to_real (type, e));
1203 }
1204 if (code == COMPLEX_TYPE)
1205 {
1206 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
1207 assert (TYPE_PRECISION (TREE_TYPE (type)) <= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
1208 return fold (convert_to_complex (type, e));
1209 }
1210 if (code == RECORD_TYPE)
1211 {
1212 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
270fc4e8
CB
1213 /* Check that at least the first field name agrees. */
1214 assert (DECL_NAME (TYPE_FIELDS (type))
1215 == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e))));
5ff904cd
JL
1216 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1217 <= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
270fc4e8
CB
1218 if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1219 == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))))
1220 return e;
5ff904cd
JL
1221 return fold (ffecom_convert_to_complex_ (type, e));
1222 }
1223
1224 assert ("conversion to non-scalar type requested" == NULL);
1225 return error_mark_node;
1226}
1227#endif
1228
1229/* Like gcc's convert(), but crashes if narrowing might happen. */
1230
1231#if FFECOM_targetCURRENT == FFECOM_targetGCC
1232static tree
1233ffecom_convert_widen_ (type, expr)
1234 tree type, expr;
1235{
1236 register tree e = expr;
1237 register enum tree_code code = TREE_CODE (type);
1238
1239 if (type == TREE_TYPE (e)
1240 || TREE_CODE (e) == ERROR_MARK)
1241 return e;
1242 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
1243 return fold (build1 (NOP_EXPR, type, e));
1244 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
1245 || code == ERROR_MARK)
1246 return error_mark_node;
1247 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
1248 {
1249 assert ("void value not ignored as it ought to be" == NULL);
1250 return error_mark_node;
1251 }
1252 assert (code != VOID_TYPE);
1253 if ((code != RECORD_TYPE)
1254 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
1255 assert ("narrowing COMPLEX to REAL" == NULL);
1256 assert (code != ENUMERAL_TYPE);
1257 if (code == INTEGER_TYPE)
1258 {
a74de6ea
CB
1259 assert ((TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE
1260 && TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)))
1261 || (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
1262 && (TYPE_PRECISION (type)
1263 == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (e))))));
5ff904cd
JL
1264 return fold (convert_to_integer (type, e));
1265 }
1266 if (code == POINTER_TYPE)
1267 {
1268 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
1269 return fold (convert_to_pointer (type, e));
1270 }
1271 if (code == REAL_TYPE)
1272 {
1273 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
1274 assert (TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)));
1275 return fold (convert_to_real (type, e));
1276 }
1277 if (code == COMPLEX_TYPE)
1278 {
1279 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
1280 assert (TYPE_PRECISION (TREE_TYPE (type)) >= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
1281 return fold (convert_to_complex (type, e));
1282 }
1283 if (code == RECORD_TYPE)
1284 {
1285 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
270fc4e8
CB
1286 /* Check that at least the first field name agrees. */
1287 assert (DECL_NAME (TYPE_FIELDS (type))
1288 == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e))));
5ff904cd
JL
1289 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1290 >= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
270fc4e8
CB
1291 if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1292 == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))))
1293 return e;
5ff904cd
JL
1294 return fold (ffecom_convert_to_complex_ (type, e));
1295 }
1296
1297 assert ("conversion to non-scalar type requested" == NULL);
1298 return error_mark_node;
1299}
1300#endif
1301
1302/* Handles making a COMPLEX type, either the standard
1303 (but buggy?) gbe way, or the safer (but less elegant?)
1304 f2c way. */
1305
1306#if FFECOM_targetCURRENT == FFECOM_targetGCC
1307static tree
1308ffecom_make_complex_type_ (tree subtype)
1309{
1310 tree type;
1311 tree realfield;
1312 tree imagfield;
1313
1314 if (ffe_is_emulate_complex ())
1315 {
1316 type = make_node (RECORD_TYPE);
1317 realfield = ffecom_decl_field (type, NULL_TREE, "r", subtype);
1318 imagfield = ffecom_decl_field (type, realfield, "i", subtype);
1319 TYPE_FIELDS (type) = realfield;
1320 layout_type (type);
1321 }
1322 else
1323 {
1324 type = make_node (COMPLEX_TYPE);
1325 TREE_TYPE (type) = subtype;
1326 layout_type (type);
1327 }
1328
1329 return type;
1330}
1331#endif
1332
1333/* Chooses either the gbe or the f2c way to build a
1334 complex constant. */
1335
1336#if FFECOM_targetCURRENT == FFECOM_targetGCC
1337static tree
1338ffecom_build_complex_constant_ (tree type, tree realpart, tree imagpart)
1339{
1340 tree bothparts;
1341
1342 if (ffe_is_emulate_complex ())
1343 {
1344 bothparts = build_tree_list (TYPE_FIELDS (type), realpart);
1345 TREE_CHAIN (bothparts) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), imagpart);
1346 bothparts = build (CONSTRUCTOR, type, NULL_TREE, bothparts);
1347 }
1348 else
1349 {
1350 bothparts = build_complex (type, realpart, imagpart);
1351 }
1352
1353 return bothparts;
1354}
1355#endif
1356
1357#if FFECOM_targetCURRENT == FFECOM_targetGCC
1358static tree
26f096f9 1359ffecom_arglist_expr_ (const char *c, ffebld expr)
5ff904cd
JL
1360{
1361 tree list;
1362 tree *plist = &list;
1363 tree trail = NULL_TREE; /* Append char length args here. */
1364 tree *ptrail = &trail;
1365 tree length;
1366 ffebld exprh;
1367 tree item;
1368 bool ptr = FALSE;
1369 tree wanted = NULL_TREE;
e2fa159e
JL
1370 static char zed[] = "0";
1371
1372 if (c == NULL)
1373 c = &zed[0];
5ff904cd
JL
1374
1375 while (expr != NULL)
1376 {
1377 if (*c != '\0')
1378 {
1379 ptr = FALSE;
1380 if (*c == '&')
1381 {
1382 ptr = TRUE;
1383 ++c;
1384 }
1385 switch (*(c++))
1386 {
1387 case '\0':
1388 ptr = TRUE;
1389 wanted = NULL_TREE;
1390 break;
1391
1392 case 'a':
1393 assert (ptr);
1394 wanted = NULL_TREE;
1395 break;
1396
1397 case 'c':
1398 wanted = ffecom_f2c_complex_type_node;
1399 break;
1400
1401 case 'd':
1402 wanted = ffecom_f2c_doublereal_type_node;
1403 break;
1404
1405 case 'e':
1406 wanted = ffecom_f2c_doublecomplex_type_node;
1407 break;
1408
1409 case 'f':
1410 wanted = ffecom_f2c_real_type_node;
1411 break;
1412
1413 case 'i':
1414 wanted = ffecom_f2c_integer_type_node;
1415 break;
1416
1417 case 'j':
1418 wanted = ffecom_f2c_longint_type_node;
1419 break;
1420
1421 default:
1422 assert ("bad argstring code" == NULL);
1423 wanted = NULL_TREE;
1424 break;
1425 }
1426 }
1427
1428 exprh = ffebld_head (expr);
1429 if (exprh == NULL)
1430 wanted = NULL_TREE;
1431
1432 if ((wanted == NULL_TREE)
1433 || (ptr
1434 && (TYPE_MODE
1435 (ffecom_tree_type[ffeinfo_basictype (ffebld_info (exprh))]
1436 [ffeinfo_kindtype (ffebld_info (exprh))])
1437 == TYPE_MODE (wanted))))
1438 *plist
1439 = build_tree_list (NULL_TREE,
1440 ffecom_arg_ptr_to_expr (exprh,
1441 &length));
1442 else
1443 {
1444 item = ffecom_arg_expr (exprh, &length);
1445 item = ffecom_convert_widen_ (wanted, item);
1446 if (ptr)
1447 {
1448 item = ffecom_1 (ADDR_EXPR,
1449 build_pointer_type (TREE_TYPE (item)),
1450 item);
1451 }
1452 *plist
1453 = build_tree_list (NULL_TREE,
1454 item);
1455 }
1456
1457 plist = &TREE_CHAIN (*plist);
1458 expr = ffebld_trail (expr);
1459 if (length != NULL_TREE)
1460 {
1461 *ptrail = build_tree_list (NULL_TREE, length);
1462 ptrail = &TREE_CHAIN (*ptrail);
1463 }
1464 }
1465
e2fa159e
JL
1466 /* We've run out of args in the call; if the implementation expects
1467 more, supply null pointers for them, which the implementation can
1468 check to see if an arg was omitted. */
1469
1470 while (*c != '\0' && *c != '0')
1471 {
1472 if (*c == '&')
1473 ++c;
1474 else
1475 assert ("missing arg to run-time routine!" == NULL);
1476
1477 switch (*(c++))
1478 {
1479 case '\0':
1480 case 'a':
1481 case 'c':
1482 case 'd':
1483 case 'e':
1484 case 'f':
1485 case 'i':
1486 case 'j':
1487 break;
1488
1489 default:
1490 assert ("bad arg string code" == NULL);
1491 break;
1492 }
1493 *plist
1494 = build_tree_list (NULL_TREE,
1495 null_pointer_node);
1496 plist = &TREE_CHAIN (*plist);
1497 }
1498
5ff904cd
JL
1499 *plist = trail;
1500
1501 return list;
1502}
1503#endif
1504
1505#if FFECOM_targetCURRENT == FFECOM_targetGCC
1506static tree
1507ffecom_widest_expr_type_ (ffebld list)
1508{
1509 ffebld item;
1510 ffebld widest = NULL;
1511 ffetype type;
1512 ffetype widest_type = NULL;
1513 tree t;
1514
1515 for (; list != NULL; list = ffebld_trail (list))
1516 {
1517 item = ffebld_head (list);
1518 if (item == NULL)
1519 continue;
1520 if ((widest != NULL)
1521 && (ffeinfo_basictype (ffebld_info (item))
1522 != ffeinfo_basictype (ffebld_info (widest))))
1523 continue;
1524 type = ffeinfo_type (ffeinfo_basictype (ffebld_info (item)),
1525 ffeinfo_kindtype (ffebld_info (item)));
1526 if ((widest == FFEINFO_kindtypeNONE)
1527 || (ffetype_size (type)
1528 > ffetype_size (widest_type)))
1529 {
1530 widest = item;
1531 widest_type = type;
1532 }
1533 }
1534
1535 assert (widest != NULL);
1536 t = ffecom_tree_type[ffeinfo_basictype (ffebld_info (widest))]
1537 [ffeinfo_kindtype (ffebld_info (widest))];
1538 assert (t != NULL_TREE);
1539 return t;
1540}
1541#endif
1542
d6cd84e0
CB
1543/* Check whether a partial overlap between two expressions is possible.
1544
1545 Can *starting* to write a portion of expr1 change the value
1546 computed (perhaps already, *partially*) by expr2?
1547
1548 Currently, this is a concern only for a COMPLEX expr1. But if it
1549 isn't in COMMON or local EQUIVALENCE, since we don't support
1550 aliasing of arguments, it isn't a concern. */
1551
1552static bool
b0791fa9 1553ffecom_possible_partial_overlap_ (ffebld expr1, ffebld expr2 ATTRIBUTE_UNUSED)
d6cd84e0
CB
1554{
1555 ffesymbol sym;
1556 ffestorag st;
1557
1558 switch (ffebld_op (expr1))
1559 {
1560 case FFEBLD_opSYMTER:
1561 sym = ffebld_symter (expr1);
1562 break;
1563
1564 case FFEBLD_opARRAYREF:
1565 if (ffebld_op (ffebld_left (expr1)) != FFEBLD_opSYMTER)
1566 return FALSE;
1567 sym = ffebld_symter (ffebld_left (expr1));
1568 break;
1569
1570 default:
1571 return FALSE;
1572 }
1573
1574 if (ffesymbol_where (sym) != FFEINFO_whereCOMMON
1575 && (ffesymbol_where (sym) != FFEINFO_whereLOCAL
1576 || ! (st = ffesymbol_storage (sym))
1577 || ! ffestorag_parent (st)))
1578 return FALSE;
1579
1580 /* It's in COMMON or local EQUIVALENCE. */
1581
1582 return TRUE;
1583}
1584
5ff904cd
JL
1585/* Check whether dest and source might overlap. ffebld versions of these
1586 might or might not be passed, will be NULL if not.
1587
1588 The test is really whether source_tree is modifiable and, if modified,
1589 might overlap destination such that the value(s) in the destination might
1590 change before it is finally modified. dest_* are the canonized
1591 destination itself. */
1592
1593#if FFECOM_targetCURRENT == FFECOM_targetGCC
1594static bool
1595ffecom_overlap_ (tree dest_decl, tree dest_offset, tree dest_size,
1596 tree source_tree, ffebld source UNUSED,
1597 bool scalar_arg)
1598{
1599 tree source_decl;
1600 tree source_offset;
1601 tree source_size;
1602 tree t;
1603
1604 if (source_tree == NULL_TREE)
1605 return FALSE;
1606
1607 switch (TREE_CODE (source_tree))
1608 {
1609 case ERROR_MARK:
1610 case IDENTIFIER_NODE:
1611 case INTEGER_CST:
1612 case REAL_CST:
1613 case COMPLEX_CST:
1614 case STRING_CST:
1615 case CONST_DECL:
1616 case VAR_DECL:
1617 case RESULT_DECL:
1618 case FIELD_DECL:
1619 case MINUS_EXPR:
1620 case MULT_EXPR:
1621 case TRUNC_DIV_EXPR:
1622 case CEIL_DIV_EXPR:
1623 case FLOOR_DIV_EXPR:
1624 case ROUND_DIV_EXPR:
1625 case TRUNC_MOD_EXPR:
1626 case CEIL_MOD_EXPR:
1627 case FLOOR_MOD_EXPR:
1628 case ROUND_MOD_EXPR:
1629 case RDIV_EXPR:
1630 case EXACT_DIV_EXPR:
1631 case FIX_TRUNC_EXPR:
1632 case FIX_CEIL_EXPR:
1633 case FIX_FLOOR_EXPR:
1634 case FIX_ROUND_EXPR:
1635 case FLOAT_EXPR:
1636 case EXPON_EXPR:
1637 case NEGATE_EXPR:
1638 case MIN_EXPR:
1639 case MAX_EXPR:
1640 case ABS_EXPR:
1641 case FFS_EXPR:
1642 case LSHIFT_EXPR:
1643 case RSHIFT_EXPR:
1644 case LROTATE_EXPR:
1645 case RROTATE_EXPR:
1646 case BIT_IOR_EXPR:
1647 case BIT_XOR_EXPR:
1648 case BIT_AND_EXPR:
1649 case BIT_ANDTC_EXPR:
1650 case BIT_NOT_EXPR:
1651 case TRUTH_ANDIF_EXPR:
1652 case TRUTH_ORIF_EXPR:
1653 case TRUTH_AND_EXPR:
1654 case TRUTH_OR_EXPR:
1655 case TRUTH_XOR_EXPR:
1656 case TRUTH_NOT_EXPR:
1657 case LT_EXPR:
1658 case LE_EXPR:
1659 case GT_EXPR:
1660 case GE_EXPR:
1661 case EQ_EXPR:
1662 case NE_EXPR:
1663 case COMPLEX_EXPR:
1664 case CONJ_EXPR:
1665 case REALPART_EXPR:
1666 case IMAGPART_EXPR:
1667 case LABEL_EXPR:
1668 case COMPONENT_REF:
1669 return FALSE;
1670
1671 case COMPOUND_EXPR:
1672 return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1673 TREE_OPERAND (source_tree, 1), NULL,
1674 scalar_arg);
1675
1676 case MODIFY_EXPR:
1677 return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1678 TREE_OPERAND (source_tree, 0), NULL,
1679 scalar_arg);
1680
1681 case CONVERT_EXPR:
1682 case NOP_EXPR:
1683 case NON_LVALUE_EXPR:
1684 case PLUS_EXPR:
1685 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1686 return TRUE;
1687
1688 ffecom_tree_canonize_ptr_ (&source_decl, &source_offset,
1689 source_tree);
1690 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1691 break;
1692
1693 case COND_EXPR:
1694 return
1695 ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1696 TREE_OPERAND (source_tree, 1), NULL,
1697 scalar_arg)
1698 || ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1699 TREE_OPERAND (source_tree, 2), NULL,
1700 scalar_arg);
1701
1702
1703 case ADDR_EXPR:
1704 ffecom_tree_canonize_ref_ (&source_decl, &source_offset,
1705 &source_size,
1706 TREE_OPERAND (source_tree, 0));
1707 break;
1708
1709 case PARM_DECL:
1710 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1711 return TRUE;
1712
1713 source_decl = source_tree;
76fa6b3b 1714 source_offset = bitsize_zero_node;
5ff904cd
JL
1715 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1716 break;
1717
1718 case SAVE_EXPR:
1719 case REFERENCE_EXPR:
1720 case PREDECREMENT_EXPR:
1721 case PREINCREMENT_EXPR:
1722 case POSTDECREMENT_EXPR:
1723 case POSTINCREMENT_EXPR:
1724 case INDIRECT_REF:
1725 case ARRAY_REF:
1726 case CALL_EXPR:
1727 default:
1728 return TRUE;
1729 }
1730
1731 /* Come here when source_decl, source_offset, and source_size filled
1732 in appropriately. */
1733
1734 if (source_decl == NULL_TREE)
1735 return FALSE; /* No decl involved, so no overlap. */
1736
1737 if (source_decl != dest_decl)
1738 return FALSE; /* Different decl, no overlap. */
1739
1740 if (TREE_CODE (dest_size) == ERROR_MARK)
1741 return TRUE; /* Assignment into entire assumed-size
1742 array? Shouldn't happen.... */
1743
1744 t = ffecom_2 (LE_EXPR, integer_type_node,
1745 ffecom_2 (PLUS_EXPR, TREE_TYPE (dest_offset),
1746 dest_offset,
1747 convert (TREE_TYPE (dest_offset),
1748 dest_size)),
1749 convert (TREE_TYPE (dest_offset),
1750 source_offset));
1751
1752 if (integer_onep (t))
1753 return FALSE; /* Destination precedes source. */
1754
1755 if (!scalar_arg
1756 || (source_size == NULL_TREE)
1757 || (TREE_CODE (source_size) == ERROR_MARK)
1758 || integer_zerop (source_size))
1759 return TRUE; /* No way to tell if dest follows source. */
1760
1761 t = ffecom_2 (LE_EXPR, integer_type_node,
1762 ffecom_2 (PLUS_EXPR, TREE_TYPE (source_offset),
1763 source_offset,
1764 convert (TREE_TYPE (source_offset),
1765 source_size)),
1766 convert (TREE_TYPE (source_offset),
1767 dest_offset));
1768
1769 if (integer_onep (t))
1770 return FALSE; /* Destination follows source. */
1771
1772 return TRUE; /* Destination and source overlap. */
1773}
1774#endif
1775
1776/* Check whether dest might overlap any of a list of arguments or is
1777 in a COMMON area the callee might know about (and thus modify). */
1778
1779#if FFECOM_targetCURRENT == FFECOM_targetGCC
1780static bool
1781ffecom_args_overlapping_ (tree dest_tree, ffebld dest UNUSED,
1782 tree args, tree callee_commons,
1783 bool scalar_args)
1784{
1785 tree arg;
1786 tree dest_decl;
1787 tree dest_offset;
1788 tree dest_size;
1789
1790 ffecom_tree_canonize_ref_ (&dest_decl, &dest_offset, &dest_size,
1791 dest_tree);
1792
1793 if (dest_decl == NULL_TREE)
1794 return FALSE; /* Seems unlikely! */
1795
1796 /* If the decl cannot be determined reliably, or if its in COMMON
1797 and the callee isn't known to not futz with COMMON via other
1798 means, overlap might happen. */
1799
1800 if ((TREE_CODE (dest_decl) == ERROR_MARK)
1801 || ((callee_commons != NULL_TREE)
1802 && TREE_PUBLIC (dest_decl)))
1803 return TRUE;
1804
1805 for (; args != NULL_TREE; args = TREE_CHAIN (args))
1806 {
1807 if (((arg = TREE_VALUE (args)) != NULL_TREE)
1808 && ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1809 arg, NULL, scalar_args))
1810 return TRUE;
1811 }
1812
1813 return FALSE;
1814}
1815#endif
1816
1817/* Build a string for a variable name as used by NAMELIST. This means that
1818 if we're using the f2c library, we build an uppercase string, since
1819 f2c does this. */
1820
1821#if FFECOM_targetCURRENT == FFECOM_targetGCC
1822static tree
26f096f9 1823ffecom_build_f2c_string_ (int i, const char *s)
5ff904cd
JL
1824{
1825 if (!ffe_is_f2c_library ())
1826 return build_string (i, s);
1827
1828 {
1829 char *tmp;
26f096f9 1830 const char *p;
5ff904cd
JL
1831 char *q;
1832 char space[34];
1833 tree t;
1834
1835 if (((size_t) i) > ARRAY_SIZE (space))
1836 tmp = malloc_new_ks (malloc_pool_image (), "f2c_string", i);
1837 else
1838 tmp = &space[0];
1839
1840 for (p = s, q = tmp; *p != '\0'; ++p, ++q)
1841 *q = ffesrc_toupper (*p);
1842 *q = '\0';
1843
1844 t = build_string (i, tmp);
1845
1846 if (((size_t) i) > ARRAY_SIZE (space))
1847 malloc_kill_ks (malloc_pool_image (), tmp, i);
1848
1849 return t;
1850 }
1851}
1852
1853#endif
1854/* Returns CALL_EXPR or equivalent with given type (pass NULL_TREE for
1855 type to just get whatever the function returns), handling the
1856 f2c value-returning convention, if required, by prepending
1857 to the arglist a pointer to a temporary to receive the return value. */
1858
1859#if FFECOM_targetCURRENT == FFECOM_targetGCC
1860static tree
1861ffecom_call_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1862 tree type, tree args, tree dest_tree,
1863 ffebld dest, bool *dest_used, tree callee_commons,
c7e4ee3a 1864 bool scalar_args, tree hook)
5ff904cd
JL
1865{
1866 tree item;
1867 tree tempvar;
1868
1869 if (dest_used != NULL)
1870 *dest_used = FALSE;
1871
1872 if (is_f2c_complex)
1873 {
1874 if ((dest_used == NULL)
1875 || (dest == NULL)
1876 || (ffeinfo_basictype (ffebld_info (dest))
1877 != FFEINFO_basictypeCOMPLEX)
1878 || (ffeinfo_kindtype (ffebld_info (dest)) != kt)
1879 || ((type != NULL_TREE) && (TREE_TYPE (dest_tree) != type))
1880 || ffecom_args_overlapping_ (dest_tree, dest, args,
1881 callee_commons,
1882 scalar_args))
1883 {
c7e4ee3a
CB
1884#ifdef HOHO
1885 tempvar = ffecom_make_tempvar (ffecom_tree_type
5ff904cd
JL
1886 [FFEINFO_basictypeCOMPLEX][kt],
1887 FFETARGET_charactersizeNONE,
c7e4ee3a
CB
1888 -1);
1889#else
1890 tempvar = hook;
1891 assert (tempvar);
1892#endif
5ff904cd
JL
1893 }
1894 else
1895 {
1896 *dest_used = TRUE;
1897 tempvar = dest_tree;
1898 type = NULL_TREE;
1899 }
1900
1901 item
1902 = build_tree_list (NULL_TREE,
1903 ffecom_1 (ADDR_EXPR,
c7e4ee3a 1904 build_pointer_type (TREE_TYPE (tempvar)),
5ff904cd
JL
1905 tempvar));
1906 TREE_CHAIN (item) = args;
1907
1908 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1909 item, NULL_TREE);
1910
1911 if (tempvar != dest_tree)
1912 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item, tempvar);
1913 }
1914 else
1915 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1916 args, NULL_TREE);
1917
1918 if ((type != NULL_TREE) && (TREE_TYPE (item) != type))
1919 item = ffecom_convert_narrow_ (type, item);
1920
1921 return item;
1922}
1923#endif
1924
1925/* Given two arguments, transform them and make a call to the given
1926 function via ffecom_call_. */
1927
1928#if FFECOM_targetCURRENT == FFECOM_targetGCC
1929static tree
1930ffecom_call_binop_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1931 tree type, ffebld left, ffebld right,
1932 tree dest_tree, ffebld dest, bool *dest_used,
c7e4ee3a 1933 tree callee_commons, bool scalar_args, tree hook)
5ff904cd
JL
1934{
1935 tree left_tree;
1936 tree right_tree;
1937 tree left_length;
1938 tree right_length;
1939
5ff904cd
JL
1940 left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
1941 right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
5ff904cd
JL
1942
1943 left_tree = build_tree_list (NULL_TREE, left_tree);
1944 right_tree = build_tree_list (NULL_TREE, right_tree);
1945 TREE_CHAIN (left_tree) = right_tree;
1946
1947 if (left_length != NULL_TREE)
1948 {
1949 left_length = build_tree_list (NULL_TREE, left_length);
1950 TREE_CHAIN (right_tree) = left_length;
1951 }
1952
1953 if (right_length != NULL_TREE)
1954 {
1955 right_length = build_tree_list (NULL_TREE, right_length);
1956 if (left_length != NULL_TREE)
1957 TREE_CHAIN (left_length) = right_length;
1958 else
1959 TREE_CHAIN (right_tree) = right_length;
1960 }
1961
1962 return ffecom_call_ (fn, kt, is_f2c_complex, type, left_tree,
1963 dest_tree, dest, dest_used, callee_commons,
c7e4ee3a 1964 scalar_args, hook);
5ff904cd
JL
1965}
1966#endif
1967
c7e4ee3a 1968/* Return ptr/length args for char subexpression
5ff904cd
JL
1969
1970 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
1971 subexpressions by constructing the appropriate trees for the ptr-to-
1972 character-text and length-of-character-text arguments in a calling
86fc7a6c
CB
1973 sequence.
1974
1975 Note that if with_null is TRUE, and the expression is an opCONTER,
1976 a null byte is appended to the string. */
5ff904cd
JL
1977
1978#if FFECOM_targetCURRENT == FFECOM_targetGCC
1979static void
86fc7a6c 1980ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
5ff904cd
JL
1981{
1982 tree item;
1983 tree high;
1984 ffetargetCharacter1 val;
86fc7a6c 1985 ffetargetCharacterSize newlen;
5ff904cd
JL
1986
1987 switch (ffebld_op (expr))
1988 {
1989 case FFEBLD_opCONTER:
1990 val = ffebld_constant_character1 (ffebld_conter (expr));
86fc7a6c
CB
1991 newlen = ffetarget_length_character1 (val);
1992 if (with_null)
1993 {
c7e4ee3a 1994 /* Begin FFETARGET-NULL-KLUDGE. */
86fc7a6c 1995 if (newlen != 0)
c7e4ee3a 1996 ++newlen;
86fc7a6c
CB
1997 }
1998 *length = build_int_2 (newlen, 0);
5ff904cd 1999 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
86fc7a6c 2000 high = build_int_2 (newlen, 0);
5ff904cd 2001 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
c7e4ee3a 2002 item = build_string (newlen,
5ff904cd 2003 ffetarget_text_character1 (val));
c7e4ee3a 2004 /* End FFETARGET-NULL-KLUDGE. */
5ff904cd
JL
2005 TREE_TYPE (item)
2006 = build_type_variant
2007 (build_array_type
2008 (char_type_node,
2009 build_range_type
2010 (ffecom_f2c_ftnlen_type_node,
2011 ffecom_f2c_ftnlen_one_node,
2012 high)),
2013 1, 0);
2014 TREE_CONSTANT (item) = 1;
2015 TREE_STATIC (item) = 1;
2016 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
2017 item);
2018 break;
2019
2020 case FFEBLD_opSYMTER:
2021 {
2022 ffesymbol s = ffebld_symter (expr);
2023
2024 item = ffesymbol_hook (s).decl_tree;
2025 if (item == NULL_TREE)
2026 {
2027 s = ffecom_sym_transform_ (s);
2028 item = ffesymbol_hook (s).decl_tree;
2029 }
2030 if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
2031 {
2032 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
2033 *length = ffesymbol_hook (s).length_tree;
2034 else
2035 {
2036 *length = build_int_2 (ffesymbol_size (s), 0);
2037 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2038 }
2039 }
2040 else if (item == error_mark_node)
2041 *length = error_mark_node;
c7e4ee3a
CB
2042 else
2043 /* FFEINFO_kindFUNCTION. */
5ff904cd
JL
2044 *length = NULL_TREE;
2045 if (!ffesymbol_hook (s).addr
2046 && (item != error_mark_node))
2047 item = ffecom_1 (ADDR_EXPR,
2048 build_pointer_type (TREE_TYPE (item)),
2049 item);
2050 }
2051 break;
2052
2053 case FFEBLD_opARRAYREF:
2054 {
5ff904cd 2055 ffecom_char_args_ (&item, length, ffebld_left (expr));
5ff904cd
JL
2056
2057 if (item == error_mark_node || *length == error_mark_node)
2058 {
2059 item = *length = error_mark_node;
2060 break;
2061 }
2062
6b55276e 2063 item = ffecom_arrayref_ (item, expr, 1);
5ff904cd
JL
2064 }
2065 break;
2066
2067 case FFEBLD_opSUBSTR:
2068 {
2069 ffebld start;
2070 ffebld end;
2071 ffebld thing = ffebld_right (expr);
2072 tree start_tree;
2073 tree end_tree;
3b304f5b 2074 const char *char_name;
6b55276e
CB
2075 ffebld left_symter;
2076 tree array;
5ff904cd
JL
2077
2078 assert (ffebld_op (thing) == FFEBLD_opITEM);
2079 start = ffebld_head (thing);
2080 thing = ffebld_trail (thing);
2081 assert (ffebld_trail (thing) == NULL);
2082 end = ffebld_head (thing);
2083
6b55276e
CB
2084 /* Determine name for pretty-printing range-check errors. */
2085 for (left_symter = ffebld_left (expr);
2086 left_symter && ffebld_op (left_symter) == FFEBLD_opARRAYREF;
2087 left_symter = ffebld_left (left_symter))
2088 ;
2089 if (ffebld_op (left_symter) == FFEBLD_opSYMTER)
2090 char_name = ffesymbol_text (ffebld_symter (left_symter));
2091 else
2092 char_name = "[expr?]";
2093
5ff904cd 2094 ffecom_char_args_ (&item, length, ffebld_left (expr));
5ff904cd
JL
2095
2096 if (item == error_mark_node || *length == error_mark_node)
2097 {
2098 item = *length = error_mark_node;
2099 break;
2100 }
2101
6b55276e
CB
2102 array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
2103
ff852b44
CB
2104 /* ~~~~Handle INTEGER*8 start/end, a la FFEBLD_opARRAYREF. */
2105
5ff904cd
JL
2106 if (start == NULL)
2107 {
2108 if (end == NULL)
2109 ;
2110 else
2111 {
6b55276e 2112 end_tree = ffecom_expr (end);
02f06e64 2113 if (flag_bounds_check)
6b55276e
CB
2114 end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
2115 char_name);
5ff904cd 2116 end_tree = convert (ffecom_f2c_ftnlen_type_node,
6b55276e 2117 end_tree);
5ff904cd
JL
2118
2119 if (end_tree == error_mark_node)
2120 {
2121 item = *length = error_mark_node;
2122 break;
2123 }
2124
2125 *length = end_tree;
2126 }
2127 }
2128 else
2129 {
6b55276e 2130 start_tree = ffecom_expr (start);
02f06e64 2131 if (flag_bounds_check)
6b55276e
CB
2132 start_tree = ffecom_subscript_check_ (array, start_tree, 0, 0,
2133 char_name);
5ff904cd 2134 start_tree = convert (ffecom_f2c_ftnlen_type_node,
6b55276e 2135 start_tree);
5ff904cd
JL
2136
2137 if (start_tree == error_mark_node)
2138 {
2139 item = *length = error_mark_node;
2140 break;
2141 }
2142
2143 start_tree = ffecom_save_tree (start_tree);
2144
2145 item = ffecom_2 (PLUS_EXPR, TREE_TYPE (item),
2146 item,
2147 ffecom_2 (MINUS_EXPR,
2148 TREE_TYPE (start_tree),
2149 start_tree,
2150 ffecom_f2c_ftnlen_one_node));
2151
2152 if (end == NULL)
2153 {
2154 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
2155 ffecom_f2c_ftnlen_one_node,
2156 ffecom_2 (MINUS_EXPR,
2157 ffecom_f2c_ftnlen_type_node,
2158 *length,
2159 start_tree));
2160 }
2161 else
2162 {
6b55276e 2163 end_tree = ffecom_expr (end);
02f06e64 2164 if (flag_bounds_check)
6b55276e
CB
2165 end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
2166 char_name);
5ff904cd 2167 end_tree = convert (ffecom_f2c_ftnlen_type_node,
6b55276e 2168 end_tree);
5ff904cd
JL
2169
2170 if (end_tree == error_mark_node)
2171 {
2172 item = *length = error_mark_node;
2173 break;
2174 }
2175
2176 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
2177 ffecom_f2c_ftnlen_one_node,
2178 ffecom_2 (MINUS_EXPR,
2179 ffecom_f2c_ftnlen_type_node,
2180 end_tree, start_tree));
2181 }
2182 }
2183 }
2184 break;
2185
2186 case FFEBLD_opFUNCREF:
2187 {
2188 ffesymbol s = ffebld_symter (ffebld_left (expr));
2189 tree tempvar;
2190 tree args;
2191 ffetargetCharacterSize size = ffeinfo_size (ffebld_info (expr));
2192 ffecomGfrt ix;
2193
2194 if (size == FFETARGET_charactersizeNONE)
c7e4ee3a
CB
2195 /* ~~Kludge alert! This should someday be fixed. */
2196 size = 24;
5ff904cd
JL
2197
2198 *length = build_int_2 (size, 0);
2199 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2200
2201 if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
2202 == FFEINFO_whereINTRINSIC)
2203 {
2204 if (size == 1)
c7e4ee3a
CB
2205 {
2206 /* Invocation of an intrinsic returning CHARACTER*1. */
5ff904cd
JL
2207 item = ffecom_expr_intrinsic_ (expr, NULL_TREE,
2208 NULL, NULL);
2209 break;
2210 }
2211 ix = ffeintrin_gfrt_direct (ffebld_symter_implementation (ffebld_left (expr)));
2212 assert (ix != FFECOM_gfrt);
2213 item = ffecom_gfrt_tree_ (ix);
2214 }
2215 else
2216 {
2217 ix = FFECOM_gfrt;
2218 item = ffesymbol_hook (s).decl_tree;
2219 if (item == NULL_TREE)
2220 {
2221 s = ffecom_sym_transform_ (s);
2222 item = ffesymbol_hook (s).decl_tree;
2223 }
2224 if (item == error_mark_node)
2225 {
2226 item = *length = error_mark_node;
2227 break;
2228 }
2229
2230 if (!ffesymbol_hook (s).addr)
2231 item = ffecom_1_fn (item);
2232 }
2233
c7e4ee3a 2234#ifdef HOHO
5ff904cd 2235 tempvar = ffecom_push_tempvar (char_type_node, size, -1, TRUE);
c7e4ee3a
CB
2236#else
2237 tempvar = ffebld_nonter_hook (expr);
2238 assert (tempvar);
2239#endif
5ff904cd
JL
2240 tempvar = ffecom_1 (ADDR_EXPR,
2241 build_pointer_type (TREE_TYPE (tempvar)),
2242 tempvar);
2243
5ff904cd
JL
2244 args = build_tree_list (NULL_TREE, tempvar);
2245
2246 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT) /* Sfunc args by value. */
2247 TREE_CHAIN (args) = ffecom_list_expr (ffebld_right (expr));
2248 else
2249 {
2250 TREE_CHAIN (args) = build_tree_list (NULL_TREE, *length);
2251 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
2252 {
2253 TREE_CHAIN (TREE_CHAIN (args))
2254 = ffecom_arglist_expr_ (ffecom_gfrt_args_ (ix),
2255 ffebld_right (expr));
2256 }
2257 else
2258 {
2259 TREE_CHAIN (TREE_CHAIN (args))
2260 = ffecom_list_ptr_to_expr (ffebld_right (expr));
2261 }
2262 }
2263
2264 item = ffecom_3s (CALL_EXPR,
2265 TREE_TYPE (TREE_TYPE (TREE_TYPE (item))),
2266 item, args, NULL_TREE);
2267 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item,
2268 tempvar);
5ff904cd
JL
2269 }
2270 break;
2271
2272 case FFEBLD_opCONVERT:
2273
5ff904cd 2274 ffecom_char_args_ (&item, length, ffebld_left (expr));
5ff904cd
JL
2275
2276 if (item == error_mark_node || *length == error_mark_node)
2277 {
2278 item = *length = error_mark_node;
2279 break;
2280 }
2281
2282 if ((ffebld_size_known (ffebld_left (expr))
2283 == FFETARGET_charactersizeNONE)
2284 || (ffebld_size_known (ffebld_left (expr)) < (ffebld_size (expr))))
2285 { /* Possible blank-padding needed, copy into
2286 temporary. */
2287 tree tempvar;
2288 tree args;
2289 tree newlen;
2290
c7e4ee3a
CB
2291#ifdef HOHO
2292 tempvar = ffecom_make_tempvar (char_type_node,
2293 ffebld_size (expr), -1);
2294#else
2295 tempvar = ffebld_nonter_hook (expr);
2296 assert (tempvar);
2297#endif
5ff904cd
JL
2298 tempvar = ffecom_1 (ADDR_EXPR,
2299 build_pointer_type (TREE_TYPE (tempvar)),
2300 tempvar);
2301
2302 newlen = build_int_2 (ffebld_size (expr), 0);
2303 TREE_TYPE (newlen) = ffecom_f2c_ftnlen_type_node;
2304
2305 args = build_tree_list (NULL_TREE, tempvar);
2306 TREE_CHAIN (args) = build_tree_list (NULL_TREE, item);
2307 TREE_CHAIN (TREE_CHAIN (args)) = build_tree_list (NULL_TREE, newlen);
2308 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (args)))
2309 = build_tree_list (NULL_TREE, *length);
2310
c7e4ee3a 2311 item = ffecom_call_gfrt (FFECOM_gfrtCOPY, args, NULL_TREE);
5ff904cd
JL
2312 TREE_SIDE_EFFECTS (item) = 1;
2313 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), fold (item),
2314 tempvar);
2315 *length = newlen;
2316 }
2317 else
2318 { /* Just truncate the length. */
2319 *length = build_int_2 (ffebld_size (expr), 0);
2320 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2321 }
2322 break;
2323
2324 default:
2325 assert ("bad op for single char arg expr" == NULL);
2326 item = NULL_TREE;
2327 break;
2328 }
2329
2330 *xitem = item;
2331}
2332#endif
2333
2334/* Check the size of the type to be sure it doesn't overflow the
2335 "portable" capacities of the compiler back end. `dummy' types
2336 can generally overflow the normal sizes as long as the computations
2337 themselves don't overflow. A particular target of the back end
2338 must still enforce its size requirements, though, and the back
2339 end takes care of this in stor-layout.c. */
2340
2341#if FFECOM_targetCURRENT == FFECOM_targetGCC
2342static tree
2343ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy)
2344{
2345 if (TREE_CODE (type) == ERROR_MARK)
2346 return type;
2347
2348 if (TYPE_SIZE (type) == NULL_TREE)
2349 return type;
2350
2351 if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
2352 return type;
2353
2354 if ((tree_int_cst_sgn (TYPE_SIZE (type)) < 0)
2b0c2df0
CB
2355 || (!dummy && (((TREE_INT_CST_HIGH (TYPE_SIZE (type)) != 0))
2356 || TREE_OVERFLOW (TYPE_SIZE (type)))))
5ff904cd
JL
2357 {
2358 ffebad_start (FFEBAD_ARRAY_LARGE);
2359 ffebad_string (ffesymbol_text (s));
2360 ffebad_here (0, ffesymbol_where_line (s), ffesymbol_where_column (s));
2361 ffebad_finish ();
2362
2363 return error_mark_node;
2364 }
2365
2366 return type;
2367}
2368#endif
2369
2370/* Builds a length argument (PARM_DECL). Also wraps type in an array type
2371 where the dimension info is (1:size) where <size> is ffesymbol_size(s) if
2372 known, length_arg if not known (FFETARGET_charactersizeNONE). */
2373
2374#if FFECOM_targetCURRENT == FFECOM_targetGCC
2375static tree
2376ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s)
2377{
2378 ffetargetCharacterSize sz = ffesymbol_size (s);
2379 tree highval;
2380 tree tlen;
2381 tree type = *xtype;
2382
2383 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
2384 tlen = NULL_TREE; /* A statement function, no length passed. */
2385 else
2386 {
2387 if (ffesymbol_where (s) == FFEINFO_whereDUMMY)
2388 tlen = ffecom_get_invented_identifier ("__g77_length_%s",
14657de8 2389 ffesymbol_text (s));
5ff904cd 2390 else
14657de8 2391 tlen = ffecom_get_invented_identifier ("__g77_%s", "length");
5ff904cd
JL
2392 tlen = build_decl (PARM_DECL, tlen, ffecom_f2c_ftnlen_type_node);
2393#if BUILT_FOR_270
2394 DECL_ARTIFICIAL (tlen) = 1;
2395#endif
2396 }
2397
2398 if (sz == FFETARGET_charactersizeNONE)
2399 {
2400 assert (tlen != NULL_TREE);
2b0c2df0 2401 highval = variable_size (tlen);
5ff904cd
JL
2402 }
2403 else
2404 {
2405 highval = build_int_2 (sz, 0);
2406 TREE_TYPE (highval) = ffecom_f2c_ftnlen_type_node;
2407 }
2408
2409 type = build_array_type (type,
2410 build_range_type (ffecom_f2c_ftnlen_type_node,
2411 ffecom_f2c_ftnlen_one_node,
2412 highval));
2413
2414 *xtype = type;
2415 return tlen;
2416}
2417
2418#endif
2419/* ffecom_concat_list_gather_ -- Gather list of concatenated string exprs
2420
2421 ffecomConcatList_ catlist;
2422 ffebld expr; // expr of CHARACTER basictype.
2423 ffetargetCharacterSize max; // max chars to gather or _...NONE if no max
2424 catlist = ffecom_concat_list_gather_(catlist,expr,max);
2425
2426 Scans expr for character subexpressions, updates and returns catlist
2427 accordingly. */
2428
2429#if FFECOM_targetCURRENT == FFECOM_targetGCC
2430static ffecomConcatList_
2431ffecom_concat_list_gather_ (ffecomConcatList_ catlist, ffebld expr,
2432 ffetargetCharacterSize max)
2433{
2434 ffetargetCharacterSize sz;
2435
2436recurse: /* :::::::::::::::::::: */
2437
2438 if (expr == NULL)
2439 return catlist;
2440
2441 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen >= max))
2442 return catlist; /* Don't append any more items. */
2443
2444 switch (ffebld_op (expr))
2445 {
2446 case FFEBLD_opCONTER:
2447 case FFEBLD_opSYMTER:
2448 case FFEBLD_opARRAYREF:
2449 case FFEBLD_opFUNCREF:
2450 case FFEBLD_opSUBSTR:
2451 case FFEBLD_opCONVERT: /* Callers should strip this off beforehand
2452 if they don't need to preserve it. */
2453 if (catlist.count == catlist.max)
2454 { /* Make a (larger) list. */
2455 ffebld *newx;
2456 int newmax;
2457
2458 newmax = (catlist.max == 0) ? 8 : catlist.max * 2;
2459 newx = malloc_new_ks (malloc_pool_image (), "catlist",
2460 newmax * sizeof (newx[0]));
2461 if (catlist.max != 0)
2462 {
2463 memcpy (newx, catlist.exprs, catlist.max * sizeof (newx[0]));
2464 malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2465 catlist.max * sizeof (newx[0]));
2466 }
2467 catlist.max = newmax;
2468 catlist.exprs = newx;
2469 }
2470 if ((sz = ffebld_size_known (expr)) != FFETARGET_charactersizeNONE)
2471 catlist.minlen += sz;
2472 else
2473 ++catlist.minlen; /* Not true for F90; can be 0 length. */
2474 if ((sz = ffebld_size_max (expr)) == FFETARGET_charactersizeNONE)
2475 catlist.maxlen = sz;
2476 else
2477 catlist.maxlen += sz;
2478 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen > max))
2479 { /* This item overlaps (or is beyond) the end
2480 of the destination. */
2481 switch (ffebld_op (expr))
2482 {
2483 case FFEBLD_opCONTER:
2484 case FFEBLD_opSYMTER:
2485 case FFEBLD_opARRAYREF:
2486 case FFEBLD_opFUNCREF:
2487 case FFEBLD_opSUBSTR:
c7e4ee3a
CB
2488 /* ~~Do useful truncations here. */
2489 break;
5ff904cd
JL
2490
2491 default:
2492 assert ("op changed or inconsistent switches!" == NULL);
2493 break;
2494 }
2495 }
2496 catlist.exprs[catlist.count++] = expr;
2497 return catlist;
2498
2499 case FFEBLD_opPAREN:
2500 expr = ffebld_left (expr);
2501 goto recurse; /* :::::::::::::::::::: */
2502
2503 case FFEBLD_opCONCATENATE:
2504 catlist = ffecom_concat_list_gather_ (catlist, ffebld_left (expr), max);
2505 expr = ffebld_right (expr);
2506 goto recurse; /* :::::::::::::::::::: */
2507
2508#if 0 /* Breaks passing small actual arg to larger
2509 dummy arg of sfunc */
2510 case FFEBLD_opCONVERT:
2511 expr = ffebld_left (expr);
2512 {
2513 ffetargetCharacterSize cmax;
2514
2515 cmax = catlist.len + ffebld_size_known (expr);
2516
2517 if ((max == FFETARGET_charactersizeNONE) || (max > cmax))
2518 max = cmax;
2519 }
2520 goto recurse; /* :::::::::::::::::::: */
2521#endif
2522
2523 case FFEBLD_opANY:
2524 return catlist;
2525
2526 default:
2527 assert ("bad op in _gather_" == NULL);
2528 return catlist;
2529 }
2530}
2531
2532#endif
2533/* ffecom_concat_list_kill_ -- Kill list of concatenated string exprs
2534
2535 ffecomConcatList_ catlist;
2536 ffecom_concat_list_kill_(catlist);
2537
2538 Anything allocated within the list info is deallocated. */
2539
2540#if FFECOM_targetCURRENT == FFECOM_targetGCC
2541static void
2542ffecom_concat_list_kill_ (ffecomConcatList_ catlist)
2543{
2544 if (catlist.max != 0)
2545 malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2546 catlist.max * sizeof (catlist.exprs[0]));
2547}
2548
2549#endif
c7e4ee3a 2550/* Make list of concatenated string exprs.
5ff904cd
JL
2551
2552 Returns a flattened list of concatenated subexpressions given a
2553 tree of such expressions. */
2554
2555#if FFECOM_targetCURRENT == FFECOM_targetGCC
2556static ffecomConcatList_
2557ffecom_concat_list_new_ (ffebld expr, ffetargetCharacterSize max)
2558{
2559 ffecomConcatList_ catlist;
2560
2561 catlist.maxlen = catlist.minlen = catlist.max = catlist.count = 0;
2562 return ffecom_concat_list_gather_ (catlist, expr, max);
2563}
2564
2565#endif
2566
2567/* Provide some kind of useful info on member of aggregate area,
2568 since current g77/gcc technology does not provide debug info
2569 on these members. */
2570
2571#if FFECOM_targetCURRENT == FFECOM_targetGCC
2572static void
26f096f9 2573ffecom_debug_kludge_ (tree aggr, const char *aggr_type, ffesymbol member,
5ff904cd
JL
2574 tree member_type UNUSED, ffetargetOffset offset)
2575{
2576 tree value;
2577 tree decl;
2578 int len;
2579 char *buff;
2580 char space[120];
2581#if 0
2582 tree type_id;
2583
2584 for (type_id = member_type;
2585 TREE_CODE (type_id) != IDENTIFIER_NODE;
2586 )
2587 {
2588 switch (TREE_CODE (type_id))
2589 {
2590 case INTEGER_TYPE:
2591 case REAL_TYPE:
2592 type_id = TYPE_NAME (type_id);
2593 break;
2594
2595 case ARRAY_TYPE:
2596 case COMPLEX_TYPE:
2597 type_id = TREE_TYPE (type_id);
2598 break;
2599
2600 default:
2601 assert ("no IDENTIFIER_NODE for type!" == NULL);
2602 type_id = error_mark_node;
2603 break;
2604 }
2605 }
2606#endif
2607
2608 if (ffecom_transform_only_dummies_
2609 || !ffe_is_debug_kludge ())
2610 return; /* Can't do this yet, maybe later. */
2611
2612 len = 60
2613 + strlen (aggr_type)
2614 + IDENTIFIER_LENGTH (DECL_NAME (aggr));
2615#if 0
2616 + IDENTIFIER_LENGTH (type_id);
2617#endif
2618
2619 if (((size_t) len) >= ARRAY_SIZE (space))
2620 buff = malloc_new_ks (malloc_pool_image (), "debug_kludge", len + 1);
2621 else
2622 buff = &space[0];
2623
2624 sprintf (&buff[0], "At (%s) `%s' plus %ld bytes",
2625 aggr_type,
2626 IDENTIFIER_POINTER (DECL_NAME (aggr)),
2627 (long int) offset);
2628
2629 value = build_string (len, buff);
2630 TREE_TYPE (value)
2631 = build_type_variant (build_array_type (char_type_node,
2632 build_range_type
2633 (integer_type_node,
2634 integer_one_node,
2635 build_int_2 (strlen (buff), 0))),
2636 1, 0);
2637 decl = build_decl (VAR_DECL,
2638 ffecom_get_identifier_ (ffesymbol_text (member)),
2639 TREE_TYPE (value));
2640 TREE_CONSTANT (decl) = 1;
2641 TREE_STATIC (decl) = 1;
2642 DECL_INITIAL (decl) = error_mark_node;
2643 DECL_IN_SYSTEM_HEADER (decl) = 1; /* Don't let -Wunused complain. */
2644 decl = start_decl (decl, FALSE);
2645 finish_decl (decl, value, FALSE);
2646
2647 if (buff != &space[0])
2648 malloc_kill_ks (malloc_pool_image (), buff, len + 1);
2649}
2650#endif
2651
2652/* ffecom_do_entry_ -- Do compilation of a particular entrypoint
2653
2654 ffesymbol fn; // the SUBROUTINE, FUNCTION, or ENTRY symbol itself
2655 int i; // entry# for this entrypoint (used by master fn)
2656 ffecom_do_entrypoint_(s,i);
2657
2658 Makes a public entry point that calls our private master fn (already
2659 compiled). */
2660
2661#if FFECOM_targetCURRENT == FFECOM_targetGCC
2662static void
2663ffecom_do_entry_ (ffesymbol fn, int entrynum)
2664{
2665 ffebld item;
2666 tree type; /* Type of function. */
2667 tree multi_retval; /* Var holding return value (union). */
2668 tree result; /* Var holding result. */
2669 ffeinfoBasictype bt;
2670 ffeinfoKindtype kt;
2671 ffeglobal g;
2672 ffeglobalType gt;
2673 bool charfunc; /* All entry points return same type
2674 CHARACTER. */
2675 bool cmplxfunc; /* Use f2c way of returning COMPLEX. */
2676 bool multi; /* Master fn has multiple return types. */
2677 bool altreturning = FALSE; /* This entry point has alternate returns. */
2678 int yes;
44d2eabc 2679 int old_lineno = lineno;
3b304f5b 2680 const char *old_input_filename = input_filename;
44d2eabc
JL
2681
2682 input_filename = ffesymbol_where_filename (fn);
2683 lineno = ffesymbol_where_filelinenum (fn);
5ff904cd
JL
2684
2685 /* c-parse.y indeed does call suspend_momentary and not only ignores the
2686 return value, but also never calls resume_momentary, when starting an
2687 outer function (see "fndef:", "setspecs:", and so on). So g77 does the
2688 same thing. It shouldn't be a problem since start_function calls
2689 temporary_allocation, but it might be necessary. If it causes a problem
2690 here, then maybe there's a bug lurking in gcc. NOTE: This identical
2691 comment appears twice in thist file. */
2692
2693 suspend_momentary ();
2694
2695 ffecom_doing_entry_ = TRUE; /* Don't bother with array dimensions. */
2696
2697 switch (ffecom_primary_entry_kind_)
2698 {
2699 case FFEINFO_kindFUNCTION:
2700
2701 /* Determine actual return type for function. */
2702
2703 gt = FFEGLOBAL_typeFUNC;
2704 bt = ffesymbol_basictype (fn);
2705 kt = ffesymbol_kindtype (fn);
2706 if (bt == FFEINFO_basictypeNONE)
2707 {
2708 ffeimplic_establish_symbol (fn);
2709 if (ffesymbol_funcresult (fn) != NULL)
2710 ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
2711 bt = ffesymbol_basictype (fn);
2712 kt = ffesymbol_kindtype (fn);
2713 }
2714
2715 if (bt == FFEINFO_basictypeCHARACTER)
2716 charfunc = TRUE, cmplxfunc = FALSE;
2717 else if ((bt == FFEINFO_basictypeCOMPLEX)
2718 && ffesymbol_is_f2c (fn))
2719 charfunc = FALSE, cmplxfunc = TRUE;
2720 else
2721 charfunc = cmplxfunc = FALSE;
2722
2723 if (charfunc)
2724 type = ffecom_tree_fun_type_void;
2725 else if (ffesymbol_is_f2c (fn))
2726 type = ffecom_tree_fun_type[bt][kt];
2727 else
2728 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
2729
2730 if ((type == NULL_TREE)
2731 || (TREE_TYPE (type) == NULL_TREE))
2732 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */
2733
2734 multi = (ffecom_master_bt_ == FFEINFO_basictypeNONE);
2735 break;
2736
2737 case FFEINFO_kindSUBROUTINE:
2738 gt = FFEGLOBAL_typeSUBR;
2739 bt = FFEINFO_basictypeNONE;
2740 kt = FFEINFO_kindtypeNONE;
2741 if (ffecom_is_altreturning_)
2742 { /* Am _I_ altreturning? */
2743 for (item = ffesymbol_dummyargs (fn);
2744 item != NULL;
2745 item = ffebld_trail (item))
2746 {
2747 if (ffebld_op (ffebld_head (item)) == FFEBLD_opSTAR)
2748 {
2749 altreturning = TRUE;
2750 break;
2751 }
2752 }
2753 if (altreturning)
2754 type = ffecom_tree_subr_type;
2755 else
2756 type = ffecom_tree_fun_type_void;
2757 }
2758 else
2759 type = ffecom_tree_fun_type_void;
2760 charfunc = FALSE;
2761 cmplxfunc = FALSE;
2762 multi = FALSE;
2763 break;
2764
2765 default:
2766 assert ("say what??" == NULL);
2767 /* Fall through. */
2768 case FFEINFO_kindANY:
2769 gt = FFEGLOBAL_typeANY;
2770 bt = FFEINFO_basictypeNONE;
2771 kt = FFEINFO_kindtypeNONE;
2772 type = error_mark_node;
2773 charfunc = FALSE;
2774 cmplxfunc = FALSE;
2775 multi = FALSE;
2776 break;
2777 }
2778
2779 /* build_decl uses the current lineno and input_filename to set the decl
2780 source info. So, I've putzed with ffestd and ffeste code to update that
2781 source info to point to the appropriate statement just before calling
2782 ffecom_do_entrypoint (which calls this fn). */
2783
2784 start_function (ffecom_get_external_identifier_ (fn),
2785 type,
2786 0, /* nested/inline */
2787 1); /* TREE_PUBLIC */
2788
2789 if (((g = ffesymbol_global (fn)) != NULL)
2790 && ((ffeglobal_type (g) == gt)
2791 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
2792 {
2793 ffeglobal_set_hook (g, current_function_decl);
2794 }
2795
2796 /* Reset args in master arg list so they get retransitioned. */
2797
2798 for (item = ffecom_master_arglist_;
2799 item != NULL;
2800 item = ffebld_trail (item))
2801 {
2802 ffebld arg;
2803 ffesymbol s;
2804
2805 arg = ffebld_head (item);
2806 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2807 continue; /* Alternate return or some such thing. */
2808 s = ffebld_symter (arg);
2809 ffesymbol_hook (s).decl_tree = NULL_TREE;
2810 ffesymbol_hook (s).length_tree = NULL_TREE;
2811 }
2812
2813 /* Build dummy arg list for this entry point. */
2814
2815 yes = suspend_momentary ();
2816
2817 if (charfunc || cmplxfunc)
2818 { /* Prepend arg for where result goes. */
2819 tree type;
2820 tree length;
2821
2822 if (charfunc)
2823 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
2824 else
2825 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
2826
14657de8 2827 result = ffecom_get_invented_identifier ("__g77_%s", "result");
5ff904cd
JL
2828
2829 /* Make length arg _and_ enhance type info for CHAR arg itself. */
2830
2831 if (charfunc)
2832 length = ffecom_char_enhance_arg_ (&type, fn);
2833 else
2834 length = NULL_TREE; /* Not ref'd if !charfunc. */
2835
2836 type = build_pointer_type (type);
2837 result = build_decl (PARM_DECL, result, type);
2838
2839 push_parm_decl (result);
2840 ffecom_func_result_ = result;
2841
2842 if (charfunc)
2843 {
2844 push_parm_decl (length);
2845 ffecom_func_length_ = length;
2846 }
2847 }
2848 else
2849 result = DECL_RESULT (current_function_decl);
2850
2851 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (fn), FALSE);
2852
2853 resume_momentary (yes);
2854
2855 store_parm_decls (0);
2856
c7e4ee3a
CB
2857 ffecom_start_compstmt ();
2858 /* Disallow temp vars at this level. */
2859 current_binding_level->prep_state = 2;
5ff904cd
JL
2860
2861 /* Make local var to hold return type for multi-type master fn. */
2862
2863 if (multi)
2864 {
2865 yes = suspend_momentary ();
2866
2867 multi_retval = ffecom_get_invented_identifier ("__g77_%s",
14657de8 2868 "multi_retval");
5ff904cd
JL
2869 multi_retval = build_decl (VAR_DECL, multi_retval,
2870 ffecom_multi_type_node_);
2871 multi_retval = start_decl (multi_retval, FALSE);
2872 finish_decl (multi_retval, NULL_TREE, FALSE);
2873
2874 resume_momentary (yes);
2875 }
2876 else
2877 multi_retval = NULL_TREE; /* Not actually ref'd if !multi. */
2878
2879 /* Here we emit the actual code for the entry point. */
2880
2881 {
2882 ffebld list;
2883 ffebld arg;
2884 ffesymbol s;
2885 tree arglist = NULL_TREE;
2886 tree *plist = &arglist;
2887 tree prepend;
2888 tree call;
2889 tree actarg;
2890 tree master_fn;
2891
2892 /* Prepare actual arg list based on master arg list. */
2893
2894 for (list = ffecom_master_arglist_;
2895 list != NULL;
2896 list = ffebld_trail (list))
2897 {
2898 arg = ffebld_head (list);
2899 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2900 continue;
2901 s = ffebld_symter (arg);
702edf1d
CB
2902 if (ffesymbol_hook (s).decl_tree == NULL_TREE
2903 || ffesymbol_hook (s).decl_tree == error_mark_node)
5ff904cd
JL
2904 actarg = null_pointer_node; /* We don't have this arg. */
2905 else
2906 actarg = ffesymbol_hook (s).decl_tree;
2907 *plist = build_tree_list (NULL_TREE, actarg);
2908 plist = &TREE_CHAIN (*plist);
2909 }
2910
2911 /* This code appends the length arguments for character
2912 variables/arrays. */
2913
2914 for (list = ffecom_master_arglist_;
2915 list != NULL;
2916 list = ffebld_trail (list))
2917 {
2918 arg = ffebld_head (list);
2919 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2920 continue;
2921 s = ffebld_symter (arg);
2922 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
2923 continue; /* Only looking for CHARACTER arguments. */
2924 if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
2925 continue; /* Only looking for variables and arrays. */
702edf1d
CB
2926 if (ffesymbol_hook (s).length_tree == NULL_TREE
2927 || ffesymbol_hook (s).length_tree == error_mark_node)
5ff904cd
JL
2928 actarg = ffecom_f2c_ftnlen_zero_node; /* We don't have this arg. */
2929 else
2930 actarg = ffesymbol_hook (s).length_tree;
2931 *plist = build_tree_list (NULL_TREE, actarg);
2932 plist = &TREE_CHAIN (*plist);
2933 }
2934
2935 /* Prepend character-value return info to actual arg list. */
2936
2937 if (charfunc)
2938 {
2939 prepend = build_tree_list (NULL_TREE, ffecom_func_result_);
2940 TREE_CHAIN (prepend)
2941 = build_tree_list (NULL_TREE, ffecom_func_length_);
2942 TREE_CHAIN (TREE_CHAIN (prepend)) = arglist;
2943 arglist = prepend;
2944 }
2945
2946 /* Prepend multi-type return value to actual arg list. */
2947
2948 if (multi)
2949 {
2950 prepend
2951 = build_tree_list (NULL_TREE,
2952 ffecom_1 (ADDR_EXPR,
2953 build_pointer_type (TREE_TYPE (multi_retval)),
2954 multi_retval));
2955 TREE_CHAIN (prepend) = arglist;
2956 arglist = prepend;
2957 }
2958
2959 /* Prepend my entry-point number to the actual arg list. */
2960
2961 prepend = build_tree_list (NULL_TREE, build_int_2 (entrynum, 0));
2962 TREE_CHAIN (prepend) = arglist;
2963 arglist = prepend;
2964
2965 /* Build the call to the master function. */
2966
2967 master_fn = ffecom_1_fn (ffecom_previous_function_decl_);
2968 call = ffecom_3s (CALL_EXPR,
2969 TREE_TYPE (TREE_TYPE (TREE_TYPE (master_fn))),
2970 master_fn, arglist, NULL_TREE);
2971
2972 /* Decide whether the master function is a function or subroutine, and
2973 handle the return value for my entry point. */
2974
2975 if (charfunc || ((ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
2976 && !altreturning))
2977 {
2978 expand_expr_stmt (call);
2979 expand_null_return ();
2980 }
2981 else if (multi && cmplxfunc)
2982 {
2983 expand_expr_stmt (call);
2984 result
2985 = ffecom_1 (INDIRECT_REF,
2986 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
2987 result);
2988 result = ffecom_modify (NULL_TREE, result,
2989 ffecom_2 (COMPONENT_REF, TREE_TYPE (result),
2990 multi_retval,
2991 ffecom_multi_fields_[bt][kt]));
2992 expand_expr_stmt (result);
2993 expand_null_return ();
2994 }
2995 else if (multi)
2996 {
2997 expand_expr_stmt (call);
2998 result
2999 = ffecom_modify (NULL_TREE, result,
3000 convert (TREE_TYPE (result),
3001 ffecom_2 (COMPONENT_REF,
3002 ffecom_tree_type[bt][kt],
3003 multi_retval,
3004 ffecom_multi_fields_[bt][kt])));
3005 expand_return (result);
3006 }
3007 else if (cmplxfunc)
3008 {
3009 result
3010 = ffecom_1 (INDIRECT_REF,
3011 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
3012 result);
3013 result = ffecom_modify (NULL_TREE, result, call);
3014 expand_expr_stmt (result);
3015 expand_null_return ();
3016 }
3017 else
3018 {
3019 result = ffecom_modify (NULL_TREE,
3020 result,
3021 convert (TREE_TYPE (result),
3022 call));
3023 expand_return (result);
3024 }
3025
3026 clear_momentary ();
3027 }
3028
c7e4ee3a 3029 ffecom_end_compstmt ();
5ff904cd
JL
3030
3031 finish_function (0);
3032
44d2eabc
JL
3033 lineno = old_lineno;
3034 input_filename = old_input_filename;
3035
5ff904cd
JL
3036 ffecom_doing_entry_ = FALSE;
3037}
3038
3039#endif
3040/* Transform expr into gcc tree with possible destination
3041
3042 Recursive descent on expr while making corresponding tree nodes and
3043 attaching type info and such. If destination supplied and compatible
3044 with temporary that would be made in certain cases, temporary isn't
092a4ef8 3045 made, destination used instead, and dest_used flag set TRUE. */
5ff904cd
JL
3046
3047#if FFECOM_targetCURRENT == FFECOM_targetGCC
3048static tree
092a4ef8
RH
3049ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
3050 bool *dest_used, bool assignp, bool widenp)
5ff904cd
JL
3051{
3052 tree item;
3053 tree list;
3054 tree args;
3055 ffeinfoBasictype bt;
3056 ffeinfoKindtype kt;
3057 tree t;
5ff904cd 3058 tree dt; /* decl_tree for an ffesymbol. */
092a4ef8 3059 tree tree_type, tree_type_x;
af752698 3060 tree left, right;
5ff904cd
JL
3061 ffesymbol s;
3062 enum tree_code code;
3063
3064 assert (expr != NULL);
3065
3066 if (dest_used != NULL)
3067 *dest_used = FALSE;
3068
3069 bt = ffeinfo_basictype (ffebld_info (expr));
3070 kt = ffeinfo_kindtype (ffebld_info (expr));
af752698 3071 tree_type = ffecom_tree_type[bt][kt];
5ff904cd 3072
092a4ef8
RH
3073 /* Widen integral arithmetic as desired while preserving signedness. */
3074 tree_type_x = NULL_TREE;
3075 if (widenp && tree_type
3076 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
3077 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
3078 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
3079
5ff904cd
JL
3080 switch (ffebld_op (expr))
3081 {
3082 case FFEBLD_opACCTER:
5ff904cd
JL
3083 {
3084 ffebitCount i;
3085 ffebit bits = ffebld_accter_bits (expr);
3086 ffetargetOffset source_offset = 0;
a6fa6420 3087 ffetargetOffset dest_offset = ffebld_accter_pad (expr);
5ff904cd
JL
3088 tree purpose;
3089
a6fa6420
CB
3090 assert (dest_offset == 0
3091 || (bt == FFEINFO_basictypeCHARACTER
3092 && kt == FFEINFO_kindtypeCHARACTER1));
5ff904cd
JL
3093
3094 list = item = NULL;
3095 for (;;)
3096 {
3097 ffebldConstantUnion cu;
3098 ffebitCount length;
3099 bool value;
3100 ffebldConstantArray ca = ffebld_accter (expr);
3101
3102 ffebit_test (bits, source_offset, &value, &length);
3103 if (length == 0)
3104 break;
3105
3106 if (value)
3107 {
3108 for (i = 0; i < length; ++i)
3109 {
3110 cu = ffebld_constantarray_get (ca, bt, kt,
3111 source_offset + i);
3112
3113 t = ffecom_constantunion (&cu, bt, kt, tree_type);
3114
a6fa6420
CB
3115 if (i == 0
3116 && dest_offset != 0)
3117 purpose = build_int_2 (dest_offset, 0);
5ff904cd
JL
3118 else
3119 purpose = NULL_TREE;
3120
3121 if (list == NULL_TREE)
3122 list = item = build_tree_list (purpose, t);
3123 else
3124 {
3125 TREE_CHAIN (item) = build_tree_list (purpose, t);
3126 item = TREE_CHAIN (item);
3127 }
3128 }
3129 }
3130 source_offset += length;
a6fa6420 3131 dest_offset += length;
5ff904cd
JL
3132 }
3133 }
3134
a6fa6420
CB
3135 item = build_int_2 ((ffebld_accter_size (expr)
3136 + ffebld_accter_pad (expr)) - 1, 0);
5ff904cd
JL
3137 ffebit_kill (ffebld_accter_bits (expr));
3138 TREE_TYPE (item) = ffecom_integer_type_node;
3139 item
3140 = build_array_type
3141 (tree_type,
3142 build_range_type (ffecom_integer_type_node,
3143 ffecom_integer_zero_node,
3144 item));
3145 list = build (CONSTRUCTOR, item, NULL_TREE, list);
3146 TREE_CONSTANT (list) = 1;
3147 TREE_STATIC (list) = 1;
3148 return list;
3149
3150 case FFEBLD_opARRTER:
5ff904cd
JL
3151 {
3152 ffetargetOffset i;
3153
a6fa6420
CB
3154 list = NULL_TREE;
3155 if (ffebld_arrter_pad (expr) == 0)
3156 item = NULL_TREE;
3157 else
3158 {
3159 assert (bt == FFEINFO_basictypeCHARACTER
3160 && kt == FFEINFO_kindtypeCHARACTER1);
3161
3162 /* Becomes PURPOSE first time through loop. */
3163 item = build_int_2 (ffebld_arrter_pad (expr), 0);
3164 }
3165
5ff904cd
JL
3166 for (i = 0; i < ffebld_arrter_size (expr); ++i)
3167 {
3168 ffebldConstantUnion cu
3169 = ffebld_constantarray_get (ffebld_arrter (expr), bt, kt, i);
3170
3171 t = ffecom_constantunion (&cu, bt, kt, tree_type);
3172
3173 if (list == NULL_TREE)
a6fa6420
CB
3174 /* Assume item is PURPOSE first time through loop. */
3175 list = item = build_tree_list (item, t);
5ff904cd
JL
3176 else
3177 {
3178 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
3179 item = TREE_CHAIN (item);
3180 }
3181 }
3182 }
3183
a6fa6420
CB
3184 item = build_int_2 ((ffebld_arrter_size (expr)
3185 + ffebld_arrter_pad (expr)) - 1, 0);
5ff904cd
JL
3186 TREE_TYPE (item) = ffecom_integer_type_node;
3187 item
3188 = build_array_type
3189 (tree_type,
3190 build_range_type (ffecom_integer_type_node,
a6fa6420 3191 ffecom_integer_zero_node,
5ff904cd
JL
3192 item));
3193 list = build (CONSTRUCTOR, item, NULL_TREE, list);
3194 TREE_CONSTANT (list) = 1;
3195 TREE_STATIC (list) = 1;
3196 return list;
3197
3198 case FFEBLD_opCONTER:
c264f113 3199 assert (ffebld_conter_pad (expr) == 0);
5ff904cd
JL
3200 item
3201 = ffecom_constantunion (&ffebld_constant_union (ffebld_conter (expr)),
3202 bt, kt, tree_type);
3203 return item;
3204
3205 case FFEBLD_opSYMTER:
3206 if ((ffebld_symter_generic (expr) != FFEINTRIN_genNONE)
3207 || (ffebld_symter_specific (expr) != FFEINTRIN_specNONE))
3208 return ffecom_ptr_to_expr (expr); /* Same as %REF(intrinsic). */
3209 s = ffebld_symter (expr);
3210 t = ffesymbol_hook (s).decl_tree;
3211
3212 if (assignp)
3213 { /* ASSIGN'ed-label expr. */
3214 if (ffe_is_ugly_assign ())
3215 {
3216 /* User explicitly wants ASSIGN'ed variables to be at the same
3217 memory address as the variables when used in non-ASSIGN
3218 contexts. That can make old, arcane, non-standard code
3219 work, but don't try to do it when a pointer wouldn't fit
3220 in the normal variable (take other approach, and warn,
3221 instead). */
3222
3223 if (t == NULL_TREE)
3224 {
3225 s = ffecom_sym_transform_ (s);
3226 t = ffesymbol_hook (s).decl_tree;
3227 assert (t != NULL_TREE);
3228 }
3229
3230 if (t == error_mark_node)
3231 return t;
3232
3233 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (t)))
3234 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
3235 {
3236 if (ffesymbol_hook (s).addr)
3237 t = ffecom_1 (INDIRECT_REF,
3238 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
3239 return t;
3240 }
3241
3242 if (ffesymbol_hook (s).assign_tree == NULL_TREE)
3243 {
3244 ffebad_start_msg ("ASSIGN'ed label cannot fit into `%A' at %0 -- using wider sibling",
3245 FFEBAD_severityWARNING);
3246 ffebad_string (ffesymbol_text (s));
3247 ffebad_here (0, ffesymbol_where_line (s),
3248 ffesymbol_where_column (s));
3249 ffebad_finish ();
3250 }
3251 }
3252
3253 /* Don't use the normal variable's tree for ASSIGN, though mark
3254 it as in the system header (housekeeping). Use an explicit,
3255 specially created sibling that is known to be wide enough
3256 to hold pointers to labels. */
3257
3258 if (t != NULL_TREE
3259 && TREE_CODE (t) == VAR_DECL)
3260 DECL_IN_SYSTEM_HEADER (t) = 1; /* Don't let -Wunused complain. */
3261
3262 t = ffesymbol_hook (s).assign_tree;
3263 if (t == NULL_TREE)
3264 {
3265 s = ffecom_sym_transform_assign_ (s);
3266 t = ffesymbol_hook (s).assign_tree;
3267 assert (t != NULL_TREE);
3268 }
3269 }
3270 else
3271 {
3272 if (t == NULL_TREE)
3273 {
3274 s = ffecom_sym_transform_ (s);
3275 t = ffesymbol_hook (s).decl_tree;
3276 assert (t != NULL_TREE);
3277 }
3278 if (ffesymbol_hook (s).addr)
3279 t = ffecom_1 (INDIRECT_REF,
3280 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
3281 }
3282 return t;
3283
3284 case FFEBLD_opARRAYREF:
ff852b44 3285 return ffecom_arrayref_ (NULL_TREE, expr, 0);
5ff904cd
JL
3286
3287 case FFEBLD_opUPLUS:
092a4ef8 3288 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
af752698 3289 return ffecom_1 (NOP_EXPR, tree_type, left);
5ff904cd 3290
c7e4ee3a
CB
3291 case FFEBLD_opPAREN:
3292 /* ~~~Make sure Fortran rules respected here */
092a4ef8 3293 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
af752698 3294 return ffecom_1 (NOP_EXPR, tree_type, left);
5ff904cd
JL
3295
3296 case FFEBLD_opUMINUS:
092a4ef8 3297 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3298 if (tree_type_x)
3299 {
3300 tree_type = tree_type_x;
3301 left = convert (tree_type, left);
3302 }
3303 return ffecom_1 (NEGATE_EXPR, tree_type, left);
5ff904cd
JL
3304
3305 case FFEBLD_opADD:
092a4ef8
RH
3306 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3307 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3308 if (tree_type_x)
3309 {
3310 tree_type = tree_type_x;
3311 left = convert (tree_type, left);
3312 right = convert (tree_type, right);
3313 }
3314 return ffecom_2 (PLUS_EXPR, tree_type, left, right);
5ff904cd
JL
3315
3316 case FFEBLD_opSUBTRACT:
092a4ef8
RH
3317 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3318 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3319 if (tree_type_x)
3320 {
3321 tree_type = tree_type_x;
3322 left = convert (tree_type, left);
3323 right = convert (tree_type, right);
3324 }
3325 return ffecom_2 (MINUS_EXPR, tree_type, left, right);
5ff904cd
JL
3326
3327 case FFEBLD_opMULTIPLY:
092a4ef8
RH
3328 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3329 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3330 if (tree_type_x)
3331 {
3332 tree_type = tree_type_x;
3333 left = convert (tree_type, left);
3334 right = convert (tree_type, right);
3335 }
3336 return ffecom_2 (MULT_EXPR, tree_type, left, right);
5ff904cd
JL
3337
3338 case FFEBLD_opDIVIDE:
092a4ef8
RH
3339 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3340 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3341 if (tree_type_x)
3342 {
3343 tree_type = tree_type_x;
3344 left = convert (tree_type, left);
3345 right = convert (tree_type, right);
3346 }
3347 return ffecom_tree_divide_ (tree_type, left, right,
c7e4ee3a
CB
3348 dest_tree, dest, dest_used,
3349 ffebld_nonter_hook (expr));
5ff904cd
JL
3350
3351 case FFEBLD_opPOWER:
5ff904cd
JL
3352 {
3353 ffebld left = ffebld_left (expr);
3354 ffebld right = ffebld_right (expr);
3355 ffecomGfrt code;
3356 ffeinfoKindtype rtkt;
270fc4e8 3357 ffeinfoKindtype ltkt;
5ff904cd
JL
3358
3359 switch (ffeinfo_basictype (ffebld_info (right)))
3360 {
3361 case FFEINFO_basictypeINTEGER:
3362 if (1 || optimize)
3363 {
c7e4ee3a 3364 item = ffecom_expr_power_integer_ (expr);
5ff904cd
JL
3365 if (item != NULL_TREE)
3366 return item;
3367 }
3368
3369 rtkt = FFEINFO_kindtypeINTEGER1;
3370 switch (ffeinfo_basictype (ffebld_info (left)))
3371 {
3372 case FFEINFO_basictypeINTEGER:
3373 if ((ffeinfo_kindtype (ffebld_info (left))
3374 == FFEINFO_kindtypeINTEGER4)
3375 || (ffeinfo_kindtype (ffebld_info (right))
3376 == FFEINFO_kindtypeINTEGER4))
3377 {
3378 code = FFECOM_gfrtPOW_QQ;
270fc4e8 3379 ltkt = FFEINFO_kindtypeINTEGER4;
5ff904cd
JL
3380 rtkt = FFEINFO_kindtypeINTEGER4;
3381 }
3382 else
6a047254
CB
3383 {
3384 code = FFECOM_gfrtPOW_II;
3385 ltkt = FFEINFO_kindtypeINTEGER1;
3386 }
5ff904cd
JL
3387 break;
3388
3389 case FFEINFO_basictypeREAL:
3390 if (ffeinfo_kindtype (ffebld_info (left))
3391 == FFEINFO_kindtypeREAL1)
6a047254
CB
3392 {
3393 code = FFECOM_gfrtPOW_RI;
3394 ltkt = FFEINFO_kindtypeREAL1;
3395 }
5ff904cd 3396 else
6a047254
CB
3397 {
3398 code = FFECOM_gfrtPOW_DI;
3399 ltkt = FFEINFO_kindtypeREAL2;
3400 }
5ff904cd
JL
3401 break;
3402
3403 case FFEINFO_basictypeCOMPLEX:
3404 if (ffeinfo_kindtype (ffebld_info (left))
3405 == FFEINFO_kindtypeREAL1)
6a047254
CB
3406 {
3407 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */
3408 ltkt = FFEINFO_kindtypeREAL1;
3409 }
5ff904cd 3410 else
6a047254
CB
3411 {
3412 code = FFECOM_gfrtPOW_ZI; /* Overlapping result okay. */
3413 ltkt = FFEINFO_kindtypeREAL2;
3414 }
5ff904cd
JL
3415 break;
3416
3417 default:
3418 assert ("bad pow_*i" == NULL);
3419 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */
6a047254 3420 ltkt = FFEINFO_kindtypeREAL1;
5ff904cd
JL
3421 break;
3422 }
270fc4e8 3423 if (ffeinfo_kindtype (ffebld_info (left)) != ltkt)
5ff904cd 3424 left = ffeexpr_convert (left, NULL, NULL,
6a047254 3425 ffeinfo_basictype (ffebld_info (left)),
270fc4e8 3426 ltkt, 0,
5ff904cd
JL
3427 FFETARGET_charactersizeNONE,
3428 FFEEXPR_contextLET);
3429 if (ffeinfo_kindtype (ffebld_info (right)) != rtkt)
3430 right = ffeexpr_convert (right, NULL, NULL,
3431 FFEINFO_basictypeINTEGER,
3432 rtkt, 0,
3433 FFETARGET_charactersizeNONE,
3434 FFEEXPR_contextLET);
3435 break;
3436
3437 case FFEINFO_basictypeREAL:
3438 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3439 left = ffeexpr_convert (left, NULL, NULL, FFEINFO_basictypeREAL,
3440 FFEINFO_kindtypeREALDOUBLE, 0,
3441 FFETARGET_charactersizeNONE,
3442 FFEEXPR_contextLET);
3443 if (ffeinfo_kindtype (ffebld_info (right))
3444 == FFEINFO_kindtypeREAL1)
3445 right = ffeexpr_convert (right, NULL, NULL,
3446 FFEINFO_basictypeREAL,
3447 FFEINFO_kindtypeREALDOUBLE, 0,
3448 FFETARGET_charactersizeNONE,
3449 FFEEXPR_contextLET);
3450 code = FFECOM_gfrtPOW_DD;
3451 break;
3452
3453 case FFEINFO_basictypeCOMPLEX:
3454 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3455 left = ffeexpr_convert (left, NULL, NULL,
3456 FFEINFO_basictypeCOMPLEX,
3457 FFEINFO_kindtypeREALDOUBLE, 0,
3458 FFETARGET_charactersizeNONE,
3459 FFEEXPR_contextLET);
3460 if (ffeinfo_kindtype (ffebld_info (right))
3461 == FFEINFO_kindtypeREAL1)
3462 right = ffeexpr_convert (right, NULL, NULL,
3463 FFEINFO_basictypeCOMPLEX,
3464 FFEINFO_kindtypeREALDOUBLE, 0,
3465 FFETARGET_charactersizeNONE,
3466 FFEEXPR_contextLET);
3467 code = FFECOM_gfrtPOW_ZZ; /* Overlapping result okay. */
3468 break;
3469
3470 default:
3471 assert ("bad pow_x*" == NULL);
3472 code = FFECOM_gfrtPOW_II;
3473 break;
3474 }
3475 return ffecom_call_binop_ (ffecom_gfrt_tree_ (code),
3476 ffecom_gfrt_kindtype (code),
3477 (ffe_is_f2c_library ()
3478 && ffecom_gfrt_complex_[code]),
3479 tree_type, left, right,
3480 dest_tree, dest, dest_used,
c7e4ee3a
CB
3481 NULL_TREE, FALSE,
3482 ffebld_nonter_hook (expr));
5ff904cd
JL
3483 }
3484
3485 case FFEBLD_opNOT:
5ff904cd
JL
3486 switch (bt)
3487 {
3488 case FFEINFO_basictypeLOGICAL:
83ffecd2 3489 item = ffecom_truth_value_invert (ffecom_expr (ffebld_left (expr)));
5ff904cd
JL
3490 return convert (tree_type, item);
3491
3492 case FFEINFO_basictypeINTEGER:
3493 return ffecom_1 (BIT_NOT_EXPR, tree_type,
3494 ffecom_expr (ffebld_left (expr)));
3495
3496 default:
3497 assert ("NOT bad basictype" == NULL);
3498 /* Fall through. */
3499 case FFEINFO_basictypeANY:
3500 return error_mark_node;
3501 }
3502 break;
3503
3504 case FFEBLD_opFUNCREF:
3505 assert (ffeinfo_basictype (ffebld_info (expr))
3506 != FFEINFO_basictypeCHARACTER);
3507 /* Fall through. */
3508 case FFEBLD_opSUBRREF:
5ff904cd
JL
3509 if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
3510 == FFEINFO_whereINTRINSIC)
3511 { /* Invocation of an intrinsic. */
3512 item = ffecom_expr_intrinsic_ (expr, dest_tree, dest,
3513 dest_used);
3514 return item;
3515 }
3516 s = ffebld_symter (ffebld_left (expr));
3517 dt = ffesymbol_hook (s).decl_tree;
3518 if (dt == NULL_TREE)
3519 {
3520 s = ffecom_sym_transform_ (s);
3521 dt = ffesymbol_hook (s).decl_tree;
3522 }
3523 if (dt == error_mark_node)
3524 return dt;
3525
3526 if (ffesymbol_hook (s).addr)
3527 item = dt;
3528 else
3529 item = ffecom_1_fn (dt);
3530
5ff904cd
JL
3531 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
3532 args = ffecom_list_expr (ffebld_right (expr));
3533 else
3534 args = ffecom_list_ptr_to_expr (ffebld_right (expr));
5ff904cd 3535
702edf1d
CB
3536 if (args == error_mark_node)
3537 return error_mark_node;
3538
5ff904cd
JL
3539 item = ffecom_call_ (item, kt,
3540 ffesymbol_is_f2c (s)
3541 && (bt == FFEINFO_basictypeCOMPLEX)
3542 && (ffesymbol_where (s)
3543 != FFEINFO_whereCONSTANT),
3544 tree_type,
3545 args,
3546 dest_tree, dest, dest_used,
c7e4ee3a
CB
3547 error_mark_node, FALSE,
3548 ffebld_nonter_hook (expr));
5ff904cd
JL
3549 TREE_SIDE_EFFECTS (item) = 1;
3550 return item;
3551
3552 case FFEBLD_opAND:
5ff904cd
JL
3553 switch (bt)
3554 {
3555 case FFEINFO_basictypeLOGICAL:
3556 item
3557 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3558 ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3559 ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3560 return convert (tree_type, item);
3561
3562 case FFEINFO_basictypeINTEGER:
3563 return ffecom_2 (BIT_AND_EXPR, tree_type,
3564 ffecom_expr (ffebld_left (expr)),
3565 ffecom_expr (ffebld_right (expr)));
3566
3567 default:
3568 assert ("AND bad basictype" == NULL);
3569 /* Fall through. */
3570 case FFEINFO_basictypeANY:
3571 return error_mark_node;
3572 }
3573 break;
3574
3575 case FFEBLD_opOR:
5ff904cd
JL
3576 switch (bt)
3577 {
3578 case FFEINFO_basictypeLOGICAL:
3579 item
3580 = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
3581 ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3582 ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3583 return convert (tree_type, item);
3584
3585 case FFEINFO_basictypeINTEGER:
3586 return ffecom_2 (BIT_IOR_EXPR, tree_type,
3587 ffecom_expr (ffebld_left (expr)),
3588 ffecom_expr (ffebld_right (expr)));
3589
3590 default:
3591 assert ("OR bad basictype" == NULL);
3592 /* Fall through. */
3593 case FFEINFO_basictypeANY:
3594 return error_mark_node;
3595 }
3596 break;
3597
3598 case FFEBLD_opXOR:
3599 case FFEBLD_opNEQV:
5ff904cd
JL
3600 switch (bt)
3601 {
3602 case FFEINFO_basictypeLOGICAL:
3603 item
3604 = ffecom_2 (NE_EXPR, integer_type_node,
3605 ffecom_expr (ffebld_left (expr)),
3606 ffecom_expr (ffebld_right (expr)));
3607 return convert (tree_type, ffecom_truth_value (item));
3608
3609 case FFEINFO_basictypeINTEGER:
3610 return ffecom_2 (BIT_XOR_EXPR, tree_type,
3611 ffecom_expr (ffebld_left (expr)),
3612 ffecom_expr (ffebld_right (expr)));
3613
3614 default:
3615 assert ("XOR/NEQV bad basictype" == NULL);
3616 /* Fall through. */
3617 case FFEINFO_basictypeANY:
3618 return error_mark_node;
3619 }
3620 break;
3621
3622 case FFEBLD_opEQV:
5ff904cd
JL
3623 switch (bt)
3624 {
3625 case FFEINFO_basictypeLOGICAL:
3626 item
3627 = ffecom_2 (EQ_EXPR, integer_type_node,
3628 ffecom_expr (ffebld_left (expr)),
3629 ffecom_expr (ffebld_right (expr)));
3630 return convert (tree_type, ffecom_truth_value (item));
3631
3632 case FFEINFO_basictypeINTEGER:
3633 return
3634 ffecom_1 (BIT_NOT_EXPR, tree_type,
3635 ffecom_2 (BIT_XOR_EXPR, tree_type,
3636 ffecom_expr (ffebld_left (expr)),
3637 ffecom_expr (ffebld_right (expr))));
3638
3639 default:
3640 assert ("EQV bad basictype" == NULL);
3641 /* Fall through. */
3642 case FFEINFO_basictypeANY:
3643 return error_mark_node;
3644 }
3645 break;
3646
3647 case FFEBLD_opCONVERT:
3648 if (ffebld_op (ffebld_left (expr)) == FFEBLD_opANY)
3649 return error_mark_node;
3650
5ff904cd
JL
3651 switch (bt)
3652 {
3653 case FFEINFO_basictypeLOGICAL:
3654 case FFEINFO_basictypeINTEGER:
3655 case FFEINFO_basictypeREAL:
3656 return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3657
3658 case FFEINFO_basictypeCOMPLEX:
3659 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3660 {
3661 case FFEINFO_basictypeINTEGER:
3662 case FFEINFO_basictypeLOGICAL:
3663 case FFEINFO_basictypeREAL:
3664 item = ffecom_expr (ffebld_left (expr));
3665 if (item == error_mark_node)
3666 return error_mark_node;
3667 /* convert() takes care of converting to the subtype first,
3668 at least in gcc-2.7.2. */
3669 item = convert (tree_type, item);
3670 return item;
3671
3672 case FFEINFO_basictypeCOMPLEX:
3673 return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3674
3675 default:
3676 assert ("CONVERT COMPLEX bad basictype" == NULL);
3677 /* Fall through. */
3678 case FFEINFO_basictypeANY:
3679 return error_mark_node;
3680 }
3681 break;
3682
3683 default:
3684 assert ("CONVERT bad basictype" == NULL);
3685 /* Fall through. */
3686 case FFEINFO_basictypeANY:
3687 return error_mark_node;
3688 }
3689 break;
3690
3691 case FFEBLD_opLT:
3692 code = LT_EXPR;
3693 goto relational; /* :::::::::::::::::::: */
3694
3695 case FFEBLD_opLE:
3696 code = LE_EXPR;
3697 goto relational; /* :::::::::::::::::::: */
3698
3699 case FFEBLD_opEQ:
3700 code = EQ_EXPR;
3701 goto relational; /* :::::::::::::::::::: */
3702
3703 case FFEBLD_opNE:
3704 code = NE_EXPR;
3705 goto relational; /* :::::::::::::::::::: */
3706
3707 case FFEBLD_opGT:
3708 code = GT_EXPR;
3709 goto relational; /* :::::::::::::::::::: */
3710
3711 case FFEBLD_opGE:
3712 code = GE_EXPR;
3713
3714 relational: /* :::::::::::::::::::: */
5ff904cd
JL
3715 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3716 {
3717 case FFEINFO_basictypeLOGICAL:
3718 case FFEINFO_basictypeINTEGER:
3719 case FFEINFO_basictypeREAL:
3720 item = ffecom_2 (code, integer_type_node,
3721 ffecom_expr (ffebld_left (expr)),
3722 ffecom_expr (ffebld_right (expr)));
3723 return convert (tree_type, item);
3724
3725 case FFEINFO_basictypeCOMPLEX:
3726 assert (code == EQ_EXPR || code == NE_EXPR);
3727 {
3728 tree real_type;
3729 tree arg1 = ffecom_expr (ffebld_left (expr));
3730 tree arg2 = ffecom_expr (ffebld_right (expr));
3731
3732 if (arg1 == error_mark_node || arg2 == error_mark_node)
3733 return error_mark_node;
3734
3735 arg1 = ffecom_save_tree (arg1);
3736 arg2 = ffecom_save_tree (arg2);
3737
3738 if (TREE_CODE (TREE_TYPE (arg1)) == COMPLEX_TYPE)
3739 {
3740 real_type = TREE_TYPE (TREE_TYPE (arg1));
3741 assert (real_type == TREE_TYPE (TREE_TYPE (arg2)));
3742 }
3743 else
3744 {
3745 real_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg1)));
3746 assert (real_type == TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg2))));
3747 }
3748
3749 item
3750 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3751 ffecom_2 (EQ_EXPR, integer_type_node,
3752 ffecom_1 (REALPART_EXPR, real_type, arg1),
3753 ffecom_1 (REALPART_EXPR, real_type, arg2)),
3754 ffecom_2 (EQ_EXPR, integer_type_node,
3755 ffecom_1 (IMAGPART_EXPR, real_type, arg1),
3756 ffecom_1 (IMAGPART_EXPR, real_type,
3757 arg2)));
3758 if (code == EQ_EXPR)
3759 item = ffecom_truth_value (item);
3760 else
3761 item = ffecom_truth_value_invert (item);
3762 return convert (tree_type, item);
3763 }
3764
3765 case FFEINFO_basictypeCHARACTER:
5ff904cd
JL
3766 {
3767 ffebld left = ffebld_left (expr);
3768 ffebld right = ffebld_right (expr);
3769 tree left_tree;
3770 tree right_tree;
3771 tree left_length;
3772 tree right_length;
3773
3774 /* f2c run-time functions do the implicit blank-padding for us,
3775 so we don't usually have to implement blank-padding ourselves.
3776 (The exception is when we pass an argument to a separately
3777 compiled statement function -- if we know the arg is not the
3778 same length as the dummy, we must truncate or extend it. If
3779 we "inline" statement functions, that necessity goes away as
3780 well.)
3781
3782 Strip off the CONVERT operators that blank-pad. (Truncation by
3783 CONVERT shouldn't happen here, but it can happen in
3784 assignments.) */
3785
3786 while (ffebld_op (left) == FFEBLD_opCONVERT)
3787 left = ffebld_left (left);
3788 while (ffebld_op (right) == FFEBLD_opCONVERT)
3789 right = ffebld_left (right);
3790
3791 left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
3792 right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
3793
3794 if (left_tree == error_mark_node || left_length == error_mark_node
3795 || right_tree == error_mark_node
3796 || right_length == error_mark_node)
c7e4ee3a 3797 return error_mark_node;
5ff904cd
JL
3798
3799 if ((ffebld_size_known (left) == 1)
3800 && (ffebld_size_known (right) == 1))
3801 {
3802 left_tree
3803 = ffecom_1 (INDIRECT_REF,
3804 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3805 left_tree);
3806 right_tree
3807 = ffecom_1 (INDIRECT_REF,
3808 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3809 right_tree);
3810
3811 item
3812 = ffecom_2 (code, integer_type_node,
3813 ffecom_2 (ARRAY_REF,
3814 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3815 left_tree,
3816 integer_one_node),
3817 ffecom_2 (ARRAY_REF,
3818 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3819 right_tree,
3820 integer_one_node));
3821 }
3822 else
3823 {
3824 item = build_tree_list (NULL_TREE, left_tree);
3825 TREE_CHAIN (item) = build_tree_list (NULL_TREE, right_tree);
3826 TREE_CHAIN (TREE_CHAIN (item)) = build_tree_list (NULL_TREE,
3827 left_length);
3828 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
3829 = build_tree_list (NULL_TREE, right_length);
c7e4ee3a 3830 item = ffecom_call_gfrt (FFECOM_gfrtCMP, item, NULL_TREE);
5ff904cd
JL
3831 item = ffecom_2 (code, integer_type_node,
3832 item,
3833 convert (TREE_TYPE (item),
3834 integer_zero_node));
3835 }
3836 item = convert (tree_type, item);
3837 }
3838
5ff904cd
JL
3839 return item;
3840
3841 default:
3842 assert ("relational bad basictype" == NULL);
3843 /* Fall through. */
3844 case FFEINFO_basictypeANY:
3845 return error_mark_node;
3846 }
3847 break;
3848
3849 case FFEBLD_opPERCENT_LOC:
5ff904cd
JL
3850 item = ffecom_arg_ptr_to_expr (ffebld_left (expr), &list);
3851 return convert (tree_type, item);
3852
3853 case FFEBLD_opITEM:
3854 case FFEBLD_opSTAR:
3855 case FFEBLD_opBOUNDS:
3856 case FFEBLD_opREPEAT:
3857 case FFEBLD_opLABTER:
3858 case FFEBLD_opLABTOK:
3859 case FFEBLD_opIMPDO:
3860 case FFEBLD_opCONCATENATE:
3861 case FFEBLD_opSUBSTR:
3862 default:
3863 assert ("bad op" == NULL);
3864 /* Fall through. */
3865 case FFEBLD_opANY:
3866 return error_mark_node;
3867 }
3868
3869#if 1
3870 assert ("didn't think anything got here anymore!!" == NULL);
3871#else
3872 switch (ffebld_arity (expr))
3873 {
3874 case 2:
3875 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3876 TREE_OPERAND (item, 1) = ffecom_expr (ffebld_right (expr));
3877 if (TREE_OPERAND (item, 0) == error_mark_node
3878 || TREE_OPERAND (item, 1) == error_mark_node)
3879 return error_mark_node;
3880 break;
3881
3882 case 1:
3883 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3884 if (TREE_OPERAND (item, 0) == error_mark_node)
3885 return error_mark_node;
3886 break;
3887
3888 default:
3889 break;
3890 }
3891
3892 return fold (item);
3893#endif
3894}
3895
3896#endif
3897/* Returns the tree that does the intrinsic invocation.
3898
3899 Note: this function applies only to intrinsics returning
3900 CHARACTER*1 or non-CHARACTER results, and to intrinsic
3901 subroutines. */
3902
3903#if FFECOM_targetCURRENT == FFECOM_targetGCC
3904static tree
3905ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
3906 ffebld dest, bool *dest_used)
3907{
3908 tree expr_tree;
3909 tree saved_expr1; /* For those who need it. */
3910 tree saved_expr2; /* For those who need it. */
3911 ffeinfoBasictype bt;
3912 ffeinfoKindtype kt;
3913 tree tree_type;
3914 tree arg1_type;
3915 tree real_type; /* REAL type corresponding to COMPLEX. */
3916 tree tempvar;
3917 ffebld list = ffebld_right (expr); /* List of (some) args. */
3918 ffebld arg1; /* For handy reference. */
3919 ffebld arg2;
3920 ffebld arg3;
3921 ffeintrinImp codegen_imp;
3922 ffecomGfrt gfrt;
3923
3924 assert (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER);
3925
3926 if (dest_used != NULL)
3927 *dest_used = FALSE;
3928
3929 bt = ffeinfo_basictype (ffebld_info (expr));
3930 kt = ffeinfo_kindtype (ffebld_info (expr));
3931 tree_type = ffecom_tree_type[bt][kt];
3932
3933 if (list != NULL)
3934 {
3935 arg1 = ffebld_head (list);
3936 if (arg1 != NULL && ffebld_op (arg1) == FFEBLD_opANY)
3937 return error_mark_node;
3938 if ((list = ffebld_trail (list)) != NULL)
3939 {
3940 arg2 = ffebld_head (list);
3941 if (arg2 != NULL && ffebld_op (arg2) == FFEBLD_opANY)
3942 return error_mark_node;
3943 if ((list = ffebld_trail (list)) != NULL)
3944 {
3945 arg3 = ffebld_head (list);
3946 if (arg3 != NULL && ffebld_op (arg3) == FFEBLD_opANY)
3947 return error_mark_node;
3948 }
3949 else
3950 arg3 = NULL;
3951 }
3952 else
3953 arg2 = arg3 = NULL;
3954 }
3955 else
3956 arg1 = arg2 = arg3 = NULL;
3957
3958 /* <list> ends up at the opITEM of the 3rd arg, or NULL if there are < 3
3959 args. This is used by the MAX/MIN expansions. */
3960
3961 if (arg1 != NULL)
3962 arg1_type = ffecom_tree_type
3963 [ffeinfo_basictype (ffebld_info (arg1))]
3964 [ffeinfo_kindtype (ffebld_info (arg1))];
3965 else
3966 arg1_type = NULL_TREE; /* Really not needed, but might catch bugs
3967 here. */
3968
3969 /* There are several ways for each of the cases in the following switch
3970 statements to exit (from simplest to use to most complicated):
3971
3972 break; (when expr_tree == NULL)
3973
3974 A standard call is made to the specific intrinsic just as if it had been
3975 passed in as a dummy procedure and called as any old procedure. This
3976 method can produce slower code but in some cases it's the easiest way for
3977 now. However, if a (presumably faster) direct call is available,
3978 that is used, so this is the easiest way in many more cases now.
3979
3980 gfrt = FFECOM_gfrtWHATEVER;
3981 break;
3982
3983 gfrt contains the gfrt index of a library function to call, passing the
3984 argument(s) by value rather than by reference. Used when a more
3985 careful choice of library function is needed than that provided
3986 by the vanilla `break;'.
3987
3988 return expr_tree;
3989
3990 The expr_tree has been completely set up and is ready to be returned
3991 as is. No further actions are taken. Use this when the tree is not
3992 in the simple form for one of the arity_n labels. */
3993
3994 /* For info on how the switch statement cases were written, see the files
3995 enclosed in comments below the switch statement. */
3996
3997 codegen_imp = ffebld_symter_implementation (ffebld_left (expr));
3998 gfrt = ffeintrin_gfrt_direct (codegen_imp);
3999 if (gfrt == FFECOM_gfrt)
4000 gfrt = ffeintrin_gfrt_indirect (codegen_imp);
4001
4002 switch (codegen_imp)
4003 {
4004 case FFEINTRIN_impABS:
4005 case FFEINTRIN_impCABS:
4006 case FFEINTRIN_impCDABS:
4007 case FFEINTRIN_impDABS:
4008 case FFEINTRIN_impIABS:
4009 if (ffeinfo_basictype (ffebld_info (arg1))
4010 == FFEINFO_basictypeCOMPLEX)
4011 {
4012 if (kt == FFEINFO_kindtypeREAL1)
4013 gfrt = FFECOM_gfrtCABS;
4014 else if (kt == FFEINFO_kindtypeREAL2)
4015 gfrt = FFECOM_gfrtCDABS;
4016 break;
4017 }
4018 return ffecom_1 (ABS_EXPR, tree_type,
4019 convert (tree_type, ffecom_expr (arg1)));
4020
4021 case FFEINTRIN_impACOS:
4022 case FFEINTRIN_impDACOS:
4023 break;
4024
4025 case FFEINTRIN_impAIMAG:
4026 case FFEINTRIN_impDIMAG:
4027 case FFEINTRIN_impIMAGPART:
4028 if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
4029 arg1_type = TREE_TYPE (arg1_type);
4030 else
4031 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
4032
4033 return
4034 convert (tree_type,
4035 ffecom_1 (IMAGPART_EXPR, arg1_type,
4036 ffecom_expr (arg1)));
4037
4038 case FFEINTRIN_impAINT:
4039 case FFEINTRIN_impDINT:
c7e4ee3a
CB
4040#if 0
4041 /* ~~Someday implement FIX_TRUNC_EXPR yielding same type as arg. */
5ff904cd
JL
4042 return ffecom_1 (FIX_TRUNC_EXPR, tree_type, ffecom_expr (arg1));
4043#else /* in the meantime, must use floor to avoid range problems with ints */
4044 /* r__1 = r1 >= 0 ? floor(r1) : -floor(-r1); */
4045 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4046 return
4047 convert (tree_type,
4048 ffecom_3 (COND_EXPR, double_type_node,
4049 ffecom_truth_value
4050 (ffecom_2 (GE_EXPR, integer_type_node,
4051 saved_expr1,
4052 convert (arg1_type,
4053 ffecom_float_zero_))),
4054 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4055 build_tree_list (NULL_TREE,
4056 convert (double_type_node,
c7e4ee3a
CB
4057 saved_expr1)),
4058 NULL_TREE),
5ff904cd
JL
4059 ffecom_1 (NEGATE_EXPR, double_type_node,
4060 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4061 build_tree_list (NULL_TREE,
4062 convert (double_type_node,
4063 ffecom_1 (NEGATE_EXPR,
4064 arg1_type,
c7e4ee3a
CB
4065 saved_expr1))),
4066 NULL_TREE)
5ff904cd
JL
4067 ))
4068 );
4069#endif
4070
4071 case FFEINTRIN_impANINT:
4072 case FFEINTRIN_impDNINT:
4073#if 0 /* This way of doing it won't handle real
4074 numbers of large magnitudes. */
4075 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4076 expr_tree = convert (tree_type,
4077 convert (integer_type_node,
4078 ffecom_3 (COND_EXPR, tree_type,
4079 ffecom_truth_value
4080 (ffecom_2 (GE_EXPR,
4081 integer_type_node,
4082 saved_expr1,
4083 ffecom_float_zero_)),
4084 ffecom_2 (PLUS_EXPR,
4085 tree_type,
4086 saved_expr1,
4087 ffecom_float_half_),
4088 ffecom_2 (MINUS_EXPR,
4089 tree_type,
4090 saved_expr1,
4091 ffecom_float_half_))));
4092 return expr_tree;
4093#else /* So we instead call floor. */
4094 /* r__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1) */
4095 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4096 return
4097 convert (tree_type,
4098 ffecom_3 (COND_EXPR, double_type_node,
4099 ffecom_truth_value
4100 (ffecom_2 (GE_EXPR, integer_type_node,
4101 saved_expr1,
4102 convert (arg1_type,
4103 ffecom_float_zero_))),
4104 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4105 build_tree_list (NULL_TREE,
4106 convert (double_type_node,
4107 ffecom_2 (PLUS_EXPR,
4108 arg1_type,
4109 saved_expr1,
4110 convert (arg1_type,
c7e4ee3a
CB
4111 ffecom_float_half_)))),
4112 NULL_TREE),
5ff904cd
JL
4113 ffecom_1 (NEGATE_EXPR, double_type_node,
4114 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4115 build_tree_list (NULL_TREE,
4116 convert (double_type_node,
4117 ffecom_2 (MINUS_EXPR,
4118 arg1_type,
4119 convert (arg1_type,
4120 ffecom_float_half_),
c7e4ee3a
CB
4121 saved_expr1))),
4122 NULL_TREE))
5ff904cd
JL
4123 )
4124 );
4125#endif
4126
4127 case FFEINTRIN_impASIN:
4128 case FFEINTRIN_impDASIN:
4129 case FFEINTRIN_impATAN:
4130 case FFEINTRIN_impDATAN:
4131 case FFEINTRIN_impATAN2:
4132 case FFEINTRIN_impDATAN2:
4133 break;
4134
4135 case FFEINTRIN_impCHAR:
4136 case FFEINTRIN_impACHAR:
c7e4ee3a
CB
4137#ifdef HOHO
4138 tempvar = ffecom_make_tempvar (char_type_node, 1, -1);
4139#else
4140 tempvar = ffebld_nonter_hook (expr);
4141 assert (tempvar);
4142#endif
5ff904cd
JL
4143 {
4144 tree tmv = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (tempvar)));
4145
4146 expr_tree = ffecom_modify (tmv,
4147 ffecom_2 (ARRAY_REF, tmv, tempvar,
4148 integer_one_node),
4149 convert (tmv, ffecom_expr (arg1)));
4150 }
4151 expr_tree = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar),
4152 expr_tree,
4153 tempvar);
4154 expr_tree = ffecom_1 (ADDR_EXPR,
4155 build_pointer_type (TREE_TYPE (expr_tree)),
4156 expr_tree);
4157 return expr_tree;
4158
4159 case FFEINTRIN_impCMPLX:
4160 case FFEINTRIN_impDCMPLX:
4161 if (arg2 == NULL)
4162 return
4163 convert (tree_type, ffecom_expr (arg1));
4164
4165 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
4166 return
4167 ffecom_2 (COMPLEX_EXPR, tree_type,
4168 convert (real_type, ffecom_expr (arg1)),
4169 convert (real_type,
4170 ffecom_expr (arg2)));
4171
4172 case FFEINTRIN_impCOMPLEX:
4173 return
4174 ffecom_2 (COMPLEX_EXPR, tree_type,
4175 ffecom_expr (arg1),
4176 ffecom_expr (arg2));
4177
4178 case FFEINTRIN_impCONJG:
4179 case FFEINTRIN_impDCONJG:
4180 {
4181 tree arg1_tree;
4182
4183 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
4184 arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4185 return
4186 ffecom_2 (COMPLEX_EXPR, tree_type,
4187 ffecom_1 (REALPART_EXPR, real_type, arg1_tree),
4188 ffecom_1 (NEGATE_EXPR, real_type,
4189 ffecom_1 (IMAGPART_EXPR, real_type, arg1_tree)));
4190 }
4191
4192 case FFEINTRIN_impCOS:
4193 case FFEINTRIN_impCCOS:
4194 case FFEINTRIN_impCDCOS:
4195 case FFEINTRIN_impDCOS:
4196 if (bt == FFEINFO_basictypeCOMPLEX)
4197 {
4198 if (kt == FFEINFO_kindtypeREAL1)
4199 gfrt = FFECOM_gfrtCCOS; /* Overlapping result okay. */
4200 else if (kt == FFEINFO_kindtypeREAL2)
4201 gfrt = FFECOM_gfrtCDCOS; /* Overlapping result okay. */
4202 }
4203 break;
4204
4205 case FFEINTRIN_impCOSH:
4206 case FFEINTRIN_impDCOSH:
4207 break;
4208
4209 case FFEINTRIN_impDBLE:
4210 case FFEINTRIN_impDFLOAT:
4211 case FFEINTRIN_impDREAL:
4212 case FFEINTRIN_impFLOAT:
4213 case FFEINTRIN_impIDINT:
4214 case FFEINTRIN_impIFIX:
4215 case FFEINTRIN_impINT2:
4216 case FFEINTRIN_impINT8:
4217 case FFEINTRIN_impINT:
4218 case FFEINTRIN_impLONG:
4219 case FFEINTRIN_impREAL:
4220 case FFEINTRIN_impSHORT:
4221 case FFEINTRIN_impSNGL:
4222 return convert (tree_type, ffecom_expr (arg1));
4223
4224 case FFEINTRIN_impDIM:
4225 case FFEINTRIN_impDDIM:
4226 case FFEINTRIN_impIDIM:
4227 saved_expr1 = ffecom_save_tree (convert (tree_type,
4228 ffecom_expr (arg1)));
4229 saved_expr2 = ffecom_save_tree (convert (tree_type,
4230 ffecom_expr (arg2)));
4231 return
4232 ffecom_3 (COND_EXPR, tree_type,
4233 ffecom_truth_value
4234 (ffecom_2 (GT_EXPR, integer_type_node,
4235 saved_expr1,
4236 saved_expr2)),
4237 ffecom_2 (MINUS_EXPR, tree_type,
4238 saved_expr1,
4239 saved_expr2),
4240 convert (tree_type, ffecom_float_zero_));
4241
4242 case FFEINTRIN_impDPROD:
4243 return
4244 ffecom_2 (MULT_EXPR, tree_type,
4245 convert (tree_type, ffecom_expr (arg1)),
4246 convert (tree_type, ffecom_expr (arg2)));
4247
4248 case FFEINTRIN_impEXP:
4249 case FFEINTRIN_impCDEXP:
4250 case FFEINTRIN_impCEXP:
4251 case FFEINTRIN_impDEXP:
4252 if (bt == FFEINFO_basictypeCOMPLEX)
4253 {
4254 if (kt == FFEINFO_kindtypeREAL1)
4255 gfrt = FFECOM_gfrtCEXP; /* Overlapping result okay. */
4256 else if (kt == FFEINFO_kindtypeREAL2)
4257 gfrt = FFECOM_gfrtCDEXP; /* Overlapping result okay. */
4258 }
4259 break;
4260
4261 case FFEINTRIN_impICHAR:
4262 case FFEINTRIN_impIACHAR:
4263#if 0 /* The simple approach. */
4264 ffecom_char_args_ (&expr_tree, &saved_expr1 /* Ignored */ , arg1);
4265 expr_tree
4266 = ffecom_1 (INDIRECT_REF,
4267 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
4268 expr_tree);
4269 expr_tree
4270 = ffecom_2 (ARRAY_REF,
4271 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
4272 expr_tree,
4273 integer_one_node);
4274 return convert (tree_type, expr_tree);
4275#else /* The more interesting (and more optimal) approach. */
4276 expr_tree = ffecom_intrinsic_ichar_ (tree_type, arg1, &saved_expr1);
4277 expr_tree = ffecom_3 (COND_EXPR, tree_type,
4278 saved_expr1,
4279 expr_tree,
4280 convert (tree_type, integer_zero_node));
4281 return expr_tree;
4282#endif
4283
4284 case FFEINTRIN_impINDEX:
4285 break;
4286
4287 case FFEINTRIN_impLEN:
4288#if 0
4289 break; /* The simple approach. */
4290#else
4291 return ffecom_intrinsic_len_ (arg1); /* The more optimal approach. */
4292#endif
4293
4294 case FFEINTRIN_impLGE:
4295 case FFEINTRIN_impLGT:
4296 case FFEINTRIN_impLLE:
4297 case FFEINTRIN_impLLT:
4298 break;
4299
4300 case FFEINTRIN_impLOG:
4301 case FFEINTRIN_impALOG:
4302 case FFEINTRIN_impCDLOG:
4303 case FFEINTRIN_impCLOG:
4304 case FFEINTRIN_impDLOG:
4305 if (bt == FFEINFO_basictypeCOMPLEX)
4306 {
4307 if (kt == FFEINFO_kindtypeREAL1)
4308 gfrt = FFECOM_gfrtCLOG; /* Overlapping result okay. */
4309 else if (kt == FFEINFO_kindtypeREAL2)
4310 gfrt = FFECOM_gfrtCDLOG; /* Overlapping result okay. */
4311 }
4312 break;
4313
4314 case FFEINTRIN_impLOG10:
4315 case FFEINTRIN_impALOG10:
4316 case FFEINTRIN_impDLOG10:
4317 if (gfrt != FFECOM_gfrt)
4318 break; /* Already picked one, stick with it. */
4319
4320 if (kt == FFEINFO_kindtypeREAL1)
4321 gfrt = FFECOM_gfrtALOG10;
4322 else if (kt == FFEINFO_kindtypeREAL2)
4323 gfrt = FFECOM_gfrtDLOG10;
4324 break;
4325
4326 case FFEINTRIN_impMAX:
4327 case FFEINTRIN_impAMAX0:
4328 case FFEINTRIN_impAMAX1:
4329 case FFEINTRIN_impDMAX1:
4330 case FFEINTRIN_impMAX0:
4331 case FFEINTRIN_impMAX1:
4332 if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4333 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4334 else
4335 arg1_type = tree_type;
4336 expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4337 convert (arg1_type, ffecom_expr (arg1)),
4338 convert (arg1_type, ffecom_expr (arg2)));
4339 for (; list != NULL; list = ffebld_trail (list))
4340 {
4341 if ((ffebld_head (list) == NULL)
4342 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4343 continue;
4344 expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4345 expr_tree,
4346 convert (arg1_type,
4347 ffecom_expr (ffebld_head (list))));
4348 }
4349 return convert (tree_type, expr_tree);
4350
4351 case FFEINTRIN_impMIN:
4352 case FFEINTRIN_impAMIN0:
4353 case FFEINTRIN_impAMIN1:
4354 case FFEINTRIN_impDMIN1:
4355 case FFEINTRIN_impMIN0:
4356 case FFEINTRIN_impMIN1:
4357 if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4358 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4359 else
4360 arg1_type = tree_type;
4361 expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4362 convert (arg1_type, ffecom_expr (arg1)),
4363 convert (arg1_type, ffecom_expr (arg2)));
4364 for (; list != NULL; list = ffebld_trail (list))
4365 {
4366 if ((ffebld_head (list) == NULL)
4367 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4368 continue;
4369 expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4370 expr_tree,
4371 convert (arg1_type,
4372 ffecom_expr (ffebld_head (list))));
4373 }
4374 return convert (tree_type, expr_tree);
4375
4376 case FFEINTRIN_impMOD:
4377 case FFEINTRIN_impAMOD:
4378 case FFEINTRIN_impDMOD:
4379 if (bt != FFEINFO_basictypeREAL)
4380 return ffecom_2 (TRUNC_MOD_EXPR, tree_type,
4381 convert (tree_type, ffecom_expr (arg1)),
4382 convert (tree_type, ffecom_expr (arg2)));
4383
4384 if (kt == FFEINFO_kindtypeREAL1)
4385 gfrt = FFECOM_gfrtAMOD;
4386 else if (kt == FFEINFO_kindtypeREAL2)
4387 gfrt = FFECOM_gfrtDMOD;
4388 break;
4389
4390 case FFEINTRIN_impNINT:
4391 case FFEINTRIN_impIDNINT:
c7e4ee3a
CB
4392#if 0
4393 /* ~~Ideally FIX_ROUND_EXPR would be implemented, but it ain't yet. */
5ff904cd
JL
4394 return ffecom_1 (FIX_ROUND_EXPR, tree_type, ffecom_expr (arg1));
4395#else
4396 /* i__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1); */
4397 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4398 return
4399 convert (ffecom_integer_type_node,
4400 ffecom_3 (COND_EXPR, arg1_type,
4401 ffecom_truth_value
4402 (ffecom_2 (GE_EXPR, integer_type_node,
4403 saved_expr1,
4404 convert (arg1_type,
4405 ffecom_float_zero_))),
4406 ffecom_2 (PLUS_EXPR, arg1_type,
4407 saved_expr1,
4408 convert (arg1_type,
4409 ffecom_float_half_)),
4410 ffecom_2 (MINUS_EXPR, arg1_type,
4411 saved_expr1,
4412 convert (arg1_type,
4413 ffecom_float_half_))));
4414#endif
4415
4416 case FFEINTRIN_impSIGN:
4417 case FFEINTRIN_impDSIGN:
4418 case FFEINTRIN_impISIGN:
4419 {
4420 tree arg2_tree = ffecom_expr (arg2);
4421
4422 saved_expr1
4423 = ffecom_save_tree
4424 (ffecom_1 (ABS_EXPR, tree_type,
4425 convert (tree_type,
4426 ffecom_expr (arg1))));
4427 expr_tree
4428 = ffecom_3 (COND_EXPR, tree_type,
4429 ffecom_truth_value
4430 (ffecom_2 (GE_EXPR, integer_type_node,
4431 arg2_tree,
4432 convert (TREE_TYPE (arg2_tree),
4433 integer_zero_node))),
4434 saved_expr1,
4435 ffecom_1 (NEGATE_EXPR, tree_type, saved_expr1));
4436 /* Make sure SAVE_EXPRs get referenced early enough. */
4437 expr_tree
4438 = ffecom_2 (COMPOUND_EXPR, tree_type,
4439 convert (void_type_node, saved_expr1),
4440 expr_tree);
4441 }
4442 return expr_tree;
4443
4444 case FFEINTRIN_impSIN:
4445 case FFEINTRIN_impCDSIN:
4446 case FFEINTRIN_impCSIN:
4447 case FFEINTRIN_impDSIN:
4448 if (bt == FFEINFO_basictypeCOMPLEX)
4449 {
4450 if (kt == FFEINFO_kindtypeREAL1)
4451 gfrt = FFECOM_gfrtCSIN; /* Overlapping result okay. */
4452 else if (kt == FFEINFO_kindtypeREAL2)
4453 gfrt = FFECOM_gfrtCDSIN; /* Overlapping result okay. */
4454 }
4455 break;
4456
4457 case FFEINTRIN_impSINH:
4458 case FFEINTRIN_impDSINH:
4459 break;
4460
4461 case FFEINTRIN_impSQRT:
4462 case FFEINTRIN_impCDSQRT:
4463 case FFEINTRIN_impCSQRT:
4464 case FFEINTRIN_impDSQRT:
4465 if (bt == FFEINFO_basictypeCOMPLEX)
4466 {
4467 if (kt == FFEINFO_kindtypeREAL1)
4468 gfrt = FFECOM_gfrtCSQRT; /* Overlapping result okay. */
4469 else if (kt == FFEINFO_kindtypeREAL2)
4470 gfrt = FFECOM_gfrtCDSQRT; /* Overlapping result okay. */
4471 }
4472 break;
4473
4474 case FFEINTRIN_impTAN:
4475 case FFEINTRIN_impDTAN:
4476 case FFEINTRIN_impTANH:
4477 case FFEINTRIN_impDTANH:
4478 break;
4479
4480 case FFEINTRIN_impREALPART:
4481 if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
4482 arg1_type = TREE_TYPE (arg1_type);
4483 else
4484 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
4485
4486 return
4487 convert (tree_type,
4488 ffecom_1 (REALPART_EXPR, arg1_type,
4489 ffecom_expr (arg1)));
4490
4491 case FFEINTRIN_impIAND:
4492 case FFEINTRIN_impAND:
4493 return ffecom_2 (BIT_AND_EXPR, tree_type,
4494 convert (tree_type,
4495 ffecom_expr (arg1)),
4496 convert (tree_type,
4497 ffecom_expr (arg2)));
4498
4499 case FFEINTRIN_impIOR:
4500 case FFEINTRIN_impOR:
4501 return ffecom_2 (BIT_IOR_EXPR, tree_type,
4502 convert (tree_type,
4503 ffecom_expr (arg1)),
4504 convert (tree_type,
4505 ffecom_expr (arg2)));
4506
4507 case FFEINTRIN_impIEOR:
4508 case FFEINTRIN_impXOR:
4509 return ffecom_2 (BIT_XOR_EXPR, tree_type,
4510 convert (tree_type,
4511 ffecom_expr (arg1)),
4512 convert (tree_type,
4513 ffecom_expr (arg2)));
4514
4515 case FFEINTRIN_impLSHIFT:
4516 return ffecom_2 (LSHIFT_EXPR, tree_type,
4517 ffecom_expr (arg1),
4518 convert (integer_type_node,
4519 ffecom_expr (arg2)));
4520
4521 case FFEINTRIN_impRSHIFT:
4522 return ffecom_2 (RSHIFT_EXPR, tree_type,
4523 ffecom_expr (arg1),
4524 convert (integer_type_node,
4525 ffecom_expr (arg2)));
4526
4527 case FFEINTRIN_impNOT:
4528 return ffecom_1 (BIT_NOT_EXPR, tree_type, ffecom_expr (arg1));
4529
4530 case FFEINTRIN_impBIT_SIZE:
4531 return convert (tree_type, TYPE_SIZE (arg1_type));
4532
4533 case FFEINTRIN_impBTEST:
4534 {
4535 ffetargetLogical1 true;
4536 ffetargetLogical1 false;
4537 tree true_tree;
4538 tree false_tree;
4539
4540 ffetarget_logical1 (&true, TRUE);
4541 ffetarget_logical1 (&false, FALSE);
4542 if (true == 1)
4543 true_tree = convert (tree_type, integer_one_node);
4544 else
4545 true_tree = convert (tree_type, build_int_2 (true, 0));
4546 if (false == 0)
4547 false_tree = convert (tree_type, integer_zero_node);
4548 else
4549 false_tree = convert (tree_type, build_int_2 (false, 0));
4550
4551 return
4552 ffecom_3 (COND_EXPR, tree_type,
4553 ffecom_truth_value
4554 (ffecom_2 (EQ_EXPR, integer_type_node,
4555 ffecom_2 (BIT_AND_EXPR, arg1_type,
4556 ffecom_expr (arg1),
4557 ffecom_2 (LSHIFT_EXPR, arg1_type,
4558 convert (arg1_type,
4559 integer_one_node),
4560 convert (integer_type_node,
4561 ffecom_expr (arg2)))),
4562 convert (arg1_type,
4563 integer_zero_node))),
4564 false_tree,
4565 true_tree);
4566 }
4567
4568 case FFEINTRIN_impIBCLR:
4569 return
4570 ffecom_2 (BIT_AND_EXPR, tree_type,
4571 ffecom_expr (arg1),
4572 ffecom_1 (BIT_NOT_EXPR, tree_type,
4573 ffecom_2 (LSHIFT_EXPR, tree_type,
4574 convert (tree_type,
4575 integer_one_node),
4576 convert (integer_type_node,
4577 ffecom_expr (arg2)))));
4578
4579 case FFEINTRIN_impIBITS:
4580 {
4581 tree arg3_tree = ffecom_save_tree (convert (integer_type_node,
4582 ffecom_expr (arg3)));
4583 tree uns_type
4584 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4585
4586 expr_tree
4587 = ffecom_2 (BIT_AND_EXPR, tree_type,
4588 ffecom_2 (RSHIFT_EXPR, tree_type,
4589 ffecom_expr (arg1),
4590 convert (integer_type_node,
4591 ffecom_expr (arg2))),
4592 convert (tree_type,
4593 ffecom_2 (RSHIFT_EXPR, uns_type,
4594 ffecom_1 (BIT_NOT_EXPR,
4595 uns_type,
4596 convert (uns_type,
4597 integer_zero_node)),
4598 ffecom_2 (MINUS_EXPR,
4599 integer_type_node,
4600 TYPE_SIZE (uns_type),
4601 arg3_tree))));
4602#if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4603 expr_tree
4604 = ffecom_3 (COND_EXPR, tree_type,
4605 ffecom_truth_value
4606 (ffecom_2 (NE_EXPR, integer_type_node,
4607 arg3_tree,
4608 integer_zero_node)),
4609 expr_tree,
4610 convert (tree_type, integer_zero_node));
4611#endif
4612 }
4613 return expr_tree;
4614
4615 case FFEINTRIN_impIBSET:
4616 return
4617 ffecom_2 (BIT_IOR_EXPR, tree_type,
4618 ffecom_expr (arg1),
4619 ffecom_2 (LSHIFT_EXPR, tree_type,
4620 convert (tree_type, integer_one_node),
4621 convert (integer_type_node,
4622 ffecom_expr (arg2))));
4623
4624 case FFEINTRIN_impISHFT:
4625 {
4626 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4627 tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4628 ffecom_expr (arg2)));
4629 tree uns_type
4630 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4631
4632 expr_tree
4633 = ffecom_3 (COND_EXPR, tree_type,
4634 ffecom_truth_value
4635 (ffecom_2 (GE_EXPR, integer_type_node,
4636 arg2_tree,
4637 integer_zero_node)),
4638 ffecom_2 (LSHIFT_EXPR, tree_type,
4639 arg1_tree,
4640 arg2_tree),
4641 convert (tree_type,
4642 ffecom_2 (RSHIFT_EXPR, uns_type,
4643 convert (uns_type, arg1_tree),
4644 ffecom_1 (NEGATE_EXPR,
4645 integer_type_node,
4646 arg2_tree))));
4647#if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4648 expr_tree
4649 = ffecom_3 (COND_EXPR, tree_type,
4650 ffecom_truth_value
4651 (ffecom_2 (NE_EXPR, integer_type_node,
4652 arg2_tree,
4653 TYPE_SIZE (uns_type))),
4654 expr_tree,
4655 convert (tree_type, integer_zero_node));
4656#endif
4657 /* Make sure SAVE_EXPRs get referenced early enough. */
4658 expr_tree
4659 = ffecom_2 (COMPOUND_EXPR, tree_type,
4660 convert (void_type_node, arg1_tree),
4661 ffecom_2 (COMPOUND_EXPR, tree_type,
4662 convert (void_type_node, arg2_tree),
4663 expr_tree));
4664 }
4665 return expr_tree;
4666
4667 case FFEINTRIN_impISHFTC:
4668 {
4669 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4670 tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4671 ffecom_expr (arg2)));
4672 tree arg3_tree = (arg3 == NULL) ? TYPE_SIZE (tree_type)
4673 : ffecom_save_tree (convert (integer_type_node, ffecom_expr (arg3)));
4674 tree shift_neg;
4675 tree shift_pos;
4676 tree mask_arg1;
4677 tree masked_arg1;
4678 tree uns_type
4679 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4680
4681 mask_arg1
4682 = ffecom_2 (LSHIFT_EXPR, tree_type,
4683 ffecom_1 (BIT_NOT_EXPR, tree_type,
4684 convert (tree_type, integer_zero_node)),
4685 arg3_tree);
4686#if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4687 mask_arg1
4688 = ffecom_3 (COND_EXPR, tree_type,
4689 ffecom_truth_value
4690 (ffecom_2 (NE_EXPR, integer_type_node,
4691 arg3_tree,
4692 TYPE_SIZE (uns_type))),
4693 mask_arg1,
4694 convert (tree_type, integer_zero_node));
4695#endif
4696 mask_arg1 = ffecom_save_tree (mask_arg1);
4697 masked_arg1
4698 = ffecom_2 (BIT_AND_EXPR, tree_type,
4699 arg1_tree,
4700 ffecom_1 (BIT_NOT_EXPR, tree_type,
4701 mask_arg1));
4702 masked_arg1 = ffecom_save_tree (masked_arg1);
4703 shift_neg
4704 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4705 convert (tree_type,
4706 ffecom_2 (RSHIFT_EXPR, uns_type,
4707 convert (uns_type, masked_arg1),
4708 ffecom_1 (NEGATE_EXPR,
4709 integer_type_node,
4710 arg2_tree))),
4711 ffecom_2 (LSHIFT_EXPR, tree_type,
4712 arg1_tree,
4713 ffecom_2 (PLUS_EXPR, integer_type_node,
4714 arg2_tree,
4715 arg3_tree)));
4716 shift_pos
4717 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4718 ffecom_2 (LSHIFT_EXPR, tree_type,
4719 arg1_tree,
4720 arg2_tree),
4721 convert (tree_type,
4722 ffecom_2 (RSHIFT_EXPR, uns_type,
4723 convert (uns_type, masked_arg1),
4724 ffecom_2 (MINUS_EXPR,
4725 integer_type_node,
4726 arg3_tree,
4727 arg2_tree))));
4728 expr_tree
4729 = ffecom_3 (COND_EXPR, tree_type,
4730 ffecom_truth_value
4731 (ffecom_2 (LT_EXPR, integer_type_node,
4732 arg2_tree,
4733 integer_zero_node)),
4734 shift_neg,
4735 shift_pos);
4736 expr_tree
4737 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4738 ffecom_2 (BIT_AND_EXPR, tree_type,
4739 mask_arg1,
4740 arg1_tree),
4741 ffecom_2 (BIT_AND_EXPR, tree_type,
4742 ffecom_1 (BIT_NOT_EXPR, tree_type,
4743 mask_arg1),
4744 expr_tree));
4745 expr_tree
4746 = ffecom_3 (COND_EXPR, tree_type,
4747 ffecom_truth_value
4748 (ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
4749 ffecom_2 (EQ_EXPR, integer_type_node,
4750 ffecom_1 (ABS_EXPR,
4751 integer_type_node,
4752 arg2_tree),
4753 arg3_tree),
4754 ffecom_2 (EQ_EXPR, integer_type_node,
4755 arg2_tree,
4756 integer_zero_node))),
4757 arg1_tree,
4758 expr_tree);
4759 /* Make sure SAVE_EXPRs get referenced early enough. */
4760 expr_tree
4761 = ffecom_2 (COMPOUND_EXPR, tree_type,
4762 convert (void_type_node, arg1_tree),
4763 ffecom_2 (COMPOUND_EXPR, tree_type,
4764 convert (void_type_node, arg2_tree),
4765 ffecom_2 (COMPOUND_EXPR, tree_type,
4766 convert (void_type_node,
4767 mask_arg1),
4768 ffecom_2 (COMPOUND_EXPR, tree_type,
4769 convert (void_type_node,
4770 masked_arg1),
4771 expr_tree))));
4772 expr_tree
4773 = ffecom_2 (COMPOUND_EXPR, tree_type,
4774 convert (void_type_node,
4775 arg3_tree),
4776 expr_tree);
4777 }
4778 return expr_tree;
4779
4780 case FFEINTRIN_impLOC:
4781 {
4782 tree arg1_tree = ffecom_expr (arg1);
4783
4784 expr_tree
4785 = convert (tree_type,
4786 ffecom_1 (ADDR_EXPR,
4787 build_pointer_type (TREE_TYPE (arg1_tree)),
4788 arg1_tree));
4789 }
4790 return expr_tree;
4791
4792 case FFEINTRIN_impMVBITS:
4793 {
4794 tree arg1_tree;
4795 tree arg2_tree;
4796 tree arg3_tree;
4797 ffebld arg4 = ffebld_head (ffebld_trail (list));
4798 tree arg4_tree;
4799 tree arg4_type;
4800 ffebld arg5 = ffebld_head (ffebld_trail (ffebld_trail (list)));
4801 tree arg5_tree;
4802 tree prep_arg1;
4803 tree prep_arg4;
4804 tree arg5_plus_arg3;
4805
5ff904cd
JL
4806 arg2_tree = convert (integer_type_node,
4807 ffecom_expr (arg2));
4808 arg3_tree = ffecom_save_tree (convert (integer_type_node,
4809 ffecom_expr (arg3)));
c7e4ee3a 4810 arg4_tree = ffecom_expr_rw (NULL_TREE, arg4);
5ff904cd
JL
4811 arg4_type = TREE_TYPE (arg4_tree);
4812
4813 arg1_tree = ffecom_save_tree (convert (arg4_type,
4814 ffecom_expr (arg1)));
4815
4816 arg5_tree = ffecom_save_tree (convert (integer_type_node,
4817 ffecom_expr (arg5)));
4818
5ff904cd
JL
4819 prep_arg1
4820 = ffecom_2 (LSHIFT_EXPR, arg4_type,
4821 ffecom_2 (BIT_AND_EXPR, arg4_type,
4822 ffecom_2 (RSHIFT_EXPR, arg4_type,
4823 arg1_tree,
4824 arg2_tree),
4825 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4826 ffecom_2 (LSHIFT_EXPR, arg4_type,
4827 ffecom_1 (BIT_NOT_EXPR,
4828 arg4_type,
4829 convert
4830 (arg4_type,
4831 integer_zero_node)),
4832 arg3_tree))),
4833 arg5_tree);
4834 arg5_plus_arg3
4835 = ffecom_save_tree (ffecom_2 (PLUS_EXPR, arg4_type,
4836 arg5_tree,
4837 arg3_tree));
4838 prep_arg4
4839 = ffecom_2 (LSHIFT_EXPR, arg4_type,
4840 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4841 convert (arg4_type,
4842 integer_zero_node)),
4843 arg5_plus_arg3);
4844#if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4845 prep_arg4
4846 = ffecom_3 (COND_EXPR, arg4_type,
4847 ffecom_truth_value
4848 (ffecom_2 (NE_EXPR, integer_type_node,
4849 arg5_plus_arg3,
4850 convert (TREE_TYPE (arg5_plus_arg3),
4851 TYPE_SIZE (arg4_type)))),
4852 prep_arg4,
4853 convert (arg4_type, integer_zero_node));
4854#endif
4855 prep_arg4
4856 = ffecom_2 (BIT_AND_EXPR, arg4_type,
4857 arg4_tree,
4858 ffecom_2 (BIT_IOR_EXPR, arg4_type,
4859 prep_arg4,
4860 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4861 ffecom_2 (LSHIFT_EXPR, arg4_type,
4862 ffecom_1 (BIT_NOT_EXPR,
4863 arg4_type,
4864 convert
4865 (arg4_type,
4866 integer_zero_node)),
4867 arg5_tree))));
4868 prep_arg1
4869 = ffecom_2 (BIT_IOR_EXPR, arg4_type,
4870 prep_arg1,
4871 prep_arg4);
4872#if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4873 prep_arg1
4874 = ffecom_3 (COND_EXPR, arg4_type,
4875 ffecom_truth_value
4876 (ffecom_2 (NE_EXPR, integer_type_node,
4877 arg3_tree,
4878 convert (TREE_TYPE (arg3_tree),
4879 integer_zero_node))),
4880 prep_arg1,
4881 arg4_tree);
4882 prep_arg1
4883 = ffecom_3 (COND_EXPR, arg4_type,
4884 ffecom_truth_value
4885 (ffecom_2 (NE_EXPR, integer_type_node,
4886 arg3_tree,
4887 convert (TREE_TYPE (arg3_tree),
4888 TYPE_SIZE (arg4_type)))),
4889 prep_arg1,
4890 arg1_tree);
4891#endif
4892 expr_tree
4893 = ffecom_2s (MODIFY_EXPR, void_type_node,
4894 arg4_tree,
4895 prep_arg1);
4896 /* Make sure SAVE_EXPRs get referenced early enough. */
4897 expr_tree
4898 = ffecom_2 (COMPOUND_EXPR, void_type_node,
4899 arg1_tree,
4900 ffecom_2 (COMPOUND_EXPR, void_type_node,
4901 arg3_tree,
4902 ffecom_2 (COMPOUND_EXPR, void_type_node,
4903 arg5_tree,
4904 ffecom_2 (COMPOUND_EXPR, void_type_node,
4905 arg5_plus_arg3,
4906 expr_tree))));
4907 expr_tree
4908 = ffecom_2 (COMPOUND_EXPR, void_type_node,
4909 arg4_tree,
4910 expr_tree);
4911
4912 }
4913 return expr_tree;
4914
4915 case FFEINTRIN_impDERF:
4916 case FFEINTRIN_impERF:
4917 case FFEINTRIN_impDERFC:
4918 case FFEINTRIN_impERFC:
4919 break;
4920
4921 case FFEINTRIN_impIARGC:
4922 /* extern int xargc; i__1 = xargc - 1; */
4923 expr_tree = ffecom_2 (MINUS_EXPR, TREE_TYPE (ffecom_tree_xargc_),
4924 ffecom_tree_xargc_,
4925 convert (TREE_TYPE (ffecom_tree_xargc_),
4926 integer_one_node));
4927 return expr_tree;
4928
4929 case FFEINTRIN_impSIGNAL_func:
4930 case FFEINTRIN_impSIGNAL_subr:
4931 {
4932 tree arg1_tree;
4933 tree arg2_tree;
4934 tree arg3_tree;
4935
5ff904cd
JL
4936 arg1_tree = convert (ffecom_f2c_integer_type_node,
4937 ffecom_expr (arg1));
4938 arg1_tree = ffecom_1 (ADDR_EXPR,
4939 build_pointer_type (TREE_TYPE (arg1_tree)),
4940 arg1_tree);
4941
4942 /* Pass procedure as a pointer to it, anything else by value. */
4943 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
4944 arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
4945 else
4946 arg2_tree = ffecom_ptr_to_expr (arg2);
4947 arg2_tree = convert (TREE_TYPE (null_pointer_node),
4948 arg2_tree);
4949
4950 if (arg3 != NULL)
c7e4ee3a 4951 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
4952 else
4953 arg3_tree = NULL_TREE;
4954
5ff904cd
JL
4955 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4956 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4957 TREE_CHAIN (arg1_tree) = arg2_tree;
4958
4959 expr_tree
4960 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4961 ffecom_gfrt_kindtype (gfrt),
4962 FALSE,
4963 ((codegen_imp == FFEINTRIN_impSIGNAL_subr) ?
4964 NULL_TREE :
4965 tree_type),
4966 arg1_tree,
c7e4ee3a
CB
4967 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
4968 ffebld_nonter_hook (expr));
5ff904cd
JL
4969
4970 if (arg3_tree != NULL_TREE)
4971 expr_tree
4972 = ffecom_modify (NULL_TREE, arg3_tree,
4973 convert (TREE_TYPE (arg3_tree),
4974 expr_tree));
4975 }
4976 return expr_tree;
4977
4978 case FFEINTRIN_impALARM:
4979 {
4980 tree arg1_tree;
4981 tree arg2_tree;
4982 tree arg3_tree;
4983
5ff904cd
JL
4984 arg1_tree = convert (ffecom_f2c_integer_type_node,
4985 ffecom_expr (arg1));
4986 arg1_tree = ffecom_1 (ADDR_EXPR,
4987 build_pointer_type (TREE_TYPE (arg1_tree)),
4988 arg1_tree);
4989
4990 /* Pass procedure as a pointer to it, anything else by value. */
4991 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
4992 arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
4993 else
4994 arg2_tree = ffecom_ptr_to_expr (arg2);
4995 arg2_tree = convert (TREE_TYPE (null_pointer_node),
4996 arg2_tree);
4997
4998 if (arg3 != NULL)
c7e4ee3a 4999 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
5000 else
5001 arg3_tree = NULL_TREE;
5002
5ff904cd
JL
5003 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5004 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5005 TREE_CHAIN (arg1_tree) = arg2_tree;
5006
5007 expr_tree
5008 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5009 ffecom_gfrt_kindtype (gfrt),
5010 FALSE,
5011 NULL_TREE,
5012 arg1_tree,
c7e4ee3a
CB
5013 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5014 ffebld_nonter_hook (expr));
5ff904cd
JL
5015
5016 if (arg3_tree != NULL_TREE)
5017 expr_tree
5018 = ffecom_modify (NULL_TREE, arg3_tree,
5019 convert (TREE_TYPE (arg3_tree),
5020 expr_tree));
5021 }
5022 return expr_tree;
5023
5024 case FFEINTRIN_impCHDIR_subr:
5025 case FFEINTRIN_impFDATE_subr:
5026 case FFEINTRIN_impFGET_subr:
5027 case FFEINTRIN_impFPUT_subr:
5028 case FFEINTRIN_impGETCWD_subr:
5029 case FFEINTRIN_impHOSTNM_subr:
5030 case FFEINTRIN_impSYSTEM_subr:
5031 case FFEINTRIN_impUNLINK_subr:
5032 {
5033 tree arg1_len = integer_zero_node;
5034 tree arg1_tree;
5035 tree arg2_tree;
5036
5ff904cd
JL
5037 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5038
5039 if (arg2 != NULL)
c7e4ee3a 5040 arg2_tree = ffecom_expr_w (NULL_TREE, arg2);
5ff904cd
JL
5041 else
5042 arg2_tree = NULL_TREE;
5043
5ff904cd
JL
5044 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5045 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5046 TREE_CHAIN (arg1_tree) = arg1_len;
5047
5048 expr_tree
5049 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5050 ffecom_gfrt_kindtype (gfrt),
5051 FALSE,
5052 NULL_TREE,
5053 arg1_tree,
c7e4ee3a
CB
5054 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5055 ffebld_nonter_hook (expr));
5ff904cd
JL
5056
5057 if (arg2_tree != NULL_TREE)
5058 expr_tree
5059 = ffecom_modify (NULL_TREE, arg2_tree,
5060 convert (TREE_TYPE (arg2_tree),
5061 expr_tree));
5062 }
5063 return expr_tree;
5064
5065 case FFEINTRIN_impEXIT:
5066 if (arg1 != NULL)
5067 break;
5068
5069 expr_tree = build_tree_list (NULL_TREE,
5070 ffecom_1 (ADDR_EXPR,
5071 build_pointer_type
5072 (ffecom_integer_type_node),
5073 integer_zero_node));
5074
5075 return
5076 ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5077 ffecom_gfrt_kindtype (gfrt),
5078 FALSE,
5079 void_type_node,
5080 expr_tree,
c7e4ee3a
CB
5081 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5082 ffebld_nonter_hook (expr));
5ff904cd
JL
5083
5084 case FFEINTRIN_impFLUSH:
5085 if (arg1 == NULL)
5086 gfrt = FFECOM_gfrtFLUSH;
5087 else
5088 gfrt = FFECOM_gfrtFLUSH1;
5089 break;
5090
5091 case FFEINTRIN_impCHMOD_subr:
5092 case FFEINTRIN_impLINK_subr:
5093 case FFEINTRIN_impRENAME_subr:
5094 case FFEINTRIN_impSYMLNK_subr:
5095 {
5096 tree arg1_len = integer_zero_node;
5097 tree arg1_tree;
5098 tree arg2_len = integer_zero_node;
5099 tree arg2_tree;
5100 tree arg3_tree;
5101
5ff904cd
JL
5102 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5103 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
5104 if (arg3 != NULL)
c7e4ee3a 5105 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
5106 else
5107 arg3_tree = NULL_TREE;
5108
5ff904cd
JL
5109 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5110 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5111 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5112 arg2_len = build_tree_list (NULL_TREE, arg2_len);
5113 TREE_CHAIN (arg1_tree) = arg2_tree;
5114 TREE_CHAIN (arg2_tree) = arg1_len;
5115 TREE_CHAIN (arg1_len) = arg2_len;
5116 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5117 ffecom_gfrt_kindtype (gfrt),
5118 FALSE,
5119 NULL_TREE,
5120 arg1_tree,
c7e4ee3a
CB
5121 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5122 ffebld_nonter_hook (expr));
5ff904cd
JL
5123 if (arg3_tree != NULL_TREE)
5124 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5125 convert (TREE_TYPE (arg3_tree),
5126 expr_tree));
5127 }
5128 return expr_tree;
5129
5130 case FFEINTRIN_impLSTAT_subr:
5131 case FFEINTRIN_impSTAT_subr:
5132 {
5133 tree arg1_len = integer_zero_node;
5134 tree arg1_tree;
5135 tree arg2_tree;
5136 tree arg3_tree;
5137
5ff904cd
JL
5138 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5139
5140 arg2_tree = ffecom_ptr_to_expr (arg2);
5141
5142 if (arg3 != NULL)
c7e4ee3a 5143 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
5144 else
5145 arg3_tree = NULL_TREE;
5146
5ff904cd
JL
5147 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5148 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5149 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5150 TREE_CHAIN (arg1_tree) = arg2_tree;
5151 TREE_CHAIN (arg2_tree) = arg1_len;
5152 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5153 ffecom_gfrt_kindtype (gfrt),
5154 FALSE,
5155 NULL_TREE,
5156 arg1_tree,
c7e4ee3a
CB
5157 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5158 ffebld_nonter_hook (expr));
5ff904cd
JL
5159 if (arg3_tree != NULL_TREE)
5160 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5161 convert (TREE_TYPE (arg3_tree),
5162 expr_tree));
5163 }
5164 return expr_tree;
5165
5166 case FFEINTRIN_impFGETC_subr:
5167 case FFEINTRIN_impFPUTC_subr:
5168 {
5169 tree arg1_tree;
5170 tree arg2_tree;
5171 tree arg2_len = integer_zero_node;
5172 tree arg3_tree;
5173
5ff904cd
JL
5174 arg1_tree = convert (ffecom_f2c_integer_type_node,
5175 ffecom_expr (arg1));
5176 arg1_tree = ffecom_1 (ADDR_EXPR,
5177 build_pointer_type (TREE_TYPE (arg1_tree)),
5178 arg1_tree);
5179
5180 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
c7e4ee3a 5181 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
5182
5183 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5184 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5185 arg2_len = build_tree_list (NULL_TREE, arg2_len);
5186 TREE_CHAIN (arg1_tree) = arg2_tree;
5187 TREE_CHAIN (arg2_tree) = arg2_len;
5188
5189 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5190 ffecom_gfrt_kindtype (gfrt),
5191 FALSE,
5192 NULL_TREE,
5193 arg1_tree,
c7e4ee3a
CB
5194 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5195 ffebld_nonter_hook (expr));
5ff904cd
JL
5196 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5197 convert (TREE_TYPE (arg3_tree),
5198 expr_tree));
5199 }
5200 return expr_tree;
5201
5202 case FFEINTRIN_impFSTAT_subr:
5203 {
5204 tree arg1_tree;
5205 tree arg2_tree;
5206 tree arg3_tree;
5207
5ff904cd
JL
5208 arg1_tree = convert (ffecom_f2c_integer_type_node,
5209 ffecom_expr (arg1));
5210 arg1_tree = ffecom_1 (ADDR_EXPR,
5211 build_pointer_type (TREE_TYPE (arg1_tree)),
5212 arg1_tree);
5213
5214 arg2_tree = convert (ffecom_f2c_ptr_to_integer_type_node,
5215 ffecom_ptr_to_expr (arg2));
5216
5217 if (arg3 == NULL)
5218 arg3_tree = NULL_TREE;
5219 else
c7e4ee3a 5220 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
5221
5222 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5223 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5224 TREE_CHAIN (arg1_tree) = arg2_tree;
5225 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5226 ffecom_gfrt_kindtype (gfrt),
5227 FALSE,
5228 NULL_TREE,
5229 arg1_tree,
c7e4ee3a
CB
5230 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5231 ffebld_nonter_hook (expr));
5ff904cd
JL
5232 if (arg3_tree != NULL_TREE) {
5233 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5234 convert (TREE_TYPE (arg3_tree),
5235 expr_tree));
5236 }
5237 }
5238 return expr_tree;
5239
5240 case FFEINTRIN_impKILL_subr:
5241 {
5242 tree arg1_tree;
5243 tree arg2_tree;
5244 tree arg3_tree;
5245
5ff904cd
JL
5246 arg1_tree = convert (ffecom_f2c_integer_type_node,
5247 ffecom_expr (arg1));
5248 arg1_tree = ffecom_1 (ADDR_EXPR,
5249 build_pointer_type (TREE_TYPE (arg1_tree)),
5250 arg1_tree);
5251
5252 arg2_tree = convert (ffecom_f2c_integer_type_node,
5253 ffecom_expr (arg2));
5254 arg2_tree = ffecom_1 (ADDR_EXPR,
5255 build_pointer_type (TREE_TYPE (arg2_tree)),
5256 arg2_tree);
5257
5258 if (arg3 == NULL)
5259 arg3_tree = NULL_TREE;
5260 else
c7e4ee3a 5261 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
5262
5263 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5264 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5265 TREE_CHAIN (arg1_tree) = arg2_tree;
5266 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5267 ffecom_gfrt_kindtype (gfrt),
5268 FALSE,
5269 NULL_TREE,
5270 arg1_tree,
c7e4ee3a
CB
5271 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5272 ffebld_nonter_hook (expr));
5ff904cd
JL
5273 if (arg3_tree != NULL_TREE) {
5274 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5275 convert (TREE_TYPE (arg3_tree),
5276 expr_tree));
5277 }
5278 }
5279 return expr_tree;
5280
5281 case FFEINTRIN_impCTIME_subr:
5282 case FFEINTRIN_impTTYNAM_subr:
5283 {
5284 tree arg1_len = integer_zero_node;
5285 tree arg1_tree;
5286 tree arg2_tree;
5287
2b0bdd9a 5288 arg1_tree = ffecom_arg_ptr_to_expr (arg2, &arg1_len);
5ff904cd 5289
c56f65d6 5290 arg2_tree = convert (((codegen_imp == FFEINTRIN_impCTIME_subr) ?
5ff904cd
JL
5291 ffecom_f2c_longint_type_node :
5292 ffecom_f2c_integer_type_node),
2b0bdd9a 5293 ffecom_expr (arg1));
5ff904cd
JL
5294 arg2_tree = ffecom_1 (ADDR_EXPR,
5295 build_pointer_type (TREE_TYPE (arg2_tree)),
5296 arg2_tree);
5297
5ff904cd
JL
5298 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5299 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5300 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5301 TREE_CHAIN (arg1_len) = arg2_tree;
5302 TREE_CHAIN (arg1_tree) = arg1_len;
5303
5304 expr_tree
5305 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5306 ffecom_gfrt_kindtype (gfrt),
5307 FALSE,
5308 NULL_TREE,
5309 arg1_tree,
c7e4ee3a
CB
5310 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5311 ffebld_nonter_hook (expr));
2b0bdd9a 5312 TREE_SIDE_EFFECTS (expr_tree) = 1;
5ff904cd
JL
5313 }
5314 return expr_tree;
5315
5316 case FFEINTRIN_impIRAND:
5317 case FFEINTRIN_impRAND:
5318 /* Arg defaults to 0 (normal random case) */
5319 {
5320 tree arg1_tree;
5321
5322 if (arg1 == NULL)
5323 arg1_tree = ffecom_integer_zero_node;
5324 else
5325 arg1_tree = ffecom_expr (arg1);
5326 arg1_tree = convert (ffecom_f2c_integer_type_node,
5327 arg1_tree);
5328 arg1_tree = ffecom_1 (ADDR_EXPR,
5329 build_pointer_type (TREE_TYPE (arg1_tree)),
5330 arg1_tree);
5331 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5332
5333 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5334 ffecom_gfrt_kindtype (gfrt),
5335 FALSE,
5336 ((codegen_imp == FFEINTRIN_impIRAND) ?
5337 ffecom_f2c_integer_type_node :
de7f278a 5338 ffecom_f2c_real_type_node),
5ff904cd
JL
5339 arg1_tree,
5340 dest_tree, dest, dest_used,
c7e4ee3a
CB
5341 NULL_TREE, TRUE,
5342 ffebld_nonter_hook (expr));
5ff904cd
JL
5343 }
5344 return expr_tree;
5345
5346 case FFEINTRIN_impFTELL_subr:
5347 case FFEINTRIN_impUMASK_subr:
5348 {
5349 tree arg1_tree;
5350 tree arg2_tree;
5351
5ff904cd
JL
5352 arg1_tree = convert (ffecom_f2c_integer_type_node,
5353 ffecom_expr (arg1));
5354 arg1_tree = ffecom_1 (ADDR_EXPR,
5355 build_pointer_type (TREE_TYPE (arg1_tree)),
5356 arg1_tree);
5357
5358 if (arg2 == NULL)
5359 arg2_tree = NULL_TREE;
5360 else
c7e4ee3a 5361 arg2_tree = ffecom_expr_w (NULL_TREE, arg2);
5ff904cd
JL
5362
5363 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5364 ffecom_gfrt_kindtype (gfrt),
5365 FALSE,
5366 NULL_TREE,
5367 build_tree_list (NULL_TREE, arg1_tree),
5368 NULL_TREE, NULL, NULL, NULL_TREE,
c7e4ee3a
CB
5369 TRUE,
5370 ffebld_nonter_hook (expr));
5ff904cd
JL
5371 if (arg2_tree != NULL_TREE) {
5372 expr_tree = ffecom_modify (NULL_TREE, arg2_tree,
5373 convert (TREE_TYPE (arg2_tree),
5374 expr_tree));
5375 }
5376 }
5377 return expr_tree;
5378
5379 case FFEINTRIN_impCPU_TIME:
5380 case FFEINTRIN_impSECOND_subr:
5381 {
5382 tree arg1_tree;
5383
c7e4ee3a 5384 arg1_tree = ffecom_expr_w (NULL_TREE, arg1);
5ff904cd
JL
5385
5386 expr_tree
5387 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5388 ffecom_gfrt_kindtype (gfrt),
5389 FALSE,
5390 NULL_TREE,
5391 NULL_TREE,
c7e4ee3a
CB
5392 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5393 ffebld_nonter_hook (expr));
5ff904cd
JL
5394
5395 expr_tree
5396 = ffecom_modify (NULL_TREE, arg1_tree,
5397 convert (TREE_TYPE (arg1_tree),
5398 expr_tree));
5399 }
5400 return expr_tree;
5401
5402 case FFEINTRIN_impDTIME_subr:
5403 case FFEINTRIN_impETIME_subr:
5404 {
5405 tree arg1_tree;
2b0bdd9a 5406 tree result_tree;
5ff904cd 5407
2b0bdd9a 5408 result_tree = ffecom_expr_w (NULL_TREE, arg2);
5ff904cd 5409
2b0bdd9a 5410 arg1_tree = ffecom_ptr_to_expr (arg1);
5ff904cd 5411
5ff904cd
JL
5412 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5413 ffecom_gfrt_kindtype (gfrt),
5414 FALSE,
5415 NULL_TREE,
2b0bdd9a 5416 build_tree_list (NULL_TREE, arg1_tree),
5ff904cd 5417 NULL_TREE, NULL, NULL, NULL_TREE,
c7e4ee3a
CB
5418 TRUE,
5419 ffebld_nonter_hook (expr));
2b0bdd9a
CB
5420 expr_tree = ffecom_modify (NULL_TREE, result_tree,
5421 convert (TREE_TYPE (result_tree),
5ff904cd
JL
5422 expr_tree));
5423 }
5424 return expr_tree;
5425
c7e4ee3a 5426 /* Straightforward calls of libf2c routines: */
5ff904cd
JL
5427 case FFEINTRIN_impABORT:
5428 case FFEINTRIN_impACCESS:
5429 case FFEINTRIN_impBESJ0:
5430 case FFEINTRIN_impBESJ1:
5431 case FFEINTRIN_impBESJN:
5432 case FFEINTRIN_impBESY0:
5433 case FFEINTRIN_impBESY1:
5434 case FFEINTRIN_impBESYN:
5435 case FFEINTRIN_impCHDIR_func:
5436 case FFEINTRIN_impCHMOD_func:
5437 case FFEINTRIN_impDATE:
9e8e701d 5438 case FFEINTRIN_impDATE_AND_TIME:
5ff904cd
JL
5439 case FFEINTRIN_impDBESJ0:
5440 case FFEINTRIN_impDBESJ1:
5441 case FFEINTRIN_impDBESJN:
5442 case FFEINTRIN_impDBESY0:
5443 case FFEINTRIN_impDBESY1:
5444 case FFEINTRIN_impDBESYN:
5445 case FFEINTRIN_impDTIME_func:
5446 case FFEINTRIN_impETIME_func:
5447 case FFEINTRIN_impFGETC_func:
5448 case FFEINTRIN_impFGET_func:
5449 case FFEINTRIN_impFNUM:
5450 case FFEINTRIN_impFPUTC_func:
5451 case FFEINTRIN_impFPUT_func:
5452 case FFEINTRIN_impFSEEK:
5453 case FFEINTRIN_impFSTAT_func:
5454 case FFEINTRIN_impFTELL_func:
5455 case FFEINTRIN_impGERROR:
5456 case FFEINTRIN_impGETARG:
5457 case FFEINTRIN_impGETCWD_func:
5458 case FFEINTRIN_impGETENV:
5459 case FFEINTRIN_impGETGID:
5460 case FFEINTRIN_impGETLOG:
5461 case FFEINTRIN_impGETPID:
5462 case FFEINTRIN_impGETUID:
5463 case FFEINTRIN_impGMTIME:
5464 case FFEINTRIN_impHOSTNM_func:
5465 case FFEINTRIN_impIDATE_unix:
5466 case FFEINTRIN_impIDATE_vxt:
5467 case FFEINTRIN_impIERRNO:
5468 case FFEINTRIN_impISATTY:
5469 case FFEINTRIN_impITIME:
5470 case FFEINTRIN_impKILL_func:
5471 case FFEINTRIN_impLINK_func:
5472 case FFEINTRIN_impLNBLNK:
5473 case FFEINTRIN_impLSTAT_func:
5474 case FFEINTRIN_impLTIME:
5475 case FFEINTRIN_impMCLOCK8:
5476 case FFEINTRIN_impMCLOCK:
5477 case FFEINTRIN_impPERROR:
5478 case FFEINTRIN_impRENAME_func:
5479 case FFEINTRIN_impSECNDS:
5480 case FFEINTRIN_impSECOND_func:
5481 case FFEINTRIN_impSLEEP:
5482 case FFEINTRIN_impSRAND:
5483 case FFEINTRIN_impSTAT_func:
5484 case FFEINTRIN_impSYMLNK_func:
5485 case FFEINTRIN_impSYSTEM_CLOCK:
5486 case FFEINTRIN_impSYSTEM_func:
5487 case FFEINTRIN_impTIME8:
5488 case FFEINTRIN_impTIME_unix:
5489 case FFEINTRIN_impTIME_vxt:
5490 case FFEINTRIN_impUMASK_func:
5491 case FFEINTRIN_impUNLINK_func:
5492 break;
5493
5494 case FFEINTRIN_impCTIME_func: /* CHARACTER functions not handled here. */
5495 case FFEINTRIN_impFDATE_func: /* CHARACTER functions not handled here. */
5496 case FFEINTRIN_impTTYNAM_func: /* CHARACTER functions not handled here. */
5497 case FFEINTRIN_impNONE:
5498 case FFEINTRIN_imp: /* Hush up gcc warning. */
5499 fprintf (stderr, "No %s implementation.\n",
5500 ffeintrin_name_implementation (ffebld_symter_implementation (ffebld_left (expr))));
5501 assert ("unimplemented intrinsic" == NULL);
5502 return error_mark_node;
5503 }
5504
5505 assert (gfrt != FFECOM_gfrt); /* Must have an implementation! */
5506
5ff904cd
JL
5507 expr_tree = ffecom_arglist_expr_ (ffecom_gfrt_args_ (gfrt),
5508 ffebld_right (expr));
5ff904cd
JL
5509
5510 return ffecom_call_ (ffecom_gfrt_tree_ (gfrt), ffecom_gfrt_kindtype (gfrt),
5511 (ffe_is_f2c_library () && ffecom_gfrt_complex_[gfrt]),
5512 tree_type,
5513 expr_tree, dest_tree, dest, dest_used,
c7e4ee3a
CB
5514 NULL_TREE, TRUE,
5515 ffebld_nonter_hook (expr));
5ff904cd 5516
c7e4ee3a
CB
5517 /* See bottom of this file for f2c transforms used to determine
5518 many of the above implementations. The info seems to confuse
5519 Emacs's C mode indentation, which is why it's been moved to
5520 the bottom of this source file. */
5521}
5ff904cd 5522
c7e4ee3a
CB
5523#endif
5524/* For power (exponentiation) where right-hand operand is type INTEGER,
5525 generate in-line code to do it the fast way (which, if the operand
5526 is a constant, might just mean a series of multiplies). */
5ff904cd 5527
c7e4ee3a
CB
5528#if FFECOM_targetCURRENT == FFECOM_targetGCC
5529static tree
5530ffecom_expr_power_integer_ (ffebld expr)
5531{
5532 tree l = ffecom_expr (ffebld_left (expr));
5533 tree r = ffecom_expr (ffebld_right (expr));
5534 tree ltype = TREE_TYPE (l);
5535 tree rtype = TREE_TYPE (r);
5536 tree result = NULL_TREE;
5ff904cd 5537
c7e4ee3a
CB
5538 if (l == error_mark_node
5539 || r == error_mark_node)
5540 return error_mark_node;
5ff904cd 5541
c7e4ee3a
CB
5542 if (TREE_CODE (r) == INTEGER_CST)
5543 {
5544 int sgn = tree_int_cst_sgn (r);
5ff904cd 5545
c7e4ee3a
CB
5546 if (sgn == 0)
5547 return convert (ltype, integer_one_node);
5ff904cd 5548
c7e4ee3a
CB
5549 if ((TREE_CODE (ltype) == INTEGER_TYPE)
5550 && (sgn < 0))
5551 {
5552 /* Reciprocal of integer is either 0, -1, or 1, so after
5553 calculating that (which we leave to the back end to do
5554 or not do optimally), don't bother with any multiplying. */
5ff904cd 5555
c7e4ee3a
CB
5556 result = ffecom_tree_divide_ (ltype,
5557 convert (ltype, integer_one_node),
5558 l,
5559 NULL_TREE, NULL, NULL, NULL_TREE);
5560 r = ffecom_1 (NEGATE_EXPR,
5561 rtype,
5562 r);
5563 if ((TREE_INT_CST_LOW (r) & 1) == 0)
5564 result = ffecom_1 (ABS_EXPR, rtype,
5565 result);
5566 }
5ff904cd 5567
c7e4ee3a
CB
5568 /* Generate appropriate series of multiplies, preceded
5569 by divide if the exponent is negative. */
5ff904cd 5570
c7e4ee3a 5571 l = save_expr (l);
5ff904cd 5572
c7e4ee3a
CB
5573 if (sgn < 0)
5574 {
5575 l = ffecom_tree_divide_ (ltype,
5576 convert (ltype, integer_one_node),
5577 l,
5578 NULL_TREE, NULL, NULL,
5579 ffebld_nonter_hook (expr));
5580 r = ffecom_1 (NEGATE_EXPR, rtype, r);
5581 assert (TREE_CODE (r) == INTEGER_CST);
5ff904cd 5582
c7e4ee3a
CB
5583 if (tree_int_cst_sgn (r) < 0)
5584 { /* The "most negative" number. */
5585 r = ffecom_1 (NEGATE_EXPR, rtype,
5586 ffecom_2 (RSHIFT_EXPR, rtype,
5587 r,
5588 integer_one_node));
5589 l = save_expr (l);
5590 l = ffecom_2 (MULT_EXPR, ltype,
5591 l,
5592 l);
5593 }
5594 }
5ff904cd 5595
c7e4ee3a
CB
5596 for (;;)
5597 {
5598 if (TREE_INT_CST_LOW (r) & 1)
5599 {
5600 if (result == NULL_TREE)
5601 result = l;
5602 else
5603 result = ffecom_2 (MULT_EXPR, ltype,
5604 result,
5605 l);
5606 }
5ff904cd 5607
c7e4ee3a
CB
5608 r = ffecom_2 (RSHIFT_EXPR, rtype,
5609 r,
5610 integer_one_node);
5611 if (integer_zerop (r))
5612 break;
5613 assert (TREE_CODE (r) == INTEGER_CST);
5ff904cd 5614
c7e4ee3a
CB
5615 l = save_expr (l);
5616 l = ffecom_2 (MULT_EXPR, ltype,
5617 l,
5618 l);
5619 }
5620 return result;
5621 }
5ff904cd 5622
c7e4ee3a
CB
5623 /* Though rhs isn't a constant, in-line code cannot be expanded
5624 while transforming dummies
5625 because the back end cannot be easily convinced to generate
5626 stores (MODIFY_EXPR), handle temporaries, and so on before
5627 all the appropriate rtx's have been generated for things like
5628 dummy args referenced in rhs -- which doesn't happen until
5629 store_parm_decls() is called (expand_function_start, I believe,
5630 does the actual rtx-stuffing of PARM_DECLs).
5ff904cd 5631
c7e4ee3a
CB
5632 So, in this case, let the caller generate the call to the
5633 run-time-library function to evaluate the power for us. */
5ff904cd 5634
c7e4ee3a
CB
5635 if (ffecom_transform_only_dummies_)
5636 return NULL_TREE;
5ff904cd 5637
c7e4ee3a
CB
5638 /* Right-hand operand not a constant, expand in-line code to figure
5639 out how to do the multiplies, &c.
5ff904cd 5640
c7e4ee3a
CB
5641 The returned expression is expressed this way in GNU C, where l and
5642 r are the "inputs":
5ff904cd 5643
c7e4ee3a
CB
5644 ({ typeof (r) rtmp = r;
5645 typeof (l) ltmp = l;
5646 typeof (l) result;
5ff904cd 5647
c7e4ee3a
CB
5648 if (rtmp == 0)
5649 result = 1;
5650 else
5651 {
5652 if ((basetypeof (l) == basetypeof (int))
5653 && (rtmp < 0))
5654 {
5655 result = ((typeof (l)) 1) / ltmp;
5656 if ((ltmp < 0) && (((-rtmp) & 1) == 0))
5657 result = -result;
5658 }
5659 else
5660 {
5661 result = 1;
5662 if ((basetypeof (l) != basetypeof (int))
5663 && (rtmp < 0))
5664 {
5665 ltmp = ((typeof (l)) 1) / ltmp;
5666 rtmp = -rtmp;
5667 if (rtmp < 0)
5668 {
5669 rtmp = -(rtmp >> 1);
5670 ltmp *= ltmp;
5671 }
5672 }
5673 for (;;)
5674 {
5675 if (rtmp & 1)
5676 result *= ltmp;
5677 if ((rtmp >>= 1) == 0)
5678 break;
5679 ltmp *= ltmp;
5680 }
5681 }
5682 }
5683 result;
5684 })
5ff904cd 5685
c7e4ee3a
CB
5686 Note that some of the above is compile-time collapsable, such as
5687 the first part of the if statements that checks the base type of
5688 l against int. The if statements are phrased that way to suggest
5689 an easy way to generate the if/else constructs here, knowing that
5690 the back end should (and probably does) eliminate the resulting
5691 dead code (either the int case or the non-int case), something
5692 it couldn't do without the redundant phrasing, requiring explicit
5693 dead-code elimination here, which would be kind of difficult to
5694 read. */
5ff904cd 5695
c7e4ee3a
CB
5696 {
5697 tree rtmp;
5698 tree ltmp;
5699 tree divide;
5700 tree basetypeof_l_is_int;
5701 tree se;
5702 tree t;
5ff904cd 5703
c7e4ee3a
CB
5704 basetypeof_l_is_int
5705 = build_int_2 ((TREE_CODE (ltype) == INTEGER_TYPE), 0);
5ff904cd 5706
c7e4ee3a 5707 se = expand_start_stmt_expr ();
5ff904cd 5708
c7e4ee3a
CB
5709 ffecom_start_compstmt ();
5710
5711#ifndef HAHA
5712 rtmp = ffecom_make_tempvar ("power_r", rtype,
5713 FFETARGET_charactersizeNONE, -1);
5714 ltmp = ffecom_make_tempvar ("power_l", ltype,
5715 FFETARGET_charactersizeNONE, -1);
5716 result = ffecom_make_tempvar ("power_res", ltype,
5717 FFETARGET_charactersizeNONE, -1);
5718 if (TREE_CODE (ltype) == COMPLEX_TYPE
5719 || TREE_CODE (ltype) == RECORD_TYPE)
5720 divide = ffecom_make_tempvar ("power_div", ltype,
5721 FFETARGET_charactersizeNONE, -1);
5722 else
5723 divide = NULL_TREE;
5724#else /* HAHA */
5725 {
5726 tree hook;
5727
5728 hook = ffebld_nonter_hook (expr);
5729 assert (hook);
5730 assert (TREE_CODE (hook) == TREE_VEC);
5731 assert (TREE_VEC_LENGTH (hook) == 4);
5732 rtmp = TREE_VEC_ELT (hook, 0);
5733 ltmp = TREE_VEC_ELT (hook, 1);
5734 result = TREE_VEC_ELT (hook, 2);
5735 divide = TREE_VEC_ELT (hook, 3);
5736 if (TREE_CODE (ltype) == COMPLEX_TYPE
5737 || TREE_CODE (ltype) == RECORD_TYPE)
5738 assert (divide);
5739 else
5740 assert (! divide);
5741 }
5742#endif /* HAHA */
5ff904cd 5743
c7e4ee3a
CB
5744 expand_expr_stmt (ffecom_modify (void_type_node,
5745 rtmp,
5746 r));
5747 expand_expr_stmt (ffecom_modify (void_type_node,
5748 ltmp,
5749 l));
5750 expand_start_cond (ffecom_truth_value
5751 (ffecom_2 (EQ_EXPR, integer_type_node,
5752 rtmp,
5753 convert (rtype, integer_zero_node))),
5754 0);
5755 expand_expr_stmt (ffecom_modify (void_type_node,
5756 result,
5757 convert (ltype, integer_one_node)));
5758 expand_start_else ();
5759 if (! integer_zerop (basetypeof_l_is_int))
5760 {
5761 expand_start_cond (ffecom_2 (LT_EXPR, integer_type_node,
5762 rtmp,
5763 convert (rtype,
5764 integer_zero_node)),
5765 0);
5766 expand_expr_stmt (ffecom_modify (void_type_node,
5767 result,
5768 ffecom_tree_divide_
5769 (ltype,
5770 convert (ltype, integer_one_node),
5771 ltmp,
5772 NULL_TREE, NULL, NULL,
5773 divide)));
5774 expand_start_cond (ffecom_truth_value
5775 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
5776 ffecom_2 (LT_EXPR, integer_type_node,
5777 ltmp,
5778 convert (ltype,
5779 integer_zero_node)),
5780 ffecom_2 (EQ_EXPR, integer_type_node,
5781 ffecom_2 (BIT_AND_EXPR,
5782 rtype,
5783 ffecom_1 (NEGATE_EXPR,
5784 rtype,
5785 rtmp),
5786 convert (rtype,
5787 integer_one_node)),
5788 convert (rtype,
5789 integer_zero_node)))),
5790 0);
5791 expand_expr_stmt (ffecom_modify (void_type_node,
5792 result,
5793 ffecom_1 (NEGATE_EXPR,
5794 ltype,
5795 result)));
5796 expand_end_cond ();
5797 expand_start_else ();
5798 }
5799 expand_expr_stmt (ffecom_modify (void_type_node,
5800 result,
5801 convert (ltype, integer_one_node)));
5802 expand_start_cond (ffecom_truth_value
5803 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
5804 ffecom_truth_value_invert
5805 (basetypeof_l_is_int),
5806 ffecom_2 (LT_EXPR, integer_type_node,
5807 rtmp,
5808 convert (rtype,
5809 integer_zero_node)))),
5810 0);
5811 expand_expr_stmt (ffecom_modify (void_type_node,
5812 ltmp,
5813 ffecom_tree_divide_
5814 (ltype,
5815 convert (ltype, integer_one_node),
5816 ltmp,
5817 NULL_TREE, NULL, NULL,
5818 divide)));
5819 expand_expr_stmt (ffecom_modify (void_type_node,
5820 rtmp,
5821 ffecom_1 (NEGATE_EXPR, rtype,
5822 rtmp)));
5823 expand_start_cond (ffecom_truth_value
5824 (ffecom_2 (LT_EXPR, integer_type_node,
5825 rtmp,
5826 convert (rtype, integer_zero_node))),
5827 0);
5828 expand_expr_stmt (ffecom_modify (void_type_node,
5829 rtmp,
5830 ffecom_1 (NEGATE_EXPR, rtype,
5831 ffecom_2 (RSHIFT_EXPR,
5832 rtype,
5833 rtmp,
5834 integer_one_node))));
5835 expand_expr_stmt (ffecom_modify (void_type_node,
5836 ltmp,
5837 ffecom_2 (MULT_EXPR, ltype,
5838 ltmp,
5839 ltmp)));
5840 expand_end_cond ();
5841 expand_end_cond ();
5842 expand_start_loop (1);
5843 expand_start_cond (ffecom_truth_value
5844 (ffecom_2 (BIT_AND_EXPR, rtype,
5845 rtmp,
5846 convert (rtype, integer_one_node))),
5847 0);
5848 expand_expr_stmt (ffecom_modify (void_type_node,
5849 result,
5850 ffecom_2 (MULT_EXPR, ltype,
5851 result,
5852 ltmp)));
5853 expand_end_cond ();
5854 expand_exit_loop_if_false (NULL,
5855 ffecom_truth_value
5856 (ffecom_modify (rtype,
5857 rtmp,
5858 ffecom_2 (RSHIFT_EXPR,
5859 rtype,
5860 rtmp,
5861 integer_one_node))));
5862 expand_expr_stmt (ffecom_modify (void_type_node,
5863 ltmp,
5864 ffecom_2 (MULT_EXPR, ltype,
5865 ltmp,
5866 ltmp)));
5867 expand_end_loop ();
5868 expand_end_cond ();
5869 if (!integer_zerop (basetypeof_l_is_int))
5870 expand_end_cond ();
5871 expand_expr_stmt (result);
5ff904cd 5872
c7e4ee3a 5873 t = ffecom_end_compstmt ();
5ff904cd 5874
c7e4ee3a 5875 result = expand_end_stmt_expr (se);
5ff904cd 5876
c7e4ee3a 5877 /* This code comes from c-parse.in, after its expand_end_stmt_expr. */
5ff904cd 5878
c7e4ee3a
CB
5879 if (TREE_CODE (t) == BLOCK)
5880 {
5881 /* Make a BIND_EXPR for the BLOCK already made. */
5882 result = build (BIND_EXPR, TREE_TYPE (result),
5883 NULL_TREE, result, t);
5884 /* Remove the block from the tree at this point.
5885 It gets put back at the proper place
5886 when the BIND_EXPR is expanded. */
5887 delete_block (t);
5888 }
5889 else
5890 result = t;
5891 }
5ff904cd 5892
c7e4ee3a
CB
5893 return result;
5894}
5ff904cd 5895
c7e4ee3a
CB
5896#endif
5897/* ffecom_expr_transform_ -- Transform symbols in expr
5ff904cd 5898
c7e4ee3a
CB
5899 ffebld expr; // FFE expression.
5900 ffecom_expr_transform_ (expr);
5ff904cd 5901
c7e4ee3a 5902 Recursive descent on expr while transforming any untransformed SYMTERs. */
5ff904cd 5903
c7e4ee3a
CB
5904#if FFECOM_targetCURRENT == FFECOM_targetGCC
5905static void
5906ffecom_expr_transform_ (ffebld expr)
5907{
5908 tree t;
5909 ffesymbol s;
5ff904cd 5910
c7e4ee3a 5911tail_recurse: /* :::::::::::::::::::: */
5ff904cd 5912
c7e4ee3a
CB
5913 if (expr == NULL)
5914 return;
5ff904cd 5915
c7e4ee3a
CB
5916 switch (ffebld_op (expr))
5917 {
5918 case FFEBLD_opSYMTER:
5919 s = ffebld_symter (expr);
5920 t = ffesymbol_hook (s).decl_tree;
5921 if ((t == NULL_TREE)
5922 && ((ffesymbol_kind (s) != FFEINFO_kindNONE)
5923 || ((ffesymbol_where (s) != FFEINFO_whereNONE)
5924 && (ffesymbol_where (s) != FFEINFO_whereINTRINSIC))))
5925 {
5926 s = ffecom_sym_transform_ (s);
5927 t = ffesymbol_hook (s).decl_tree; /* Sfunc expr non-dummy,
5928 DIMENSION expr? */
5929 }
5930 break; /* Ok if (t == NULL) here. */
5ff904cd 5931
c7e4ee3a
CB
5932 case FFEBLD_opITEM:
5933 ffecom_expr_transform_ (ffebld_head (expr));
5934 expr = ffebld_trail (expr);
5935 goto tail_recurse; /* :::::::::::::::::::: */
5ff904cd 5936
c7e4ee3a
CB
5937 default:
5938 break;
5939 }
5ff904cd 5940
c7e4ee3a
CB
5941 switch (ffebld_arity (expr))
5942 {
5943 case 2:
5944 ffecom_expr_transform_ (ffebld_left (expr));
5945 expr = ffebld_right (expr);
5946 goto tail_recurse; /* :::::::::::::::::::: */
5ff904cd 5947
c7e4ee3a
CB
5948 case 1:
5949 expr = ffebld_left (expr);
5950 goto tail_recurse; /* :::::::::::::::::::: */
5ff904cd 5951
c7e4ee3a
CB
5952 default:
5953 break;
5954 }
5ff904cd 5955
c7e4ee3a
CB
5956 return;
5957}
5ff904cd 5958
c7e4ee3a
CB
5959#endif
5960/* Make a type based on info in live f2c.h file. */
5ff904cd 5961
c7e4ee3a
CB
5962#if FFECOM_targetCURRENT == FFECOM_targetGCC
5963static void
5964ffecom_f2c_make_type_ (tree *type, int tcode, const char *name)
5965{
5966 switch (tcode)
5967 {
5968 case FFECOM_f2ccodeCHAR:
5969 *type = make_signed_type (CHAR_TYPE_SIZE);
5970 break;
5ff904cd 5971
c7e4ee3a
CB
5972 case FFECOM_f2ccodeSHORT:
5973 *type = make_signed_type (SHORT_TYPE_SIZE);
5974 break;
5ff904cd 5975
c7e4ee3a
CB
5976 case FFECOM_f2ccodeINT:
5977 *type = make_signed_type (INT_TYPE_SIZE);
5978 break;
5ff904cd 5979
c7e4ee3a
CB
5980 case FFECOM_f2ccodeLONG:
5981 *type = make_signed_type (LONG_TYPE_SIZE);
5982 break;
5ff904cd 5983
c7e4ee3a
CB
5984 case FFECOM_f2ccodeLONGLONG:
5985 *type = make_signed_type (LONG_LONG_TYPE_SIZE);
5986 break;
5ff904cd 5987
c7e4ee3a
CB
5988 case FFECOM_f2ccodeCHARPTR:
5989 *type = build_pointer_type (DEFAULT_SIGNED_CHAR
5990 ? signed_char_type_node
5991 : unsigned_char_type_node);
5992 break;
5ff904cd 5993
c7e4ee3a
CB
5994 case FFECOM_f2ccodeFLOAT:
5995 *type = make_node (REAL_TYPE);
5996 TYPE_PRECISION (*type) = FLOAT_TYPE_SIZE;
5997 layout_type (*type);
5998 break;
5999
6000 case FFECOM_f2ccodeDOUBLE:
6001 *type = make_node (REAL_TYPE);
6002 TYPE_PRECISION (*type) = DOUBLE_TYPE_SIZE;
6003 layout_type (*type);
6004 break;
6005
6006 case FFECOM_f2ccodeLONGDOUBLE:
6007 *type = make_node (REAL_TYPE);
6008 TYPE_PRECISION (*type) = LONG_DOUBLE_TYPE_SIZE;
6009 layout_type (*type);
6010 break;
5ff904cd 6011
c7e4ee3a
CB
6012 case FFECOM_f2ccodeTWOREALS:
6013 *type = ffecom_make_complex_type_ (ffecom_f2c_real_type_node);
6014 break;
5ff904cd 6015
c7e4ee3a
CB
6016 case FFECOM_f2ccodeTWODOUBLEREALS:
6017 *type = ffecom_make_complex_type_ (ffecom_f2c_doublereal_type_node);
6018 break;
5ff904cd 6019
c7e4ee3a
CB
6020 default:
6021 assert ("unexpected FFECOM_f2ccodeXYZZY!" == NULL);
6022 *type = error_mark_node;
6023 return;
6024 }
5ff904cd 6025
c7e4ee3a 6026 pushdecl (build_decl (TYPE_DECL,
14657de8 6027 ffecom_get_invented_identifier ("__g77_f2c_%s", name),
c7e4ee3a
CB
6028 *type));
6029}
5ff904cd 6030
c7e4ee3a
CB
6031#endif
6032#if FFECOM_targetCURRENT == FFECOM_targetGCC
6033/* Set the f2c list-directed-I/O code for whatever (integral) type has the
6034 given size. */
5ff904cd 6035
c7e4ee3a
CB
6036static void
6037ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size,
6038 int code)
6039{
6040 int j;
6041 tree t;
5ff904cd 6042
c7e4ee3a 6043 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
05bccae2
RK
6044 if ((t = ffecom_tree_type[bt][j]) != NULL_TREE
6045 && compare_tree_int (TYPE_SIZE (t), size) == 0)
c7e4ee3a
CB
6046 {
6047 assert (code != -1);
6048 ffecom_f2c_typecode_[bt][j] = code;
6049 code = -1;
6050 }
6051}
5ff904cd 6052
c7e4ee3a
CB
6053#endif
6054/* Finish up globals after doing all program units in file
5ff904cd 6055
c7e4ee3a 6056 Need to handle only uninitialized COMMON areas. */
5ff904cd 6057
c7e4ee3a
CB
6058#if FFECOM_targetCURRENT == FFECOM_targetGCC
6059static ffeglobal
6060ffecom_finish_global_ (ffeglobal global)
6061{
6062 tree cbtype;
6063 tree cbt;
6064 tree size;
5ff904cd 6065
c7e4ee3a
CB
6066 if (ffeglobal_type (global) != FFEGLOBAL_typeCOMMON)
6067 return global;
5ff904cd 6068
c7e4ee3a
CB
6069 if (ffeglobal_common_init (global))
6070 return global;
5ff904cd 6071
c7e4ee3a
CB
6072 cbt = ffeglobal_hook (global);
6073 if ((cbt == NULL_TREE)
6074 || !ffeglobal_common_have_size (global))
6075 return global; /* No need to make common, never ref'd. */
5ff904cd 6076
c7e4ee3a 6077 suspend_momentary ();
5ff904cd 6078
c7e4ee3a 6079 DECL_EXTERNAL (cbt) = 0;
5ff904cd 6080
c7e4ee3a 6081 /* Give the array a size now. */
5ff904cd 6082
c7e4ee3a
CB
6083 size = build_int_2 ((ffeglobal_common_size (global)
6084 + ffeglobal_common_pad (global)) - 1,
6085 0);
5ff904cd 6086
c7e4ee3a
CB
6087 cbtype = TREE_TYPE (cbt);
6088 TYPE_DOMAIN (cbtype) = build_range_type (integer_type_node,
6089 integer_zero_node,
6090 size);
6091 if (!TREE_TYPE (size))
6092 TREE_TYPE (size) = TYPE_DOMAIN (cbtype);
6093 layout_type (cbtype);
5ff904cd 6094
c7e4ee3a
CB
6095 cbt = start_decl (cbt, FALSE);
6096 assert (cbt == ffeglobal_hook (global));
5ff904cd 6097
c7e4ee3a 6098 finish_decl (cbt, NULL_TREE, FALSE);
5ff904cd 6099
c7e4ee3a
CB
6100 return global;
6101}
5ff904cd 6102
c7e4ee3a
CB
6103#endif
6104/* Finish up any untransformed symbols. */
5ff904cd 6105
c7e4ee3a
CB
6106#if FFECOM_targetCURRENT == FFECOM_targetGCC
6107static ffesymbol
6108ffecom_finish_symbol_transform_ (ffesymbol s)
5ff904cd 6109{
c7e4ee3a
CB
6110 if ((s == NULL) || (TREE_CODE (current_function_decl) == ERROR_MARK))
6111 return s;
5ff904cd 6112
c7e4ee3a
CB
6113 /* It's easy to know to transform an untransformed symbol, to make sure
6114 we put out debugging info for it. But COMMON variables, unlike
6115 EQUIVALENCE ones, aren't given declarations in addition to the
6116 tree expressions that specify offsets, because COMMON variables
6117 can be referenced in the outer scope where only dummy arguments
6118 (PARM_DECLs) should really be seen. To be safe, just don't do any
6119 VAR_DECLs for COMMON variables when we transform them for real
6120 use, and therefore we do all the VAR_DECL creating here. */
5ff904cd 6121
c7e4ee3a
CB
6122 if (ffesymbol_hook (s).decl_tree == NULL_TREE)
6123 {
6124 if (ffesymbol_kind (s) != FFEINFO_kindNONE
6125 || (ffesymbol_where (s) != FFEINFO_whereNONE
6126 && ffesymbol_where (s) != FFEINFO_whereINTRINSIC
6127 && ffesymbol_where (s) != FFEINFO_whereDUMMY))
6128 /* Not transformed, and not CHARACTER*(*), and not a dummy
6129 argument, which can happen only if the entry point names
6130 it "rides in on" are all invalidated for other reasons. */
6131 s = ffecom_sym_transform_ (s);
6132 }
5ff904cd 6133
c7e4ee3a
CB
6134 if ((ffesymbol_where (s) == FFEINFO_whereCOMMON)
6135 && (ffesymbol_hook (s).decl_tree != error_mark_node))
6136 {
c7e4ee3a 6137 int yes = suspend_momentary ();
5ff904cd 6138
c7e4ee3a
CB
6139 /* This isn't working, at least for dbxout. The .s file looks
6140 okay to me (burley), but in gdb 4.9 at least, the variables
6141 appear to reside somewhere outside of the common area, so
6142 it doesn't make sense to mislead anyone by generating the info
6143 on those variables until this is fixed. NOTE: Same problem
6144 with EQUIVALENCE, sadly...see similar #if later. */
6145 ffecom_member_phase2_ (ffesymbol_storage (ffesymbol_common (s)),
6146 ffesymbol_storage (s));
5ff904cd 6147
c7e4ee3a 6148 resume_momentary (yes);
5ff904cd
JL
6149 }
6150
c7e4ee3a
CB
6151 return s;
6152}
5ff904cd 6153
c7e4ee3a
CB
6154#endif
6155/* Append underscore(s) to name before calling get_identifier. "us"
6156 is nonzero if the name already contains an underscore and thus
6157 needs two underscores appended. */
5ff904cd 6158
c7e4ee3a
CB
6159#if FFECOM_targetCURRENT == FFECOM_targetGCC
6160static tree
6161ffecom_get_appended_identifier_ (char us, const char *name)
6162{
6163 int i;
6164 char *newname;
6165 tree id;
5ff904cd 6166
c7e4ee3a
CB
6167 newname = xmalloc ((i = strlen (name)) + 1
6168 + ffe_is_underscoring ()
6169 + us);
6170 memcpy (newname, name, i);
6171 newname[i] = '_';
6172 newname[i + us] = '_';
6173 newname[i + 1 + us] = '\0';
6174 id = get_identifier (newname);
5ff904cd 6175
c7e4ee3a 6176 free (newname);
5ff904cd 6177
c7e4ee3a
CB
6178 return id;
6179}
5ff904cd 6180
c7e4ee3a
CB
6181#endif
6182/* Decide whether to append underscore to name before calling
6183 get_identifier. */
5ff904cd 6184
c7e4ee3a
CB
6185#if FFECOM_targetCURRENT == FFECOM_targetGCC
6186static tree
6187ffecom_get_external_identifier_ (ffesymbol s)
6188{
6189 char us;
6190 const char *name = ffesymbol_text (s);
5ff904cd 6191
c7e4ee3a 6192 /* If name is a built-in name, just return it as is. */
5ff904cd 6193
c7e4ee3a
CB
6194 if (!ffe_is_underscoring ()
6195 || (strcmp (name, FFETARGET_nameBLANK_COMMON) == 0)
6196#if FFETARGET_isENFORCED_MAIN_NAME
6197 || (strcmp (name, FFETARGET_nameENFORCED_NAME) == 0)
6198#else
6199 || (strcmp (name, FFETARGET_nameUNNAMED_MAIN) == 0)
6200#endif
6201 || (strcmp (name, FFETARGET_nameUNNAMED_BLOCK_DATA) == 0))
6202 return get_identifier (name);
5ff904cd 6203
c7e4ee3a
CB
6204 us = ffe_is_second_underscore ()
6205 ? (strchr (name, '_') != NULL)
6206 : 0;
5ff904cd 6207
c7e4ee3a
CB
6208 return ffecom_get_appended_identifier_ (us, name);
6209}
5ff904cd 6210
c7e4ee3a
CB
6211#endif
6212/* Decide whether to append underscore to internal name before calling
6213 get_identifier.
6214
6215 This is for non-external, top-function-context names only. Transform
6216 identifier so it doesn't conflict with the transformed result
6217 of using a _different_ external name. E.g. if "CALL FOO" is
6218 transformed into "FOO_();", then the variable in "FOO_ = 3"
6219 must be transformed into something that does not conflict, since
6220 these two things should be independent.
5ff904cd 6221
c7e4ee3a
CB
6222 The transformation is as follows. If the name does not contain
6223 an underscore, there is no possible conflict, so just return.
6224 If the name does contain an underscore, then transform it just
6225 like we transform an external identifier. */
5ff904cd 6226
c7e4ee3a
CB
6227#if FFECOM_targetCURRENT == FFECOM_targetGCC
6228static tree
6229ffecom_get_identifier_ (const char *name)
6230{
6231 /* If name does not contain an underscore, just return it as is. */
6232
6233 if (!ffe_is_underscoring ()
6234 || (strchr (name, '_') == NULL))
6235 return get_identifier (name);
6236
6237 return ffecom_get_appended_identifier_ (ffe_is_second_underscore (),
6238 name);
5ff904cd
JL
6239}
6240
6241#endif
c7e4ee3a 6242/* ffecom_gen_sfuncdef_ -- Generate definition of statement function
5ff904cd 6243
c7e4ee3a
CB
6244 tree t;
6245 ffesymbol s; // kindFUNCTION, whereIMMEDIATE.
6246 t = ffecom_gen_sfuncdef_(s,ffesymbol_basictype(s),
6247 ffesymbol_kindtype(s));
5ff904cd 6248
c7e4ee3a
CB
6249 Call after setting up containing function and getting trees for all
6250 other symbols. */
5ff904cd
JL
6251
6252#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
6253static tree
6254ffecom_gen_sfuncdef_ (ffesymbol s, ffeinfoBasictype bt, ffeinfoKindtype kt)
5ff904cd 6255{
c7e4ee3a
CB
6256 ffebld expr = ffesymbol_sfexpr (s);
6257 tree type;
6258 tree func;
6259 tree result;
6260 bool charfunc = (bt == FFEINFO_basictypeCHARACTER);
6261 static bool recurse = FALSE;
6262 int yes;
6263 int old_lineno = lineno;
3b304f5b 6264 const char *old_input_filename = input_filename;
5ff904cd 6265
c7e4ee3a 6266 ffecom_nested_entry_ = s;
5ff904cd 6267
c7e4ee3a
CB
6268 /* For now, we don't have a handy pointer to where the sfunc is actually
6269 defined, though that should be easy to add to an ffesymbol. (The
6270 token/where info available might well point to the place where the type
6271 of the sfunc is declared, especially if that precedes the place where
6272 the sfunc itself is defined, which is typically the case.) We should
6273 put out a null pointer rather than point somewhere wrong, but I want to
6274 see how it works at this point. */
5ff904cd 6275
c7e4ee3a
CB
6276 input_filename = ffesymbol_where_filename (s);
6277 lineno = ffesymbol_where_filelinenum (s);
5ff904cd 6278
c7e4ee3a
CB
6279 /* Pretransform the expression so any newly discovered things belong to the
6280 outer program unit, not to the statement function. */
5ff904cd 6281
c7e4ee3a 6282 ffecom_expr_transform_ (expr);
5ff904cd 6283
c7e4ee3a
CB
6284 /* Make sure no recursive invocation of this fn (a specific case of failing
6285 to pretransform an sfunc's expression, i.e. where its expression
6286 references another untransformed sfunc) happens. */
6287
6288 assert (!recurse);
6289 recurse = TRUE;
6290
6291 yes = suspend_momentary ();
6292
6293 push_f_function_context ();
6294
6295 if (charfunc)
6296 type = void_type_node;
6297 else
5ff904cd 6298 {
c7e4ee3a
CB
6299 type = ffecom_tree_type[bt][kt];
6300 if (type == NULL_TREE)
6301 type = integer_type_node; /* _sym_exec_transition reports
6302 error. */
6303 }
5ff904cd 6304
c7e4ee3a
CB
6305 start_function (ffecom_get_identifier_ (ffesymbol_text (s)),
6306 build_function_type (type, NULL_TREE),
6307 1, /* nested/inline */
6308 0); /* TREE_PUBLIC */
5ff904cd 6309
c7e4ee3a
CB
6310 /* We don't worry about COMPLEX return values here, because this is
6311 entirely internal to our code, and gcc has the ability to return COMPLEX
6312 directly as a value. */
6313
6314 yes = suspend_momentary ();
6315
6316 if (charfunc)
6317 { /* Prepend arg for where result goes. */
6318 tree type;
6319
6320 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
6321
14657de8 6322 result = ffecom_get_invented_identifier ("__g77_%s", "result");
c7e4ee3a
CB
6323
6324 ffecom_char_enhance_arg_ (&type, s); /* Ignore returned length. */
6325
6326 type = build_pointer_type (type);
6327 result = build_decl (PARM_DECL, result, type);
6328
6329 push_parm_decl (result);
5ff904cd 6330 }
c7e4ee3a
CB
6331 else
6332 result = NULL_TREE; /* Not ref'd if !charfunc. */
5ff904cd 6333
c7e4ee3a 6334 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (s), TRUE);
5ff904cd 6335
c7e4ee3a 6336 resume_momentary (yes);
5ff904cd 6337
c7e4ee3a
CB
6338 store_parm_decls (0);
6339
6340 ffecom_start_compstmt ();
6341
6342 if (expr != NULL)
5ff904cd 6343 {
c7e4ee3a
CB
6344 if (charfunc)
6345 {
6346 ffetargetCharacterSize sz = ffesymbol_size (s);
6347 tree result_length;
5ff904cd 6348
c7e4ee3a
CB
6349 result_length = build_int_2 (sz, 0);
6350 TREE_TYPE (result_length) = ffecom_f2c_ftnlen_type_node;
5ff904cd 6351
c7e4ee3a 6352 ffecom_prepare_let_char_ (sz, expr);
5ff904cd 6353
c7e4ee3a 6354 ffecom_prepare_end ();
5ff904cd 6355
c7e4ee3a
CB
6356 ffecom_let_char_ (result, result_length, sz, expr);
6357 expand_null_return ();
6358 }
6359 else
6360 {
6361 ffecom_prepare_expr (expr);
5ff904cd 6362
c7e4ee3a 6363 ffecom_prepare_end ();
5ff904cd 6364
c7e4ee3a
CB
6365 expand_return (ffecom_modify (NULL_TREE,
6366 DECL_RESULT (current_function_decl),
6367 ffecom_expr (expr)));
6368 }
5ff904cd 6369
c7e4ee3a
CB
6370 clear_momentary ();
6371 }
5ff904cd 6372
c7e4ee3a 6373 ffecom_end_compstmt ();
5ff904cd 6374
c7e4ee3a
CB
6375 func = current_function_decl;
6376 finish_function (1);
5ff904cd 6377
c7e4ee3a 6378 pop_f_function_context ();
5ff904cd 6379
c7e4ee3a 6380 resume_momentary (yes);
5ff904cd 6381
c7e4ee3a
CB
6382 recurse = FALSE;
6383
6384 lineno = old_lineno;
6385 input_filename = old_input_filename;
6386
6387 ffecom_nested_entry_ = NULL;
6388
6389 return func;
5ff904cd
JL
6390}
6391
6392#endif
5ff904cd 6393
c7e4ee3a
CB
6394#if FFECOM_targetCURRENT == FFECOM_targetGCC
6395static const char *
6396ffecom_gfrt_args_ (ffecomGfrt ix)
5ff904cd 6397{
c7e4ee3a
CB
6398 return ffecom_gfrt_argstring_[ix];
6399}
5ff904cd 6400
c7e4ee3a
CB
6401#endif
6402#if FFECOM_targetCURRENT == FFECOM_targetGCC
6403static tree
6404ffecom_gfrt_tree_ (ffecomGfrt ix)
6405{
6406 if (ffecom_gfrt_[ix] == NULL_TREE)
6407 ffecom_make_gfrt_ (ix);
6408
6409 return ffecom_1 (ADDR_EXPR,
6410 build_pointer_type (TREE_TYPE (ffecom_gfrt_[ix])),
6411 ffecom_gfrt_[ix]);
5ff904cd
JL
6412}
6413
6414#endif
c7e4ee3a 6415/* Return initialize-to-zero expression for this VAR_DECL. */
5ff904cd
JL
6416
6417#if FFECOM_targetCURRENT == FFECOM_targetGCC
7189a4b0
GK
6418/* A somewhat evil way to prevent the garbage collector
6419 from collecting 'tree' structures. */
6420#define NUM_TRACKED_CHUNK 63
6421static struct tree_ggc_tracker
6422{
6423 struct tree_ggc_tracker *next;
6424 tree trees[NUM_TRACKED_CHUNK];
6425} *tracker_head = NULL;
6426
6427static void
54551044 6428mark_tracker_head (void *arg)
7189a4b0
GK
6429{
6430 struct tree_ggc_tracker *head;
6431 int i;
6432
6433 for (head = * (struct tree_ggc_tracker **) arg;
6434 head != NULL;
6435 head = head->next)
6436 {
6437 ggc_mark (head);
6438 for (i = 0; i < NUM_TRACKED_CHUNK; i++)
6439 ggc_mark_tree (head->trees[i]);
6440 }
6441}
6442
6443void
6444ffecom_save_tree_forever (tree t)
6445{
6446 int i;
6447 if (tracker_head != NULL)
6448 for (i = 0; i < NUM_TRACKED_CHUNK; i++)
6449 if (tracker_head->trees[i] == NULL)
6450 {
6451 tracker_head->trees[i] = t;
6452 return;
6453 }
6454
6455 {
6456 /* Need to allocate a new block. */
6457 struct tree_ggc_tracker *old_head = tracker_head;
6458
6459 tracker_head = ggc_alloc (sizeof (*tracker_head));
6460 tracker_head->next = old_head;
6461 tracker_head->trees[0] = t;
6462 for (i = 1; i < NUM_TRACKED_CHUNK; i++)
6463 tracker_head->trees[i] = NULL;
6464 }
6465}
6466
c7e4ee3a
CB
6467static tree
6468ffecom_init_zero_ (tree decl)
5ff904cd 6469{
c7e4ee3a
CB
6470 tree init;
6471 int incremental = TREE_STATIC (decl);
6472 tree type = TREE_TYPE (decl);
5ff904cd 6473
c7e4ee3a
CB
6474 if (incremental)
6475 {
c7e4ee3a
CB
6476 make_decl_rtl (decl, NULL, TREE_PUBLIC (decl) ? 1 : 0);
6477 assemble_variable (decl, TREE_PUBLIC (decl) ? 1 : 0, 0, 1);
c7e4ee3a 6478 }
5ff904cd 6479
c7e4ee3a 6480 push_momentary ();
5ff904cd 6481
c7e4ee3a
CB
6482 if ((TREE_CODE (type) != ARRAY_TYPE)
6483 && (TREE_CODE (type) != RECORD_TYPE)
6484 && (TREE_CODE (type) != UNION_TYPE)
6485 && !incremental)
6486 init = convert (type, integer_zero_node);
6487 else if (!incremental)
6488 {
6489 int momentary = suspend_momentary ();
5ff904cd 6490
c7e4ee3a
CB
6491 init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
6492 TREE_CONSTANT (init) = 1;
6493 TREE_STATIC (init) = 1;
5ff904cd 6494
c7e4ee3a
CB
6495 resume_momentary (momentary);
6496 }
6497 else
6498 {
6499 int momentary = suspend_momentary ();
5ff904cd 6500
c7e4ee3a
CB
6501 assemble_zeros (int_size_in_bytes (type));
6502 init = error_mark_node;
5ff904cd 6503
c7e4ee3a
CB
6504 resume_momentary (momentary);
6505 }
5ff904cd 6506
c7e4ee3a 6507 pop_momentary_nofree ();
5ff904cd 6508
c7e4ee3a 6509 return init;
5ff904cd
JL
6510}
6511
6512#endif
5ff904cd 6513#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
6514static tree
6515ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg,
6516 tree *maybe_tree)
5ff904cd 6517{
c7e4ee3a
CB
6518 tree expr_tree;
6519 tree length_tree;
5ff904cd 6520
c7e4ee3a 6521 switch (ffebld_op (arg))
6829256f 6522 {
c7e4ee3a
CB
6523 case FFEBLD_opCONTER: /* For F90, check 0-length. */
6524 if (ffetarget_length_character1
6525 (ffebld_constant_character1
6526 (ffebld_conter (arg))) == 0)
6527 {
6528 *maybe_tree = integer_zero_node;
6529 return convert (tree_type, integer_zero_node);
6530 }
5ff904cd 6531
c7e4ee3a
CB
6532 *maybe_tree = integer_one_node;
6533 expr_tree = build_int_2 (*ffetarget_text_character1
6534 (ffebld_constant_character1
6535 (ffebld_conter (arg))),
6536 0);
6537 TREE_TYPE (expr_tree) = tree_type;
6538 return expr_tree;
5ff904cd 6539
c7e4ee3a
CB
6540 case FFEBLD_opSYMTER:
6541 case FFEBLD_opARRAYREF:
6542 case FFEBLD_opFUNCREF:
6543 case FFEBLD_opSUBSTR:
6544 ffecom_char_args_ (&expr_tree, &length_tree, arg);
5ff904cd 6545
c7e4ee3a
CB
6546 if ((expr_tree == error_mark_node)
6547 || (length_tree == error_mark_node))
6548 {
6549 *maybe_tree = error_mark_node;
6550 return error_mark_node;
6551 }
5ff904cd 6552
c7e4ee3a
CB
6553 if (integer_zerop (length_tree))
6554 {
6555 *maybe_tree = integer_zero_node;
6556 return convert (tree_type, integer_zero_node);
6557 }
6558
6559 expr_tree
6560 = ffecom_1 (INDIRECT_REF,
6561 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
6562 expr_tree);
6563 expr_tree
6564 = ffecom_2 (ARRAY_REF,
6565 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
6566 expr_tree,
6567 integer_one_node);
6568 expr_tree = convert (tree_type, expr_tree);
6569
6570 if (TREE_CODE (length_tree) == INTEGER_CST)
6571 *maybe_tree = integer_one_node;
6572 else /* Must check length at run time. */
6573 *maybe_tree
6574 = ffecom_truth_value
6575 (ffecom_2 (GT_EXPR, integer_type_node,
6576 length_tree,
6577 ffecom_f2c_ftnlen_zero_node));
6578 return expr_tree;
6579
6580 case FFEBLD_opPAREN:
6581 case FFEBLD_opCONVERT:
6582 if (ffeinfo_size (ffebld_info (arg)) == 0)
6583 {
6584 *maybe_tree = integer_zero_node;
6585 return convert (tree_type, integer_zero_node);
6586 }
6587 return ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
6588 maybe_tree);
6589
6590 case FFEBLD_opCONCATENATE:
6591 {
6592 tree maybe_left;
6593 tree maybe_right;
6594 tree expr_left;
6595 tree expr_right;
6596
6597 expr_left = ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
6598 &maybe_left);
6599 expr_right = ffecom_intrinsic_ichar_ (tree_type, ffebld_right (arg),
6600 &maybe_right);
6601 *maybe_tree = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
6602 maybe_left,
6603 maybe_right);
6604 expr_tree = ffecom_3 (COND_EXPR, tree_type,
6605 maybe_left,
6606 expr_left,
6607 expr_right);
6608 return expr_tree;
6609 }
6610
6611 default:
6612 assert ("bad op in ICHAR" == NULL);
6613 return error_mark_node;
6614 }
5ff904cd
JL
6615}
6616
6617#endif
c7e4ee3a
CB
6618/* ffecom_intrinsic_len_ -- Return length info for char arg (LEN())
6619
6620 tree length_arg;
6621 ffebld expr;
6622 length_arg = ffecom_intrinsic_len_ (expr);
6623
6624 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
6625 subexpressions by constructing the appropriate tree for the
6626 length-of-character-text argument in a calling sequence. */
5ff904cd
JL
6627
6628#if FFECOM_targetCURRENT == FFECOM_targetGCC
6629static tree
c7e4ee3a 6630ffecom_intrinsic_len_ (ffebld expr)
5ff904cd 6631{
c7e4ee3a
CB
6632 ffetargetCharacter1 val;
6633 tree length;
6634
6635 switch (ffebld_op (expr))
6636 {
6637 case FFEBLD_opCONTER:
6638 val = ffebld_constant_character1 (ffebld_conter (expr));
6639 length = build_int_2 (ffetarget_length_character1 (val), 0);
6640 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6641 break;
6642
6643 case FFEBLD_opSYMTER:
6644 {
6645 ffesymbol s = ffebld_symter (expr);
6646 tree item;
6647
6648 item = ffesymbol_hook (s).decl_tree;
6649 if (item == NULL_TREE)
6650 {
6651 s = ffecom_sym_transform_ (s);
6652 item = ffesymbol_hook (s).decl_tree;
6653 }
6654 if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
6655 {
6656 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
6657 length = ffesymbol_hook (s).length_tree;
6658 else
6659 {
6660 length = build_int_2 (ffesymbol_size (s), 0);
6661 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6662 }
6663 }
6664 else if (item == error_mark_node)
6665 length = error_mark_node;
6666 else /* FFEINFO_kindFUNCTION: */
6667 length = NULL_TREE;
6668 }
6669 break;
5ff904cd 6670
c7e4ee3a
CB
6671 case FFEBLD_opARRAYREF:
6672 length = ffecom_intrinsic_len_ (ffebld_left (expr));
6673 break;
5ff904cd 6674
c7e4ee3a
CB
6675 case FFEBLD_opSUBSTR:
6676 {
6677 ffebld start;
6678 ffebld end;
6679 ffebld thing = ffebld_right (expr);
6680 tree start_tree;
6681 tree end_tree;
5ff904cd 6682
c7e4ee3a
CB
6683 assert (ffebld_op (thing) == FFEBLD_opITEM);
6684 start = ffebld_head (thing);
6685 thing = ffebld_trail (thing);
6686 assert (ffebld_trail (thing) == NULL);
6687 end = ffebld_head (thing);
5ff904cd 6688
c7e4ee3a 6689 length = ffecom_intrinsic_len_ (ffebld_left (expr));
5ff904cd 6690
c7e4ee3a
CB
6691 if (length == error_mark_node)
6692 break;
5ff904cd 6693
c7e4ee3a
CB
6694 if (start == NULL)
6695 {
6696 if (end == NULL)
6697 ;
6698 else
6699 {
6700 length = convert (ffecom_f2c_ftnlen_type_node,
6701 ffecom_expr (end));
6702 }
6703 }
6704 else
6705 {
6706 start_tree = convert (ffecom_f2c_ftnlen_type_node,
6707 ffecom_expr (start));
5ff904cd 6708
c7e4ee3a
CB
6709 if (start_tree == error_mark_node)
6710 {
6711 length = error_mark_node;
6712 break;
6713 }
5ff904cd 6714
c7e4ee3a
CB
6715 if (end == NULL)
6716 {
6717 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6718 ffecom_f2c_ftnlen_one_node,
6719 ffecom_2 (MINUS_EXPR,
6720 ffecom_f2c_ftnlen_type_node,
6721 length,
6722 start_tree));
6723 }
6724 else
6725 {
6726 end_tree = convert (ffecom_f2c_ftnlen_type_node,
6727 ffecom_expr (end));
5ff904cd 6728
c7e4ee3a
CB
6729 if (end_tree == error_mark_node)
6730 {
6731 length = error_mark_node;
6732 break;
6733 }
5ff904cd 6734
c7e4ee3a
CB
6735 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6736 ffecom_f2c_ftnlen_one_node,
6737 ffecom_2 (MINUS_EXPR,
6738 ffecom_f2c_ftnlen_type_node,
6739 end_tree, start_tree));
6740 }
6741 }
6742 }
6743 break;
5ff904cd 6744
c7e4ee3a
CB
6745 case FFEBLD_opCONCATENATE:
6746 length
6747 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6748 ffecom_intrinsic_len_ (ffebld_left (expr)),
6749 ffecom_intrinsic_len_ (ffebld_right (expr)));
6750 break;
5ff904cd 6751
c7e4ee3a
CB
6752 case FFEBLD_opFUNCREF:
6753 case FFEBLD_opCONVERT:
6754 length = build_int_2 (ffebld_size (expr), 0);
6755 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6756 break;
5ff904cd 6757
c7e4ee3a
CB
6758 default:
6759 assert ("bad op for single char arg expr" == NULL);
6760 length = ffecom_f2c_ftnlen_zero_node;
6761 break;
6762 }
5ff904cd 6763
c7e4ee3a 6764 assert (length != NULL_TREE);
5ff904cd 6765
c7e4ee3a 6766 return length;
5ff904cd
JL
6767}
6768
6769#endif
c7e4ee3a 6770/* Handle CHARACTER assignments.
5ff904cd 6771
c7e4ee3a
CB
6772 Generates code to do the assignment. Used by ordinary assignment
6773 statement handler ffecom_let_stmt and by statement-function
6774 handler to generate code for a statement function. */
5ff904cd
JL
6775
6776#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
6777static void
6778ffecom_let_char_ (tree dest_tree, tree dest_length,
6779 ffetargetCharacterSize dest_size, ffebld source)
5ff904cd 6780{
c7e4ee3a
CB
6781 ffecomConcatList_ catlist;
6782 tree source_length;
6783 tree source_tree;
6784 tree expr_tree;
5ff904cd 6785
c7e4ee3a
CB
6786 if ((dest_tree == error_mark_node)
6787 || (dest_length == error_mark_node))
6788 return;
5ff904cd 6789
c7e4ee3a
CB
6790 assert (dest_tree != NULL_TREE);
6791 assert (dest_length != NULL_TREE);
5ff904cd 6792
c7e4ee3a
CB
6793 /* Source might be an opCONVERT, which just means it is a different size
6794 than the destination. Since the underlying implementation here handles
6795 that (directly or via the s_copy or s_cat run-time-library functions),
6796 we don't need the "convenience" of an opCONVERT that tells us to
6797 truncate or blank-pad, particularly since the resulting implementation
6798 would probably be slower than otherwise. */
5ff904cd 6799
c7e4ee3a
CB
6800 while (ffebld_op (source) == FFEBLD_opCONVERT)
6801 source = ffebld_left (source);
5ff904cd 6802
c7e4ee3a
CB
6803 catlist = ffecom_concat_list_new_ (source, dest_size);
6804 switch (ffecom_concat_list_count_ (catlist))
6805 {
6806 case 0: /* Shouldn't happen, but in case it does... */
6807 ffecom_concat_list_kill_ (catlist);
6808 source_tree = null_pointer_node;
6809 source_length = ffecom_f2c_ftnlen_zero_node;
6810 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6811 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
6812 TREE_CHAIN (TREE_CHAIN (expr_tree))
6813 = build_tree_list (NULL_TREE, dest_length);
6814 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6815 = build_tree_list (NULL_TREE, source_length);
5ff904cd 6816
c7e4ee3a
CB
6817 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree, NULL_TREE);
6818 TREE_SIDE_EFFECTS (expr_tree) = 1;
5ff904cd 6819
c7e4ee3a 6820 expand_expr_stmt (expr_tree);
5ff904cd 6821
c7e4ee3a 6822 return;
5ff904cd 6823
c7e4ee3a
CB
6824 case 1: /* The (fairly) easy case. */
6825 ffecom_char_args_ (&source_tree, &source_length,
6826 ffecom_concat_list_expr_ (catlist, 0));
6827 ffecom_concat_list_kill_ (catlist);
6828 assert (source_tree != NULL_TREE);
6829 assert (source_length != NULL_TREE);
6830
6831 if ((source_tree == error_mark_node)
6832 || (source_length == error_mark_node))
6833 return;
6834
6835 if (dest_size == 1)
6836 {
6837 dest_tree
6838 = ffecom_1 (INDIRECT_REF,
6839 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6840 (dest_tree))),
6841 dest_tree);
6842 dest_tree
6843 = ffecom_2 (ARRAY_REF,
6844 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6845 (dest_tree))),
6846 dest_tree,
6847 integer_one_node);
6848 source_tree
6849 = ffecom_1 (INDIRECT_REF,
6850 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6851 (source_tree))),
6852 source_tree);
6853 source_tree
6854 = ffecom_2 (ARRAY_REF,
6855 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6856 (source_tree))),
6857 source_tree,
6858 integer_one_node);
5ff904cd 6859
c7e4ee3a 6860 expr_tree = ffecom_modify (void_type_node, dest_tree, source_tree);
5ff904cd 6861
c7e4ee3a 6862 expand_expr_stmt (expr_tree);
5ff904cd 6863
c7e4ee3a
CB
6864 return;
6865 }
5ff904cd 6866
c7e4ee3a
CB
6867 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6868 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
6869 TREE_CHAIN (TREE_CHAIN (expr_tree))
6870 = build_tree_list (NULL_TREE, dest_length);
6871 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6872 = build_tree_list (NULL_TREE, source_length);
5ff904cd 6873
c7e4ee3a
CB
6874 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree, NULL_TREE);
6875 TREE_SIDE_EFFECTS (expr_tree) = 1;
5ff904cd 6876
c7e4ee3a 6877 expand_expr_stmt (expr_tree);
5ff904cd 6878
c7e4ee3a 6879 return;
5ff904cd 6880
c7e4ee3a
CB
6881 default: /* Must actually concatenate things. */
6882 break;
6883 }
5ff904cd 6884
c7e4ee3a 6885 /* Heavy-duty concatenation. */
5ff904cd 6886
c7e4ee3a
CB
6887 {
6888 int count = ffecom_concat_list_count_ (catlist);
6889 int i;
6890 tree lengths;
6891 tree items;
6892 tree length_array;
6893 tree item_array;
6894 tree citem;
6895 tree clength;
5ff904cd 6896
c7e4ee3a
CB
6897#ifdef HOHO
6898 length_array
6899 = lengths
6900 = ffecom_push_tempvar (ffecom_f2c_ftnlen_type_node,
6901 FFETARGET_charactersizeNONE, count, TRUE);
6902 item_array = items = ffecom_push_tempvar (ffecom_f2c_address_type_node,
6903 FFETARGET_charactersizeNONE,
6904 count, TRUE);
6905#else
6906 {
6907 tree hook;
6908
6909 hook = ffebld_nonter_hook (source);
6910 assert (hook);
6911 assert (TREE_CODE (hook) == TREE_VEC);
6912 assert (TREE_VEC_LENGTH (hook) == 2);
6913 length_array = lengths = TREE_VEC_ELT (hook, 0);
6914 item_array = items = TREE_VEC_ELT (hook, 1);
5ff904cd 6915 }
c7e4ee3a 6916#endif
5ff904cd 6917
c7e4ee3a
CB
6918 for (i = 0; i < count; ++i)
6919 {
6920 ffecom_char_args_ (&citem, &clength,
6921 ffecom_concat_list_expr_ (catlist, i));
6922 if ((citem == error_mark_node)
6923 || (clength == error_mark_node))
6924 {
6925 ffecom_concat_list_kill_ (catlist);
6926 return;
6927 }
5ff904cd 6928
c7e4ee3a
CB
6929 items
6930 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
6931 ffecom_modify (void_type_node,
6932 ffecom_2 (ARRAY_REF,
6933 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
6934 item_array,
6935 build_int_2 (i, 0)),
6936 citem),
6937 items);
6938 lengths
6939 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
6940 ffecom_modify (void_type_node,
6941 ffecom_2 (ARRAY_REF,
6942 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
6943 length_array,
6944 build_int_2 (i, 0)),
6945 clength),
6946 lengths);
6947 }
5ff904cd 6948
c7e4ee3a
CB
6949 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6950 TREE_CHAIN (expr_tree)
6951 = build_tree_list (NULL_TREE,
6952 ffecom_1 (ADDR_EXPR,
6953 build_pointer_type (TREE_TYPE (items)),
6954 items));
6955 TREE_CHAIN (TREE_CHAIN (expr_tree))
6956 = build_tree_list (NULL_TREE,
6957 ffecom_1 (ADDR_EXPR,
6958 build_pointer_type (TREE_TYPE (lengths)),
6959 lengths));
6960 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6961 = build_tree_list
6962 (NULL_TREE,
6963 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
6964 convert (ffecom_f2c_ftnlen_type_node,
6965 build_int_2 (count, 0))));
6966 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree))))
6967 = build_tree_list (NULL_TREE, dest_length);
5ff904cd 6968
c7e4ee3a
CB
6969 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCAT, expr_tree, NULL_TREE);
6970 TREE_SIDE_EFFECTS (expr_tree) = 1;
5ff904cd 6971
c7e4ee3a
CB
6972 expand_expr_stmt (expr_tree);
6973 }
5ff904cd 6974
c7e4ee3a
CB
6975 ffecom_concat_list_kill_ (catlist);
6976}
5ff904cd 6977
c7e4ee3a
CB
6978#endif
6979/* ffecom_make_gfrt_ -- Make initial info for run-time routine
5ff904cd 6980
c7e4ee3a
CB
6981 ffecomGfrt ix;
6982 ffecom_make_gfrt_(ix);
5ff904cd 6983
c7e4ee3a
CB
6984 Assumes gfrt_[ix] is NULL_TREE, and replaces it with the FUNCTION_DECL
6985 for the indicated run-time routine (ix). */
5ff904cd 6986
c7e4ee3a
CB
6987#if FFECOM_targetCURRENT == FFECOM_targetGCC
6988static void
6989ffecom_make_gfrt_ (ffecomGfrt ix)
6990{
6991 tree t;
6992 tree ttype;
5ff904cd 6993
c7e4ee3a
CB
6994 switch (ffecom_gfrt_type_[ix])
6995 {
6996 case FFECOM_rttypeVOID_:
6997 ttype = void_type_node;
6998 break;
5ff904cd 6999
c7e4ee3a
CB
7000 case FFECOM_rttypeVOIDSTAR_:
7001 ttype = TREE_TYPE (null_pointer_node); /* `void *'. */
7002 break;
5ff904cd 7003
c7e4ee3a
CB
7004 case FFECOM_rttypeFTNINT_:
7005 ttype = ffecom_f2c_ftnint_type_node;
7006 break;
5ff904cd 7007
c7e4ee3a
CB
7008 case FFECOM_rttypeINTEGER_:
7009 ttype = ffecom_f2c_integer_type_node;
7010 break;
5ff904cd 7011
c7e4ee3a
CB
7012 case FFECOM_rttypeLONGINT_:
7013 ttype = ffecom_f2c_longint_type_node;
7014 break;
5ff904cd 7015
c7e4ee3a
CB
7016 case FFECOM_rttypeLOGICAL_:
7017 ttype = ffecom_f2c_logical_type_node;
7018 break;
5ff904cd 7019
c7e4ee3a
CB
7020 case FFECOM_rttypeREAL_F2C_:
7021 ttype = double_type_node;
7022 break;
5ff904cd 7023
c7e4ee3a
CB
7024 case FFECOM_rttypeREAL_GNU_:
7025 ttype = float_type_node;
7026 break;
5ff904cd 7027
c7e4ee3a
CB
7028 case FFECOM_rttypeCOMPLEX_F2C_:
7029 ttype = void_type_node;
7030 break;
5ff904cd 7031
c7e4ee3a
CB
7032 case FFECOM_rttypeCOMPLEX_GNU_:
7033 ttype = ffecom_f2c_complex_type_node;
7034 break;
5ff904cd 7035
c7e4ee3a
CB
7036 case FFECOM_rttypeDOUBLE_:
7037 ttype = double_type_node;
7038 break;
5ff904cd 7039
c7e4ee3a
CB
7040 case FFECOM_rttypeDOUBLEREAL_:
7041 ttype = ffecom_f2c_doublereal_type_node;
7042 break;
5ff904cd 7043
c7e4ee3a
CB
7044 case FFECOM_rttypeDBLCMPLX_F2C_:
7045 ttype = void_type_node;
7046 break;
5ff904cd 7047
c7e4ee3a
CB
7048 case FFECOM_rttypeDBLCMPLX_GNU_:
7049 ttype = ffecom_f2c_doublecomplex_type_node;
7050 break;
5ff904cd 7051
c7e4ee3a
CB
7052 case FFECOM_rttypeCHARACTER_:
7053 ttype = void_type_node;
7054 break;
7055
7056 default:
7057 ttype = NULL;
7058 assert ("bad rttype" == NULL);
7059 break;
5ff904cd 7060 }
5ff904cd 7061
c7e4ee3a
CB
7062 ttype = build_function_type (ttype, NULL_TREE);
7063 t = build_decl (FUNCTION_DECL,
7064 get_identifier (ffecom_gfrt_name_[ix]),
7065 ttype);
7066 DECL_EXTERNAL (t) = 1;
7067 TREE_PUBLIC (t) = 1;
7068 TREE_THIS_VOLATILE (t) = ffecom_gfrt_volatile_[ix] ? 1 : 0;
5ff904cd 7069
c7e4ee3a 7070 t = start_decl (t, TRUE);
5ff904cd 7071
c7e4ee3a 7072 finish_decl (t, NULL_TREE, TRUE);
5ff904cd 7073
c7e4ee3a 7074 ffecom_gfrt_[ix] = t;
5ff904cd
JL
7075}
7076
7077#endif
c7e4ee3a
CB
7078/* Phase 1 pass over each member of a COMMON/EQUIVALENCE group. */
7079
5ff904cd 7080#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
7081static void
7082ffecom_member_phase1_ (ffestorag mst UNUSED, ffestorag st)
5ff904cd 7083{
c7e4ee3a 7084 ffesymbol s = ffestorag_symbol (st);
5ff904cd 7085
c7e4ee3a
CB
7086 if (ffesymbol_namelisted (s))
7087 ffecom_member_namelisted_ = TRUE;
7088}
5ff904cd 7089
c7e4ee3a
CB
7090#endif
7091/* Phase 2 pass over each member of a COMMON/EQUIVALENCE group. Declare
7092 the member so debugger will see it. Otherwise nobody should be
7093 referencing the member. */
5ff904cd 7094
c7e4ee3a 7095#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
7096static void
7097ffecom_member_phase2_ (ffestorag mst, ffestorag st)
7098{
7099 ffesymbol s;
7100 tree t;
7101 tree mt;
7102 tree type;
5ff904cd 7103
c7e4ee3a
CB
7104 if ((mst == NULL)
7105 || ((mt = ffestorag_hook (mst)) == NULL)
7106 || (mt == error_mark_node))
7107 return;
5ff904cd 7108
c7e4ee3a
CB
7109 if ((st == NULL)
7110 || ((s = ffestorag_symbol (st)) == NULL))
7111 return;
5ff904cd 7112
c7e4ee3a
CB
7113 type = ffecom_type_localvar_ (s,
7114 ffesymbol_basictype (s),
7115 ffesymbol_kindtype (s));
7116 if (type == error_mark_node)
7117 return;
5ff904cd 7118
c7e4ee3a
CB
7119 t = build_decl (VAR_DECL,
7120 ffecom_get_identifier_ (ffesymbol_text (s)),
7121 type);
5ff904cd 7122
c7e4ee3a
CB
7123 TREE_STATIC (t) = TREE_STATIC (mt);
7124 DECL_INITIAL (t) = NULL_TREE;
7125 TREE_ASM_WRITTEN (t) = 1;
5ff904cd 7126
c7e4ee3a
CB
7127 DECL_RTL (t)
7128 = gen_rtx (MEM, TYPE_MODE (type),
7129 plus_constant (XEXP (DECL_RTL (mt), 0),
7130 ffestorag_modulo (mst)
7131 + ffestorag_offset (st)
7132 - ffestorag_offset (mst)));
5ff904cd 7133
c7e4ee3a 7134 t = start_decl (t, FALSE);
5ff904cd 7135
c7e4ee3a 7136 finish_decl (t, NULL_TREE, FALSE);
5ff904cd
JL
7137}
7138
c7e4ee3a
CB
7139#endif
7140/* Prepare source expression for assignment into a destination perhaps known
7141 to be of a specific size. */
5ff904cd 7142
c7e4ee3a
CB
7143static void
7144ffecom_prepare_let_char_ (ffetargetCharacterSize dest_size, ffebld source)
5ff904cd 7145{
c7e4ee3a
CB
7146 ffecomConcatList_ catlist;
7147 int count;
7148 int i;
7149 tree ltmp;
7150 tree itmp;
7151 tree tempvar = NULL_TREE;
5ff904cd 7152
c7e4ee3a
CB
7153 while (ffebld_op (source) == FFEBLD_opCONVERT)
7154 source = ffebld_left (source);
5ff904cd 7155
c7e4ee3a
CB
7156 catlist = ffecom_concat_list_new_ (source, dest_size);
7157 count = ffecom_concat_list_count_ (catlist);
5ff904cd 7158
c7e4ee3a
CB
7159 if (count >= 2)
7160 {
7161 ltmp
7162 = ffecom_make_tempvar ("let_char_len", ffecom_f2c_ftnlen_type_node,
7163 FFETARGET_charactersizeNONE, count);
7164 itmp
7165 = ffecom_make_tempvar ("let_char_item", ffecom_f2c_address_type_node,
7166 FFETARGET_charactersizeNONE, count);
7167
7168 tempvar = make_tree_vec (2);
7169 TREE_VEC_ELT (tempvar, 0) = ltmp;
7170 TREE_VEC_ELT (tempvar, 1) = itmp;
7171 }
5ff904cd 7172
c7e4ee3a
CB
7173 for (i = 0; i < count; ++i)
7174 ffecom_prepare_arg_ptr_to_expr (ffecom_concat_list_expr_ (catlist, i));
5ff904cd 7175
c7e4ee3a 7176 ffecom_concat_list_kill_ (catlist);
5ff904cd 7177
c7e4ee3a
CB
7178 if (tempvar)
7179 {
7180 ffebld_nonter_set_hook (source, tempvar);
7181 current_binding_level->prep_state = 1;
7182 }
7183}
5ff904cd 7184
c7e4ee3a 7185/* ffecom_push_dummy_decls_ -- Transform dummy args, push parm decls in order
5ff904cd 7186
c7e4ee3a
CB
7187 Ignores STAR (alternate-return) dummies. All other get exec-transitioned
7188 (which generates their trees) and then their trees get push_parm_decl'd.
5ff904cd 7189
c7e4ee3a
CB
7190 The second arg is TRUE if the dummies are for a statement function, in
7191 which case lengths are not pushed for character arguments (since they are
7192 always known by both the caller and the callee, though the code allows
7193 for someday permitting CHAR*(*) stmtfunc dummies). */
5ff904cd 7194
c7e4ee3a
CB
7195#if FFECOM_targetCURRENT == FFECOM_targetGCC
7196static void
7197ffecom_push_dummy_decls_ (ffebld dummy_list, bool stmtfunc)
7198{
7199 ffebld dummy;
7200 ffebld dumlist;
7201 ffesymbol s;
7202 tree parm;
5ff904cd 7203
c7e4ee3a 7204 ffecom_transform_only_dummies_ = TRUE;
5ff904cd 7205
c7e4ee3a 7206 /* First push the parms corresponding to actual dummy "contents". */
5ff904cd 7207
c7e4ee3a
CB
7208 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
7209 {
7210 dummy = ffebld_head (dumlist);
7211 switch (ffebld_op (dummy))
7212 {
7213 case FFEBLD_opSTAR:
7214 case FFEBLD_opANY:
7215 continue; /* Forget alternate returns. */
5ff904cd 7216
c7e4ee3a
CB
7217 default:
7218 break;
7219 }
7220 assert (ffebld_op (dummy) == FFEBLD_opSYMTER);
7221 s = ffebld_symter (dummy);
7222 parm = ffesymbol_hook (s).decl_tree;
7223 if (parm == NULL_TREE)
7224 {
7225 s = ffecom_sym_transform_ (s);
7226 parm = ffesymbol_hook (s).decl_tree;
7227 assert (parm != NULL_TREE);
7228 }
7229 if (parm != error_mark_node)
7230 push_parm_decl (parm);
5ff904cd
JL
7231 }
7232
c7e4ee3a 7233 /* Then, for CHARACTER dummies, push the parms giving their lengths. */
5ff904cd 7234
c7e4ee3a
CB
7235 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
7236 {
7237 dummy = ffebld_head (dumlist);
7238 switch (ffebld_op (dummy))
7239 {
7240 case FFEBLD_opSTAR:
7241 case FFEBLD_opANY:
7242 continue; /* Forget alternate returns, they mean
7243 NOTHING! */
7244
7245 default:
7246 break;
7247 }
7248 s = ffebld_symter (dummy);
7249 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
7250 continue; /* Only looking for CHARACTER arguments. */
7251 if (stmtfunc && (ffesymbol_size (s) != FFETARGET_charactersizeNONE))
7252 continue; /* Stmtfunc arg with known size needs no
7253 length param. */
7254 if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
7255 continue; /* Only looking for variables and arrays. */
7256 parm = ffesymbol_hook (s).length_tree;
7257 assert (parm != NULL_TREE);
7258 if (parm != error_mark_node)
7259 push_parm_decl (parm);
7260 }
7261
7262 ffecom_transform_only_dummies_ = FALSE;
5ff904cd
JL
7263}
7264
7265#endif
c7e4ee3a 7266/* ffecom_start_progunit_ -- Beginning of program unit
5ff904cd 7267
c7e4ee3a
CB
7268 Does GNU back end stuff necessary to teach it about the start of its
7269 equivalent of a Fortran program unit. */
5ff904cd
JL
7270
7271#if FFECOM_targetCURRENT == FFECOM_targetGCC
7272static void
c7e4ee3a 7273ffecom_start_progunit_ ()
5ff904cd 7274{
c7e4ee3a
CB
7275 ffesymbol fn = ffecom_primary_entry_;
7276 ffebld arglist;
7277 tree id; /* Identifier (name) of function. */
7278 tree type; /* Type of function. */
7279 tree result; /* Result of function. */
7280 ffeinfoBasictype bt;
7281 ffeinfoKindtype kt;
7282 ffeglobal g;
7283 ffeglobalType gt;
7284 ffeglobalType egt = FFEGLOBAL_type;
7285 bool charfunc;
7286 bool cmplxfunc;
7287 bool altentries = (ffecom_num_entrypoints_ != 0);
7288 bool multi
7289 = altentries
7290 && (ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
7291 && (ffecom_master_bt_ == FFEINFO_basictypeNONE);
7292 bool main_program = FALSE;
7293 int old_lineno = lineno;
3b304f5b 7294 const char *old_input_filename = input_filename;
c7e4ee3a 7295 int yes;
5ff904cd 7296
c7e4ee3a
CB
7297 assert (fn != NULL);
7298 assert (ffesymbol_hook (fn).decl_tree == NULL_TREE);
5ff904cd 7299
c7e4ee3a
CB
7300 input_filename = ffesymbol_where_filename (fn);
7301 lineno = ffesymbol_where_filelinenum (fn);
5ff904cd 7302
c7e4ee3a
CB
7303 /* c-parse.y indeed does call suspend_momentary and not only ignores the
7304 return value, but also never calls resume_momentary, when starting an
7305 outer function (see "fndef:", "setspecs:", and so on). So g77 does the
7306 same thing. It shouldn't be a problem since start_function calls
7307 temporary_allocation, but it might be necessary. If it causes a problem
7308 here, then maybe there's a bug lurking in gcc. NOTE: This identical
7309 comment appears twice in thist file. */
7310
7311 suspend_momentary ();
7312
7313 switch (ffecom_primary_entry_kind_)
7314 {
7315 case FFEINFO_kindPROGRAM:
7316 main_program = TRUE;
7317 gt = FFEGLOBAL_typeMAIN;
7318 bt = FFEINFO_basictypeNONE;
7319 kt = FFEINFO_kindtypeNONE;
7320 type = ffecom_tree_fun_type_void;
7321 charfunc = FALSE;
7322 cmplxfunc = FALSE;
7323 break;
7324
7325 case FFEINFO_kindBLOCKDATA:
7326 gt = FFEGLOBAL_typeBDATA;
7327 bt = FFEINFO_basictypeNONE;
7328 kt = FFEINFO_kindtypeNONE;
7329 type = ffecom_tree_fun_type_void;
7330 charfunc = FALSE;
7331 cmplxfunc = FALSE;
7332 break;
7333
7334 case FFEINFO_kindFUNCTION:
7335 gt = FFEGLOBAL_typeFUNC;
7336 egt = FFEGLOBAL_typeEXT;
7337 bt = ffesymbol_basictype (fn);
7338 kt = ffesymbol_kindtype (fn);
7339 if (bt == FFEINFO_basictypeNONE)
7340 {
7341 ffeimplic_establish_symbol (fn);
7342 if (ffesymbol_funcresult (fn) != NULL)
7343 ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
7344 bt = ffesymbol_basictype (fn);
7345 kt = ffesymbol_kindtype (fn);
7346 }
7347
7348 if (multi)
7349 charfunc = cmplxfunc = FALSE;
7350 else if (bt == FFEINFO_basictypeCHARACTER)
7351 charfunc = TRUE, cmplxfunc = FALSE;
7352 else if ((bt == FFEINFO_basictypeCOMPLEX)
7353 && ffesymbol_is_f2c (fn)
7354 && !altentries)
7355 charfunc = FALSE, cmplxfunc = TRUE;
7356 else
7357 charfunc = cmplxfunc = FALSE;
7358
7359 if (multi || charfunc)
7360 type = ffecom_tree_fun_type_void;
7361 else if (ffesymbol_is_f2c (fn) && !altentries)
7362 type = ffecom_tree_fun_type[bt][kt];
7363 else
7364 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
7365
7366 if ((type == NULL_TREE)
7367 || (TREE_TYPE (type) == NULL_TREE))
7368 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */
7369 break;
7370
7371 case FFEINFO_kindSUBROUTINE:
7372 gt = FFEGLOBAL_typeSUBR;
7373 egt = FFEGLOBAL_typeEXT;
7374 bt = FFEINFO_basictypeNONE;
7375 kt = FFEINFO_kindtypeNONE;
7376 if (ffecom_is_altreturning_)
7377 type = ffecom_tree_subr_type;
7378 else
7379 type = ffecom_tree_fun_type_void;
7380 charfunc = FALSE;
7381 cmplxfunc = FALSE;
7382 break;
5ff904cd 7383
c7e4ee3a
CB
7384 default:
7385 assert ("say what??" == NULL);
7386 /* Fall through. */
7387 case FFEINFO_kindANY:
7388 gt = FFEGLOBAL_typeANY;
7389 bt = FFEINFO_basictypeNONE;
7390 kt = FFEINFO_kindtypeNONE;
7391 type = error_mark_node;
7392 charfunc = FALSE;
7393 cmplxfunc = FALSE;
7394 break;
7395 }
5ff904cd 7396
c7e4ee3a 7397 if (altentries)
5ff904cd 7398 {
c7e4ee3a 7399 id = ffecom_get_invented_identifier ("__g77_masterfun_%s",
14657de8 7400 ffesymbol_text (fn));
c7e4ee3a
CB
7401 }
7402#if FFETARGET_isENFORCED_MAIN
7403 else if (main_program)
7404 id = get_identifier (FFETARGET_nameENFORCED_MAIN_NAME);
7405#endif
7406 else
7407 id = ffecom_get_external_identifier_ (fn);
5ff904cd 7408
c7e4ee3a
CB
7409 start_function (id,
7410 type,
7411 0, /* nested/inline */
7412 !altentries); /* TREE_PUBLIC */
5ff904cd 7413
c7e4ee3a 7414 TREE_USED (current_function_decl) = 1; /* Avoid spurious warning if altentries. */
5ff904cd 7415
c7e4ee3a
CB
7416 if (!altentries
7417 && ((g = ffesymbol_global (fn)) != NULL)
7418 && ((ffeglobal_type (g) == gt)
7419 || (ffeglobal_type (g) == egt)))
7420 {
7421 ffeglobal_set_hook (g, current_function_decl);
7422 }
5ff904cd 7423
c7e4ee3a 7424 yes = suspend_momentary ();
5ff904cd 7425
c7e4ee3a
CB
7426 /* Arg handling needs exec-transitioned ffesymbols to work with. But
7427 exec-transitioning needs current_function_decl to be filled in. So we
7428 do these things in two phases. */
5ff904cd 7429
c7e4ee3a
CB
7430 if (altentries)
7431 { /* 1st arg identifies which entrypoint. */
7432 ffecom_which_entrypoint_decl_
7433 = build_decl (PARM_DECL,
7434 ffecom_get_invented_identifier ("__g77_%s",
14657de8 7435 "which_entrypoint"),
c7e4ee3a
CB
7436 integer_type_node);
7437 push_parm_decl (ffecom_which_entrypoint_decl_);
7438 }
5ff904cd 7439
c7e4ee3a
CB
7440 if (charfunc
7441 || cmplxfunc
7442 || multi)
7443 { /* Arg for result (return value). */
7444 tree type;
7445 tree length;
5ff904cd 7446
c7e4ee3a
CB
7447 if (charfunc)
7448 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
7449 else if (cmplxfunc)
7450 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
7451 else
7452 type = ffecom_multi_type_node_;
5ff904cd 7453
14657de8 7454 result = ffecom_get_invented_identifier ("__g77_%s", "result");
5ff904cd 7455
c7e4ee3a 7456 /* Make length arg _and_ enhance type info for CHAR arg itself. */
5ff904cd 7457
c7e4ee3a
CB
7458 if (charfunc)
7459 length = ffecom_char_enhance_arg_ (&type, fn);
7460 else
7461 length = NULL_TREE; /* Not ref'd if !charfunc. */
5ff904cd 7462
c7e4ee3a
CB
7463 type = build_pointer_type (type);
7464 result = build_decl (PARM_DECL, result, type);
5ff904cd 7465
c7e4ee3a
CB
7466 push_parm_decl (result);
7467 if (multi)
7468 ffecom_multi_retval_ = result;
7469 else
7470 ffecom_func_result_ = result;
5ff904cd 7471
c7e4ee3a
CB
7472 if (charfunc)
7473 {
7474 push_parm_decl (length);
7475 ffecom_func_length_ = length;
7476 }
5ff904cd
JL
7477 }
7478
c7e4ee3a
CB
7479 if (ffecom_primary_entry_is_proc_)
7480 {
7481 if (altentries)
7482 arglist = ffecom_master_arglist_;
7483 else
7484 arglist = ffesymbol_dummyargs (fn);
7485 ffecom_push_dummy_decls_ (arglist, FALSE);
7486 }
5ff904cd 7487
c7e4ee3a 7488 resume_momentary (yes);
5ff904cd 7489
c7e4ee3a
CB
7490 if (TREE_CODE (current_function_decl) != ERROR_MARK)
7491 store_parm_decls (main_program ? 1 : 0);
5ff904cd 7492
c7e4ee3a
CB
7493 ffecom_start_compstmt ();
7494 /* Disallow temp vars at this level. */
7495 current_binding_level->prep_state = 2;
5ff904cd 7496
c7e4ee3a
CB
7497 lineno = old_lineno;
7498 input_filename = old_input_filename;
5ff904cd 7499
c7e4ee3a
CB
7500 /* This handles any symbols still untransformed, in case -g specified.
7501 This used to be done in ffecom_finish_progunit, but it turns out to
7502 be necessary to do it here so that statement functions are
7503 expanded before code. But don't bother for BLOCK DATA. */
5ff904cd 7504
c7e4ee3a
CB
7505 if (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
7506 ffesymbol_drive (ffecom_finish_symbol_transform_);
5ff904cd
JL
7507}
7508
7509#endif
c7e4ee3a 7510/* ffecom_sym_transform_ -- Transform FFE sym into backend sym
5ff904cd 7511
c7e4ee3a
CB
7512 ffesymbol s;
7513 ffecom_sym_transform_(s);
7514
7515 The ffesymbol_hook info for s is updated with appropriate backend info
7516 on the symbol. */
7517
7518#if FFECOM_targetCURRENT == FFECOM_targetGCC
7519static ffesymbol
7520ffecom_sym_transform_ (ffesymbol s)
7521{
7522 tree t; /* Transformed thingy. */
7523 tree tlen; /* Length if CHAR*(*). */
7524 bool addr; /* Is t the address of the thingy? */
7525 ffeinfoBasictype bt;
7526 ffeinfoKindtype kt;
7527 ffeglobal g;
7528 int yes;
7529 int old_lineno = lineno;
3b304f5b 7530 const char *old_input_filename = input_filename;
5ff904cd 7531
c7e4ee3a
CB
7532 /* Must ensure special ASSIGN variables are declared at top of outermost
7533 block, else they'll end up in the innermost block when their first
7534 ASSIGN is seen, which leaves them out of scope when they're the
7535 subject of a GOTO or I/O statement.
5ff904cd 7536
c7e4ee3a
CB
7537 We make this variable even if -fugly-assign. Just let it go unused,
7538 in case it turns out there are cases where we really want to use this
7539 variable anyway (e.g. ASSIGN to INTEGER*2 variable). */
5ff904cd 7540
c7e4ee3a
CB
7541 if (! ffecom_transform_only_dummies_
7542 && ffesymbol_assigned (s)
7543 && ! ffesymbol_hook (s).assign_tree)
7544 s = ffecom_sym_transform_assign_ (s);
5ff904cd 7545
c7e4ee3a 7546 if (ffesymbol_sfdummyparent (s) == NULL)
5ff904cd 7547 {
c7e4ee3a
CB
7548 input_filename = ffesymbol_where_filename (s);
7549 lineno = ffesymbol_where_filelinenum (s);
7550 }
7551 else
7552 {
7553 ffesymbol sf = ffesymbol_sfdummyparent (s);
5ff904cd 7554
c7e4ee3a
CB
7555 input_filename = ffesymbol_where_filename (sf);
7556 lineno = ffesymbol_where_filelinenum (sf);
7557 }
6d433196 7558
c7e4ee3a
CB
7559 bt = ffeinfo_basictype (ffebld_info (s));
7560 kt = ffeinfo_kindtype (ffebld_info (s));
5ff904cd 7561
c7e4ee3a
CB
7562 t = NULL_TREE;
7563 tlen = NULL_TREE;
7564 addr = FALSE;
5ff904cd 7565
c7e4ee3a
CB
7566 switch (ffesymbol_kind (s))
7567 {
7568 case FFEINFO_kindNONE:
7569 switch (ffesymbol_where (s))
7570 {
7571 case FFEINFO_whereDUMMY: /* Subroutine or function. */
7572 assert (ffecom_transform_only_dummies_);
5ff904cd 7573
c7e4ee3a
CB
7574 /* Before 0.4, this could be ENTITY/DUMMY, but see
7575 ffestu_sym_end_transition -- no longer true (in particular, if
7576 it could be an ENTITY, it _will_ be made one, so that
7577 possibility won't come through here). So we never make length
7578 arg for CHARACTER type. */
5ff904cd 7579
c7e4ee3a
CB
7580 t = build_decl (PARM_DECL,
7581 ffecom_get_identifier_ (ffesymbol_text (s)),
7582 ffecom_tree_ptr_to_subr_type);
7583#if BUILT_FOR_270
7584 DECL_ARTIFICIAL (t) = 1;
7585#endif
7586 addr = TRUE;
7587 break;
5ff904cd 7588
c7e4ee3a
CB
7589 case FFEINFO_whereGLOBAL: /* Subroutine or function. */
7590 assert (!ffecom_transform_only_dummies_);
5ff904cd 7591
c7e4ee3a
CB
7592 if (((g = ffesymbol_global (s)) != NULL)
7593 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
7594 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
7595 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
7596 && (ffeglobal_hook (g) != NULL_TREE)
7597 && ffe_is_globals ())
7598 {
7599 t = ffeglobal_hook (g);
7600 break;
7601 }
5ff904cd 7602
c7e4ee3a
CB
7603 t = build_decl (FUNCTION_DECL,
7604 ffecom_get_external_identifier_ (s),
7605 ffecom_tree_subr_type); /* Assume subr. */
7606 DECL_EXTERNAL (t) = 1;
7607 TREE_PUBLIC (t) = 1;
5ff904cd 7608
c7e4ee3a
CB
7609 t = start_decl (t, FALSE);
7610 finish_decl (t, NULL_TREE, FALSE);
795232f7 7611
c7e4ee3a
CB
7612 if ((g != NULL)
7613 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
7614 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
7615 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
7616 ffeglobal_set_hook (g, t);
5ff904cd 7617
7189a4b0 7618 ffecom_save_tree_forever (t);
5ff904cd 7619
c7e4ee3a 7620 break;
5ff904cd 7621
c7e4ee3a
CB
7622 default:
7623 assert ("NONE where unexpected" == NULL);
7624 /* Fall through. */
7625 case FFEINFO_whereANY:
7626 break;
7627 }
5ff904cd 7628 break;
5ff904cd 7629
c7e4ee3a
CB
7630 case FFEINFO_kindENTITY:
7631 switch (ffeinfo_where (ffesymbol_info (s)))
7632 {
5ff904cd 7633
c7e4ee3a
CB
7634 case FFEINFO_whereCONSTANT:
7635 /* ~~Debugging info needed? */
7636 assert (!ffecom_transform_only_dummies_);
7637 t = error_mark_node; /* Shouldn't ever see this in expr. */
7638 break;
5ff904cd 7639
c7e4ee3a
CB
7640 case FFEINFO_whereLOCAL:
7641 assert (!ffecom_transform_only_dummies_);
5ff904cd 7642
c7e4ee3a
CB
7643 {
7644 ffestorag st = ffesymbol_storage (s);
7645 tree type;
5ff904cd 7646
c7e4ee3a
CB
7647 if ((st != NULL)
7648 && (ffestorag_size (st) == 0))
7649 {
7650 t = error_mark_node;
7651 break;
7652 }
5ff904cd 7653
c7e4ee3a
CB
7654 yes = suspend_momentary ();
7655 type = ffecom_type_localvar_ (s, bt, kt);
7656 resume_momentary (yes);
5ff904cd 7657
c7e4ee3a
CB
7658 if (type == error_mark_node)
7659 {
7660 t = error_mark_node;
7661 break;
7662 }
5ff904cd 7663
c7e4ee3a
CB
7664 if ((st != NULL)
7665 && (ffestorag_parent (st) != NULL))
7666 { /* Child of EQUIVALENCE parent. */
7667 ffestorag est;
7668 tree et;
7669 int yes;
7670 ffetargetOffset offset;
5ff904cd 7671
c7e4ee3a
CB
7672 est = ffestorag_parent (st);
7673 ffecom_transform_equiv_ (est);
5ff904cd 7674
c7e4ee3a
CB
7675 et = ffestorag_hook (est);
7676 assert (et != NULL_TREE);
5ff904cd 7677
c7e4ee3a
CB
7678 if (! TREE_STATIC (et))
7679 put_var_into_stack (et);
5ff904cd 7680
c7e4ee3a 7681 yes = suspend_momentary ();
5ff904cd 7682
c7e4ee3a
CB
7683 offset = ffestorag_modulo (est)
7684 + ffestorag_offset (ffesymbol_storage (s))
7685 - ffestorag_offset (est);
5ff904cd 7686
c7e4ee3a 7687 ffecom_debug_kludge_ (et, "EQUIVALENCE", s, type, offset);
5ff904cd 7688
c7e4ee3a 7689 /* (t_type *) (((char *) &et) + offset) */
5ff904cd 7690
c7e4ee3a
CB
7691 t = convert (string_type_node, /* (char *) */
7692 ffecom_1 (ADDR_EXPR,
7693 build_pointer_type (TREE_TYPE (et)),
7694 et));
7695 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
7696 t,
7697 build_int_2 (offset, 0));
7698 t = convert (build_pointer_type (type),
7699 t);
d50108c7 7700 TREE_CONSTANT (t) = staticp (et);
5ff904cd 7701
c7e4ee3a 7702 addr = TRUE;
5ff904cd 7703
c7e4ee3a
CB
7704 resume_momentary (yes);
7705 }
7706 else
7707 {
7708 tree initexpr;
7709 bool init = ffesymbol_is_init (s);
5ff904cd 7710
c7e4ee3a 7711 yes = suspend_momentary ();
5ff904cd 7712
c7e4ee3a
CB
7713 t = build_decl (VAR_DECL,
7714 ffecom_get_identifier_ (ffesymbol_text (s)),
7715 type);
5ff904cd 7716
c7e4ee3a
CB
7717 if (init
7718 || ffesymbol_namelisted (s)
7719#ifdef FFECOM_sizeMAXSTACKITEM
7720 || ((st != NULL)
7721 && (ffestorag_size (st) > FFECOM_sizeMAXSTACKITEM))
7722#endif
7723 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
7724 && (ffecom_primary_entry_kind_
7725 != FFEINFO_kindBLOCKDATA)
7726 && (ffesymbol_is_save (s) || ffe_is_saveall ())))
7727 TREE_STATIC (t) = !ffesymbol_attr (s, FFESYMBOL_attrADJUSTABLE);
7728 else
7729 TREE_STATIC (t) = 0; /* No need to make static. */
5ff904cd 7730
c7e4ee3a
CB
7731 if (init || ffe_is_init_local_zero ())
7732 DECL_INITIAL (t) = error_mark_node;
5ff904cd 7733
c7e4ee3a
CB
7734 /* Keep -Wunused from complaining about var if it
7735 is used as sfunc arg or DATA implied-DO. */
7736 if (ffesymbol_attrs (s) & FFESYMBOL_attrsSFARG)
7737 DECL_IN_SYSTEM_HEADER (t) = 1;
5ff904cd 7738
c7e4ee3a 7739 t = start_decl (t, FALSE);
5ff904cd 7740
c7e4ee3a
CB
7741 if (init)
7742 {
7743 if (ffesymbol_init (s) != NULL)
7744 initexpr = ffecom_expr (ffesymbol_init (s));
7745 else
7746 initexpr = ffecom_init_zero_ (t);
7747 }
7748 else if (ffe_is_init_local_zero ())
7749 initexpr = ffecom_init_zero_ (t);
7750 else
7751 initexpr = NULL_TREE; /* Not ref'd if !init. */
5ff904cd 7752
c7e4ee3a 7753 finish_decl (t, initexpr, FALSE);
5ff904cd 7754
06ceef4e 7755 if (st != NULL && DECL_SIZE (t) != error_mark_node)
c7e4ee3a 7756 {
06ceef4e 7757 assert (TREE_CODE (DECL_SIZE_UNIT (t)) == INTEGER_CST);
05bccae2
RK
7758 assert (0 == compare_tree_int (DECL_SIZE_UNIT (t),
7759 ffestorag_size (st)));
c7e4ee3a 7760 }
5ff904cd 7761
c7e4ee3a
CB
7762 resume_momentary (yes);
7763 }
7764 }
5ff904cd 7765 break;
5ff904cd 7766
c7e4ee3a
CB
7767 case FFEINFO_whereRESULT:
7768 assert (!ffecom_transform_only_dummies_);
5ff904cd 7769
c7e4ee3a
CB
7770 if (bt == FFEINFO_basictypeCHARACTER)
7771 { /* Result is already in list of dummies, use
7772 it (& length). */
7773 t = ffecom_func_result_;
7774 tlen = ffecom_func_length_;
7775 addr = TRUE;
7776 break;
7777 }
7778 if ((ffecom_num_entrypoints_ == 0)
7779 && (bt == FFEINFO_basictypeCOMPLEX)
7780 && (ffesymbol_is_f2c (ffecom_primary_entry_)))
7781 { /* Result is already in list of dummies, use
7782 it. */
7783 t = ffecom_func_result_;
7784 addr = TRUE;
7785 break;
7786 }
7787 if (ffecom_func_result_ != NULL_TREE)
7788 {
7789 t = ffecom_func_result_;
7790 break;
7791 }
7792 if ((ffecom_num_entrypoints_ != 0)
7793 && (ffecom_master_bt_ == FFEINFO_basictypeNONE))
7794 {
7795 yes = suspend_momentary ();
5ff904cd 7796
c7e4ee3a
CB
7797 assert (ffecom_multi_retval_ != NULL_TREE);
7798 t = ffecom_1 (INDIRECT_REF, ffecom_multi_type_node_,
7799 ffecom_multi_retval_);
7800 t = ffecom_2 (COMPONENT_REF, ffecom_tree_type[bt][kt],
7801 t, ffecom_multi_fields_[bt][kt]);
5ff904cd 7802
c7e4ee3a
CB
7803 resume_momentary (yes);
7804 break;
7805 }
5ff904cd 7806
c7e4ee3a 7807 yes = suspend_momentary ();
5ff904cd 7808
c7e4ee3a
CB
7809 t = build_decl (VAR_DECL,
7810 ffecom_get_identifier_ (ffesymbol_text (s)),
7811 ffecom_tree_type[bt][kt]);
7812 TREE_STATIC (t) = 0; /* Put result on stack. */
7813 t = start_decl (t, FALSE);
7814 finish_decl (t, NULL_TREE, FALSE);
5ff904cd 7815
c7e4ee3a 7816 ffecom_func_result_ = t;
5ff904cd 7817
c7e4ee3a
CB
7818 resume_momentary (yes);
7819 break;
5ff904cd 7820
c7e4ee3a
CB
7821 case FFEINFO_whereDUMMY:
7822 {
7823 tree type;
7824 ffebld dl;
7825 ffebld dim;
7826 tree low;
7827 tree high;
7828 tree old_sizes;
7829 bool adjustable = FALSE; /* Conditionally adjustable? */
5ff904cd 7830
c7e4ee3a
CB
7831 type = ffecom_tree_type[bt][kt];
7832 if (ffesymbol_sfdummyparent (s) != NULL)
7833 {
7834 if (current_function_decl == ffecom_outer_function_decl_)
7835 { /* Exec transition before sfunc
7836 context; get it later. */
7837 break;
7838 }
7839 t = ffecom_get_identifier_ (ffesymbol_text
7840 (ffesymbol_sfdummyparent (s)));
7841 }
7842 else
7843 t = ffecom_get_identifier_ (ffesymbol_text (s));
5ff904cd 7844
c7e4ee3a 7845 assert (ffecom_transform_only_dummies_);
5ff904cd 7846
c7e4ee3a
CB
7847 old_sizes = get_pending_sizes ();
7848 put_pending_sizes (old_sizes);
5ff904cd 7849
c7e4ee3a
CB
7850 if (bt == FFEINFO_basictypeCHARACTER)
7851 tlen = ffecom_char_enhance_arg_ (&type, s);
7852 type = ffecom_check_size_overflow_ (s, type, TRUE);
5ff904cd 7853
c7e4ee3a
CB
7854 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
7855 {
7856 if (type == error_mark_node)
7857 break;
5ff904cd 7858
c7e4ee3a
CB
7859 dim = ffebld_head (dl);
7860 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
7861 if ((ffebld_left (dim) == NULL) || ffecom_doing_entry_)
7862 low = ffecom_integer_one_node;
7863 else
7864 low = ffecom_expr (ffebld_left (dim));
7865 assert (ffebld_right (dim) != NULL);
7866 if ((ffebld_op (ffebld_right (dim)) == FFEBLD_opSTAR)
7867 || ffecom_doing_entry_)
7868 {
7869 /* Used to just do high=low. But for ffecom_tree_
7870 canonize_ref_, it probably is important to correctly
7871 assess the size. E.g. given COMPLEX C(*),CFUNC and
7872 C(2)=CFUNC(C), overlap can happen, while it can't
7873 for, say, C(1)=CFUNC(C(2)). */
7874 /* Even more recently used to set to INT_MAX, but that
7875 broke when some overflow checking went into the back
7876 end. Now we just leave the upper bound unspecified. */
7877 high = NULL;
7878 }
7879 else
7880 high = ffecom_expr (ffebld_right (dim));
5ff904cd 7881
c7e4ee3a
CB
7882 /* Determine whether array is conditionally adjustable,
7883 to decide whether back-end magic is needed.
5ff904cd 7884
c7e4ee3a
CB
7885 Normally the front end uses the back-end function
7886 variable_size to wrap SAVE_EXPR's around expressions
7887 affecting the size/shape of an array so that the
7888 size/shape info doesn't change during execution
7889 of the compiled code even though variables and
7890 functions referenced in those expressions might.
5ff904cd 7891
c7e4ee3a
CB
7892 variable_size also makes sure those saved expressions
7893 get evaluated immediately upon entry to the
7894 compiled procedure -- the front end normally doesn't
7895 have to worry about that.
3cf0cea4 7896
c7e4ee3a
CB
7897 However, there is a problem with this that affects
7898 g77's implementation of entry points, and that is
7899 that it is _not_ true that each invocation of the
7900 compiled procedure is permitted to evaluate
7901 array size/shape info -- because it is possible
7902 that, for some invocations, that info is invalid (in
7903 which case it is "promised" -- i.e. a violation of
7904 the Fortran standard -- that the compiled code
7905 won't reference the array or its size/shape
7906 during that particular invocation).
5ff904cd 7907
c7e4ee3a 7908 To phrase this in C terms, consider this gcc function:
5ff904cd 7909
c7e4ee3a
CB
7910 void foo (int *n, float (*a)[*n])
7911 {
7912 // a is "pointer to array ...", fyi.
7913 }
5ff904cd 7914
c7e4ee3a
CB
7915 Suppose that, for some invocations, it is permitted
7916 for a caller of foo to do this:
5ff904cd 7917
c7e4ee3a 7918 foo (NULL, NULL);
5ff904cd 7919
c7e4ee3a
CB
7920 Now the _written_ code for foo can take such a call
7921 into account by either testing explicitly for whether
7922 (a == NULL) || (n == NULL) -- presumably it is
7923 not permitted to reference *a in various fashions
7924 if (n == NULL) I suppose -- or it can avoid it by
7925 looking at other info (other arguments, static/global
7926 data, etc.).
5ff904cd 7927
c7e4ee3a
CB
7928 However, this won't work in gcc 2.5.8 because it'll
7929 automatically emit the code to save the "*n"
7930 expression, which'll yield a NULL dereference for
7931 the "foo (NULL, NULL)" call, something the code
7932 for foo cannot prevent.
5ff904cd 7933
c7e4ee3a
CB
7934 g77 definitely needs to avoid executing such
7935 code anytime the pointer to the adjustable array
7936 is NULL, because even if its bounds expressions
7937 don't have any references to possible "absent"
7938 variables like "*n" -- say all variable references
7939 are to COMMON variables, i.e. global (though in C,
7940 local static could actually make sense) -- the
7941 expressions could yield other run-time problems
7942 for allowably "dead" values in those variables.
5ff904cd 7943
c7e4ee3a
CB
7944 For example, let's consider a more complicated
7945 version of foo:
5ff904cd 7946
c7e4ee3a
CB
7947 extern int i;
7948 extern int j;
5ff904cd 7949
c7e4ee3a
CB
7950 void foo (float (*a)[i/j])
7951 {
7952 ...
7953 }
5ff904cd 7954
c7e4ee3a
CB
7955 The above is (essentially) quite valid for Fortran
7956 but, again, for a call like "foo (NULL);", it is
7957 permitted for i and j to be undefined when the
7958 call is made. If j happened to be zero, for
7959 example, emitting the code to evaluate "i/j"
7960 could result in a run-time error.
5ff904cd 7961
c7e4ee3a
CB
7962 Offhand, though I don't have my F77 or F90
7963 standards handy, it might even be valid for a
7964 bounds expression to contain a function reference,
7965 in which case I doubt it is permitted for an
7966 implementation to invoke that function in the
7967 Fortran case involved here (invocation of an
7968 alternate ENTRY point that doesn't have the adjustable
7969 array as one of its arguments).
5ff904cd 7970
c7e4ee3a
CB
7971 So, the code that the compiler would normally emit
7972 to preevaluate the size/shape info for an
7973 adjustable array _must not_ be executed at run time
7974 in certain cases. Specifically, for Fortran,
7975 the case is when the pointer to the adjustable
7976 array == NULL. (For gnu-ish C, it might be nice
7977 for the source code itself to specify an expression
7978 that, if TRUE, inhibits execution of the code. Or
7979 reverse the sense for elegance.)
5ff904cd 7980
c7e4ee3a
CB
7981 (Note that g77 could use a different test than NULL,
7982 actually, since it happens to always pass an
7983 integer to the called function that specifies which
7984 entry point is being invoked. Hmm, this might
7985 solve the next problem.)
7986
7987 One way a user could, I suppose, write "foo" so
7988 it works is to insert COND_EXPR's for the
7989 size/shape info so the dangerous stuff isn't
7990 actually done, as in:
7991
7992 void foo (int *n, float (*a)[(a == NULL) ? 0 : *n])
7993 {
7994 ...
7995 }
5ff904cd 7996
c7e4ee3a
CB
7997 The next problem is that the front end needs to
7998 be able to tell the back end about the array's
7999 decl _before_ it tells it about the conditional
8000 expression to inhibit evaluation of size/shape info,
8001 as shown above.
5ff904cd 8002
c7e4ee3a
CB
8003 To solve this, the front end needs to be able
8004 to give the back end the expression to inhibit
8005 generation of the preevaluation code _after_
8006 it makes the decl for the adjustable array.
5ff904cd 8007
c7e4ee3a
CB
8008 Until then, the above example using the COND_EXPR
8009 doesn't pass muster with gcc because the "(a == NULL)"
8010 part has a reference to "a", which is still
8011 undefined at that point.
5ff904cd 8012
c7e4ee3a
CB
8013 g77 will therefore use a different mechanism in the
8014 meantime. */
5ff904cd 8015
c7e4ee3a
CB
8016 if (!adjustable
8017 && ((TREE_CODE (low) != INTEGER_CST)
8018 || (high && TREE_CODE (high) != INTEGER_CST)))
8019 adjustable = TRUE;
5ff904cd 8020
c7e4ee3a
CB
8021#if 0 /* Old approach -- see below. */
8022 if (TREE_CODE (low) != INTEGER_CST)
8023 low = ffecom_3 (COND_EXPR, integer_type_node,
8024 ffecom_adjarray_passed_ (s),
8025 low,
8026 ffecom_integer_zero_node);
5ff904cd 8027
c7e4ee3a
CB
8028 if (high && TREE_CODE (high) != INTEGER_CST)
8029 high = ffecom_3 (COND_EXPR, integer_type_node,
8030 ffecom_adjarray_passed_ (s),
8031 high,
8032 ffecom_integer_zero_node);
8033#endif
5ff904cd 8034
c7e4ee3a
CB
8035 /* ~~~gcc/stor-layout.c (layout_type) should do this,
8036 probably. Fixes 950302-1.f. */
5ff904cd 8037
c7e4ee3a
CB
8038 if (TREE_CODE (low) != INTEGER_CST)
8039 low = variable_size (low);
5ff904cd 8040
c7e4ee3a
CB
8041 /* ~~~Similarly, this fixes dumb0.f. The C front end
8042 does this, which is why dumb0.c would work. */
5ff904cd 8043
c7e4ee3a
CB
8044 if (high && TREE_CODE (high) != INTEGER_CST)
8045 high = variable_size (high);
5ff904cd 8046
c7e4ee3a
CB
8047 type
8048 = build_array_type
8049 (type,
8050 build_range_type (ffecom_integer_type_node,
8051 low, high));
8052 type = ffecom_check_size_overflow_ (s, type, TRUE);
8053 }
5ff904cd 8054
c7e4ee3a
CB
8055 if (type == error_mark_node)
8056 {
8057 t = error_mark_node;
8058 break;
8059 }
5ff904cd 8060
c7e4ee3a
CB
8061 if ((ffesymbol_sfdummyparent (s) == NULL)
8062 || (ffesymbol_basictype (s) == FFEINFO_basictypeCHARACTER))
8063 {
8064 type = build_pointer_type (type);
8065 addr = TRUE;
8066 }
5ff904cd 8067
c7e4ee3a 8068 t = build_decl (PARM_DECL, t, type);
5ff904cd 8069#if BUILT_FOR_270
c7e4ee3a 8070 DECL_ARTIFICIAL (t) = 1;
5ff904cd 8071#endif
5ff904cd 8072
c7e4ee3a
CB
8073 /* If this arg is present in every entry point's list of
8074 dummy args, then we're done. */
5ff904cd 8075
c7e4ee3a
CB
8076 if (ffesymbol_numentries (s)
8077 == (ffecom_num_entrypoints_ + 1))
5ff904cd 8078 break;
5ff904cd 8079
c7e4ee3a 8080#if 1
5ff904cd 8081
c7e4ee3a
CB
8082 /* If variable_size in stor-layout has been called during
8083 the above, then get_pending_sizes should have the
8084 yet-to-be-evaluated saved expressions pending.
8085 Make the whole lot of them get emitted, conditionally
8086 on whether the array decl ("t" above) is not NULL. */
5ff904cd 8087
c7e4ee3a
CB
8088 {
8089 tree sizes = get_pending_sizes ();
8090 tree tem;
5ff904cd 8091
c7e4ee3a
CB
8092 for (tem = sizes;
8093 tem != old_sizes;
8094 tem = TREE_CHAIN (tem))
8095 {
8096 tree temv = TREE_VALUE (tem);
5ff904cd 8097
c7e4ee3a
CB
8098 if (sizes == tem)
8099 sizes = temv;
8100 else
8101 sizes
8102 = ffecom_2 (COMPOUND_EXPR,
8103 TREE_TYPE (sizes),
8104 temv,
8105 sizes);
8106 }
5ff904cd 8107
c7e4ee3a
CB
8108 if (sizes != tem)
8109 {
8110 sizes
8111 = ffecom_3 (COND_EXPR,
8112 TREE_TYPE (sizes),
8113 ffecom_2 (NE_EXPR,
8114 integer_type_node,
8115 t,
8116 null_pointer_node),
8117 sizes,
8118 convert (TREE_TYPE (sizes),
8119 integer_zero_node));
8120 sizes = ffecom_save_tree (sizes);
5ff904cd 8121
c7e4ee3a
CB
8122 sizes
8123 = tree_cons (NULL_TREE, sizes, tem);
8124 }
5ff904cd 8125
c7e4ee3a
CB
8126 if (sizes)
8127 put_pending_sizes (sizes);
8128 }
5ff904cd 8129
c7e4ee3a
CB
8130#else
8131#if 0
8132 if (adjustable
8133 && (ffesymbol_numentries (s)
8134 != ffecom_num_entrypoints_ + 1))
8135 DECL_SOMETHING (t)
8136 = ffecom_2 (NE_EXPR, integer_type_node,
8137 t,
8138 null_pointer_node);
8139#else
8140#if 0
8141 if (adjustable
8142 && (ffesymbol_numentries (s)
8143 != ffecom_num_entrypoints_ + 1))
8144 {
8145 ffebad_start (FFEBAD_MISSING_ADJARRAY_UNSUPPORTED);
8146 ffebad_here (0, ffesymbol_where_line (s),
8147 ffesymbol_where_column (s));
8148 ffebad_string (ffesymbol_text (s));
8149 ffebad_finish ();
8150 }
8151#endif
8152#endif
8153#endif
8154 }
5ff904cd
JL
8155 break;
8156
c7e4ee3a 8157 case FFEINFO_whereCOMMON:
5ff904cd 8158 {
c7e4ee3a
CB
8159 ffesymbol cs;
8160 ffeglobal cg;
8161 tree ct;
5ff904cd
JL
8162 ffestorag st = ffesymbol_storage (s);
8163 tree type;
c7e4ee3a 8164 int yes;
5ff904cd 8165
c7e4ee3a
CB
8166 cs = ffesymbol_common (s); /* The COMMON area itself. */
8167 if (st != NULL) /* Else not laid out. */
5ff904cd 8168 {
c7e4ee3a
CB
8169 ffecom_transform_common_ (cs);
8170 st = ffesymbol_storage (s);
5ff904cd
JL
8171 }
8172
c7e4ee3a 8173 yes = suspend_momentary ();
5ff904cd 8174
c7e4ee3a 8175 type = ffecom_type_localvar_ (s, bt, kt);
5ff904cd 8176
c7e4ee3a
CB
8177 cg = ffesymbol_global (cs); /* The global COMMON info. */
8178 if ((cg == NULL)
8179 || (ffeglobal_type (cg) != FFEGLOBAL_typeCOMMON))
8180 ct = NULL_TREE;
8181 else
8182 ct = ffeglobal_hook (cg); /* The common area's tree. */
5ff904cd 8183
c7e4ee3a
CB
8184 if ((ct == NULL_TREE)
8185 || (st == NULL)
8186 || (type == error_mark_node))
8187 t = error_mark_node;
8188 else
8189 {
8190 ffetargetOffset offset;
8191 ffestorag cst;
5ff904cd 8192
c7e4ee3a
CB
8193 cst = ffestorag_parent (st);
8194 assert (cst == ffesymbol_storage (cs));
5ff904cd 8195
c7e4ee3a
CB
8196 offset = ffestorag_modulo (cst)
8197 + ffestorag_offset (st)
8198 - ffestorag_offset (cst);
5ff904cd 8199
c7e4ee3a 8200 ffecom_debug_kludge_ (ct, "COMMON", s, type, offset);
5ff904cd 8201
c7e4ee3a 8202 /* (t_type *) (((char *) &ct) + offset) */
5ff904cd
JL
8203
8204 t = convert (string_type_node, /* (char *) */
8205 ffecom_1 (ADDR_EXPR,
c7e4ee3a
CB
8206 build_pointer_type (TREE_TYPE (ct)),
8207 ct));
5ff904cd
JL
8208 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
8209 t,
8210 build_int_2 (offset, 0));
8211 t = convert (build_pointer_type (type),
8212 t);
d50108c7 8213 TREE_CONSTANT (t) = 1;
5ff904cd
JL
8214
8215 addr = TRUE;
5ff904cd 8216 }
5ff904cd 8217
c7e4ee3a
CB
8218 resume_momentary (yes);
8219 }
8220 break;
5ff904cd 8221
c7e4ee3a
CB
8222 case FFEINFO_whereIMMEDIATE:
8223 case FFEINFO_whereGLOBAL:
8224 case FFEINFO_whereFLEETING:
8225 case FFEINFO_whereFLEETING_CADDR:
8226 case FFEINFO_whereFLEETING_IADDR:
8227 case FFEINFO_whereINTRINSIC:
8228 case FFEINFO_whereCONSTANT_SUBOBJECT:
8229 default:
8230 assert ("ENTITY where unheard of" == NULL);
8231 /* Fall through. */
8232 case FFEINFO_whereANY:
8233 t = error_mark_node;
8234 break;
8235 }
8236 break;
5ff904cd 8237
c7e4ee3a
CB
8238 case FFEINFO_kindFUNCTION:
8239 switch (ffeinfo_where (ffesymbol_info (s)))
8240 {
8241 case FFEINFO_whereLOCAL: /* Me. */
8242 assert (!ffecom_transform_only_dummies_);
8243 t = current_function_decl;
5ff904cd
JL
8244 break;
8245
c7e4ee3a 8246 case FFEINFO_whereGLOBAL:
5ff904cd
JL
8247 assert (!ffecom_transform_only_dummies_);
8248
c7e4ee3a
CB
8249 if (((g = ffesymbol_global (s)) != NULL)
8250 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8251 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8252 && (ffeglobal_hook (g) != NULL_TREE)
8253 && ffe_is_globals ())
5ff904cd 8254 {
c7e4ee3a 8255 t = ffeglobal_hook (g);
5ff904cd
JL
8256 break;
8257 }
5ff904cd 8258
c7e4ee3a
CB
8259 if (ffesymbol_is_f2c (s)
8260 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
8261 t = ffecom_tree_fun_type[bt][kt];
8262 else
8263 t = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
5ff904cd 8264
c7e4ee3a
CB
8265 t = build_decl (FUNCTION_DECL,
8266 ffecom_get_external_identifier_ (s),
8267 t);
8268 DECL_EXTERNAL (t) = 1;
8269 TREE_PUBLIC (t) = 1;
5ff904cd 8270
5ff904cd
JL
8271 t = start_decl (t, FALSE);
8272 finish_decl (t, NULL_TREE, FALSE);
8273
c7e4ee3a
CB
8274 if ((g != NULL)
8275 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8276 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8277 ffeglobal_set_hook (g, t);
8278
7189a4b0 8279 ffecom_save_tree_forever (t);
5ff904cd 8280
5ff904cd
JL
8281 break;
8282
8283 case FFEINFO_whereDUMMY:
c7e4ee3a 8284 assert (ffecom_transform_only_dummies_);
5ff904cd 8285
c7e4ee3a
CB
8286 if (ffesymbol_is_f2c (s)
8287 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
8288 t = ffecom_tree_ptr_to_fun_type[bt][kt];
8289 else
8290 t = build_pointer_type
8291 (build_function_type (ffecom_tree_type[bt][kt], NULL_TREE));
8292
8293 t = build_decl (PARM_DECL,
8294 ffecom_get_identifier_ (ffesymbol_text (s)),
8295 t);
8296#if BUILT_FOR_270
8297 DECL_ARTIFICIAL (t) = 1;
8298#endif
8299 addr = TRUE;
8300 break;
8301
8302 case FFEINFO_whereCONSTANT: /* Statement function. */
8303 assert (!ffecom_transform_only_dummies_);
8304 t = ffecom_gen_sfuncdef_ (s, bt, kt);
8305 break;
8306
8307 case FFEINFO_whereINTRINSIC:
8308 assert (!ffecom_transform_only_dummies_);
8309 break; /* Let actual references generate their
8310 decls. */
8311
8312 default:
8313 assert ("FUNCTION where unheard of" == NULL);
8314 /* Fall through. */
8315 case FFEINFO_whereANY:
8316 t = error_mark_node;
8317 break;
8318 }
8319 break;
8320
8321 case FFEINFO_kindSUBROUTINE:
8322 switch (ffeinfo_where (ffesymbol_info (s)))
8323 {
8324 case FFEINFO_whereLOCAL: /* Me. */
8325 assert (!ffecom_transform_only_dummies_);
8326 t = current_function_decl;
8327 break;
5ff904cd 8328
c7e4ee3a
CB
8329 case FFEINFO_whereGLOBAL:
8330 assert (!ffecom_transform_only_dummies_);
5ff904cd 8331
c7e4ee3a
CB
8332 if (((g = ffesymbol_global (s)) != NULL)
8333 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8334 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8335 && (ffeglobal_hook (g) != NULL_TREE)
8336 && ffe_is_globals ())
8337 {
8338 t = ffeglobal_hook (g);
8339 break;
8340 }
5ff904cd 8341
c7e4ee3a
CB
8342 t = build_decl (FUNCTION_DECL,
8343 ffecom_get_external_identifier_ (s),
8344 ffecom_tree_subr_type);
8345 DECL_EXTERNAL (t) = 1;
8346 TREE_PUBLIC (t) = 1;
5ff904cd 8347
c7e4ee3a
CB
8348 t = start_decl (t, FALSE);
8349 finish_decl (t, NULL_TREE, FALSE);
5ff904cd 8350
c7e4ee3a
CB
8351 if ((g != NULL)
8352 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8353 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8354 ffeglobal_set_hook (g, t);
5ff904cd 8355
7189a4b0 8356 ffecom_save_tree_forever (t);
5ff904cd 8357
c7e4ee3a 8358 break;
5ff904cd 8359
c7e4ee3a
CB
8360 case FFEINFO_whereDUMMY:
8361 assert (ffecom_transform_only_dummies_);
5ff904cd 8362
c7e4ee3a
CB
8363 t = build_decl (PARM_DECL,
8364 ffecom_get_identifier_ (ffesymbol_text (s)),
8365 ffecom_tree_ptr_to_subr_type);
8366#if BUILT_FOR_270
8367 DECL_ARTIFICIAL (t) = 1;
8368#endif
8369 addr = TRUE;
8370 break;
5ff904cd 8371
c7e4ee3a
CB
8372 case FFEINFO_whereINTRINSIC:
8373 assert (!ffecom_transform_only_dummies_);
8374 break; /* Let actual references generate their
8375 decls. */
5ff904cd 8376
c7e4ee3a
CB
8377 default:
8378 assert ("SUBROUTINE where unheard of" == NULL);
8379 /* Fall through. */
8380 case FFEINFO_whereANY:
8381 t = error_mark_node;
8382 break;
8383 }
8384 break;
5ff904cd 8385
c7e4ee3a
CB
8386 case FFEINFO_kindPROGRAM:
8387 switch (ffeinfo_where (ffesymbol_info (s)))
8388 {
8389 case FFEINFO_whereLOCAL: /* Me. */
8390 assert (!ffecom_transform_only_dummies_);
8391 t = current_function_decl;
8392 break;
5ff904cd 8393
c7e4ee3a
CB
8394 case FFEINFO_whereCOMMON:
8395 case FFEINFO_whereDUMMY:
8396 case FFEINFO_whereGLOBAL:
8397 case FFEINFO_whereRESULT:
8398 case FFEINFO_whereFLEETING:
8399 case FFEINFO_whereFLEETING_CADDR:
8400 case FFEINFO_whereFLEETING_IADDR:
8401 case FFEINFO_whereIMMEDIATE:
8402 case FFEINFO_whereINTRINSIC:
8403 case FFEINFO_whereCONSTANT:
8404 case FFEINFO_whereCONSTANT_SUBOBJECT:
8405 default:
8406 assert ("PROGRAM where unheard of" == NULL);
8407 /* Fall through. */
8408 case FFEINFO_whereANY:
8409 t = error_mark_node;
8410 break;
8411 }
8412 break;
5ff904cd 8413
c7e4ee3a
CB
8414 case FFEINFO_kindBLOCKDATA:
8415 switch (ffeinfo_where (ffesymbol_info (s)))
8416 {
8417 case FFEINFO_whereLOCAL: /* Me. */
8418 assert (!ffecom_transform_only_dummies_);
8419 t = current_function_decl;
8420 break;
5ff904cd 8421
c7e4ee3a
CB
8422 case FFEINFO_whereGLOBAL:
8423 assert (!ffecom_transform_only_dummies_);
5ff904cd 8424
c7e4ee3a
CB
8425 t = build_decl (FUNCTION_DECL,
8426 ffecom_get_external_identifier_ (s),
8427 ffecom_tree_blockdata_type);
8428 DECL_EXTERNAL (t) = 1;
8429 TREE_PUBLIC (t) = 1;
5ff904cd 8430
c7e4ee3a
CB
8431 t = start_decl (t, FALSE);
8432 finish_decl (t, NULL_TREE, FALSE);
5ff904cd 8433
7189a4b0 8434 ffecom_save_tree_forever (t);
5ff904cd 8435
c7e4ee3a 8436 break;
5ff904cd 8437
c7e4ee3a
CB
8438 case FFEINFO_whereCOMMON:
8439 case FFEINFO_whereDUMMY:
8440 case FFEINFO_whereRESULT:
8441 case FFEINFO_whereFLEETING:
8442 case FFEINFO_whereFLEETING_CADDR:
8443 case FFEINFO_whereFLEETING_IADDR:
8444 case FFEINFO_whereIMMEDIATE:
8445 case FFEINFO_whereINTRINSIC:
8446 case FFEINFO_whereCONSTANT:
8447 case FFEINFO_whereCONSTANT_SUBOBJECT:
8448 default:
8449 assert ("BLOCKDATA where unheard of" == NULL);
8450 /* Fall through. */
8451 case FFEINFO_whereANY:
8452 t = error_mark_node;
8453 break;
8454 }
8455 break;
5ff904cd 8456
c7e4ee3a
CB
8457 case FFEINFO_kindCOMMON:
8458 switch (ffeinfo_where (ffesymbol_info (s)))
8459 {
8460 case FFEINFO_whereLOCAL:
8461 assert (!ffecom_transform_only_dummies_);
8462 ffecom_transform_common_ (s);
8463 break;
8464
8465 case FFEINFO_whereNONE:
8466 case FFEINFO_whereCOMMON:
8467 case FFEINFO_whereDUMMY:
8468 case FFEINFO_whereGLOBAL:
8469 case FFEINFO_whereRESULT:
8470 case FFEINFO_whereFLEETING:
8471 case FFEINFO_whereFLEETING_CADDR:
8472 case FFEINFO_whereFLEETING_IADDR:
8473 case FFEINFO_whereIMMEDIATE:
8474 case FFEINFO_whereINTRINSIC:
8475 case FFEINFO_whereCONSTANT:
8476 case FFEINFO_whereCONSTANT_SUBOBJECT:
8477 default:
8478 assert ("COMMON where unheard of" == NULL);
8479 /* Fall through. */
8480 case FFEINFO_whereANY:
8481 t = error_mark_node;
8482 break;
8483 }
8484 break;
5ff904cd 8485
c7e4ee3a
CB
8486 case FFEINFO_kindCONSTRUCT:
8487 switch (ffeinfo_where (ffesymbol_info (s)))
8488 {
8489 case FFEINFO_whereLOCAL:
8490 assert (!ffecom_transform_only_dummies_);
8491 break;
5ff904cd 8492
c7e4ee3a
CB
8493 case FFEINFO_whereNONE:
8494 case FFEINFO_whereCOMMON:
8495 case FFEINFO_whereDUMMY:
8496 case FFEINFO_whereGLOBAL:
8497 case FFEINFO_whereRESULT:
8498 case FFEINFO_whereFLEETING:
8499 case FFEINFO_whereFLEETING_CADDR:
8500 case FFEINFO_whereFLEETING_IADDR:
8501 case FFEINFO_whereIMMEDIATE:
8502 case FFEINFO_whereINTRINSIC:
8503 case FFEINFO_whereCONSTANT:
8504 case FFEINFO_whereCONSTANT_SUBOBJECT:
8505 default:
8506 assert ("CONSTRUCT where unheard of" == NULL);
8507 /* Fall through. */
8508 case FFEINFO_whereANY:
8509 t = error_mark_node;
8510 break;
8511 }
8512 break;
5ff904cd 8513
c7e4ee3a
CB
8514 case FFEINFO_kindNAMELIST:
8515 switch (ffeinfo_where (ffesymbol_info (s)))
8516 {
8517 case FFEINFO_whereLOCAL:
8518 assert (!ffecom_transform_only_dummies_);
8519 t = ffecom_transform_namelist_ (s);
8520 break;
5ff904cd 8521
c7e4ee3a
CB
8522 case FFEINFO_whereNONE:
8523 case FFEINFO_whereCOMMON:
8524 case FFEINFO_whereDUMMY:
8525 case FFEINFO_whereGLOBAL:
8526 case FFEINFO_whereRESULT:
8527 case FFEINFO_whereFLEETING:
8528 case FFEINFO_whereFLEETING_CADDR:
8529 case FFEINFO_whereFLEETING_IADDR:
8530 case FFEINFO_whereIMMEDIATE:
8531 case FFEINFO_whereINTRINSIC:
8532 case FFEINFO_whereCONSTANT:
8533 case FFEINFO_whereCONSTANT_SUBOBJECT:
8534 default:
8535 assert ("NAMELIST where unheard of" == NULL);
8536 /* Fall through. */
8537 case FFEINFO_whereANY:
8538 t = error_mark_node;
8539 break;
8540 }
8541 break;
5ff904cd 8542
c7e4ee3a
CB
8543 default:
8544 assert ("kind unheard of" == NULL);
8545 /* Fall through. */
8546 case FFEINFO_kindANY:
8547 t = error_mark_node;
8548 break;
8549 }
5ff904cd 8550
c7e4ee3a
CB
8551 ffesymbol_hook (s).decl_tree = t;
8552 ffesymbol_hook (s).length_tree = tlen;
8553 ffesymbol_hook (s).addr = addr;
5ff904cd 8554
c7e4ee3a
CB
8555 lineno = old_lineno;
8556 input_filename = old_input_filename;
5ff904cd 8557
c7e4ee3a
CB
8558 return s;
8559}
5ff904cd 8560
5ff904cd 8561#endif
c7e4ee3a 8562/* Transform into ASSIGNable symbol.
5ff904cd 8563
c7e4ee3a
CB
8564 Symbol has already been transformed, but for whatever reason, the
8565 resulting decl_tree has been deemed not usable for an ASSIGN target.
8566 (E.g. it isn't wide enough to hold a pointer.) So, here we invent
8567 another local symbol of type void * and stuff that in the assign_tree
8568 argument. The F77/F90 standards allow this implementation. */
5ff904cd 8569
c7e4ee3a
CB
8570#if FFECOM_targetCURRENT == FFECOM_targetGCC
8571static ffesymbol
8572ffecom_sym_transform_assign_ (ffesymbol s)
8573{
8574 tree t; /* Transformed thingy. */
8575 int yes;
8576 int old_lineno = lineno;
3b304f5b 8577 const char *old_input_filename = input_filename;
5ff904cd 8578
c7e4ee3a
CB
8579 if (ffesymbol_sfdummyparent (s) == NULL)
8580 {
8581 input_filename = ffesymbol_where_filename (s);
8582 lineno = ffesymbol_where_filelinenum (s);
8583 }
8584 else
8585 {
8586 ffesymbol sf = ffesymbol_sfdummyparent (s);
5ff904cd 8587
c7e4ee3a
CB
8588 input_filename = ffesymbol_where_filename (sf);
8589 lineno = ffesymbol_where_filelinenum (sf);
8590 }
5ff904cd 8591
c7e4ee3a 8592 assert (!ffecom_transform_only_dummies_);
5ff904cd 8593
c7e4ee3a 8594 yes = suspend_momentary ();
5ff904cd 8595
c7e4ee3a
CB
8596 t = build_decl (VAR_DECL,
8597 ffecom_get_invented_identifier ("__g77_ASSIGN_%s",
14657de8 8598 ffesymbol_text (s)),
c7e4ee3a 8599 TREE_TYPE (null_pointer_node));
5ff904cd 8600
c7e4ee3a
CB
8601 switch (ffesymbol_where (s))
8602 {
8603 case FFEINFO_whereLOCAL:
8604 /* Unlike for regular vars, SAVE status is easy to determine for
8605 ASSIGNed vars, since there's no initialization, there's no
8606 effective storage association (so "SAVE J" does not apply to
8607 K even given "EQUIVALENCE (J,K)"), there's no size issue
8608 to worry about, etc. */
8609 if ((ffesymbol_is_save (s) || ffe_is_saveall ())
8610 && (ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
8611 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA))
8612 TREE_STATIC (t) = 1; /* SAVEd in proc, make static. */
8613 else
8614 TREE_STATIC (t) = 0; /* No need to make static. */
8615 break;
5ff904cd 8616
c7e4ee3a
CB
8617 case FFEINFO_whereCOMMON:
8618 TREE_STATIC (t) = 1; /* Assume COMMONs always SAVEd. */
8619 break;
5ff904cd 8620
c7e4ee3a
CB
8621 case FFEINFO_whereDUMMY:
8622 /* Note that twinning a DUMMY means the caller won't see
8623 the ASSIGNed value. But both F77 and F90 allow implementations
8624 to do this, i.e. disallow Fortran code that would try and
8625 take advantage of actually putting a label into a variable
8626 via a dummy argument (or any other storage association, for
8627 that matter). */
8628 TREE_STATIC (t) = 0;
8629 break;
5ff904cd 8630
c7e4ee3a
CB
8631 default:
8632 TREE_STATIC (t) = 0;
8633 break;
8634 }
5ff904cd 8635
c7e4ee3a
CB
8636 t = start_decl (t, FALSE);
8637 finish_decl (t, NULL_TREE, FALSE);
5ff904cd 8638
c7e4ee3a 8639 resume_momentary (yes);
5ff904cd 8640
c7e4ee3a 8641 ffesymbol_hook (s).assign_tree = t;
5ff904cd 8642
c7e4ee3a
CB
8643 lineno = old_lineno;
8644 input_filename = old_input_filename;
5ff904cd 8645
c7e4ee3a
CB
8646 return s;
8647}
5ff904cd 8648
c7e4ee3a
CB
8649#endif
8650/* Implement COMMON area in back end.
5ff904cd 8651
c7e4ee3a
CB
8652 Because COMMON-based variables can be referenced in the dimension
8653 expressions of dummy (adjustable) arrays, and because dummies
8654 (in the gcc back end) need to be put in the outer binding level
8655 of a function (which has two binding levels, the outer holding
8656 the dummies and the inner holding the other vars), special care
8657 must be taken to handle COMMON areas.
5ff904cd 8658
c7e4ee3a
CB
8659 The current strategy is basically to always tell the back end about
8660 the COMMON area as a top-level external reference to just a block
8661 of storage of the master type of that area (e.g. integer, real,
8662 character, whatever -- not a structure). As a distinct action,
8663 if initial values are provided, tell the back end about the area
8664 as a top-level non-external (initialized) area and remember not to
8665 allow further initialization or expansion of the area. Meanwhile,
8666 if no initialization happens at all, tell the back end about
8667 the largest size we've seen declared so the space does get reserved.
8668 (This function doesn't handle all that stuff, but it does some
8669 of the important things.)
5ff904cd 8670
c7e4ee3a
CB
8671 Meanwhile, for COMMON variables themselves, just keep creating
8672 references like *((float *) (&common_area + offset)) each time
8673 we reference the variable. In other words, don't make a VAR_DECL
8674 or any kind of component reference (like we used to do before 0.4),
8675 though we might do that as well just for debugging purposes (and
8676 stuff the rtl with the appropriate offset expression). */
5ff904cd 8677
c7e4ee3a
CB
8678#if FFECOM_targetCURRENT == FFECOM_targetGCC
8679static void
8680ffecom_transform_common_ (ffesymbol s)
8681{
8682 ffestorag st = ffesymbol_storage (s);
8683 ffeglobal g = ffesymbol_global (s);
8684 tree cbt;
8685 tree cbtype;
8686 tree init;
8687 tree high;
8688 bool is_init = ffestorag_is_init (st);
5ff904cd 8689
c7e4ee3a 8690 assert (st != NULL);
5ff904cd 8691
c7e4ee3a
CB
8692 if ((g == NULL)
8693 || (ffeglobal_type (g) != FFEGLOBAL_typeCOMMON))
8694 return;
5ff904cd 8695
c7e4ee3a 8696 /* First update the size of the area in global terms. */
5ff904cd 8697
c7e4ee3a 8698 ffeglobal_size_common (s, ffestorag_size (st));
5ff904cd 8699
c7e4ee3a
CB
8700 if (!ffeglobal_common_init (g))
8701 is_init = FALSE; /* No explicit init, don't let erroneous joins init. */
5ff904cd 8702
c7e4ee3a 8703 cbt = ffeglobal_hook (g);
5ff904cd 8704
c7e4ee3a
CB
8705 /* If we already have declared this common block for a previous program
8706 unit, and either we already initialized it or we don't have new
8707 initialization for it, just return what we have without changing it. */
5ff904cd 8708
c7e4ee3a
CB
8709 if ((cbt != NULL_TREE)
8710 && (!is_init
8711 || !DECL_EXTERNAL (cbt)))
b7a80862
AV
8712 {
8713 if (st->hook == NULL) ffestorag_set_hook (st, cbt);
8714 return;
8715 }
5ff904cd 8716
c7e4ee3a 8717 /* Process inits. */
5ff904cd 8718
c7e4ee3a
CB
8719 if (is_init)
8720 {
8721 if (ffestorag_init (st) != NULL)
5ff904cd 8722 {
c7e4ee3a 8723 ffebld sexp;
5ff904cd 8724
c7e4ee3a
CB
8725 /* Set the padding for the expression, so ffecom_expr
8726 knows to insert that many zeros. */
8727 switch (ffebld_op (sexp = ffestorag_init (st)))
5ff904cd 8728 {
c7e4ee3a
CB
8729 case FFEBLD_opCONTER:
8730 ffebld_conter_set_pad (sexp, ffestorag_modulo (st));
5ff904cd 8731 break;
5ff904cd 8732
c7e4ee3a
CB
8733 case FFEBLD_opARRTER:
8734 ffebld_arrter_set_pad (sexp, ffestorag_modulo (st));
8735 break;
5ff904cd 8736
c7e4ee3a
CB
8737 case FFEBLD_opACCTER:
8738 ffebld_accter_set_pad (sexp, ffestorag_modulo (st));
8739 break;
5ff904cd 8740
c7e4ee3a
CB
8741 default:
8742 assert ("bad op for cmn init (pad)" == NULL);
8743 break;
8744 }
5ff904cd 8745
c7e4ee3a
CB
8746 init = ffecom_expr (sexp);
8747 if (init == error_mark_node)
8748 { /* Hopefully the back end complained! */
8749 init = NULL_TREE;
8750 if (cbt != NULL_TREE)
8751 return;
8752 }
8753 }
8754 else
8755 init = error_mark_node;
8756 }
8757 else
8758 init = NULL_TREE;
5ff904cd 8759
c7e4ee3a 8760 /* cbtype must be permanently allocated! */
5ff904cd 8761
c7e4ee3a
CB
8762 /* Allocate the MAX of the areas so far, seen filewide. */
8763 high = build_int_2 ((ffeglobal_common_size (g)
8764 + ffeglobal_common_pad (g)) - 1, 0);
8765 TREE_TYPE (high) = ffecom_integer_type_node;
5ff904cd 8766
c7e4ee3a
CB
8767 if (init)
8768 cbtype = build_array_type (char_type_node,
8769 build_range_type (integer_type_node,
8770 integer_zero_node,
8771 high));
8772 else
8773 cbtype = build_array_type (char_type_node, NULL_TREE);
5ff904cd 8774
c7e4ee3a
CB
8775 if (cbt == NULL_TREE)
8776 {
8777 cbt
8778 = build_decl (VAR_DECL,
8779 ffecom_get_external_identifier_ (s),
8780 cbtype);
8781 TREE_STATIC (cbt) = 1;
8782 TREE_PUBLIC (cbt) = 1;
8783 }
8784 else
8785 {
8786 assert (is_init);
8787 TREE_TYPE (cbt) = cbtype;
8788 }
8789 DECL_EXTERNAL (cbt) = init ? 0 : 1;
8790 DECL_INITIAL (cbt) = init ? error_mark_node : NULL_TREE;
5ff904cd 8791
c7e4ee3a
CB
8792 cbt = start_decl (cbt, TRUE);
8793 if (ffeglobal_hook (g) != NULL)
8794 assert (cbt == ffeglobal_hook (g));
5ff904cd 8795
c7e4ee3a 8796 assert (!init || !DECL_EXTERNAL (cbt));
5ff904cd 8797
c7e4ee3a
CB
8798 /* Make sure that any type can live in COMMON and be referenced
8799 without getting a bus error. We could pick the most restrictive
8800 alignment of all entities actually placed in the COMMON, but
8801 this seems easy enough. */
5ff904cd 8802
c7e4ee3a 8803 DECL_ALIGN (cbt) = BIGGEST_ALIGNMENT;
11cf4d18 8804 DECL_USER_ALIGN (cbt) = 0;
5ff904cd 8805
c7e4ee3a
CB
8806 if (is_init && (ffestorag_init (st) == NULL))
8807 init = ffecom_init_zero_ (cbt);
5ff904cd 8808
c7e4ee3a 8809 finish_decl (cbt, init, TRUE);
5ff904cd 8810
c7e4ee3a
CB
8811 if (is_init)
8812 ffestorag_set_init (st, ffebld_new_any ());
5ff904cd 8813
c7e4ee3a
CB
8814 if (init)
8815 {
06ceef4e
RK
8816 assert (DECL_SIZE_UNIT (cbt) != NULL_TREE);
8817 assert (TREE_CODE (DECL_SIZE_UNIT (cbt)) == INTEGER_CST);
05bccae2
RK
8818 assert (0 == compare_tree_int (DECL_SIZE_UNIT (cbt),
8819 (ffeglobal_common_size (g)
8820 + ffeglobal_common_pad (g))));
c7e4ee3a 8821 }
5ff904cd 8822
c7e4ee3a 8823 ffeglobal_set_hook (g, cbt);
5ff904cd 8824
c7e4ee3a 8825 ffestorag_set_hook (st, cbt);
5ff904cd 8826
7189a4b0 8827 ffecom_save_tree_forever (cbt);
c7e4ee3a 8828}
5ff904cd 8829
c7e4ee3a
CB
8830#endif
8831/* Make master area for local EQUIVALENCE. */
5ff904cd 8832
c7e4ee3a
CB
8833#if FFECOM_targetCURRENT == FFECOM_targetGCC
8834static void
8835ffecom_transform_equiv_ (ffestorag eqst)
8836{
8837 tree eqt;
8838 tree eqtype;
8839 tree init;
8840 tree high;
8841 bool is_init = ffestorag_is_init (eqst);
8842 int yes;
5ff904cd 8843
c7e4ee3a 8844 assert (eqst != NULL);
5ff904cd 8845
c7e4ee3a 8846 eqt = ffestorag_hook (eqst);
5ff904cd 8847
c7e4ee3a
CB
8848 if (eqt != NULL_TREE)
8849 return;
5ff904cd 8850
c7e4ee3a
CB
8851 /* Process inits. */
8852
8853 if (is_init)
8854 {
8855 if (ffestorag_init (eqst) != NULL)
5ff904cd 8856 {
c7e4ee3a 8857 ffebld sexp;
5ff904cd 8858
c7e4ee3a
CB
8859 /* Set the padding for the expression, so ffecom_expr
8860 knows to insert that many zeros. */
8861 switch (ffebld_op (sexp = ffestorag_init (eqst)))
8862 {
8863 case FFEBLD_opCONTER:
8864 ffebld_conter_set_pad (sexp, ffestorag_modulo (eqst));
8865 break;
5ff904cd 8866
c7e4ee3a
CB
8867 case FFEBLD_opARRTER:
8868 ffebld_arrter_set_pad (sexp, ffestorag_modulo (eqst));
8869 break;
5ff904cd 8870
c7e4ee3a
CB
8871 case FFEBLD_opACCTER:
8872 ffebld_accter_set_pad (sexp, ffestorag_modulo (eqst));
8873 break;
5ff904cd 8874
c7e4ee3a
CB
8875 default:
8876 assert ("bad op for eqv init (pad)" == NULL);
8877 break;
8878 }
5ff904cd 8879
c7e4ee3a
CB
8880 init = ffecom_expr (sexp);
8881 if (init == error_mark_node)
8882 init = NULL_TREE; /* Hopefully the back end complained! */
8883 }
8884 else
8885 init = error_mark_node;
8886 }
8887 else if (ffe_is_init_local_zero ())
8888 init = error_mark_node;
8889 else
8890 init = NULL_TREE;
5ff904cd 8891
c7e4ee3a
CB
8892 ffecom_member_namelisted_ = FALSE;
8893 ffestorag_drive (ffestorag_list_equivs (eqst),
8894 &ffecom_member_phase1_,
8895 eqst);
5ff904cd 8896
c7e4ee3a 8897 yes = suspend_momentary ();
5ff904cd 8898
c7e4ee3a
CB
8899 high = build_int_2 ((ffestorag_size (eqst)
8900 + ffestorag_modulo (eqst)) - 1, 0);
8901 TREE_TYPE (high) = ffecom_integer_type_node;
5ff904cd 8902
c7e4ee3a
CB
8903 eqtype = build_array_type (char_type_node,
8904 build_range_type (ffecom_integer_type_node,
8905 ffecom_integer_zero_node,
8906 high));
8907
8908 eqt = build_decl (VAR_DECL,
8909 ffecom_get_invented_identifier ("__g77_equiv_%s",
8910 ffesymbol_text
14657de8 8911 (ffestorag_symbol (eqst))),
c7e4ee3a
CB
8912 eqtype);
8913 DECL_EXTERNAL (eqt) = 0;
8914 if (is_init
8915 || ffecom_member_namelisted_
8916#ifdef FFECOM_sizeMAXSTACKITEM
8917 || (ffestorag_size (eqst) > FFECOM_sizeMAXSTACKITEM)
8918#endif
8919 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
8920 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
8921 && (ffestorag_is_save (eqst) || ffe_is_saveall ())))
8922 TREE_STATIC (eqt) = 1;
8923 else
8924 TREE_STATIC (eqt) = 0;
8925 TREE_PUBLIC (eqt) = 0;
8926 DECL_CONTEXT (eqt) = current_function_decl;
8927 if (init)
8928 DECL_INITIAL (eqt) = error_mark_node;
8929 else
8930 DECL_INITIAL (eqt) = NULL_TREE;
5ff904cd 8931
c7e4ee3a 8932 eqt = start_decl (eqt, FALSE);
5ff904cd 8933
c7e4ee3a
CB
8934 /* Make sure that any type can live in EQUIVALENCE and be referenced
8935 without getting a bus error. We could pick the most restrictive
8936 alignment of all entities actually placed in the EQUIVALENCE, but
8937 this seems easy enough. */
5ff904cd 8938
c7e4ee3a 8939 DECL_ALIGN (eqt) = BIGGEST_ALIGNMENT;
11cf4d18 8940 DECL_USER_ALIGN (eqt) = 0;
5ff904cd 8941
c7e4ee3a
CB
8942 if ((!is_init && ffe_is_init_local_zero ())
8943 || (is_init && (ffestorag_init (eqst) == NULL)))
8944 init = ffecom_init_zero_ (eqt);
5ff904cd 8945
c7e4ee3a 8946 finish_decl (eqt, init, FALSE);
5ff904cd 8947
c7e4ee3a
CB
8948 if (is_init)
8949 ffestorag_set_init (eqst, ffebld_new_any ());
5ff904cd 8950
c7e4ee3a 8951 {
06ceef4e 8952 assert (TREE_CODE (DECL_SIZE_UNIT (eqt)) == INTEGER_CST);
05bccae2
RK
8953 assert (0 == compare_tree_int (DECL_SIZE_UNIT (eqt),
8954 (ffestorag_size (eqst)
8955 + ffestorag_modulo (eqst))));
c7e4ee3a 8956 }
5ff904cd 8957
c7e4ee3a 8958 ffestorag_set_hook (eqst, eqt);
5ff904cd 8959
c7e4ee3a
CB
8960#ifdef SOMEONE_GETS_DEBUG_SUPPORT_WORKING
8961 ffestorag_drive (ffestorag_list_equivs (eqst),
8962 &ffecom_member_phase2_,
8963 eqst);
8964#endif
8965
8966 resume_momentary (yes);
5ff904cd
JL
8967}
8968
8969#endif
c7e4ee3a 8970/* Implement NAMELIST in back end. See f2c/format.c for more info. */
5ff904cd
JL
8971
8972#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
8973static tree
8974ffecom_transform_namelist_ (ffesymbol s)
5ff904cd 8975{
c7e4ee3a
CB
8976 tree nmlt;
8977 tree nmltype = ffecom_type_namelist_ ();
8978 tree nmlinits;
8979 tree nameinit;
8980 tree varsinit;
8981 tree nvarsinit;
8982 tree field;
8983 tree high;
5ff904cd 8984 int yes;
c7e4ee3a
CB
8985 int i;
8986 static int mynumber = 0;
5ff904cd 8987
c7e4ee3a 8988 yes = suspend_momentary ();
5ff904cd 8989
c7e4ee3a
CB
8990 nmlt = build_decl (VAR_DECL,
8991 ffecom_get_invented_identifier ("__g77_namelist_%d",
14657de8 8992 mynumber++),
c7e4ee3a
CB
8993 nmltype);
8994 TREE_STATIC (nmlt) = 1;
8995 DECL_INITIAL (nmlt) = error_mark_node;
5ff904cd 8996
c7e4ee3a 8997 nmlt = start_decl (nmlt, FALSE);
5ff904cd 8998
c7e4ee3a 8999 /* Process inits. */
5ff904cd 9000
c7e4ee3a 9001 i = strlen (ffesymbol_text (s));
5ff904cd 9002
c7e4ee3a
CB
9003 high = build_int_2 (i, 0);
9004 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
9005
9006 nameinit = ffecom_build_f2c_string_ (i + 1,
9007 ffesymbol_text (s));
9008 TREE_TYPE (nameinit)
9009 = build_type_variant
9010 (build_array_type
9011 (char_type_node,
9012 build_range_type (ffecom_f2c_ftnlen_type_node,
9013 ffecom_f2c_ftnlen_one_node,
9014 high)),
9015 1, 0);
9016 TREE_CONSTANT (nameinit) = 1;
9017 TREE_STATIC (nameinit) = 1;
9018 nameinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (nameinit)),
9019 nameinit);
9020
9021 varsinit = ffecom_vardesc_array_ (s);
9022 varsinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (varsinit)),
9023 varsinit);
9024 TREE_CONSTANT (varsinit) = 1;
9025 TREE_STATIC (varsinit) = 1;
9026
9027 {
9028 ffebld b;
9029
9030 for (i = 0, b = ffesymbol_namelist (s); b != NULL; b = ffebld_trail (b))
9031 ++i;
9032 }
9033 nvarsinit = build_int_2 (i, 0);
9034 TREE_TYPE (nvarsinit) = integer_type_node;
9035 TREE_CONSTANT (nvarsinit) = 1;
9036 TREE_STATIC (nvarsinit) = 1;
9037
9038 nmlinits = build_tree_list ((field = TYPE_FIELDS (nmltype)), nameinit);
9039 TREE_CHAIN (nmlinits) = build_tree_list ((field = TREE_CHAIN (field)),
9040 varsinit);
9041 TREE_CHAIN (TREE_CHAIN (nmlinits))
9042 = build_tree_list ((field = TREE_CHAIN (field)), nvarsinit);
9043
9044 nmlinits = build (CONSTRUCTOR, nmltype, NULL_TREE, nmlinits);
9045 TREE_CONSTANT (nmlinits) = 1;
9046 TREE_STATIC (nmlinits) = 1;
9047
9048 finish_decl (nmlt, nmlinits, FALSE);
9049
9050 nmlt = ffecom_1 (ADDR_EXPR, build_pointer_type (nmltype), nmlt);
9051
9052 resume_momentary (yes);
9053
9054 return nmlt;
9055}
9056
9057#endif
9058
9059/* A subroutine of ffecom_tree_canonize_ref_. The incoming tree is
9060 analyzed on the assumption it is calculating a pointer to be
9061 indirected through. It must return the proper decl and offset,
9062 taking into account different units of measurements for offsets. */
9063
9064#if FFECOM_targetCURRENT == FFECOM_targetGCC
9065static void
9066ffecom_tree_canonize_ptr_ (tree *decl, tree *offset,
9067 tree t)
9068{
9069 switch (TREE_CODE (t))
9070 {
9071 case NOP_EXPR:
9072 case CONVERT_EXPR:
9073 case NON_LVALUE_EXPR:
9074 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
5ff904cd
JL
9075 break;
9076
c7e4ee3a
CB
9077 case PLUS_EXPR:
9078 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
9079 if ((*decl == NULL_TREE)
9080 || (*decl == error_mark_node))
9081 break;
9082
9083 if (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST)
9084 {
9085 /* An offset into COMMON. */
fed3cef0
RK
9086 *offset = fold (build (PLUS_EXPR, TREE_TYPE (*offset),
9087 *offset, TREE_OPERAND (t, 1)));
c7e4ee3a
CB
9088 /* Convert offset (presumably in bytes) into canonical units
9089 (presumably bits). */
76fa6b3b
ZW
9090 *offset = size_binop (MULT_EXPR,
9091 convert (bitsizetype, *offset),
9092 TYPE_SIZE (TREE_TYPE (TREE_TYPE (t))));
c7e4ee3a
CB
9093 break;
9094 }
9095 /* Not a COMMON reference, so an unrecognized pattern. */
9096 *decl = error_mark_node;
5ff904cd
JL
9097 break;
9098
c7e4ee3a
CB
9099 case PARM_DECL:
9100 *decl = t;
770ae6cc 9101 *offset = bitsize_zero_node;
5ff904cd
JL
9102 break;
9103
c7e4ee3a
CB
9104 case ADDR_EXPR:
9105 if (TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL)
9106 {
9107 /* A reference to COMMON. */
9108 *decl = TREE_OPERAND (t, 0);
770ae6cc 9109 *offset = bitsize_zero_node;
c7e4ee3a
CB
9110 break;
9111 }
9112 /* Fall through. */
5ff904cd 9113 default:
c7e4ee3a
CB
9114 /* Not a COMMON reference, so an unrecognized pattern. */
9115 *decl = error_mark_node;
5ff904cd
JL
9116 break;
9117 }
c7e4ee3a
CB
9118}
9119#endif
5ff904cd 9120
c7e4ee3a
CB
9121/* Given a tree that is possibly intended for use as an lvalue, return
9122 information representing a canonical view of that tree as a decl, an
9123 offset into that decl, and a size for the lvalue.
5ff904cd 9124
c7e4ee3a
CB
9125 If there's no applicable decl, NULL_TREE is returned for the decl,
9126 and the other fields are left undefined.
5ff904cd 9127
c7e4ee3a
CB
9128 If the tree doesn't fit the recognizable forms, an ERROR_MARK node
9129 is returned for the decl, and the other fields are left undefined.
5ff904cd 9130
c7e4ee3a
CB
9131 Otherwise, the decl returned currently is either a VAR_DECL or a
9132 PARM_DECL.
5ff904cd 9133
c7e4ee3a
CB
9134 The offset returned is always valid, but of course not necessarily
9135 a constant, and not necessarily converted into the appropriate
9136 type, leaving that up to the caller (so as to avoid that overhead
9137 if the decls being looked at are different anyway).
5ff904cd 9138
c7e4ee3a
CB
9139 If the size cannot be determined (e.g. an adjustable array),
9140 an ERROR_MARK node is returned for the size. Otherwise, the
9141 size returned is valid, not necessarily a constant, and not
9142 necessarily converted into the appropriate type as with the
9143 offset.
5ff904cd 9144
c7e4ee3a
CB
9145 Note that the offset and size expressions are expressed in the
9146 base storage units (usually bits) rather than in the units of
9147 the type of the decl, because two decls with different types
9148 might overlap but with apparently non-overlapping array offsets,
9149 whereas converting the array offsets to consistant offsets will
9150 reveal the overlap. */
5ff904cd
JL
9151
9152#if FFECOM_targetCURRENT == FFECOM_targetGCC
9153static void
c7e4ee3a
CB
9154ffecom_tree_canonize_ref_ (tree *decl, tree *offset,
9155 tree *size, tree t)
5ff904cd 9156{
c7e4ee3a
CB
9157 /* The default path is to report a nonexistant decl. */
9158 *decl = NULL_TREE;
5ff904cd 9159
c7e4ee3a 9160 if (t == NULL_TREE)
5ff904cd
JL
9161 return;
9162
c7e4ee3a
CB
9163 switch (TREE_CODE (t))
9164 {
9165 case ERROR_MARK:
9166 case IDENTIFIER_NODE:
9167 case INTEGER_CST:
9168 case REAL_CST:
9169 case COMPLEX_CST:
9170 case STRING_CST:
9171 case CONST_DECL:
9172 case PLUS_EXPR:
9173 case MINUS_EXPR:
9174 case MULT_EXPR:
9175 case TRUNC_DIV_EXPR:
9176 case CEIL_DIV_EXPR:
9177 case FLOOR_DIV_EXPR:
9178 case ROUND_DIV_EXPR:
9179 case TRUNC_MOD_EXPR:
9180 case CEIL_MOD_EXPR:
9181 case FLOOR_MOD_EXPR:
9182 case ROUND_MOD_EXPR:
9183 case RDIV_EXPR:
9184 case EXACT_DIV_EXPR:
9185 case FIX_TRUNC_EXPR:
9186 case FIX_CEIL_EXPR:
9187 case FIX_FLOOR_EXPR:
9188 case FIX_ROUND_EXPR:
9189 case FLOAT_EXPR:
9190 case EXPON_EXPR:
9191 case NEGATE_EXPR:
9192 case MIN_EXPR:
9193 case MAX_EXPR:
9194 case ABS_EXPR:
9195 case FFS_EXPR:
9196 case LSHIFT_EXPR:
9197 case RSHIFT_EXPR:
9198 case LROTATE_EXPR:
9199 case RROTATE_EXPR:
9200 case BIT_IOR_EXPR:
9201 case BIT_XOR_EXPR:
9202 case BIT_AND_EXPR:
9203 case BIT_ANDTC_EXPR:
9204 case BIT_NOT_EXPR:
9205 case TRUTH_ANDIF_EXPR:
9206 case TRUTH_ORIF_EXPR:
9207 case TRUTH_AND_EXPR:
9208 case TRUTH_OR_EXPR:
9209 case TRUTH_XOR_EXPR:
9210 case TRUTH_NOT_EXPR:
9211 case LT_EXPR:
9212 case LE_EXPR:
9213 case GT_EXPR:
9214 case GE_EXPR:
9215 case EQ_EXPR:
9216 case NE_EXPR:
9217 case COMPLEX_EXPR:
9218 case CONJ_EXPR:
9219 case REALPART_EXPR:
9220 case IMAGPART_EXPR:
9221 case LABEL_EXPR:
9222 case COMPONENT_REF:
9223 case COMPOUND_EXPR:
9224 case ADDR_EXPR:
9225 return;
5ff904cd 9226
c7e4ee3a
CB
9227 case VAR_DECL:
9228 case PARM_DECL:
9229 *decl = t;
770ae6cc 9230 *offset = bitsize_zero_node;
c7e4ee3a
CB
9231 *size = TYPE_SIZE (TREE_TYPE (t));
9232 return;
5ff904cd 9233
c7e4ee3a
CB
9234 case ARRAY_REF:
9235 {
9236 tree array = TREE_OPERAND (t, 0);
9237 tree element = TREE_OPERAND (t, 1);
9238 tree init_offset;
9239
9240 if ((array == NULL_TREE)
9241 || (element == NULL_TREE))
9242 {
9243 *decl = error_mark_node;
9244 return;
9245 }
9246
9247 ffecom_tree_canonize_ref_ (decl, &init_offset, size,
9248 array);
9249 if ((*decl == NULL_TREE)
9250 || (*decl == error_mark_node))
9251 return;
9252
76fa6b3b
ZW
9253 /* Calculate ((element - base) * NBBY) + init_offset. */
9254 *offset = fold (build (MINUS_EXPR, TREE_TYPE (element),
9255 element,
9256 TYPE_MIN_VALUE (TYPE_DOMAIN
9257 (TREE_TYPE (array)))));
9258
9259 *offset = size_binop (MULT_EXPR,
9260 convert (bitsizetype, *offset),
9261 TYPE_SIZE (TREE_TYPE (TREE_TYPE (array))));
9262
9263 *offset = size_binop (PLUS_EXPR, init_offset, *offset);
c7e4ee3a
CB
9264
9265 *size = TYPE_SIZE (TREE_TYPE (t));
9266 return;
9267 }
9268
9269 case INDIRECT_REF:
9270
9271 /* Most of this code is to handle references to COMMON. And so
9272 far that is useful only for calling library functions, since
9273 external (user) functions might reference common areas. But
9274 even calling an external function, it's worthwhile to decode
9275 COMMON references because if not storing into COMMON, we don't
9276 want COMMON-based arguments to gratuitously force use of a
9277 temporary. */
9278
9279 *size = TYPE_SIZE (TREE_TYPE (t));
5ff904cd 9280
c7e4ee3a
CB
9281 ffecom_tree_canonize_ptr_ (decl, offset,
9282 TREE_OPERAND (t, 0));
5ff904cd 9283
c7e4ee3a 9284 return;
5ff904cd 9285
c7e4ee3a
CB
9286 case CONVERT_EXPR:
9287 case NOP_EXPR:
9288 case MODIFY_EXPR:
9289 case NON_LVALUE_EXPR:
9290 case RESULT_DECL:
9291 case FIELD_DECL:
9292 case COND_EXPR: /* More cases than we can handle. */
9293 case SAVE_EXPR:
9294 case REFERENCE_EXPR:
9295 case PREDECREMENT_EXPR:
9296 case PREINCREMENT_EXPR:
9297 case POSTDECREMENT_EXPR:
9298 case POSTINCREMENT_EXPR:
9299 case CALL_EXPR:
9300 default:
9301 *decl = error_mark_node;
9302 return;
9303 }
9304}
9305#endif
5ff904cd 9306
c7e4ee3a 9307/* Do divide operation appropriate to type of operands. */
5ff904cd 9308
c7e4ee3a
CB
9309#if FFECOM_targetCURRENT == FFECOM_targetGCC
9310static tree
9311ffecom_tree_divide_ (tree tree_type, tree left, tree right,
9312 tree dest_tree, ffebld dest, bool *dest_used,
9313 tree hook)
9314{
9315 if ((left == error_mark_node)
9316 || (right == error_mark_node))
9317 return error_mark_node;
a6fa6420 9318
c7e4ee3a
CB
9319 switch (TREE_CODE (tree_type))
9320 {
9321 case INTEGER_TYPE:
9322 return ffecom_2 (TRUNC_DIV_EXPR, tree_type,
9323 left,
9324 right);
a6fa6420 9325
c7e4ee3a 9326 case COMPLEX_TYPE:
c64f913e
CB
9327 if (! optimize_size)
9328 return ffecom_2 (RDIV_EXPR, tree_type,
9329 left,
9330 right);
c7e4ee3a
CB
9331 {
9332 ffecomGfrt ix;
a6fa6420 9333
c7e4ee3a
CB
9334 if (TREE_TYPE (tree_type)
9335 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9336 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */
9337 else
9338 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */
a6fa6420 9339
c7e4ee3a
CB
9340 left = ffecom_1 (ADDR_EXPR,
9341 build_pointer_type (TREE_TYPE (left)),
9342 left);
9343 left = build_tree_list (NULL_TREE, left);
9344 right = ffecom_1 (ADDR_EXPR,
9345 build_pointer_type (TREE_TYPE (right)),
9346 right);
9347 right = build_tree_list (NULL_TREE, right);
9348 TREE_CHAIN (left) = right;
a6fa6420 9349
c7e4ee3a
CB
9350 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9351 ffecom_gfrt_kindtype (ix),
9352 ffe_is_f2c_library (),
9353 tree_type,
9354 left,
9355 dest_tree, dest, dest_used,
9356 NULL_TREE, TRUE, hook);
9357 }
9358 break;
5ff904cd 9359
c7e4ee3a
CB
9360 case RECORD_TYPE:
9361 {
9362 ffecomGfrt ix;
5ff904cd 9363
c7e4ee3a
CB
9364 if (TREE_TYPE (TYPE_FIELDS (tree_type))
9365 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9366 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */
9367 else
9368 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */
5ff904cd 9369
c7e4ee3a
CB
9370 left = ffecom_1 (ADDR_EXPR,
9371 build_pointer_type (TREE_TYPE (left)),
9372 left);
9373 left = build_tree_list (NULL_TREE, left);
9374 right = ffecom_1 (ADDR_EXPR,
9375 build_pointer_type (TREE_TYPE (right)),
9376 right);
9377 right = build_tree_list (NULL_TREE, right);
9378 TREE_CHAIN (left) = right;
a6fa6420 9379
c7e4ee3a
CB
9380 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9381 ffecom_gfrt_kindtype (ix),
9382 ffe_is_f2c_library (),
9383 tree_type,
9384 left,
9385 dest_tree, dest, dest_used,
9386 NULL_TREE, TRUE, hook);
9387 }
9388 break;
5ff904cd 9389
c7e4ee3a
CB
9390 default:
9391 return ffecom_2 (RDIV_EXPR, tree_type,
9392 left,
9393 right);
5ff904cd 9394 }
c7e4ee3a 9395}
5ff904cd 9396
c7e4ee3a
CB
9397#endif
9398/* Build type info for non-dummy variable. */
5ff904cd 9399
c7e4ee3a
CB
9400#if FFECOM_targetCURRENT == FFECOM_targetGCC
9401static tree
9402ffecom_type_localvar_ (ffesymbol s, ffeinfoBasictype bt,
9403 ffeinfoKindtype kt)
9404{
9405 tree type;
9406 ffebld dl;
9407 ffebld dim;
9408 tree lowt;
9409 tree hight;
5ff904cd 9410
c7e4ee3a
CB
9411 type = ffecom_tree_type[bt][kt];
9412 if (bt == FFEINFO_basictypeCHARACTER)
9413 {
9414 hight = build_int_2 (ffesymbol_size (s), 0);
9415 TREE_TYPE (hight) = ffecom_f2c_ftnlen_type_node;
5ff904cd 9416
c7e4ee3a
CB
9417 type
9418 = build_array_type
9419 (type,
9420 build_range_type (ffecom_f2c_ftnlen_type_node,
9421 ffecom_f2c_ftnlen_one_node,
9422 hight));
9423 type = ffecom_check_size_overflow_ (s, type, FALSE);
9424 }
5ff904cd 9425
c7e4ee3a
CB
9426 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
9427 {
9428 if (type == error_mark_node)
9429 break;
5ff904cd 9430
c7e4ee3a
CB
9431 dim = ffebld_head (dl);
9432 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
5ff904cd 9433
c7e4ee3a
CB
9434 if (ffebld_left (dim) == NULL)
9435 lowt = integer_one_node;
9436 else
9437 lowt = ffecom_expr (ffebld_left (dim));
5ff904cd 9438
c7e4ee3a
CB
9439 if (TREE_CODE (lowt) != INTEGER_CST)
9440 lowt = variable_size (lowt);
5ff904cd 9441
c7e4ee3a
CB
9442 assert (ffebld_right (dim) != NULL);
9443 hight = ffecom_expr (ffebld_right (dim));
5ff904cd 9444
c7e4ee3a
CB
9445 if (TREE_CODE (hight) != INTEGER_CST)
9446 hight = variable_size (hight);
5ff904cd 9447
c7e4ee3a
CB
9448 type = build_array_type (type,
9449 build_range_type (ffecom_integer_type_node,
9450 lowt, hight));
9451 type = ffecom_check_size_overflow_ (s, type, FALSE);
9452 }
5ff904cd 9453
c7e4ee3a 9454 return type;
5ff904cd
JL
9455}
9456
9457#endif
c7e4ee3a 9458/* Build Namelist type. */
5ff904cd 9459
c7e4ee3a
CB
9460#if FFECOM_targetCURRENT == FFECOM_targetGCC
9461static tree
9462ffecom_type_namelist_ ()
9463{
9464 static tree type = NULL_TREE;
5ff904cd 9465
c7e4ee3a
CB
9466 if (type == NULL_TREE)
9467 {
9468 static tree namefield, varsfield, nvarsfield;
9469 tree vardesctype;
5ff904cd 9470
c7e4ee3a 9471 vardesctype = ffecom_type_vardesc_ ();
5ff904cd 9472
c7e4ee3a 9473 type = make_node (RECORD_TYPE);
a6fa6420 9474
c7e4ee3a 9475 vardesctype = build_pointer_type (build_pointer_type (vardesctype));
a6fa6420 9476
c7e4ee3a
CB
9477 namefield = ffecom_decl_field (type, NULL_TREE, "name",
9478 string_type_node);
9479 varsfield = ffecom_decl_field (type, namefield, "vars", vardesctype);
9480 nvarsfield = ffecom_decl_field (type, varsfield, "nvars",
9481 integer_type_node);
a6fa6420 9482
c7e4ee3a
CB
9483 TYPE_FIELDS (type) = namefield;
9484 layout_type (type);
a6fa6420 9485
7189a4b0 9486 ggc_add_tree_root (&type, 1);
5ff904cd 9487 }
5ff904cd 9488
c7e4ee3a
CB
9489 return type;
9490}
5ff904cd 9491
c7e4ee3a 9492#endif
5ff904cd 9493
c7e4ee3a 9494/* Build Vardesc type. */
5ff904cd 9495
c7e4ee3a
CB
9496#if FFECOM_targetCURRENT == FFECOM_targetGCC
9497static tree
9498ffecom_type_vardesc_ ()
9499{
9500 static tree type = NULL_TREE;
9501 static tree namefield, addrfield, dimsfield, typefield;
5ff904cd 9502
c7e4ee3a
CB
9503 if (type == NULL_TREE)
9504 {
c7e4ee3a 9505 type = make_node (RECORD_TYPE);
5ff904cd 9506
c7e4ee3a
CB
9507 namefield = ffecom_decl_field (type, NULL_TREE, "name",
9508 string_type_node);
9509 addrfield = ffecom_decl_field (type, namefield, "addr",
9510 string_type_node);
9511 dimsfield = ffecom_decl_field (type, addrfield, "dims",
9512 ffecom_f2c_ptr_to_ftnlen_type_node);
9513 typefield = ffecom_decl_field (type, dimsfield, "type",
9514 integer_type_node);
5ff904cd 9515
c7e4ee3a
CB
9516 TYPE_FIELDS (type) = namefield;
9517 layout_type (type);
9518
7189a4b0 9519 ggc_add_tree_root (&type, 1);
c7e4ee3a
CB
9520 }
9521
9522 return type;
5ff904cd
JL
9523}
9524
9525#endif
5ff904cd
JL
9526
9527#if FFECOM_targetCURRENT == FFECOM_targetGCC
9528static tree
c7e4ee3a 9529ffecom_vardesc_ (ffebld expr)
5ff904cd 9530{
c7e4ee3a 9531 ffesymbol s;
5ff904cd 9532
c7e4ee3a
CB
9533 assert (ffebld_op (expr) == FFEBLD_opSYMTER);
9534 s = ffebld_symter (expr);
5ff904cd 9535
c7e4ee3a
CB
9536 if (ffesymbol_hook (s).vardesc_tree == NULL_TREE)
9537 {
9538 int i;
9539 tree vardesctype = ffecom_type_vardesc_ ();
9540 tree var;
9541 tree nameinit;
9542 tree dimsinit;
9543 tree addrinit;
9544 tree typeinit;
9545 tree field;
9546 tree varinits;
9547 int yes;
9548 static int mynumber = 0;
5ff904cd 9549
c7e4ee3a 9550 yes = suspend_momentary ();
5ff904cd 9551
c7e4ee3a
CB
9552 var = build_decl (VAR_DECL,
9553 ffecom_get_invented_identifier ("__g77_vardesc_%d",
14657de8 9554 mynumber++),
c7e4ee3a
CB
9555 vardesctype);
9556 TREE_STATIC (var) = 1;
9557 DECL_INITIAL (var) = error_mark_node;
5ff904cd 9558
c7e4ee3a 9559 var = start_decl (var, FALSE);
5ff904cd 9560
c7e4ee3a 9561 /* Process inits. */
5ff904cd 9562
c7e4ee3a
CB
9563 nameinit = ffecom_build_f2c_string_ ((i = strlen (ffesymbol_text (s)))
9564 + 1,
9565 ffesymbol_text (s));
9566 TREE_TYPE (nameinit)
9567 = build_type_variant
9568 (build_array_type
9569 (char_type_node,
9570 build_range_type (integer_type_node,
9571 integer_one_node,
9572 build_int_2 (i, 0))),
9573 1, 0);
9574 TREE_CONSTANT (nameinit) = 1;
9575 TREE_STATIC (nameinit) = 1;
9576 nameinit = ffecom_1 (ADDR_EXPR,
9577 build_pointer_type (TREE_TYPE (nameinit)),
9578 nameinit);
5ff904cd 9579
c7e4ee3a 9580 addrinit = ffecom_arg_ptr_to_expr (expr, &typeinit);
5ff904cd 9581
c7e4ee3a 9582 dimsinit = ffecom_vardesc_dims_ (s);
5ff904cd 9583
c7e4ee3a
CB
9584 if (typeinit == NULL_TREE)
9585 {
9586 ffeinfoBasictype bt = ffesymbol_basictype (s);
9587 ffeinfoKindtype kt = ffesymbol_kindtype (s);
9588 int tc = ffecom_f2c_typecode (bt, kt);
5ff904cd 9589
c7e4ee3a
CB
9590 assert (tc != -1);
9591 typeinit = build_int_2 (tc, (tc < 0) ? -1 : 0);
9592 }
9593 else
9594 typeinit = ffecom_1 (NEGATE_EXPR, TREE_TYPE (typeinit), typeinit);
5ff904cd 9595
c7e4ee3a
CB
9596 varinits = build_tree_list ((field = TYPE_FIELDS (vardesctype)),
9597 nameinit);
9598 TREE_CHAIN (varinits) = build_tree_list ((field = TREE_CHAIN (field)),
9599 addrinit);
9600 TREE_CHAIN (TREE_CHAIN (varinits))
9601 = build_tree_list ((field = TREE_CHAIN (field)), dimsinit);
9602 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (varinits)))
9603 = build_tree_list ((field = TREE_CHAIN (field)), typeinit);
5ff904cd 9604
c7e4ee3a
CB
9605 varinits = build (CONSTRUCTOR, vardesctype, NULL_TREE, varinits);
9606 TREE_CONSTANT (varinits) = 1;
9607 TREE_STATIC (varinits) = 1;
5ff904cd 9608
c7e4ee3a 9609 finish_decl (var, varinits, FALSE);
5ff904cd 9610
c7e4ee3a 9611 var = ffecom_1 (ADDR_EXPR, build_pointer_type (vardesctype), var);
5ff904cd 9612
c7e4ee3a 9613 resume_momentary (yes);
5ff904cd 9614
c7e4ee3a
CB
9615 ffesymbol_hook (s).vardesc_tree = var;
9616 }
5ff904cd 9617
c7e4ee3a
CB
9618 return ffesymbol_hook (s).vardesc_tree;
9619}
5ff904cd 9620
c7e4ee3a 9621#endif
5ff904cd 9622#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
9623static tree
9624ffecom_vardesc_array_ (ffesymbol s)
5ff904cd 9625{
c7e4ee3a
CB
9626 ffebld b;
9627 tree list;
9628 tree item = NULL_TREE;
9629 tree var;
9630 int i;
9631 int yes;
9632 static int mynumber = 0;
5ff904cd 9633
c7e4ee3a
CB
9634 for (i = 0, list = NULL_TREE, b = ffesymbol_namelist (s);
9635 b != NULL;
9636 b = ffebld_trail (b), ++i)
9637 {
9638 tree t;
5ff904cd 9639
c7e4ee3a 9640 t = ffecom_vardesc_ (ffebld_head (b));
5ff904cd 9641
c7e4ee3a
CB
9642 if (list == NULL_TREE)
9643 list = item = build_tree_list (NULL_TREE, t);
9644 else
5ff904cd 9645 {
c7e4ee3a
CB
9646 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
9647 item = TREE_CHAIN (item);
5ff904cd 9648 }
5ff904cd 9649 }
5ff904cd 9650
c7e4ee3a 9651 yes = suspend_momentary ();
5ff904cd 9652
c7e4ee3a
CB
9653 item = build_array_type (build_pointer_type (ffecom_type_vardesc_ ()),
9654 build_range_type (integer_type_node,
9655 integer_one_node,
9656 build_int_2 (i, 0)));
9657 list = build (CONSTRUCTOR, item, NULL_TREE, list);
9658 TREE_CONSTANT (list) = 1;
9659 TREE_STATIC (list) = 1;
5ff904cd 9660
14657de8 9661 var = ffecom_get_invented_identifier ("__g77_vardesc_array_%d", mynumber++);
c7e4ee3a
CB
9662 var = build_decl (VAR_DECL, var, item);
9663 TREE_STATIC (var) = 1;
9664 DECL_INITIAL (var) = error_mark_node;
9665 var = start_decl (var, FALSE);
9666 finish_decl (var, list, FALSE);
5ff904cd 9667
c7e4ee3a 9668 resume_momentary (yes);
5ff904cd 9669
c7e4ee3a
CB
9670 return var;
9671}
5ff904cd 9672
c7e4ee3a
CB
9673#endif
9674#if FFECOM_targetCURRENT == FFECOM_targetGCC
9675static tree
9676ffecom_vardesc_dims_ (ffesymbol s)
9677{
9678 if (ffesymbol_dims (s) == NULL)
9679 return convert (ffecom_f2c_ptr_to_ftnlen_type_node,
9680 integer_zero_node);
5ff904cd 9681
c7e4ee3a
CB
9682 {
9683 ffebld b;
9684 ffebld e;
9685 tree list;
9686 tree backlist;
9687 tree item = NULL_TREE;
9688 tree var;
9689 int yes;
9690 tree numdim;
9691 tree numelem;
9692 tree baseoff = NULL_TREE;
9693 static int mynumber = 0;
9694
9695 numdim = build_int_2 ((int) ffesymbol_rank (s), 0);
9696 TREE_TYPE (numdim) = ffecom_f2c_ftnlen_type_node;
9697
9698 numelem = ffecom_expr (ffesymbol_arraysize (s));
9699 TREE_TYPE (numelem) = ffecom_f2c_ftnlen_type_node;
9700
9701 list = NULL_TREE;
9702 backlist = NULL_TREE;
9703 for (b = ffesymbol_dims (s), e = ffesymbol_extents (s);
9704 b != NULL;
9705 b = ffebld_trail (b), e = ffebld_trail (e))
5ff904cd 9706 {
c7e4ee3a
CB
9707 tree t;
9708 tree low;
9709 tree back;
5ff904cd 9710
c7e4ee3a
CB
9711 if (ffebld_trail (b) == NULL)
9712 t = NULL_TREE;
9713 else
5ff904cd 9714 {
c7e4ee3a
CB
9715 t = convert (ffecom_f2c_ftnlen_type_node,
9716 ffecom_expr (ffebld_head (e)));
5ff904cd 9717
c7e4ee3a
CB
9718 if (list == NULL_TREE)
9719 list = item = build_tree_list (NULL_TREE, t);
9720 else
9721 {
9722 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
9723 item = TREE_CHAIN (item);
9724 }
9725 }
5ff904cd 9726
c7e4ee3a
CB
9727 if (ffebld_left (ffebld_head (b)) == NULL)
9728 low = ffecom_integer_one_node;
9729 else
9730 low = ffecom_expr (ffebld_left (ffebld_head (b)));
9731 low = convert (ffecom_f2c_ftnlen_type_node, low);
5ff904cd 9732
c7e4ee3a
CB
9733 back = build_tree_list (low, t);
9734 TREE_CHAIN (back) = backlist;
9735 backlist = back;
9736 }
5ff904cd 9737
c7e4ee3a
CB
9738 for (item = backlist; item != NULL_TREE; item = TREE_CHAIN (item))
9739 {
9740 if (TREE_VALUE (item) == NULL_TREE)
9741 baseoff = TREE_PURPOSE (item);
9742 else
9743 baseoff = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
9744 TREE_PURPOSE (item),
9745 ffecom_2 (MULT_EXPR,
9746 ffecom_f2c_ftnlen_type_node,
9747 TREE_VALUE (item),
9748 baseoff));
5ff904cd
JL
9749 }
9750
c7e4ee3a 9751 /* backlist now dead, along with all TREE_PURPOSEs on it. */
5ff904cd 9752
c7e4ee3a
CB
9753 baseoff = build_tree_list (NULL_TREE, baseoff);
9754 TREE_CHAIN (baseoff) = list;
5ff904cd 9755
c7e4ee3a
CB
9756 numelem = build_tree_list (NULL_TREE, numelem);
9757 TREE_CHAIN (numelem) = baseoff;
5ff904cd 9758
c7e4ee3a
CB
9759 numdim = build_tree_list (NULL_TREE, numdim);
9760 TREE_CHAIN (numdim) = numelem;
5ff904cd 9761
c7e4ee3a 9762 yes = suspend_momentary ();
5ff904cd 9763
c7e4ee3a
CB
9764 item = build_array_type (ffecom_f2c_ftnlen_type_node,
9765 build_range_type (integer_type_node,
9766 integer_zero_node,
9767 build_int_2
9768 ((int) ffesymbol_rank (s)
9769 + 2, 0)));
9770 list = build (CONSTRUCTOR, item, NULL_TREE, numdim);
9771 TREE_CONSTANT (list) = 1;
9772 TREE_STATIC (list) = 1;
9773
14657de8 9774 var = ffecom_get_invented_identifier ("__g77_dims_%d", mynumber++);
c7e4ee3a
CB
9775 var = build_decl (VAR_DECL, var, item);
9776 TREE_STATIC (var) = 1;
9777 DECL_INITIAL (var) = error_mark_node;
9778 var = start_decl (var, FALSE);
9779 finish_decl (var, list, FALSE);
9780
9781 var = ffecom_1 (ADDR_EXPR, build_pointer_type (item), var);
9782
9783 resume_momentary (yes);
9784
9785 return var;
9786 }
5ff904cd 9787}
c7e4ee3a 9788
5ff904cd 9789#endif
c7e4ee3a
CB
9790/* Essentially does a "fold (build1 (code, type, node))" while checking
9791 for certain housekeeping things.
5ff904cd 9792
c7e4ee3a
CB
9793 NOTE: for building an ADDR_EXPR around a FUNCTION_DECL, use
9794 ffecom_1_fn instead. */
5ff904cd
JL
9795
9796#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
9797tree
9798ffecom_1 (enum tree_code code, tree type, tree node)
5ff904cd 9799{
c7e4ee3a
CB
9800 tree item;
9801
9802 if ((node == error_mark_node)
9803 || (type == error_mark_node))
5ff904cd
JL
9804 return error_mark_node;
9805
c7e4ee3a 9806 if (code == ADDR_EXPR)
5ff904cd 9807 {
c7e4ee3a
CB
9808 if (!mark_addressable (node))
9809 assert ("can't mark_addressable this node!" == NULL);
9810 }
5ff904cd 9811
c7e4ee3a
CB
9812 switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
9813 {
9814 tree realtype;
5ff904cd 9815
c7e4ee3a
CB
9816 case REALPART_EXPR:
9817 item = build (COMPONENT_REF, type, node, TYPE_FIELDS (TREE_TYPE (node)));
5ff904cd
JL
9818 break;
9819
c7e4ee3a
CB
9820 case IMAGPART_EXPR:
9821 item = build (COMPONENT_REF, type, node, TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (node))));
9822 break;
5ff904cd 9823
5ff904cd 9824
c7e4ee3a
CB
9825 case NEGATE_EXPR:
9826 if (TREE_CODE (type) != RECORD_TYPE)
9827 {
9828 item = build1 (code, type, node);
9829 break;
9830 }
9831 node = ffecom_stabilize_aggregate_ (node);
9832 realtype = TREE_TYPE (TYPE_FIELDS (type));
9833 item =
9834 ffecom_2 (COMPLEX_EXPR, type,
9835 ffecom_1 (NEGATE_EXPR, realtype,
9836 ffecom_1 (REALPART_EXPR, realtype,
9837 node)),
9838 ffecom_1 (NEGATE_EXPR, realtype,
9839 ffecom_1 (IMAGPART_EXPR, realtype,
9840 node)));
5ff904cd
JL
9841 break;
9842
9843 default:
c7e4ee3a
CB
9844 item = build1 (code, type, node);
9845 break;
5ff904cd 9846 }
5ff904cd 9847
c7e4ee3a
CB
9848 if (TREE_SIDE_EFFECTS (node))
9849 TREE_SIDE_EFFECTS (item) = 1;
9850 if ((code == ADDR_EXPR) && staticp (node))
9851 TREE_CONSTANT (item) = 1;
9852 return fold (item);
9853}
5ff904cd 9854#endif
5ff904cd 9855
c7e4ee3a
CB
9856/* Like ffecom_1 (ADDR_EXPR, TREE_TYPE (node), node), except
9857 handles TREE_CODE (node) == FUNCTION_DECL. In particular,
9858 does not set TREE_ADDRESSABLE (because calling an inline
9859 function does not mean the function needs to be separately
9860 compiled). */
5ff904cd
JL
9861
9862#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
9863tree
9864ffecom_1_fn (tree node)
5ff904cd 9865{
c7e4ee3a 9866 tree item;
5ff904cd 9867 tree type;
5ff904cd 9868
c7e4ee3a
CB
9869 if (node == error_mark_node)
9870 return error_mark_node;
5ff904cd 9871
c7e4ee3a
CB
9872 type = build_type_variant (TREE_TYPE (node),
9873 TREE_READONLY (node),
9874 TREE_THIS_VOLATILE (node));
9875 item = build1 (ADDR_EXPR,
9876 build_pointer_type (type), node);
9877 if (TREE_SIDE_EFFECTS (node))
9878 TREE_SIDE_EFFECTS (item) = 1;
9879 if (staticp (node))
9880 TREE_CONSTANT (item) = 1;
9881 return fold (item);
5ff904cd 9882}
5ff904cd 9883#endif
c7e4ee3a
CB
9884
9885/* Essentially does a "fold (build (code, type, node1, node2))" while
9886 checking for certain housekeeping things. */
5ff904cd
JL
9887
9888#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
9889tree
9890ffecom_2 (enum tree_code code, tree type, tree node1,
9891 tree node2)
5ff904cd 9892{
c7e4ee3a 9893 tree item;
5ff904cd 9894
c7e4ee3a
CB
9895 if ((node1 == error_mark_node)
9896 || (node2 == error_mark_node)
9897 || (type == error_mark_node))
9898 return error_mark_node;
9899
9900 switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
5ff904cd 9901 {
c7e4ee3a 9902 tree a, b, c, d, realtype;
5ff904cd 9903
c7e4ee3a
CB
9904 case CONJ_EXPR:
9905 assert ("no CONJ_EXPR support yet" == NULL);
9906 return error_mark_node;
5ff904cd 9907
c7e4ee3a
CB
9908 case COMPLEX_EXPR:
9909 item = build_tree_list (TYPE_FIELDS (type), node1);
9910 TREE_CHAIN (item) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), node2);
9911 item = build (CONSTRUCTOR, type, NULL_TREE, item);
9912 break;
5ff904cd 9913
c7e4ee3a
CB
9914 case PLUS_EXPR:
9915 if (TREE_CODE (type) != RECORD_TYPE)
9916 {
9917 item = build (code, type, node1, node2);
9918 break;
9919 }
9920 node1 = ffecom_stabilize_aggregate_ (node1);
9921 node2 = ffecom_stabilize_aggregate_ (node2);
9922 realtype = TREE_TYPE (TYPE_FIELDS (type));
9923 item =
9924 ffecom_2 (COMPLEX_EXPR, type,
9925 ffecom_2 (PLUS_EXPR, realtype,
9926 ffecom_1 (REALPART_EXPR, realtype,
9927 node1),
9928 ffecom_1 (REALPART_EXPR, realtype,
9929 node2)),
9930 ffecom_2 (PLUS_EXPR, realtype,
9931 ffecom_1 (IMAGPART_EXPR, realtype,
9932 node1),
9933 ffecom_1 (IMAGPART_EXPR, realtype,
9934 node2)));
9935 break;
5ff904cd 9936
c7e4ee3a
CB
9937 case MINUS_EXPR:
9938 if (TREE_CODE (type) != RECORD_TYPE)
9939 {
9940 item = build (code, type, node1, node2);
9941 break;
9942 }
9943 node1 = ffecom_stabilize_aggregate_ (node1);
9944 node2 = ffecom_stabilize_aggregate_ (node2);
9945 realtype = TREE_TYPE (TYPE_FIELDS (type));
9946 item =
9947 ffecom_2 (COMPLEX_EXPR, type,
9948 ffecom_2 (MINUS_EXPR, realtype,
9949 ffecom_1 (REALPART_EXPR, realtype,
9950 node1),
9951 ffecom_1 (REALPART_EXPR, realtype,
9952 node2)),
9953 ffecom_2 (MINUS_EXPR, realtype,
9954 ffecom_1 (IMAGPART_EXPR, realtype,
9955 node1),
9956 ffecom_1 (IMAGPART_EXPR, realtype,
9957 node2)));
9958 break;
5ff904cd 9959
c7e4ee3a
CB
9960 case MULT_EXPR:
9961 if (TREE_CODE (type) != RECORD_TYPE)
9962 {
9963 item = build (code, type, node1, node2);
9964 break;
9965 }
9966 node1 = ffecom_stabilize_aggregate_ (node1);
9967 node2 = ffecom_stabilize_aggregate_ (node2);
9968 realtype = TREE_TYPE (TYPE_FIELDS (type));
9969 a = save_expr (ffecom_1 (REALPART_EXPR, realtype,
9970 node1));
9971 b = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
9972 node1));
9973 c = save_expr (ffecom_1 (REALPART_EXPR, realtype,
9974 node2));
9975 d = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
9976 node2));
9977 item =
9978 ffecom_2 (COMPLEX_EXPR, type,
9979 ffecom_2 (MINUS_EXPR, realtype,
9980 ffecom_2 (MULT_EXPR, realtype,
9981 a,
9982 c),
9983 ffecom_2 (MULT_EXPR, realtype,
9984 b,
9985 d)),
9986 ffecom_2 (PLUS_EXPR, realtype,
9987 ffecom_2 (MULT_EXPR, realtype,
9988 a,
9989 d),
9990 ffecom_2 (MULT_EXPR, realtype,
9991 c,
9992 b)));
9993 break;
5ff904cd 9994
c7e4ee3a
CB
9995 case EQ_EXPR:
9996 if ((TREE_CODE (node1) != RECORD_TYPE)
9997 && (TREE_CODE (node2) != RECORD_TYPE))
9998 {
9999 item = build (code, type, node1, node2);
10000 break;
10001 }
10002 assert (TREE_CODE (node1) == RECORD_TYPE);
10003 assert (TREE_CODE (node2) == RECORD_TYPE);
10004 node1 = ffecom_stabilize_aggregate_ (node1);
10005 node2 = ffecom_stabilize_aggregate_ (node2);
10006 realtype = TREE_TYPE (TYPE_FIELDS (type));
10007 item =
10008 ffecom_2 (TRUTH_ANDIF_EXPR, type,
10009 ffecom_2 (code, type,
10010 ffecom_1 (REALPART_EXPR, realtype,
10011 node1),
10012 ffecom_1 (REALPART_EXPR, realtype,
10013 node2)),
10014 ffecom_2 (code, type,
10015 ffecom_1 (IMAGPART_EXPR, realtype,
10016 node1),
10017 ffecom_1 (IMAGPART_EXPR, realtype,
10018 node2)));
10019 break;
10020
10021 case NE_EXPR:
10022 if ((TREE_CODE (node1) != RECORD_TYPE)
10023 && (TREE_CODE (node2) != RECORD_TYPE))
10024 {
10025 item = build (code, type, node1, node2);
10026 break;
10027 }
10028 assert (TREE_CODE (node1) == RECORD_TYPE);
10029 assert (TREE_CODE (node2) == RECORD_TYPE);
10030 node1 = ffecom_stabilize_aggregate_ (node1);
10031 node2 = ffecom_stabilize_aggregate_ (node2);
10032 realtype = TREE_TYPE (TYPE_FIELDS (type));
10033 item =
10034 ffecom_2 (TRUTH_ORIF_EXPR, type,
10035 ffecom_2 (code, type,
10036 ffecom_1 (REALPART_EXPR, realtype,
10037 node1),
10038 ffecom_1 (REALPART_EXPR, realtype,
10039 node2)),
10040 ffecom_2 (code, type,
10041 ffecom_1 (IMAGPART_EXPR, realtype,
10042 node1),
10043 ffecom_1 (IMAGPART_EXPR, realtype,
10044 node2)));
10045 break;
5ff904cd 10046
c7e4ee3a
CB
10047 default:
10048 item = build (code, type, node1, node2);
10049 break;
5ff904cd
JL
10050 }
10051
c7e4ee3a
CB
10052 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2))
10053 TREE_SIDE_EFFECTS (item) = 1;
10054 return fold (item);
5ff904cd
JL
10055}
10056
10057#endif
c7e4ee3a 10058/* ffecom_2pass_advise_entrypoint -- Advise that there's this entrypoint
5ff904cd 10059
c7e4ee3a
CB
10060 ffesymbol s; // the ENTRY point itself
10061 if (ffecom_2pass_advise_entrypoint(s))
10062 // the ENTRY point has been accepted
5ff904cd 10063
c7e4ee3a
CB
10064 Does whatever compiler needs to do when it learns about the entrypoint,
10065 like determine the return type of the master function, count the
10066 number of entrypoints, etc. Returns FALSE if the return type is
10067 not compatible with the return type(s) of other entrypoint(s).
5ff904cd 10068
c7e4ee3a
CB
10069 NOTE: for every call to this fn that returns TRUE, _do_entrypoint must
10070 later (after _finish_progunit) be called with the same entrypoint(s)
10071 as passed to this fn for which TRUE was returned.
5ff904cd 10072
c7e4ee3a
CB
10073 03-Jan-92 JCB 2.0
10074 Return FALSE if the return type conflicts with previous entrypoints. */
5ff904cd
JL
10075
10076#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
10077bool
10078ffecom_2pass_advise_entrypoint (ffesymbol entry)
5ff904cd 10079{
c7e4ee3a
CB
10080 ffebld list; /* opITEM. */
10081 ffebld mlist; /* opITEM. */
10082 ffebld plist; /* opITEM. */
10083 ffebld arg; /* ffebld_head(opITEM). */
10084 ffebld item; /* opITEM. */
10085 ffesymbol s; /* ffebld_symter(arg). */
10086 ffeinfoBasictype bt = ffesymbol_basictype (entry);
10087 ffeinfoKindtype kt = ffesymbol_kindtype (entry);
10088 ffetargetCharacterSize size = ffesymbol_size (entry);
10089 bool ok;
5ff904cd 10090
c7e4ee3a
CB
10091 if (ffecom_num_entrypoints_ == 0)
10092 { /* First entrypoint, make list of main
10093 arglist's dummies. */
10094 assert (ffecom_primary_entry_ != NULL);
5ff904cd 10095
c7e4ee3a
CB
10096 ffecom_master_bt_ = ffesymbol_basictype (ffecom_primary_entry_);
10097 ffecom_master_kt_ = ffesymbol_kindtype (ffecom_primary_entry_);
10098 ffecom_master_size_ = ffesymbol_size (ffecom_primary_entry_);
5ff904cd 10099
c7e4ee3a
CB
10100 for (plist = NULL, list = ffesymbol_dummyargs (ffecom_primary_entry_);
10101 list != NULL;
10102 list = ffebld_trail (list))
10103 {
10104 arg = ffebld_head (list);
10105 if (ffebld_op (arg) != FFEBLD_opSYMTER)
10106 continue; /* Alternate return or some such thing. */
10107 item = ffebld_new_item (arg, NULL);
10108 if (plist == NULL)
10109 ffecom_master_arglist_ = item;
10110 else
10111 ffebld_set_trail (plist, item);
10112 plist = item;
10113 }
5ff904cd
JL
10114 }
10115
c7e4ee3a
CB
10116 /* If necessary, scan entry arglist for alternate returns. Do this scan
10117 apparently redundantly (it's done below to UNIONize the arglists) so
10118 that we don't complain about RETURN 1 if an offending ENTRY is the only
10119 one with an alternate return. */
5ff904cd 10120
c7e4ee3a 10121 if (!ffecom_is_altreturning_)
5ff904cd 10122 {
c7e4ee3a
CB
10123 for (list = ffesymbol_dummyargs (entry);
10124 list != NULL;
10125 list = ffebld_trail (list))
10126 {
10127 arg = ffebld_head (list);
10128 if (ffebld_op (arg) == FFEBLD_opSTAR)
10129 {
10130 ffecom_is_altreturning_ = TRUE;
10131 break;
10132 }
10133 }
10134 }
5ff904cd 10135
c7e4ee3a 10136 /* Now check type compatibility. */
5ff904cd 10137
c7e4ee3a
CB
10138 switch (ffecom_master_bt_)
10139 {
10140 case FFEINFO_basictypeNONE:
10141 ok = (bt != FFEINFO_basictypeCHARACTER);
10142 break;
5ff904cd 10143
c7e4ee3a
CB
10144 case FFEINFO_basictypeCHARACTER:
10145 ok
10146 = (bt == FFEINFO_basictypeCHARACTER)
10147 && (kt == ffecom_master_kt_)
10148 && (size == ffecom_master_size_);
10149 break;
5ff904cd 10150
c7e4ee3a
CB
10151 case FFEINFO_basictypeANY:
10152 return FALSE; /* Just don't bother. */
5ff904cd 10153
c7e4ee3a
CB
10154 default:
10155 if (bt == FFEINFO_basictypeCHARACTER)
5ff904cd 10156 {
c7e4ee3a
CB
10157 ok = FALSE;
10158 break;
5ff904cd 10159 }
c7e4ee3a
CB
10160 ok = TRUE;
10161 if ((bt != ffecom_master_bt_) || (kt != ffecom_master_kt_))
10162 {
10163 ffecom_master_bt_ = FFEINFO_basictypeNONE;
10164 ffecom_master_kt_ = FFEINFO_kindtypeNONE;
10165 }
10166 break;
10167 }
5ff904cd 10168
c7e4ee3a
CB
10169 if (!ok)
10170 {
10171 ffebad_start (FFEBAD_ENTRY_CONFLICTS);
10172 ffest_ffebad_here_current_stmt (0);
10173 ffebad_finish ();
10174 return FALSE; /* Can't handle entrypoint. */
10175 }
5ff904cd 10176
c7e4ee3a 10177 /* Entrypoint type compatible with previous types. */
5ff904cd 10178
c7e4ee3a 10179 ++ffecom_num_entrypoints_;
5ff904cd 10180
c7e4ee3a
CB
10181 /* Master-arg-list = UNION(Master-arg-list,entry-arg-list). */
10182
10183 for (list = ffesymbol_dummyargs (entry);
10184 list != NULL;
10185 list = ffebld_trail (list))
10186 {
10187 arg = ffebld_head (list);
10188 if (ffebld_op (arg) != FFEBLD_opSYMTER)
10189 continue; /* Alternate return or some such thing. */
10190 s = ffebld_symter (arg);
10191 for (plist = NULL, mlist = ffecom_master_arglist_;
10192 mlist != NULL;
10193 plist = mlist, mlist = ffebld_trail (mlist))
10194 { /* plist points to previous item for easy
10195 appending of arg. */
10196 if (ffebld_symter (ffebld_head (mlist)) == s)
10197 break; /* Already have this arg in the master list. */
10198 }
10199 if (mlist != NULL)
10200 continue; /* Already have this arg in the master list. */
5ff904cd 10201
c7e4ee3a 10202 /* Append this arg to the master list. */
5ff904cd 10203
c7e4ee3a
CB
10204 item = ffebld_new_item (arg, NULL);
10205 if (plist == NULL)
10206 ffecom_master_arglist_ = item;
10207 else
10208 ffebld_set_trail (plist, item);
5ff904cd
JL
10209 }
10210
c7e4ee3a 10211 return TRUE;
5ff904cd
JL
10212}
10213
10214#endif
c7e4ee3a
CB
10215/* ffecom_2pass_do_entrypoint -- Do compilation of entrypoint
10216
10217 ffesymbol s; // the ENTRY point itself
10218 ffecom_2pass_do_entrypoint(s);
10219
10220 Does whatever compiler needs to do to make the entrypoint actually
10221 happen. Must be called for each entrypoint after
10222 ffecom_finish_progunit is called. */
10223
5ff904cd 10224#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
10225void
10226ffecom_2pass_do_entrypoint (ffesymbol entry)
5ff904cd 10227{
c7e4ee3a
CB
10228 static int mfn_num = 0;
10229 static int ent_num;
5ff904cd 10230
c7e4ee3a
CB
10231 if (mfn_num != ffecom_num_fns_)
10232 { /* First entrypoint for this program unit. */
10233 ent_num = 1;
10234 mfn_num = ffecom_num_fns_;
10235 ffecom_do_entry_ (ffecom_primary_entry_, 0);
10236 }
10237 else
10238 ++ent_num;
5ff904cd 10239
c7e4ee3a 10240 --ffecom_num_entrypoints_;
5ff904cd 10241
c7e4ee3a
CB
10242 ffecom_do_entry_ (entry, ent_num);
10243}
5ff904cd 10244
c7e4ee3a 10245#endif
5ff904cd 10246
c7e4ee3a
CB
10247/* Essentially does a "fold (build (code, type, node1, node2))" while
10248 checking for certain housekeeping things. Always sets
10249 TREE_SIDE_EFFECTS. */
5ff904cd 10250
c7e4ee3a
CB
10251#if FFECOM_targetCURRENT == FFECOM_targetGCC
10252tree
10253ffecom_2s (enum tree_code code, tree type, tree node1,
10254 tree node2)
10255{
10256 tree item;
5ff904cd 10257
c7e4ee3a
CB
10258 if ((node1 == error_mark_node)
10259 || (node2 == error_mark_node)
10260 || (type == error_mark_node))
10261 return error_mark_node;
5ff904cd 10262
c7e4ee3a
CB
10263 item = build (code, type, node1, node2);
10264 TREE_SIDE_EFFECTS (item) = 1;
10265 return fold (item);
5ff904cd
JL
10266}
10267
10268#endif
c7e4ee3a
CB
10269/* Essentially does a "fold (build (code, type, node1, node2, node3))" while
10270 checking for certain housekeeping things. */
10271
5ff904cd 10272#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
10273tree
10274ffecom_3 (enum tree_code code, tree type, tree node1,
10275 tree node2, tree node3)
5ff904cd 10276{
c7e4ee3a 10277 tree item;
5ff904cd 10278
c7e4ee3a
CB
10279 if ((node1 == error_mark_node)
10280 || (node2 == error_mark_node)
10281 || (node3 == error_mark_node)
10282 || (type == error_mark_node))
10283 return error_mark_node;
5ff904cd 10284
c7e4ee3a
CB
10285 item = build (code, type, node1, node2, node3);
10286 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2)
10287 || (node3 != NULL_TREE && TREE_SIDE_EFFECTS (node3)))
10288 TREE_SIDE_EFFECTS (item) = 1;
10289 return fold (item);
10290}
5ff904cd 10291
c7e4ee3a
CB
10292#endif
10293/* Essentially does a "fold (build (code, type, node1, node2, node3))" while
10294 checking for certain housekeeping things. Always sets
10295 TREE_SIDE_EFFECTS. */
5ff904cd 10296
c7e4ee3a
CB
10297#if FFECOM_targetCURRENT == FFECOM_targetGCC
10298tree
10299ffecom_3s (enum tree_code code, tree type, tree node1,
10300 tree node2, tree node3)
10301{
10302 tree item;
5ff904cd 10303
c7e4ee3a
CB
10304 if ((node1 == error_mark_node)
10305 || (node2 == error_mark_node)
10306 || (node3 == error_mark_node)
10307 || (type == error_mark_node))
10308 return error_mark_node;
5ff904cd 10309
c7e4ee3a
CB
10310 item = build (code, type, node1, node2, node3);
10311 TREE_SIDE_EFFECTS (item) = 1;
10312 return fold (item);
10313}
5ff904cd 10314
c7e4ee3a 10315#endif
5ff904cd 10316
c7e4ee3a 10317/* ffecom_arg_expr -- Transform argument expr into gcc tree
5ff904cd 10318
c7e4ee3a 10319 See use by ffecom_list_expr.
5ff904cd 10320
c7e4ee3a
CB
10321 If expression is NULL, returns an integer zero tree. If it is not
10322 a CHARACTER expression, returns whatever ffecom_expr
10323 returns and sets the length return value to NULL_TREE. Otherwise
10324 generates code to evaluate the character expression, returns the proper
10325 pointer to the result, but does NOT set the length return value to a tree
10326 that specifies the length of the result. (In other words, the length
10327 variable is always set to NULL_TREE, because a length is never passed.)
5ff904cd 10328
c7e4ee3a
CB
10329 21-Dec-91 JCB 1.1
10330 Don't set returned length, since nobody needs it (yet; someday if
10331 we allow CHARACTER*(*) dummies to statement functions, we'll need
10332 it). */
5ff904cd 10333
c7e4ee3a
CB
10334#if FFECOM_targetCURRENT == FFECOM_targetGCC
10335tree
10336ffecom_arg_expr (ffebld expr, tree *length)
10337{
10338 tree ign;
5ff904cd 10339
c7e4ee3a 10340 *length = NULL_TREE;
5ff904cd 10341
c7e4ee3a
CB
10342 if (expr == NULL)
10343 return integer_zero_node;
5ff904cd 10344
c7e4ee3a
CB
10345 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10346 return ffecom_expr (expr);
5ff904cd 10347
c7e4ee3a
CB
10348 return ffecom_arg_ptr_to_expr (expr, &ign);
10349}
10350
10351#endif
10352/* Transform expression into constant argument-pointer-to-expression tree.
10353
10354 If the expression can be transformed into a argument-pointer-to-expression
10355 tree that is constant, that is done, and the tree returned. Else
10356 NULL_TREE is returned.
5ff904cd 10357
c7e4ee3a
CB
10358 That way, a caller can attempt to provide compile-time initialization
10359 of a variable and, if that fails, *then* choose to start a new block
10360 and resort to using temporaries, as appropriate. */
5ff904cd 10361
c7e4ee3a
CB
10362tree
10363ffecom_arg_ptr_to_const_expr (ffebld expr, tree *length)
10364{
10365 if (! expr)
10366 return integer_zero_node;
5ff904cd 10367
c7e4ee3a
CB
10368 if (ffebld_op (expr) == FFEBLD_opANY)
10369 {
10370 if (length)
10371 *length = error_mark_node;
10372 return error_mark_node;
10373 }
10374
10375 if (ffebld_arity (expr) == 0
10376 && (ffebld_op (expr) != FFEBLD_opSYMTER
10377 || ffebld_where (expr) == FFEINFO_whereCOMMON
10378 || ffebld_where (expr) == FFEINFO_whereGLOBAL
10379 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
10380 {
10381 tree t;
10382
10383 t = ffecom_arg_ptr_to_expr (expr, length);
10384 assert (TREE_CONSTANT (t));
10385 assert (! length || TREE_CONSTANT (*length));
10386 return t;
10387 }
10388
10389 if (length
10390 && ffebld_size (expr) != FFETARGET_charactersizeNONE)
10391 *length = build_int_2 (ffebld_size (expr), 0);
10392 else if (length)
10393 *length = NULL_TREE;
10394 return NULL_TREE;
5ff904cd
JL
10395}
10396
c7e4ee3a 10397/* ffecom_arg_ptr_to_expr -- Transform argument expr into gcc tree
5ff904cd 10398
c7e4ee3a
CB
10399 See use by ffecom_list_ptr_to_expr.
10400
10401 If expression is NULL, returns an integer zero tree. If it is not
10402 a CHARACTER expression, returns whatever ffecom_ptr_to_expr
10403 returns and sets the length return value to NULL_TREE. Otherwise
10404 generates code to evaluate the character expression, returns the proper
10405 pointer to the result, AND sets the length return value to a tree that
10406 specifies the length of the result.
10407
10408 If the length argument is NULL, this is a slightly special
10409 case of building a FORMAT expression, that is, an expression that
10410 will be used at run time without regard to length. For the current
10411 implementation, which uses the libf2c library, this means it is nice
10412 to append a null byte to the end of the expression, where feasible,
10413 to make sure any diagnostic about the FORMAT string terminates at
10414 some useful point.
10415
10416 For now, treat %REF(char-expr) as the same as char-expr with a NULL
10417 length argument. This might even be seen as a feature, if a null
10418 byte can always be appended. */
5ff904cd
JL
10419
10420#if FFECOM_targetCURRENT == FFECOM_targetGCC
10421tree
c7e4ee3a 10422ffecom_arg_ptr_to_expr (ffebld expr, tree *length)
5ff904cd
JL
10423{
10424 tree item;
c7e4ee3a
CB
10425 tree ign_length;
10426 ffecomConcatList_ catlist;
5ff904cd 10427
c7e4ee3a
CB
10428 if (length != NULL)
10429 *length = NULL_TREE;
5ff904cd 10430
c7e4ee3a
CB
10431 if (expr == NULL)
10432 return integer_zero_node;
5ff904cd 10433
c7e4ee3a 10434 switch (ffebld_op (expr))
5ff904cd 10435 {
c7e4ee3a
CB
10436 case FFEBLD_opPERCENT_VAL:
10437 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10438 return ffecom_expr (ffebld_left (expr));
10439 {
10440 tree temp_exp;
10441 tree temp_length;
5ff904cd 10442
c7e4ee3a
CB
10443 temp_exp = ffecom_arg_ptr_to_expr (ffebld_left (expr), &temp_length);
10444 if (temp_exp == error_mark_node)
10445 return error_mark_node;
5ff904cd 10446
c7e4ee3a
CB
10447 return ffecom_1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (temp_exp)),
10448 temp_exp);
10449 }
5ff904cd 10450
c7e4ee3a
CB
10451 case FFEBLD_opPERCENT_REF:
10452 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10453 return ffecom_ptr_to_expr (ffebld_left (expr));
10454 if (length != NULL)
10455 {
10456 ign_length = NULL_TREE;
10457 length = &ign_length;
10458 }
10459 expr = ffebld_left (expr);
10460 break;
5ff904cd 10461
c7e4ee3a
CB
10462 case FFEBLD_opPERCENT_DESCR:
10463 switch (ffeinfo_basictype (ffebld_info (expr)))
5ff904cd 10464 {
c7e4ee3a
CB
10465#ifdef PASS_HOLLERITH_BY_DESCRIPTOR
10466 case FFEINFO_basictypeHOLLERITH:
10467#endif
10468 case FFEINFO_basictypeCHARACTER:
10469 break; /* Passed by descriptor anyway. */
10470
10471 default:
10472 item = ffecom_ptr_to_expr (expr);
10473 if (item != error_mark_node)
10474 *length = TYPE_SIZE (TREE_TYPE (TREE_TYPE (item)));
5ff904cd
JL
10475 break;
10476 }
5ff904cd
JL
10477 break;
10478
10479 default:
5ff904cd
JL
10480 break;
10481 }
10482
c7e4ee3a
CB
10483#ifdef PASS_HOLLERITH_BY_DESCRIPTOR
10484 if ((ffeinfo_basictype (ffebld_info (expr)) == FFEINFO_basictypeHOLLERITH)
10485 && (length != NULL))
10486 { /* Pass Hollerith by descriptor. */
10487 ffetargetHollerith h;
10488
10489 assert (ffebld_op (expr) == FFEBLD_opCONTER);
10490 h = ffebld_cu_val_hollerith (ffebld_constant_union
10491 (ffebld_conter (expr)));
10492 *length
10493 = build_int_2 (h.length, 0);
10494 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
10495 }
10496#endif
10497
10498 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10499 return ffecom_ptr_to_expr (expr);
10500
10501 assert (ffeinfo_kindtype (ffebld_info (expr))
10502 == FFEINFO_kindtypeCHARACTER1);
10503
47d98fa2
CB
10504 while (ffebld_op (expr) == FFEBLD_opPAREN)
10505 expr = ffebld_left (expr);
10506
c7e4ee3a
CB
10507 catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
10508 switch (ffecom_concat_list_count_ (catlist))
10509 {
10510 case 0: /* Shouldn't happen, but in case it does... */
10511 if (length != NULL)
10512 {
10513 *length = ffecom_f2c_ftnlen_zero_node;
10514 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
10515 }
10516 ffecom_concat_list_kill_ (catlist);
10517 return null_pointer_node;
10518
10519 case 1: /* The (fairly) easy case. */
10520 if (length == NULL)
10521 ffecom_char_args_with_null_ (&item, &ign_length,
10522 ffecom_concat_list_expr_ (catlist, 0));
10523 else
10524 ffecom_char_args_ (&item, length,
10525 ffecom_concat_list_expr_ (catlist, 0));
10526 ffecom_concat_list_kill_ (catlist);
10527 assert (item != NULL_TREE);
10528 return item;
10529
10530 default: /* Must actually concatenate things. */
10531 break;
10532 }
10533
10534 {
10535 int count = ffecom_concat_list_count_ (catlist);
10536 int i;
10537 tree lengths;
10538 tree items;
10539 tree length_array;
10540 tree item_array;
10541 tree citem;
10542 tree clength;
10543 tree temporary;
10544 tree num;
10545 tree known_length;
10546 ffetargetCharacterSize sz;
10547
10548 sz = ffecom_concat_list_maxlen_ (catlist);
10549 /* ~~Kludge! */
10550 assert (sz != FFETARGET_charactersizeNONE);
10551
10552#ifdef HOHO
10553 length_array
10554 = lengths
10555 = ffecom_push_tempvar (ffecom_f2c_ftnlen_type_node,
10556 FFETARGET_charactersizeNONE, count, TRUE);
10557 item_array
10558 = items
10559 = ffecom_push_tempvar (ffecom_f2c_address_type_node,
10560 FFETARGET_charactersizeNONE, count, TRUE);
10561 temporary = ffecom_push_tempvar (char_type_node,
10562 sz, -1, TRUE);
10563#else
10564 {
10565 tree hook;
10566
10567 hook = ffebld_nonter_hook (expr);
10568 assert (hook);
10569 assert (TREE_CODE (hook) == TREE_VEC);
10570 assert (TREE_VEC_LENGTH (hook) == 3);
10571 length_array = lengths = TREE_VEC_ELT (hook, 0);
10572 item_array = items = TREE_VEC_ELT (hook, 1);
10573 temporary = TREE_VEC_ELT (hook, 2);
10574 }
10575#endif
10576
10577 known_length = ffecom_f2c_ftnlen_zero_node;
10578
10579 for (i = 0; i < count; ++i)
10580 {
10581 if ((i == count)
10582 && (length == NULL))
10583 ffecom_char_args_with_null_ (&citem, &clength,
10584 ffecom_concat_list_expr_ (catlist, i));
10585 else
10586 ffecom_char_args_ (&citem, &clength,
10587 ffecom_concat_list_expr_ (catlist, i));
10588 if ((citem == error_mark_node)
10589 || (clength == error_mark_node))
10590 {
10591 ffecom_concat_list_kill_ (catlist);
10592 *length = error_mark_node;
10593 return error_mark_node;
10594 }
10595
10596 items
10597 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
10598 ffecom_modify (void_type_node,
10599 ffecom_2 (ARRAY_REF,
10600 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
10601 item_array,
10602 build_int_2 (i, 0)),
10603 citem),
10604 items);
10605 clength = ffecom_save_tree (clength);
10606 if (length != NULL)
10607 known_length
10608 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
10609 known_length,
10610 clength);
10611 lengths
10612 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
10613 ffecom_modify (void_type_node,
10614 ffecom_2 (ARRAY_REF,
10615 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
10616 length_array,
10617 build_int_2 (i, 0)),
10618 clength),
10619 lengths);
10620 }
10621
10622 temporary = ffecom_1 (ADDR_EXPR,
10623 build_pointer_type (TREE_TYPE (temporary)),
10624 temporary);
10625
10626 item = build_tree_list (NULL_TREE, temporary);
10627 TREE_CHAIN (item)
10628 = build_tree_list (NULL_TREE,
10629 ffecom_1 (ADDR_EXPR,
10630 build_pointer_type (TREE_TYPE (items)),
10631 items));
10632 TREE_CHAIN (TREE_CHAIN (item))
10633 = build_tree_list (NULL_TREE,
10634 ffecom_1 (ADDR_EXPR,
10635 build_pointer_type (TREE_TYPE (lengths)),
10636 lengths));
10637 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
10638 = build_tree_list
10639 (NULL_TREE,
10640 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
10641 convert (ffecom_f2c_ftnlen_type_node,
10642 build_int_2 (count, 0))));
10643 num = build_int_2 (sz, 0);
10644 TREE_TYPE (num) = ffecom_f2c_ftnlen_type_node;
10645 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item))))
10646 = build_tree_list (NULL_TREE, num);
10647
10648 item = ffecom_call_gfrt (FFECOM_gfrtCAT, item, NULL_TREE);
5ff904cd 10649 TREE_SIDE_EFFECTS (item) = 1;
c7e4ee3a
CB
10650 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (temporary),
10651 item,
10652 temporary);
10653
10654 if (length != NULL)
10655 *length = known_length;
10656 }
10657
10658 ffecom_concat_list_kill_ (catlist);
10659 assert (item != NULL_TREE);
10660 return item;
5ff904cd 10661}
c7e4ee3a 10662
5ff904cd 10663#endif
c7e4ee3a 10664/* Generate call to run-time function.
5ff904cd 10665
c7e4ee3a
CB
10666 The first arg is the GNU Fortran Run-Time function index, the second
10667 arg is the list of arguments to pass to it. Returned is the expression
10668 (WITHOUT TREE_SIDE_EFFECTS set!) that makes the call and returns the
10669 result (which may be void). */
5ff904cd
JL
10670
10671#if FFECOM_targetCURRENT == FFECOM_targetGCC
10672tree
c7e4ee3a 10673ffecom_call_gfrt (ffecomGfrt ix, tree args, tree hook)
5ff904cd 10674{
c7e4ee3a
CB
10675 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
10676 ffecom_gfrt_kindtype (ix),
10677 ffe_is_f2c_library () && ffecom_gfrt_complex_[ix],
10678 NULL_TREE, args, NULL_TREE, NULL,
10679 NULL, NULL_TREE, TRUE, hook);
5ff904cd
JL
10680}
10681#endif
10682
c7e4ee3a 10683/* Transform constant-union to tree. */
5ff904cd
JL
10684
10685#if FFECOM_targetCURRENT == FFECOM_targetGCC
10686tree
c7e4ee3a
CB
10687ffecom_constantunion (ffebldConstantUnion *cu, ffeinfoBasictype bt,
10688 ffeinfoKindtype kt, tree tree_type)
5ff904cd
JL
10689{
10690 tree item;
10691
c7e4ee3a 10692 switch (bt)
5ff904cd 10693 {
c7e4ee3a
CB
10694 case FFEINFO_basictypeINTEGER:
10695 {
10696 int val;
5ff904cd 10697
c7e4ee3a
CB
10698 switch (kt)
10699 {
10700#if FFETARGET_okINTEGER1
10701 case FFEINFO_kindtypeINTEGER1:
10702 val = ffebld_cu_val_integer1 (*cu);
10703 break;
10704#endif
5ff904cd 10705
c7e4ee3a
CB
10706#if FFETARGET_okINTEGER2
10707 case FFEINFO_kindtypeINTEGER2:
10708 val = ffebld_cu_val_integer2 (*cu);
10709 break;
10710#endif
5ff904cd 10711
c7e4ee3a
CB
10712#if FFETARGET_okINTEGER3
10713 case FFEINFO_kindtypeINTEGER3:
10714 val = ffebld_cu_val_integer3 (*cu);
10715 break;
10716#endif
5ff904cd 10717
c7e4ee3a
CB
10718#if FFETARGET_okINTEGER4
10719 case FFEINFO_kindtypeINTEGER4:
10720 val = ffebld_cu_val_integer4 (*cu);
10721 break;
10722#endif
5ff904cd 10723
c7e4ee3a
CB
10724 default:
10725 assert ("bad INTEGER constant kind type" == NULL);
10726 /* Fall through. */
10727 case FFEINFO_kindtypeANY:
10728 return error_mark_node;
10729 }
10730 item = build_int_2 (val, (val < 0) ? -1 : 0);
10731 TREE_TYPE (item) = tree_type;
10732 }
5ff904cd 10733 break;
5ff904cd 10734
c7e4ee3a
CB
10735 case FFEINFO_basictypeLOGICAL:
10736 {
10737 int val;
5ff904cd 10738
c7e4ee3a
CB
10739 switch (kt)
10740 {
10741#if FFETARGET_okLOGICAL1
10742 case FFEINFO_kindtypeLOGICAL1:
10743 val = ffebld_cu_val_logical1 (*cu);
10744 break;
5ff904cd 10745#endif
5ff904cd 10746
c7e4ee3a
CB
10747#if FFETARGET_okLOGICAL2
10748 case FFEINFO_kindtypeLOGICAL2:
10749 val = ffebld_cu_val_logical2 (*cu);
10750 break;
10751#endif
5ff904cd 10752
c7e4ee3a
CB
10753#if FFETARGET_okLOGICAL3
10754 case FFEINFO_kindtypeLOGICAL3:
10755 val = ffebld_cu_val_logical3 (*cu);
10756 break;
10757#endif
5ff904cd 10758
c7e4ee3a
CB
10759#if FFETARGET_okLOGICAL4
10760 case FFEINFO_kindtypeLOGICAL4:
10761 val = ffebld_cu_val_logical4 (*cu);
10762 break;
10763#endif
5ff904cd 10764
c7e4ee3a
CB
10765 default:
10766 assert ("bad LOGICAL constant kind type" == NULL);
10767 /* Fall through. */
10768 case FFEINFO_kindtypeANY:
10769 return error_mark_node;
10770 }
10771 item = build_int_2 (val, (val < 0) ? -1 : 0);
10772 TREE_TYPE (item) = tree_type;
10773 }
10774 break;
5ff904cd 10775
c7e4ee3a
CB
10776 case FFEINFO_basictypeREAL:
10777 {
10778 REAL_VALUE_TYPE val;
5ff904cd 10779
c7e4ee3a
CB
10780 switch (kt)
10781 {
10782#if FFETARGET_okREAL1
10783 case FFEINFO_kindtypeREAL1:
10784 val = ffetarget_value_real1 (ffebld_cu_val_real1 (*cu));
10785 break;
10786#endif
5ff904cd 10787
c7e4ee3a
CB
10788#if FFETARGET_okREAL2
10789 case FFEINFO_kindtypeREAL2:
10790 val = ffetarget_value_real2 (ffebld_cu_val_real2 (*cu));
10791 break;
10792#endif
5ff904cd 10793
c7e4ee3a
CB
10794#if FFETARGET_okREAL3
10795 case FFEINFO_kindtypeREAL3:
10796 val = ffetarget_value_real3 (ffebld_cu_val_real3 (*cu));
10797 break;
10798#endif
5ff904cd 10799
c7e4ee3a
CB
10800#if FFETARGET_okREAL4
10801 case FFEINFO_kindtypeREAL4:
10802 val = ffetarget_value_real4 (ffebld_cu_val_real4 (*cu));
10803 break;
10804#endif
5ff904cd 10805
c7e4ee3a
CB
10806 default:
10807 assert ("bad REAL constant kind type" == NULL);
10808 /* Fall through. */
10809 case FFEINFO_kindtypeANY:
10810 return error_mark_node;
10811 }
10812 item = build_real (tree_type, val);
10813 }
5ff904cd
JL
10814 break;
10815
c7e4ee3a
CB
10816 case FFEINFO_basictypeCOMPLEX:
10817 {
10818 REAL_VALUE_TYPE real;
10819 REAL_VALUE_TYPE imag;
10820 tree el_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
5ff904cd 10821
c7e4ee3a
CB
10822 switch (kt)
10823 {
10824#if FFETARGET_okCOMPLEX1
10825 case FFEINFO_kindtypeREAL1:
10826 real = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).real);
10827 imag = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).imaginary);
10828 break;
10829#endif
5ff904cd 10830
c7e4ee3a
CB
10831#if FFETARGET_okCOMPLEX2
10832 case FFEINFO_kindtypeREAL2:
10833 real = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).real);
10834 imag = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).imaginary);
10835 break;
10836#endif
5ff904cd 10837
c7e4ee3a
CB
10838#if FFETARGET_okCOMPLEX3
10839 case FFEINFO_kindtypeREAL3:
10840 real = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).real);
10841 imag = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).imaginary);
10842 break;
10843#endif
5ff904cd 10844
c7e4ee3a
CB
10845#if FFETARGET_okCOMPLEX4
10846 case FFEINFO_kindtypeREAL4:
10847 real = ffetarget_value_real4 (ffebld_cu_val_complex4 (*cu).real);
10848 imag = ffetarget_value_real4 (ffebld_cu_val_complex4 (*cu).imaginary);
10849 break;
10850#endif
5ff904cd 10851
c7e4ee3a
CB
10852 default:
10853 assert ("bad REAL constant kind type" == NULL);
10854 /* Fall through. */
10855 case FFEINFO_kindtypeANY:
10856 return error_mark_node;
10857 }
10858 item = ffecom_build_complex_constant_ (tree_type,
10859 build_real (el_type, real),
10860 build_real (el_type, imag));
10861 }
10862 break;
5ff904cd 10863
c7e4ee3a
CB
10864 case FFEINFO_basictypeCHARACTER:
10865 { /* Happens only in DATA and similar contexts. */
10866 ffetargetCharacter1 val;
5ff904cd 10867
c7e4ee3a
CB
10868 switch (kt)
10869 {
10870#if FFETARGET_okCHARACTER1
10871 case FFEINFO_kindtypeLOGICAL1:
10872 val = ffebld_cu_val_character1 (*cu);
10873 break;
10874#endif
10875
10876 default:
10877 assert ("bad CHARACTER constant kind type" == NULL);
10878 /* Fall through. */
10879 case FFEINFO_kindtypeANY:
10880 return error_mark_node;
10881 }
10882 item = build_string (ffetarget_length_character1 (val),
10883 ffetarget_text_character1 (val));
10884 TREE_TYPE (item)
10885 = build_type_variant (build_array_type (char_type_node,
10886 build_range_type
10887 (integer_type_node,
10888 integer_one_node,
10889 build_int_2
10890 (ffetarget_length_character1
10891 (val), 0))),
10892 1, 0);
10893 }
10894 break;
5ff904cd 10895
c7e4ee3a
CB
10896 case FFEINFO_basictypeHOLLERITH:
10897 {
10898 ffetargetHollerith h;
5ff904cd 10899
c7e4ee3a 10900 h = ffebld_cu_val_hollerith (*cu);
5ff904cd 10901
c7e4ee3a
CB
10902 /* If not at least as wide as default INTEGER, widen it. */
10903 if (h.length >= FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE)
10904 item = build_string (h.length, h.text);
10905 else
10906 {
10907 char str[FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE];
5ff904cd 10908
c7e4ee3a
CB
10909 memcpy (str, h.text, h.length);
10910 memset (&str[h.length], ' ',
10911 FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE
10912 - h.length);
10913 item = build_string (FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE,
10914 str);
10915 }
10916 TREE_TYPE (item)
10917 = build_type_variant (build_array_type (char_type_node,
10918 build_range_type
10919 (integer_type_node,
10920 integer_one_node,
10921 build_int_2
10922 (h.length, 0))),
10923 1, 0);
10924 }
10925 break;
5ff904cd 10926
c7e4ee3a
CB
10927 case FFEINFO_basictypeTYPELESS:
10928 {
10929 ffetargetInteger1 ival;
10930 ffetargetTypeless tless;
10931 ffebad error;
5ff904cd 10932
c7e4ee3a
CB
10933 tless = ffebld_cu_val_typeless (*cu);
10934 error = ffetarget_convert_integer1_typeless (&ival, tless);
10935 assert (error == FFEBAD);
5ff904cd 10936
c7e4ee3a
CB
10937 item = build_int_2 ((int) ival, 0);
10938 }
10939 break;
5ff904cd 10940
c7e4ee3a
CB
10941 default:
10942 assert ("not yet on constant type" == NULL);
10943 /* Fall through. */
10944 case FFEINFO_basictypeANY:
10945 return error_mark_node;
5ff904cd 10946 }
5ff904cd 10947
c7e4ee3a 10948 TREE_CONSTANT (item) = 1;
5ff904cd 10949
c7e4ee3a 10950 return item;
5ff904cd
JL
10951}
10952
10953#endif
10954
c7e4ee3a
CB
10955/* Transform expression into constant tree.
10956
10957 If the expression can be transformed into a tree that is constant,
10958 that is done, and the tree returned. Else NULL_TREE is returned.
10959
10960 That way, a caller can attempt to provide compile-time initialization
10961 of a variable and, if that fails, *then* choose to start a new block
10962 and resort to using temporaries, as appropriate. */
5ff904cd 10963
5ff904cd 10964tree
c7e4ee3a 10965ffecom_const_expr (ffebld expr)
5ff904cd 10966{
c7e4ee3a
CB
10967 if (! expr)
10968 return integer_zero_node;
5ff904cd 10969
c7e4ee3a 10970 if (ffebld_op (expr) == FFEBLD_opANY)
5ff904cd
JL
10971 return error_mark_node;
10972
c7e4ee3a
CB
10973 if (ffebld_arity (expr) == 0
10974 && (ffebld_op (expr) != FFEBLD_opSYMTER
10975#if NEWCOMMON
10976 /* ~~Enable once common/equivalence is handled properly? */
10977 || ffebld_where (expr) == FFEINFO_whereCOMMON
5ff904cd 10978#endif
c7e4ee3a
CB
10979 || ffebld_where (expr) == FFEINFO_whereGLOBAL
10980 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
10981 {
10982 tree t;
5ff904cd 10983
c7e4ee3a
CB
10984 t = ffecom_expr (expr);
10985 assert (TREE_CONSTANT (t));
10986 return t;
10987 }
5ff904cd 10988
c7e4ee3a 10989 return NULL_TREE;
5ff904cd
JL
10990}
10991
c7e4ee3a 10992/* Handy way to make a field in a struct/union. */
5ff904cd
JL
10993
10994#if FFECOM_targetCURRENT == FFECOM_targetGCC
10995tree
c7e4ee3a
CB
10996ffecom_decl_field (tree context, tree prevfield,
10997 const char *name, tree type)
5ff904cd 10998{
c7e4ee3a 10999 tree field;
5ff904cd 11000
c7e4ee3a
CB
11001 field = build_decl (FIELD_DECL, get_identifier (name), type);
11002 DECL_CONTEXT (field) = context;
8ba77681 11003 DECL_ALIGN (field) = 0;
11cf4d18 11004 DECL_USER_ALIGN (field) = 0;
c7e4ee3a
CB
11005 if (prevfield != NULL_TREE)
11006 TREE_CHAIN (prevfield) = field;
5ff904cd 11007
c7e4ee3a 11008 return field;
5ff904cd
JL
11009}
11010
11011#endif
5ff904cd 11012
c7e4ee3a
CB
11013void
11014ffecom_close_include (FILE *f)
11015{
11016#if FFECOM_GCC_INCLUDE
11017 ffecom_close_include_ (f);
11018#endif
11019}
5ff904cd 11020
c7e4ee3a
CB
11021int
11022ffecom_decode_include_option (char *spec)
11023{
11024#if FFECOM_GCC_INCLUDE
11025 return ffecom_decode_include_option_ (spec);
11026#else
11027 return 1;
11028#endif
11029}
5ff904cd 11030
c7e4ee3a 11031/* End a compound statement (block). */
5ff904cd
JL
11032
11033#if FFECOM_targetCURRENT == FFECOM_targetGCC
11034tree
c7e4ee3a 11035ffecom_end_compstmt (void)
5ff904cd 11036{
c7e4ee3a
CB
11037 return bison_rule_compstmt_ ();
11038}
11039#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
5ff904cd 11040
c7e4ee3a 11041/* ffecom_end_transition -- Perform end transition on all symbols
5ff904cd 11042
c7e4ee3a 11043 ffecom_end_transition();
5ff904cd 11044
c7e4ee3a 11045 Calls ffecom_sym_end_transition for each global and local symbol. */
5ff904cd 11046
c7e4ee3a
CB
11047void
11048ffecom_end_transition ()
11049{
11050#if FFECOM_targetCURRENT == FFECOM_targetGCC
11051 ffebld item;
5ff904cd 11052#endif
5ff904cd 11053
c7e4ee3a
CB
11054 if (ffe_is_ffedebug ())
11055 fprintf (dmpout, "; end_stmt_transition\n");
86fc7a6c 11056
c7e4ee3a
CB
11057#if FFECOM_targetCURRENT == FFECOM_targetGCC
11058 ffecom_list_blockdata_ = NULL;
11059 ffecom_list_common_ = NULL;
11060#endif
86fc7a6c 11061
c7e4ee3a
CB
11062 ffesymbol_drive (ffecom_sym_end_transition);
11063 if (ffe_is_ffedebug ())
11064 {
11065 ffestorag_report ();
11066#if FFECOM_targetCURRENT == FFECOM_targetFFE
11067 ffesymbol_report_all ();
11068#endif
11069 }
5ff904cd
JL
11070
11071#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
11072 ffecom_start_progunit_ ();
11073
11074 for (item = ffecom_list_blockdata_;
11075 item != NULL;
11076 item = ffebld_trail (item))
11077 {
11078 ffebld callee;
11079 ffesymbol s;
11080 tree dt;
11081 tree t;
11082 tree var;
11083 int yes;
11084 static int number = 0;
11085
11086 callee = ffebld_head (item);
11087 s = ffebld_symter (callee);
11088 t = ffesymbol_hook (s).decl_tree;
11089 if (t == NULL_TREE)
11090 {
11091 s = ffecom_sym_transform_ (s);
11092 t = ffesymbol_hook (s).decl_tree;
11093 }
5ff904cd 11094
c7e4ee3a 11095 yes = suspend_momentary ();
5ff904cd 11096
c7e4ee3a 11097 dt = build_pointer_type (TREE_TYPE (t));
5ff904cd 11098
c7e4ee3a
CB
11099 var = build_decl (VAR_DECL,
11100 ffecom_get_invented_identifier ("__g77_forceload_%d",
14657de8 11101 number++),
c7e4ee3a
CB
11102 dt);
11103 DECL_EXTERNAL (var) = 0;
11104 TREE_STATIC (var) = 1;
11105 TREE_PUBLIC (var) = 0;
11106 DECL_INITIAL (var) = error_mark_node;
11107 TREE_USED (var) = 1;
5ff904cd 11108
c7e4ee3a 11109 var = start_decl (var, FALSE);
702edf1d 11110
c7e4ee3a 11111 t = ffecom_1 (ADDR_EXPR, dt, t);
5ff904cd 11112
c7e4ee3a 11113 finish_decl (var, t, FALSE);
5ff904cd 11114
c7e4ee3a
CB
11115 resume_momentary (yes);
11116 }
11117
11118 /* This handles any COMMON areas that weren't referenced but have, for
11119 example, important initial data. */
11120
11121 for (item = ffecom_list_common_;
11122 item != NULL;
11123 item = ffebld_trail (item))
11124 ffecom_transform_common_ (ffebld_symter (ffebld_head (item)));
11125
11126 ffecom_list_common_ = NULL;
5ff904cd 11127#endif
c7e4ee3a 11128}
5ff904cd 11129
c7e4ee3a 11130/* ffecom_exec_transition -- Perform exec transition on all symbols
5ff904cd 11131
c7e4ee3a 11132 ffecom_exec_transition();
5ff904cd 11133
c7e4ee3a
CB
11134 Calls ffecom_sym_exec_transition for each global and local symbol.
11135 Make sure error updating not inhibited. */
5ff904cd 11136
c7e4ee3a
CB
11137void
11138ffecom_exec_transition ()
11139{
11140 bool inhibited;
5ff904cd 11141
c7e4ee3a
CB
11142 if (ffe_is_ffedebug ())
11143 fprintf (dmpout, "; exec_stmt_transition\n");
5ff904cd 11144
c7e4ee3a
CB
11145 inhibited = ffebad_inhibit ();
11146 ffebad_set_inhibit (FALSE);
5ff904cd 11147
c7e4ee3a
CB
11148 ffesymbol_drive (ffecom_sym_exec_transition); /* Don't retract! */
11149 ffeequiv_exec_transition (); /* Handle all pending EQUIVALENCEs. */
11150 if (ffe_is_ffedebug ())
5ff904cd 11151 {
c7e4ee3a
CB
11152 ffestorag_report ();
11153#if FFECOM_targetCURRENT == FFECOM_targetFFE
11154 ffesymbol_report_all ();
11155#endif
11156 }
5ff904cd 11157
c7e4ee3a
CB
11158 if (inhibited)
11159 ffebad_set_inhibit (TRUE);
11160}
5ff904cd 11161
c7e4ee3a 11162/* Handle assignment statement.
5ff904cd 11163
c7e4ee3a
CB
11164 Convert dest and source using ffecom_expr, then join them
11165 with an ASSIGN op and pass the whole thing to expand_expr_stmt. */
5ff904cd 11166
c7e4ee3a
CB
11167#if FFECOM_targetCURRENT == FFECOM_targetGCC
11168void
11169ffecom_expand_let_stmt (ffebld dest, ffebld source)
11170{
11171 tree dest_tree;
11172 tree dest_length;
11173 tree source_tree;
11174 tree expr_tree;
5ff904cd 11175
c7e4ee3a
CB
11176 if (ffeinfo_basictype (ffebld_info (dest)) != FFEINFO_basictypeCHARACTER)
11177 {
11178 bool dest_used;
d6cd84e0 11179 tree assign_temp;
5ff904cd 11180
c7e4ee3a
CB
11181 /* This attempts to replicate the test below, but must not be
11182 true when the test below is false. (Always err on the side
11183 of creating unused temporaries, to avoid ICEs.) */
11184 if (ffebld_op (dest) != FFEBLD_opSYMTER
11185 || ((dest_tree = ffesymbol_hook (ffebld_symter (dest)).decl_tree)
11186 && (TREE_CODE (dest_tree) != VAR_DECL
11187 || TREE_ADDRESSABLE (dest_tree))))
11188 {
11189 ffecom_prepare_expr_ (source, dest);
11190 dest_used = TRUE;
11191 }
11192 else
11193 {
11194 ffecom_prepare_expr_ (source, NULL);
11195 dest_used = FALSE;
11196 }
5ff904cd 11197
c7e4ee3a 11198 ffecom_prepare_expr_w (NULL_TREE, dest);
5ff904cd 11199
d6cd84e0
CB
11200 /* For COMPLEX assignment like C1=C2, if partial overlap is possible,
11201 create a temporary through which the assignment is to take place,
11202 since MODIFY_EXPR doesn't handle partial overlap properly. */
11203 if (ffebld_basictype (dest) == FFEINFO_basictypeCOMPLEX
11204 && ffecom_possible_partial_overlap_ (dest, source))
11205 {
11206 assign_temp = ffecom_make_tempvar ("complex_let",
11207 ffecom_tree_type
11208 [ffebld_basictype (dest)]
11209 [ffebld_kindtype (dest)],
11210 FFETARGET_charactersizeNONE,
11211 -1);
11212 }
11213 else
11214 assign_temp = NULL_TREE;
11215
c7e4ee3a 11216 ffecom_prepare_end ();
5ff904cd 11217
c7e4ee3a
CB
11218 dest_tree = ffecom_expr_w (NULL_TREE, dest);
11219 if (dest_tree == error_mark_node)
11220 return;
5ff904cd 11221
c7e4ee3a
CB
11222 if ((TREE_CODE (dest_tree) != VAR_DECL)
11223 || TREE_ADDRESSABLE (dest_tree))
11224 source_tree = ffecom_expr_ (source, dest_tree, dest, &dest_used,
11225 FALSE, FALSE);
11226 else
11227 {
11228 assert (! dest_used);
11229 dest_used = FALSE;
11230 source_tree = ffecom_expr (source);
11231 }
11232 if (source_tree == error_mark_node)
11233 return;
5ff904cd 11234
c7e4ee3a
CB
11235 if (dest_used)
11236 expr_tree = source_tree;
d6cd84e0
CB
11237 else if (assign_temp)
11238 {
11239#ifdef MOVE_EXPR
11240 /* The back end understands a conceptual move (evaluate source;
11241 store into dest), so use that, in case it can determine
11242 that it is going to use, say, two registers as temporaries
11243 anyway. So don't use the temp (and someday avoid generating
11244 it, once this code starts triggering regularly). */
11245 expr_tree = ffecom_2s (MOVE_EXPR, void_type_node,
11246 dest_tree,
11247 source_tree);
11248#else
11249 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11250 assign_temp,
11251 source_tree);
11252 expand_expr_stmt (expr_tree);
11253 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11254 dest_tree,
11255 assign_temp);
11256#endif
11257 }
c7e4ee3a
CB
11258 else
11259 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11260 dest_tree,
11261 source_tree);
5ff904cd 11262
c7e4ee3a
CB
11263 expand_expr_stmt (expr_tree);
11264 return;
11265 }
5ff904cd 11266
c7e4ee3a
CB
11267 ffecom_prepare_let_char_ (ffebld_size_known (dest), source);
11268 ffecom_prepare_expr_w (NULL_TREE, dest);
11269
11270 ffecom_prepare_end ();
11271
11272 ffecom_char_args_ (&dest_tree, &dest_length, dest);
11273 ffecom_let_char_ (dest_tree, dest_length, ffebld_size_known (dest),
11274 source);
5ff904cd
JL
11275}
11276
11277#endif
c7e4ee3a 11278/* ffecom_expr -- Transform expr into gcc tree
5ff904cd 11279
c7e4ee3a
CB
11280 tree t;
11281 ffebld expr; // FFE expression.
11282 tree = ffecom_expr(expr);
5ff904cd 11283
c7e4ee3a
CB
11284 Recursive descent on expr while making corresponding tree nodes and
11285 attaching type info and such. */
5ff904cd
JL
11286
11287#if FFECOM_targetCURRENT == FFECOM_targetGCC
11288tree
c7e4ee3a 11289ffecom_expr (ffebld expr)
5ff904cd 11290{
c7e4ee3a 11291 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, FALSE, FALSE);
5ff904cd 11292}
c7e4ee3a 11293
5ff904cd 11294#endif
c7e4ee3a 11295/* Like ffecom_expr, but return tree usable for assigned GOTO or FORMAT. */
5ff904cd 11296
c7e4ee3a
CB
11297#if FFECOM_targetCURRENT == FFECOM_targetGCC
11298tree
11299ffecom_expr_assign (ffebld expr)
11300{
11301 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE);
11302}
5ff904cd 11303
c7e4ee3a
CB
11304#endif
11305/* Like ffecom_expr_rw, but return tree usable for ASSIGN. */
5ff904cd
JL
11306
11307#if FFECOM_targetCURRENT == FFECOM_targetGCC
11308tree
c7e4ee3a 11309ffecom_expr_assign_w (ffebld expr)
5ff904cd 11310{
c7e4ee3a
CB
11311 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE);
11312}
5ff904cd 11313
5ff904cd 11314#endif
c7e4ee3a
CB
11315/* Transform expr for use as into read/write tree and stabilize the
11316 reference. Not for use on CHARACTER expressions.
5ff904cd 11317
c7e4ee3a
CB
11318 Recursive descent on expr while making corresponding tree nodes and
11319 attaching type info and such. */
5ff904cd 11320
c7e4ee3a
CB
11321#if FFECOM_targetCURRENT == FFECOM_targetGCC
11322tree
11323ffecom_expr_rw (tree type, ffebld expr)
11324{
11325 assert (expr != NULL);
11326 /* Different target types not yet supported. */
11327 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
11328
11329 return stabilize_reference (ffecom_expr (expr));
11330}
5ff904cd 11331
5ff904cd 11332#endif
c7e4ee3a
CB
11333/* Transform expr for use as into write tree and stabilize the
11334 reference. Not for use on CHARACTER expressions.
5ff904cd 11335
c7e4ee3a
CB
11336 Recursive descent on expr while making corresponding tree nodes and
11337 attaching type info and such. */
5ff904cd 11338
c7e4ee3a
CB
11339#if FFECOM_targetCURRENT == FFECOM_targetGCC
11340tree
11341ffecom_expr_w (tree type, ffebld expr)
11342{
11343 assert (expr != NULL);
11344 /* Different target types not yet supported. */
11345 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
11346
11347 return stabilize_reference (ffecom_expr (expr));
11348}
5ff904cd 11349
5ff904cd 11350#endif
c7e4ee3a
CB
11351/* Do global stuff. */
11352
11353#if FFECOM_targetCURRENT == FFECOM_targetGCC
11354void
11355ffecom_finish_compile ()
11356{
11357 assert (ffecom_outer_function_decl_ == NULL_TREE);
11358 assert (current_function_decl == NULL_TREE);
11359
11360 ffeglobal_drive (ffecom_finish_global_);
11361}
5ff904cd 11362
5ff904cd 11363#endif
c7e4ee3a
CB
11364/* Public entry point for front end to access finish_decl. */
11365
11366#if FFECOM_targetCURRENT == FFECOM_targetGCC
11367void
11368ffecom_finish_decl (tree decl, tree init, bool is_top_level)
11369{
11370 assert (!is_top_level);
11371 finish_decl (decl, init, FALSE);
11372}
5ff904cd 11373
5ff904cd 11374#endif
c7e4ee3a
CB
11375/* Finish a program unit. */
11376
11377#if FFECOM_targetCURRENT == FFECOM_targetGCC
11378void
11379ffecom_finish_progunit ()
11380{
11381 ffecom_end_compstmt ();
11382
11383 ffecom_previous_function_decl_ = current_function_decl;
11384 ffecom_which_entrypoint_decl_ = NULL_TREE;
11385
11386 finish_function (0);
11387}
5ff904cd 11388
5ff904cd 11389#endif
14657de8
KG
11390
11391/* Wrapper for get_identifier. pattern is sprintf-like. */
c7e4ee3a
CB
11392
11393#if FFECOM_targetCURRENT == FFECOM_targetGCC
11394tree
14657de8 11395ffecom_get_invented_identifier (const char *pattern, ...)
c7e4ee3a
CB
11396{
11397 tree decl;
11398 char *nam;
14657de8 11399 va_list ap;
c7e4ee3a 11400
14657de8
KG
11401 va_start (ap, pattern);
11402 if (vasprintf (&nam, pattern, ap) == 0)
11403 abort ();
11404 va_end (ap);
c7e4ee3a 11405 decl = get_identifier (nam);
14657de8 11406 free (nam);
c7e4ee3a 11407 IDENTIFIER_INVENTED (decl) = 1;
c7e4ee3a
CB
11408 return decl;
11409}
11410
11411ffeinfoBasictype
11412ffecom_gfrt_basictype (ffecomGfrt gfrt)
11413{
11414 assert (gfrt < FFECOM_gfrt);
11415
11416 switch (ffecom_gfrt_type_[gfrt])
11417 {
11418 case FFECOM_rttypeVOID_:
11419 case FFECOM_rttypeVOIDSTAR_:
11420 return FFEINFO_basictypeNONE;
11421
11422 case FFECOM_rttypeFTNINT_:
11423 return FFEINFO_basictypeINTEGER;
11424
11425 case FFECOM_rttypeINTEGER_:
11426 return FFEINFO_basictypeINTEGER;
11427
11428 case FFECOM_rttypeLONGINT_:
11429 return FFEINFO_basictypeINTEGER;
11430
11431 case FFECOM_rttypeLOGICAL_:
11432 return FFEINFO_basictypeLOGICAL;
11433
11434 case FFECOM_rttypeREAL_F2C_:
11435 case FFECOM_rttypeREAL_GNU_:
11436 return FFEINFO_basictypeREAL;
11437
11438 case FFECOM_rttypeCOMPLEX_F2C_:
11439 case FFECOM_rttypeCOMPLEX_GNU_:
11440 return FFEINFO_basictypeCOMPLEX;
11441
11442 case FFECOM_rttypeDOUBLE_:
11443 case FFECOM_rttypeDOUBLEREAL_:
11444 return FFEINFO_basictypeREAL;
11445
11446 case FFECOM_rttypeDBLCMPLX_F2C_:
11447 case FFECOM_rttypeDBLCMPLX_GNU_:
11448 return FFEINFO_basictypeCOMPLEX;
11449
11450 case FFECOM_rttypeCHARACTER_:
11451 return FFEINFO_basictypeCHARACTER;
11452
11453 default:
11454 return FFEINFO_basictypeANY;
11455 }
11456}
11457
11458ffeinfoKindtype
11459ffecom_gfrt_kindtype (ffecomGfrt gfrt)
11460{
11461 assert (gfrt < FFECOM_gfrt);
11462
11463 switch (ffecom_gfrt_type_[gfrt])
11464 {
11465 case FFECOM_rttypeVOID_:
11466 case FFECOM_rttypeVOIDSTAR_:
11467 return FFEINFO_kindtypeNONE;
5ff904cd 11468
c7e4ee3a
CB
11469 case FFECOM_rttypeFTNINT_:
11470 return FFEINFO_kindtypeINTEGER1;
5ff904cd 11471
c7e4ee3a
CB
11472 case FFECOM_rttypeINTEGER_:
11473 return FFEINFO_kindtypeINTEGER1;
5ff904cd 11474
c7e4ee3a
CB
11475 case FFECOM_rttypeLONGINT_:
11476 return FFEINFO_kindtypeINTEGER4;
5ff904cd 11477
c7e4ee3a
CB
11478 case FFECOM_rttypeLOGICAL_:
11479 return FFEINFO_kindtypeLOGICAL1;
5ff904cd 11480
c7e4ee3a
CB
11481 case FFECOM_rttypeREAL_F2C_:
11482 case FFECOM_rttypeREAL_GNU_:
11483 return FFEINFO_kindtypeREAL1;
5ff904cd 11484
c7e4ee3a
CB
11485 case FFECOM_rttypeCOMPLEX_F2C_:
11486 case FFECOM_rttypeCOMPLEX_GNU_:
11487 return FFEINFO_kindtypeREAL1;
5ff904cd 11488
c7e4ee3a
CB
11489 case FFECOM_rttypeDOUBLE_:
11490 case FFECOM_rttypeDOUBLEREAL_:
11491 return FFEINFO_kindtypeREAL2;
5ff904cd 11492
c7e4ee3a
CB
11493 case FFECOM_rttypeDBLCMPLX_F2C_:
11494 case FFECOM_rttypeDBLCMPLX_GNU_:
11495 return FFEINFO_kindtypeREAL2;
5ff904cd 11496
c7e4ee3a
CB
11497 case FFECOM_rttypeCHARACTER_:
11498 return FFEINFO_kindtypeCHARACTER1;
5ff904cd 11499
c7e4ee3a
CB
11500 default:
11501 return FFEINFO_kindtypeANY;
11502 }
11503}
5ff904cd 11504
c7e4ee3a
CB
11505void
11506ffecom_init_0 ()
11507{
11508 tree endlink;
11509 int i;
11510 int j;
11511 tree t;
11512 tree field;
11513 ffetype type;
11514 ffetype base_type;
7189a4b0
GK
11515 tree double_ftype_double;
11516 tree float_ftype_float;
11517 tree ldouble_ftype_ldouble;
11518 tree ffecom_tree_ptr_to_fun_type_void;
5ff904cd 11519
c7e4ee3a
CB
11520 /* This block of code comes from the now-obsolete cktyps.c. It checks
11521 whether the compiler environment is buggy in known ways, some of which
11522 would, if not explicitly checked here, result in subtle bugs in g77. */
5ff904cd 11523
c7e4ee3a
CB
11524 if (ffe_is_do_internal_checks ())
11525 {
11526 static char names[][12]
11527 =
11528 {"bar", "bletch", "foo", "foobar"};
11529 char *name;
11530 unsigned long ul;
11531 double fl;
5ff904cd 11532
c7e4ee3a 11533 name = bsearch ("foo", &names[0], ARRAY_SIZE (names), sizeof (names[0]),
b0791fa9 11534 (int (*)(const void *, const void *)) strcmp);
c7e4ee3a
CB
11535 if (name != (char *) &names[2])
11536 {
11537 assert ("bsearch doesn't work, #define FFEPROJ_BSEARCH 0 in proj.h"
11538 == NULL);
11539 abort ();
11540 }
5ff904cd 11541
c7e4ee3a
CB
11542 ul = strtoul ("123456789", NULL, 10);
11543 if (ul != 123456789L)
11544 {
11545 assert ("strtoul doesn't have enough range, #define FFEPROJ_STRTOUL 0\
11546 in proj.h" == NULL);
11547 abort ();
11548 }
5ff904cd 11549
c7e4ee3a
CB
11550 fl = atof ("56.789");
11551 if ((fl < 56.788) || (fl > 56.79))
11552 {
11553 assert ("atof not type double, fix your #include <stdio.h>"
11554 == NULL);
11555 abort ();
11556 }
11557 }
5ff904cd 11558
c7e4ee3a
CB
11559#if FFECOM_GCC_INCLUDE
11560 ffecom_initialize_char_syntax_ ();
11561#endif
5ff904cd 11562
c7e4ee3a
CB
11563 ffecom_outer_function_decl_ = NULL_TREE;
11564 current_function_decl = NULL_TREE;
11565 named_labels = NULL_TREE;
11566 current_binding_level = NULL_BINDING_LEVEL;
11567 free_binding_level = NULL_BINDING_LEVEL;
11568 /* Make the binding_level structure for global names. */
11569 pushlevel (0);
11570 global_binding_level = current_binding_level;
11571 current_binding_level->prep_state = 2;
5ff904cd 11572
81b3411c 11573 build_common_tree_nodes (1);
5ff904cd 11574
81b3411c 11575 /* Define `int' and `char' first so that dbx will output them first. */
c7e4ee3a
CB
11576 pushdecl (build_decl (TYPE_DECL, get_identifier ("int"),
11577 integer_type_node));
c7e4ee3a
CB
11578 pushdecl (build_decl (TYPE_DECL, get_identifier ("char"),
11579 char_type_node));
c7e4ee3a
CB
11580 pushdecl (build_decl (TYPE_DECL, get_identifier ("long int"),
11581 long_integer_type_node));
c7e4ee3a
CB
11582 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned int"),
11583 unsigned_type_node));
c7e4ee3a
CB
11584 pushdecl (build_decl (TYPE_DECL, get_identifier ("long unsigned int"),
11585 long_unsigned_type_node));
c7e4ee3a
CB
11586 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long int"),
11587 long_long_integer_type_node));
c7e4ee3a
CB
11588 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long unsigned int"),
11589 long_long_unsigned_type_node));
c7e4ee3a
CB
11590 pushdecl (build_decl (TYPE_DECL, get_identifier ("short int"),
11591 short_integer_type_node));
c7e4ee3a
CB
11592 pushdecl (build_decl (TYPE_DECL, get_identifier ("short unsigned int"),
11593 short_unsigned_type_node));
5ff904cd 11594
ff852b44
CB
11595 /* Set the sizetype before we make other types. This *should* be the
11596 first type we create. */
11597
11598 set_sizetype
11599 (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE))));
11600 ffecom_typesize_pointer_
11601 = TREE_INT_CST_LOW (TYPE_SIZE (sizetype)) / BITS_PER_UNIT;
11602
81b3411c 11603 build_common_tree_nodes_2 (0);
ff852b44 11604
c7e4ee3a 11605 /* Define both `signed char' and `unsigned char'. */
c7e4ee3a
CB
11606 pushdecl (build_decl (TYPE_DECL, get_identifier ("signed char"),
11607 signed_char_type_node));
5ff904cd 11608
c7e4ee3a
CB
11609 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned char"),
11610 unsigned_char_type_node));
5ff904cd 11611
c7e4ee3a
CB
11612 pushdecl (build_decl (TYPE_DECL, get_identifier ("float"),
11613 float_type_node));
c7e4ee3a
CB
11614 pushdecl (build_decl (TYPE_DECL, get_identifier ("double"),
11615 double_type_node));
c7e4ee3a
CB
11616 pushdecl (build_decl (TYPE_DECL, get_identifier ("long double"),
11617 long_double_type_node));
5ff904cd 11618
81b3411c 11619 /* For now, override what build_common_tree_nodes has done. */
c7e4ee3a 11620 complex_integer_type_node = ffecom_make_complex_type_ (integer_type_node);
81b3411c
BS
11621 complex_float_type_node = ffecom_make_complex_type_ (float_type_node);
11622 complex_double_type_node = ffecom_make_complex_type_ (double_type_node);
11623 complex_long_double_type_node
11624 = ffecom_make_complex_type_ (long_double_type_node);
11625
c7e4ee3a
CB
11626 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex int"),
11627 complex_integer_type_node));
c7e4ee3a
CB
11628 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex float"),
11629 complex_float_type_node));
c7e4ee3a
CB
11630 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex double"),
11631 complex_double_type_node));
c7e4ee3a
CB
11632 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex long double"),
11633 complex_long_double_type_node));
5ff904cd 11634
c7e4ee3a
CB
11635 pushdecl (build_decl (TYPE_DECL, get_identifier ("void"),
11636 void_type_node));
c7e4ee3a
CB
11637 /* We are not going to have real types in C with less than byte alignment,
11638 so we might as well not have any types that claim to have it. */
11639 TYPE_ALIGN (void_type_node) = BITS_PER_UNIT;
11cf4d18 11640 TYPE_USER_ALIGN (void_type_node) = 0;
5ff904cd 11641
c7e4ee3a 11642 string_type_node = build_pointer_type (char_type_node);
5ff904cd 11643
c7e4ee3a
CB
11644 ffecom_tree_fun_type_void
11645 = build_function_type (void_type_node, NULL_TREE);
5ff904cd 11646
c7e4ee3a
CB
11647 ffecom_tree_ptr_to_fun_type_void
11648 = build_pointer_type (ffecom_tree_fun_type_void);
5ff904cd 11649
c7e4ee3a 11650 endlink = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
5ff904cd 11651
c7e4ee3a
CB
11652 float_ftype_float
11653 = build_function_type (float_type_node,
11654 tree_cons (NULL_TREE, float_type_node, endlink));
5ff904cd 11655
c7e4ee3a
CB
11656 double_ftype_double
11657 = build_function_type (double_type_node,
11658 tree_cons (NULL_TREE, double_type_node, endlink));
5ff904cd 11659
c7e4ee3a
CB
11660 ldouble_ftype_ldouble
11661 = build_function_type (long_double_type_node,
11662 tree_cons (NULL_TREE, long_double_type_node,
11663 endlink));
5ff904cd 11664
c7e4ee3a
CB
11665 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11666 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11667 {
11668 ffecom_tree_type[i][j] = NULL_TREE;
11669 ffecom_tree_fun_type[i][j] = NULL_TREE;
11670 ffecom_tree_ptr_to_fun_type[i][j] = NULL_TREE;
11671 ffecom_f2c_typecode_[i][j] = -1;
11672 }
5ff904cd 11673
c7e4ee3a
CB
11674 /* Set up standard g77 types. Note that INTEGER and LOGICAL are set
11675 to size FLOAT_TYPE_SIZE because they have to be the same size as
11676 REAL, which also is FLOAT_TYPE_SIZE, according to the standard.
11677 Compiler options and other such stuff that change the ways these
11678 types are set should not affect this particular setup. */
5ff904cd 11679
c7e4ee3a
CB
11680 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1]
11681 = t = make_signed_type (FLOAT_TYPE_SIZE);
11682 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer"),
11683 t));
11684 type = ffetype_new ();
11685 base_type = type;
11686 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER1,
11687 type);
11688 ffetype_set_ams (type,
11689 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11690 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11691 ffetype_set_star (base_type,
11692 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11693 type);
11694 ffetype_set_kind (base_type, 1, type);
ff852b44 11695 ffecom_typesize_integer1_ = ffetype_size (type);
c7e4ee3a 11696 assert (ffetype_size (type) == sizeof (ffetargetInteger1));
5ff904cd 11697
c7e4ee3a
CB
11698 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER1]
11699 = t = make_unsigned_type (FLOAT_TYPE_SIZE); /* HOLLERITH means unsigned. */
11700 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned"),
11701 t));
5ff904cd 11702
c7e4ee3a
CB
11703 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER2]
11704 = t = make_signed_type (CHAR_TYPE_SIZE);
11705 pushdecl (build_decl (TYPE_DECL, get_identifier ("byte"),
11706 t));
11707 type = ffetype_new ();
11708 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER2,
11709 type);
11710 ffetype_set_ams (type,
11711 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11712 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11713 ffetype_set_star (base_type,
11714 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11715 type);
11716 ffetype_set_kind (base_type, 3, type);
11717 assert (ffetype_size (type) == sizeof (ffetargetInteger2));
5ff904cd 11718
c7e4ee3a
CB
11719 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER2]
11720 = t = make_unsigned_type (CHAR_TYPE_SIZE);
11721 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned byte"),
11722 t));
11723
11724 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER3]
11725 = t = make_signed_type (CHAR_TYPE_SIZE * 2);
11726 pushdecl (build_decl (TYPE_DECL, get_identifier ("word"),
11727 t));
11728 type = ffetype_new ();
11729 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER3,
11730 type);
11731 ffetype_set_ams (type,
11732 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11733 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11734 ffetype_set_star (base_type,
11735 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11736 type);
11737 ffetype_set_kind (base_type, 6, type);
11738 assert (ffetype_size (type) == sizeof (ffetargetInteger3));
5ff904cd 11739
c7e4ee3a
CB
11740 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER3]
11741 = t = make_unsigned_type (CHAR_TYPE_SIZE * 2);
11742 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned word"),
11743 t));
5ff904cd 11744
c7e4ee3a
CB
11745 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER4]
11746 = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
11747 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer4"),
11748 t));
11749 type = ffetype_new ();
11750 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER4,
11751 type);
11752 ffetype_set_ams (type,
11753 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11754 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11755 ffetype_set_star (base_type,
11756 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11757 type);
11758 ffetype_set_kind (base_type, 2, type);
11759 assert (ffetype_size (type) == sizeof (ffetargetInteger4));
5ff904cd 11760
c7e4ee3a
CB
11761 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER4]
11762 = t = make_unsigned_type (FLOAT_TYPE_SIZE * 2);
11763 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned4"),
11764 t));
5ff904cd 11765
c7e4ee3a
CB
11766#if 0
11767 if (ffe_is_do_internal_checks ()
11768 && LONG_TYPE_SIZE != FLOAT_TYPE_SIZE
11769 && LONG_TYPE_SIZE != CHAR_TYPE_SIZE
11770 && LONG_TYPE_SIZE != SHORT_TYPE_SIZE
11771 && LONG_TYPE_SIZE != LONG_LONG_TYPE_SIZE)
5ff904cd 11772 {
c7e4ee3a
CB
11773 fprintf (stderr, "Sorry, no g77 support for LONG_TYPE_SIZE (%d bits) yet.\n",
11774 LONG_TYPE_SIZE);
5ff904cd 11775 }
c7e4ee3a 11776#endif
5ff904cd 11777
c7e4ee3a
CB
11778 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL1]
11779 = t = make_signed_type (FLOAT_TYPE_SIZE);
11780 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical"),
11781 t));
11782 type = ffetype_new ();
11783 base_type = type;
11784 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL1,
11785 type);
11786 ffetype_set_ams (type,
11787 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11788 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11789 ffetype_set_star (base_type,
11790 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11791 type);
11792 ffetype_set_kind (base_type, 1, type);
11793 assert (ffetype_size (type) == sizeof (ffetargetLogical1));
5ff904cd 11794
c7e4ee3a
CB
11795 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL2]
11796 = t = make_signed_type (CHAR_TYPE_SIZE);
11797 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical2"),
11798 t));
11799 type = ffetype_new ();
11800 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL2,
11801 type);
11802 ffetype_set_ams (type,
11803 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11804 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11805 ffetype_set_star (base_type,
11806 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11807 type);
11808 ffetype_set_kind (base_type, 3, type);
11809 assert (ffetype_size (type) == sizeof (ffetargetLogical2));
5ff904cd 11810
c7e4ee3a
CB
11811 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL3]
11812 = t = make_signed_type (CHAR_TYPE_SIZE * 2);
11813 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical3"),
11814 t));
11815 type = ffetype_new ();
11816 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL3,
11817 type);
11818 ffetype_set_ams (type,
11819 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11820 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11821 ffetype_set_star (base_type,
11822 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11823 type);
11824 ffetype_set_kind (base_type, 6, type);
11825 assert (ffetype_size (type) == sizeof (ffetargetLogical3));
5ff904cd 11826
c7e4ee3a
CB
11827 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL4]
11828 = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
11829 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical4"),
11830 t));
11831 type = ffetype_new ();
11832 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL4,
11833 type);
11834 ffetype_set_ams (type,
11835 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11836 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11837 ffetype_set_star (base_type,
11838 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11839 type);
11840 ffetype_set_kind (base_type, 2, type);
11841 assert (ffetype_size (type) == sizeof (ffetargetLogical4));
5ff904cd 11842
c7e4ee3a
CB
11843 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
11844 = t = make_node (REAL_TYPE);
11845 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE;
11846 pushdecl (build_decl (TYPE_DECL, get_identifier ("real"),
11847 t));
11848 layout_type (t);
11849 type = ffetype_new ();
11850 base_type = type;
11851 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREAL1,
11852 type);
11853 ffetype_set_ams (type,
11854 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11855 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11856 ffetype_set_star (base_type,
11857 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11858 type);
11859 ffetype_set_kind (base_type, 1, type);
11860 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
11861 = FFETARGET_f2cTYREAL;
11862 assert (ffetype_size (type) == sizeof (ffetargetReal1));
5ff904cd 11863
c7e4ee3a
CB
11864 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREALDOUBLE]
11865 = t = make_node (REAL_TYPE);
11866 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE * 2; /* Always twice REAL. */
11867 pushdecl (build_decl (TYPE_DECL, get_identifier ("double precision"),
11868 t));
11869 layout_type (t);
11870 type = ffetype_new ();
11871 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREALDOUBLE,
11872 type);
11873 ffetype_set_ams (type,
11874 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11875 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11876 ffetype_set_star (base_type,
11877 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11878 type);
11879 ffetype_set_kind (base_type, 2, type);
11880 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]
11881 = FFETARGET_f2cTYDREAL;
11882 assert (ffetype_size (type) == sizeof (ffetargetReal2));
5ff904cd 11883
c7e4ee3a
CB
11884 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
11885 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]);
11886 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex"),
11887 t));
11888 type = ffetype_new ();
11889 base_type = type;
11890 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREAL1,
11891 type);
11892 ffetype_set_ams (type,
11893 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11894 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11895 ffetype_set_star (base_type,
11896 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11897 type);
11898 ffetype_set_kind (base_type, 1, type);
11899 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
11900 = FFETARGET_f2cTYCOMPLEX;
11901 assert (ffetype_size (type) == sizeof (ffetargetComplex1));
5ff904cd 11902
c7e4ee3a
CB
11903 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREALDOUBLE]
11904 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]);
11905 pushdecl (build_decl (TYPE_DECL, get_identifier ("double complex"),
11906 t));
11907 type = ffetype_new ();
11908 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREALDOUBLE,
11909 type);
11910 ffetype_set_ams (type,
11911 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11912 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11913 ffetype_set_star (base_type,
11914 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11915 type);
11916 ffetype_set_kind (base_type, 2,
11917 type);
11918 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL2]
11919 = FFETARGET_f2cTYDCOMPLEX;
11920 assert (ffetype_size (type) == sizeof (ffetargetComplex2));
5ff904cd 11921
c7e4ee3a 11922 /* Make function and ptr-to-function types for non-CHARACTER types. */
5ff904cd 11923
c7e4ee3a
CB
11924 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11925 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11926 {
11927 if ((t = ffecom_tree_type[i][j]) != NULL_TREE)
11928 {
11929 if (i == FFEINFO_basictypeINTEGER)
11930 {
11931 /* Figure out the smallest INTEGER type that can hold
11932 a pointer on this machine. */
11933 if (GET_MODE_SIZE (TYPE_MODE (t))
11934 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
11935 {
11936 if ((ffecom_pointer_kind_ == FFEINFO_kindtypeNONE)
11937 || (GET_MODE_SIZE (TYPE_MODE (ffecom_tree_type[i][ffecom_pointer_kind_]))
11938 > GET_MODE_SIZE (TYPE_MODE (t))))
11939 ffecom_pointer_kind_ = j;
11940 }
11941 }
11942 else if (i == FFEINFO_basictypeCOMPLEX)
11943 t = void_type_node;
11944 /* For f2c compatibility, REAL functions are really
11945 implemented as DOUBLE PRECISION. */
11946 else if ((i == FFEINFO_basictypeREAL)
11947 && (j == FFEINFO_kindtypeREAL1))
11948 t = ffecom_tree_type
11949 [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2];
5ff904cd 11950
c7e4ee3a
CB
11951 t = ffecom_tree_fun_type[i][j] = build_function_type (t,
11952 NULL_TREE);
11953 ffecom_tree_ptr_to_fun_type[i][j] = build_pointer_type (t);
11954 }
11955 }
5ff904cd 11956
c7e4ee3a 11957 /* Set up pointer types. */
5ff904cd 11958
c7e4ee3a
CB
11959 if (ffecom_pointer_kind_ == FFEINFO_basictypeNONE)
11960 fatal ("no INTEGER type can hold a pointer on this configuration");
11961 else if (0 && ffe_is_do_internal_checks ())
11962 fprintf (stderr, "Pointer type kt=%d\n", ffecom_pointer_kind_);
11963 ffetype_set_kind (ffeinfo_type (FFEINFO_basictypeINTEGER,
11964 FFEINFO_kindtypeINTEGERDEFAULT),
11965 7,
11966 ffeinfo_type (FFEINFO_basictypeINTEGER,
11967 ffecom_pointer_kind_));
5ff904cd 11968
c7e4ee3a
CB
11969 if (ffe_is_ugly_assign ())
11970 ffecom_label_kind_ = ffecom_pointer_kind_; /* Require ASSIGN etc to this. */
11971 else
11972 ffecom_label_kind_ = FFEINFO_kindtypeINTEGERDEFAULT;
11973 if (0 && ffe_is_do_internal_checks ())
11974 fprintf (stderr, "Label type kt=%d\n", ffecom_label_kind_);
5ff904cd 11975
c7e4ee3a
CB
11976 ffecom_integer_type_node
11977 = ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1];
11978 ffecom_integer_zero_node = convert (ffecom_integer_type_node,
11979 integer_zero_node);
11980 ffecom_integer_one_node = convert (ffecom_integer_type_node,
11981 integer_one_node);
5ff904cd 11982
c7e4ee3a
CB
11983 /* Yes, the "FLOAT_TYPE_SIZE" references below are intentional.
11984 Turns out that by TYLONG, runtime/libI77/lio.h really means
11985 "whatever size an ftnint is". For consistency and sanity,
11986 com.h and runtime/f2c.h.in agree that flag, ftnint, and ftlen
11987 all are INTEGER, which we also make out of whatever back-end
11988 integer type is FLOAT_TYPE_SIZE bits wide. This change, from
11989 LONG_TYPE_SIZE, for TYLONG and TYLOGICAL, was necessary to
11990 accommodate machines like the Alpha. Note that this suggests
11991 f2c and libf2c are missing a distinction perhaps needed on
11992 some machines between "int" and "long int". -- burley 0.5.5 950215 */
5ff904cd 11993
c7e4ee3a
CB
11994 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, FLOAT_TYPE_SIZE,
11995 FFETARGET_f2cTYLONG);
11996 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, SHORT_TYPE_SIZE,
11997 FFETARGET_f2cTYSHORT);
11998 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, CHAR_TYPE_SIZE,
11999 FFETARGET_f2cTYINT1);
12000 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, LONG_LONG_TYPE_SIZE,
12001 FFETARGET_f2cTYQUAD);
12002 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, FLOAT_TYPE_SIZE,
12003 FFETARGET_f2cTYLOGICAL);
12004 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, SHORT_TYPE_SIZE,
12005 FFETARGET_f2cTYLOGICAL2);
12006 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, CHAR_TYPE_SIZE,
12007 FFETARGET_f2cTYLOGICAL1);
12008 /* ~~~Not really such a type in libf2c, e.g. I/O support? */
12009 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, LONG_LONG_TYPE_SIZE,
12010 FFETARGET_f2cTYQUAD);
5ff904cd 12011
c7e4ee3a
CB
12012 /* CHARACTER stuff is all special-cased, so it is not handled in the above
12013 loop. CHARACTER items are built as arrays of unsigned char. */
5ff904cd 12014
c7e4ee3a
CB
12015 ffecom_tree_type[FFEINFO_basictypeCHARACTER]
12016 [FFEINFO_kindtypeCHARACTER1] = t = char_type_node;
12017 type = ffetype_new ();
12018 base_type = type;
12019 ffeinfo_set_type (FFEINFO_basictypeCHARACTER,
12020 FFEINFO_kindtypeCHARACTER1,
12021 type);
12022 ffetype_set_ams (type,
12023 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12024 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12025 ffetype_set_kind (base_type, 1, type);
12026 assert (ffetype_size (type)
12027 == sizeof (((ffetargetCharacter1) { 0, NULL }).text[0]));
5ff904cd 12028
c7e4ee3a
CB
12029 ffecom_tree_fun_type[FFEINFO_basictypeCHARACTER]
12030 [FFEINFO_kindtypeCHARACTER1] = ffecom_tree_fun_type_void;
12031 ffecom_tree_ptr_to_fun_type[FFEINFO_basictypeCHARACTER]
12032 [FFEINFO_kindtypeCHARACTER1]
12033 = ffecom_tree_ptr_to_fun_type_void;
12034 ffecom_f2c_typecode_[FFEINFO_basictypeCHARACTER][FFEINFO_kindtypeCHARACTER1]
12035 = FFETARGET_f2cTYCHAR;
5ff904cd 12036
c7e4ee3a
CB
12037 ffecom_f2c_typecode_[FFEINFO_basictypeANY][FFEINFO_kindtypeANY]
12038 = 0;
5ff904cd 12039
c7e4ee3a 12040 /* Make multi-return-value type and fields. */
5ff904cd 12041
c7e4ee3a 12042 ffecom_multi_type_node_ = make_node (UNION_TYPE);
5ff904cd 12043
c7e4ee3a 12044 field = NULL_TREE;
5ff904cd 12045
c7e4ee3a
CB
12046 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
12047 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
12048 {
12049 char name[30];
5ff904cd 12050
c7e4ee3a
CB
12051 if (ffecom_tree_type[i][j] == NULL_TREE)
12052 continue; /* Not supported. */
12053 sprintf (&name[0], "bt_%s_kt_%s",
12054 ffeinfo_basictype_string ((ffeinfoBasictype) i),
12055 ffeinfo_kindtype_string ((ffeinfoKindtype) j));
12056 ffecom_multi_fields_[i][j] = build_decl (FIELD_DECL,
12057 get_identifier (name),
12058 ffecom_tree_type[i][j]);
12059 DECL_CONTEXT (ffecom_multi_fields_[i][j])
12060 = ffecom_multi_type_node_;
8ba77681 12061 DECL_ALIGN (ffecom_multi_fields_[i][j]) = 0;
11cf4d18 12062 DECL_USER_ALIGN (ffecom_multi_fields_[i][j]) = 0;
c7e4ee3a
CB
12063 TREE_CHAIN (ffecom_multi_fields_[i][j]) = field;
12064 field = ffecom_multi_fields_[i][j];
12065 }
5ff904cd 12066
c7e4ee3a
CB
12067 TYPE_FIELDS (ffecom_multi_type_node_) = field;
12068 layout_type (ffecom_multi_type_node_);
5ff904cd 12069
c7e4ee3a
CB
12070 /* Subroutines usually return integer because they might have alternate
12071 returns. */
5ff904cd 12072
c7e4ee3a
CB
12073 ffecom_tree_subr_type
12074 = build_function_type (integer_type_node, NULL_TREE);
12075 ffecom_tree_ptr_to_subr_type
12076 = build_pointer_type (ffecom_tree_subr_type);
12077 ffecom_tree_blockdata_type
12078 = build_function_type (void_type_node, NULL_TREE);
5ff904cd 12079
c7e4ee3a 12080 builtin_function ("__builtin_sqrtf", float_ftype_float,
26db82d8 12081 BUILT_IN_FSQRT, BUILT_IN_NORMAL, "sqrtf");
c7e4ee3a 12082 builtin_function ("__builtin_fsqrt", double_ftype_double,
26db82d8 12083 BUILT_IN_FSQRT, BUILT_IN_NORMAL, "sqrt");
c7e4ee3a 12084 builtin_function ("__builtin_sqrtl", ldouble_ftype_ldouble,
26db82d8 12085 BUILT_IN_FSQRT, BUILT_IN_NORMAL, "sqrtl");
c7e4ee3a 12086 builtin_function ("__builtin_sinf", float_ftype_float,
26db82d8 12087 BUILT_IN_SIN, BUILT_IN_NORMAL, "sinf");
c7e4ee3a 12088 builtin_function ("__builtin_sin", double_ftype_double,
26db82d8 12089 BUILT_IN_SIN, BUILT_IN_NORMAL, "sin");
c7e4ee3a 12090 builtin_function ("__builtin_sinl", ldouble_ftype_ldouble,
26db82d8 12091 BUILT_IN_SIN, BUILT_IN_NORMAL, "sinl");
c7e4ee3a 12092 builtin_function ("__builtin_cosf", float_ftype_float,
26db82d8 12093 BUILT_IN_COS, BUILT_IN_NORMAL, "cosf");
c7e4ee3a 12094 builtin_function ("__builtin_cos", double_ftype_double,
26db82d8 12095 BUILT_IN_COS, BUILT_IN_NORMAL, "cos");
c7e4ee3a 12096 builtin_function ("__builtin_cosl", ldouble_ftype_ldouble,
26db82d8 12097 BUILT_IN_COS, BUILT_IN_NORMAL, "cosl");
5ff904cd 12098
c7e4ee3a
CB
12099#if BUILT_FOR_270
12100 pedantic_lvalues = FALSE;
5ff904cd 12101#endif
5ff904cd 12102
c7e4ee3a
CB
12103 ffecom_f2c_make_type_ (&ffecom_f2c_integer_type_node,
12104 FFECOM_f2cINTEGER,
12105 "integer");
12106 ffecom_f2c_make_type_ (&ffecom_f2c_address_type_node,
12107 FFECOM_f2cADDRESS,
12108 "address");
12109 ffecom_f2c_make_type_ (&ffecom_f2c_real_type_node,
12110 FFECOM_f2cREAL,
12111 "real");
12112 ffecom_f2c_make_type_ (&ffecom_f2c_doublereal_type_node,
12113 FFECOM_f2cDOUBLEREAL,
12114 "doublereal");
12115 ffecom_f2c_make_type_ (&ffecom_f2c_complex_type_node,
12116 FFECOM_f2cCOMPLEX,
12117 "complex");
12118 ffecom_f2c_make_type_ (&ffecom_f2c_doublecomplex_type_node,
12119 FFECOM_f2cDOUBLECOMPLEX,
12120 "doublecomplex");
12121 ffecom_f2c_make_type_ (&ffecom_f2c_longint_type_node,
12122 FFECOM_f2cLONGINT,
12123 "longint");
12124 ffecom_f2c_make_type_ (&ffecom_f2c_logical_type_node,
12125 FFECOM_f2cLOGICAL,
12126 "logical");
12127 ffecom_f2c_make_type_ (&ffecom_f2c_flag_type_node,
12128 FFECOM_f2cFLAG,
12129 "flag");
12130 ffecom_f2c_make_type_ (&ffecom_f2c_ftnlen_type_node,
12131 FFECOM_f2cFTNLEN,
12132 "ftnlen");
12133 ffecom_f2c_make_type_ (&ffecom_f2c_ftnint_type_node,
12134 FFECOM_f2cFTNINT,
12135 "ftnint");
5ff904cd 12136
c7e4ee3a
CB
12137 ffecom_f2c_ftnlen_zero_node
12138 = convert (ffecom_f2c_ftnlen_type_node, integer_zero_node);
5ff904cd 12139
c7e4ee3a
CB
12140 ffecom_f2c_ftnlen_one_node
12141 = convert (ffecom_f2c_ftnlen_type_node, integer_one_node);
5ff904cd 12142
c7e4ee3a
CB
12143 ffecom_f2c_ftnlen_two_node = build_int_2 (2, 0);
12144 TREE_TYPE (ffecom_f2c_ftnlen_two_node) = ffecom_integer_type_node;
5ff904cd 12145
c7e4ee3a
CB
12146 ffecom_f2c_ptr_to_ftnlen_type_node
12147 = build_pointer_type (ffecom_f2c_ftnlen_type_node);
5ff904cd 12148
c7e4ee3a
CB
12149 ffecom_f2c_ptr_to_ftnint_type_node
12150 = build_pointer_type (ffecom_f2c_ftnint_type_node);
5ff904cd 12151
c7e4ee3a
CB
12152 ffecom_f2c_ptr_to_integer_type_node
12153 = build_pointer_type (ffecom_f2c_integer_type_node);
5ff904cd 12154
c7e4ee3a
CB
12155 ffecom_f2c_ptr_to_real_type_node
12156 = build_pointer_type (ffecom_f2c_real_type_node);
5ff904cd 12157
c7e4ee3a
CB
12158 ffecom_float_zero_ = build_real (float_type_node, dconst0);
12159 ffecom_double_zero_ = build_real (double_type_node, dconst0);
12160 {
12161 REAL_VALUE_TYPE point_5;
5ff904cd 12162
c7e4ee3a
CB
12163#ifdef REAL_ARITHMETIC
12164 REAL_ARITHMETIC (point_5, RDIV_EXPR, dconst1, dconst2);
12165#else
12166 point_5 = .5;
12167#endif
12168 ffecom_float_half_ = build_real (float_type_node, point_5);
12169 ffecom_double_half_ = build_real (double_type_node, point_5);
12170 }
5ff904cd 12171
c7e4ee3a 12172 /* Do "extern int xargc;". */
5ff904cd 12173
c7e4ee3a
CB
12174 ffecom_tree_xargc_ = build_decl (VAR_DECL,
12175 get_identifier ("f__xargc"),
12176 integer_type_node);
12177 DECL_EXTERNAL (ffecom_tree_xargc_) = 1;
12178 TREE_STATIC (ffecom_tree_xargc_) = 1;
12179 TREE_PUBLIC (ffecom_tree_xargc_) = 1;
12180 ffecom_tree_xargc_ = start_decl (ffecom_tree_xargc_, FALSE);
12181 finish_decl (ffecom_tree_xargc_, NULL_TREE, FALSE);
5ff904cd 12182
c7e4ee3a
CB
12183#if 0 /* This is being fixed, and seems to be working now. */
12184 if ((FLOAT_TYPE_SIZE != 32)
12185 || (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))) != 32))
5ff904cd 12186 {
c7e4ee3a
CB
12187 warning ("configuration: REAL, INTEGER, and LOGICAL are %d bits wide,",
12188 (int) FLOAT_TYPE_SIZE);
12189 warning ("and pointers are %d bits wide, but g77 doesn't yet work",
12190 (int) TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))));
12191 warning ("properly unless they all are 32 bits wide.");
12192 warning ("Please keep this in mind before you report bugs. g77 should");
12193 warning ("support non-32-bit machines better as of version 0.6.");
12194 }
12195#endif
5ff904cd 12196
c7e4ee3a
CB
12197#if 0 /* Code in ste.c that would crash has been commented out. */
12198 if (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)
12199 < TYPE_PRECISION (string_type_node))
12200 /* I/O will probably crash. */
12201 warning ("configuration: char * holds %d bits, but ftnlen only %d",
12202 TYPE_PRECISION (string_type_node),
12203 TYPE_PRECISION (ffecom_f2c_ftnlen_type_node));
12204#endif
5ff904cd 12205
c7e4ee3a
CB
12206#if 0 /* ASSIGN-related stuff has been changed to accommodate this. */
12207 if (TYPE_PRECISION (ffecom_integer_type_node)
12208 < TYPE_PRECISION (string_type_node))
12209 /* ASSIGN 10 TO I will crash. */
12210 warning ("configuration: char * holds %d bits, but INTEGER only %d --\n\
12211 ASSIGN statement might fail",
12212 TYPE_PRECISION (string_type_node),
12213 TYPE_PRECISION (ffecom_integer_type_node));
12214#endif
12215}
5ff904cd 12216
c7e4ee3a
CB
12217#endif
12218/* ffecom_init_2 -- Initialize
5ff904cd 12219
c7e4ee3a 12220 ffecom_init_2(); */
5ff904cd 12221
c7e4ee3a
CB
12222#if FFECOM_targetCURRENT == FFECOM_targetGCC
12223void
12224ffecom_init_2 ()
12225{
12226 assert (ffecom_outer_function_decl_ == NULL_TREE);
12227 assert (current_function_decl == NULL_TREE);
12228 assert (ffecom_which_entrypoint_decl_ == NULL_TREE);
5ff904cd 12229
c7e4ee3a
CB
12230 ffecom_master_arglist_ = NULL;
12231 ++ffecom_num_fns_;
12232 ffecom_primary_entry_ = NULL;
12233 ffecom_is_altreturning_ = FALSE;
12234 ffecom_func_result_ = NULL_TREE;
12235 ffecom_multi_retval_ = NULL_TREE;
12236}
5ff904cd 12237
c7e4ee3a
CB
12238#endif
12239/* ffecom_list_expr -- Transform list of exprs into gcc tree
5ff904cd 12240
c7e4ee3a
CB
12241 tree t;
12242 ffebld expr; // FFE opITEM list.
12243 tree = ffecom_list_expr(expr);
5ff904cd 12244
c7e4ee3a 12245 List of actual args is transformed into corresponding gcc backend list. */
5ff904cd 12246
c7e4ee3a
CB
12247#if FFECOM_targetCURRENT == FFECOM_targetGCC
12248tree
12249ffecom_list_expr (ffebld expr)
5ff904cd 12250{
c7e4ee3a
CB
12251 tree list;
12252 tree *plist = &list;
12253 tree trail = NULL_TREE; /* Append char length args here. */
12254 tree *ptrail = &trail;
12255 tree length;
5ff904cd 12256
c7e4ee3a 12257 while (expr != NULL)
5ff904cd 12258 {
c7e4ee3a 12259 tree texpr = ffecom_arg_expr (ffebld_head (expr), &length);
5ff904cd 12260
c7e4ee3a
CB
12261 if (texpr == error_mark_node)
12262 return error_mark_node;
5ff904cd 12263
c7e4ee3a
CB
12264 *plist = build_tree_list (NULL_TREE, texpr);
12265 plist = &TREE_CHAIN (*plist);
12266 expr = ffebld_trail (expr);
12267 if (length != NULL_TREE)
5ff904cd 12268 {
c7e4ee3a
CB
12269 *ptrail = build_tree_list (NULL_TREE, length);
12270 ptrail = &TREE_CHAIN (*ptrail);
5ff904cd
JL
12271 }
12272 }
12273
c7e4ee3a 12274 *plist = trail;
5ff904cd 12275
c7e4ee3a
CB
12276 return list;
12277}
5ff904cd 12278
c7e4ee3a
CB
12279#endif
12280/* ffecom_list_ptr_to_expr -- Transform list of exprs into gcc tree
5ff904cd 12281
c7e4ee3a
CB
12282 tree t;
12283 ffebld expr; // FFE opITEM list.
12284 tree = ffecom_list_ptr_to_expr(expr);
5ff904cd 12285
c7e4ee3a
CB
12286 List of actual args is transformed into corresponding gcc backend list for
12287 use in calling an external procedure (vs. a statement function). */
5ff904cd 12288
c7e4ee3a
CB
12289#if FFECOM_targetCURRENT == FFECOM_targetGCC
12290tree
12291ffecom_list_ptr_to_expr (ffebld expr)
12292{
12293 tree list;
12294 tree *plist = &list;
12295 tree trail = NULL_TREE; /* Append char length args here. */
12296 tree *ptrail = &trail;
12297 tree length;
5ff904cd 12298
c7e4ee3a
CB
12299 while (expr != NULL)
12300 {
12301 tree texpr = ffecom_arg_ptr_to_expr (ffebld_head (expr), &length);
5ff904cd 12302
c7e4ee3a
CB
12303 if (texpr == error_mark_node)
12304 return error_mark_node;
5ff904cd 12305
c7e4ee3a
CB
12306 *plist = build_tree_list (NULL_TREE, texpr);
12307 plist = &TREE_CHAIN (*plist);
12308 expr = ffebld_trail (expr);
12309 if (length != NULL_TREE)
12310 {
12311 *ptrail = build_tree_list (NULL_TREE, length);
12312 ptrail = &TREE_CHAIN (*ptrail);
12313 }
12314 }
5ff904cd 12315
c7e4ee3a 12316 *plist = trail;
5ff904cd 12317
c7e4ee3a
CB
12318 return list;
12319}
5ff904cd 12320
c7e4ee3a
CB
12321#endif
12322/* Obtain gcc's LABEL_DECL tree for label. */
5ff904cd 12323
c7e4ee3a
CB
12324#if FFECOM_targetCURRENT == FFECOM_targetGCC
12325tree
12326ffecom_lookup_label (ffelab label)
12327{
12328 tree glabel;
5ff904cd 12329
c7e4ee3a
CB
12330 if (ffelab_hook (label) == NULL_TREE)
12331 {
12332 char labelname[16];
5ff904cd 12333
c7e4ee3a
CB
12334 switch (ffelab_type (label))
12335 {
12336 case FFELAB_typeLOOPEND:
12337 case FFELAB_typeNOTLOOP:
12338 case FFELAB_typeENDIF:
12339 sprintf (labelname, "%" ffelabValue_f "u", ffelab_value (label));
12340 glabel = build_decl (LABEL_DECL, get_identifier (labelname),
12341 void_type_node);
12342 DECL_CONTEXT (glabel) = current_function_decl;
12343 DECL_MODE (glabel) = VOIDmode;
12344 break;
5ff904cd 12345
c7e4ee3a 12346 case FFELAB_typeFORMAT:
c7e4ee3a
CB
12347 glabel = build_decl (VAR_DECL,
12348 ffecom_get_invented_identifier
14657de8 12349 ("__g77_format_%d", (int) ffelab_value (label)),
c7e4ee3a
CB
12350 build_type_variant (build_array_type
12351 (char_type_node,
12352 NULL_TREE),
12353 1, 0));
12354 TREE_CONSTANT (glabel) = 1;
12355 TREE_STATIC (glabel) = 1;
12356 DECL_CONTEXT (glabel) = 0;
12357 DECL_INITIAL (glabel) = NULL;
12358 make_decl_rtl (glabel, NULL, 0);
12359 expand_decl (glabel);
5ff904cd 12360
7189a4b0 12361 ffecom_save_tree_forever (glabel);
5ff904cd 12362
c7e4ee3a 12363 break;
5ff904cd 12364
c7e4ee3a
CB
12365 case FFELAB_typeANY:
12366 glabel = error_mark_node;
12367 break;
5ff904cd 12368
c7e4ee3a
CB
12369 default:
12370 assert ("bad label type" == NULL);
12371 glabel = NULL;
12372 break;
12373 }
12374 ffelab_set_hook (label, glabel);
12375 }
12376 else
12377 {
12378 glabel = ffelab_hook (label);
12379 }
5ff904cd 12380
c7e4ee3a
CB
12381 return glabel;
12382}
5ff904cd 12383
c7e4ee3a
CB
12384#endif
12385/* Stabilizes the arguments. Don't use this if the lhs and rhs come from
12386 a single source specification (as in the fourth argument of MVBITS).
12387 If the type is NULL_TREE, the type of lhs is used to make the type of
12388 the MODIFY_EXPR. */
5ff904cd 12389
c7e4ee3a
CB
12390#if FFECOM_targetCURRENT == FFECOM_targetGCC
12391tree
12392ffecom_modify (tree newtype, tree lhs,
12393 tree rhs)
12394{
12395 if (lhs == error_mark_node || rhs == error_mark_node)
12396 return error_mark_node;
5ff904cd 12397
c7e4ee3a
CB
12398 if (newtype == NULL_TREE)
12399 newtype = TREE_TYPE (lhs);
5ff904cd 12400
c7e4ee3a
CB
12401 if (TREE_SIDE_EFFECTS (lhs))
12402 lhs = stabilize_reference (lhs);
5ff904cd 12403
c7e4ee3a
CB
12404 return ffecom_2s (MODIFY_EXPR, newtype, lhs, rhs);
12405}
5ff904cd 12406
c7e4ee3a 12407#endif
5ff904cd 12408
c7e4ee3a 12409/* Register source file name. */
5ff904cd 12410
c7e4ee3a 12411void
b0791fa9 12412ffecom_file (const char *name)
c7e4ee3a
CB
12413{
12414#if FFECOM_GCC_INCLUDE
12415 ffecom_file_ (name);
12416#endif
12417}
5ff904cd 12418
c7e4ee3a 12419/* ffecom_notify_init_storage -- An aggregate storage is now fully init'ed
5ff904cd 12420
c7e4ee3a
CB
12421 ffestorag st;
12422 ffecom_notify_init_storage(st);
5ff904cd 12423
c7e4ee3a
CB
12424 Gets called when all possible units in an aggregate storage area (a LOCAL
12425 with equivalences or a COMMON) have been initialized. The initialization
12426 info either is in ffestorag_init or, if that is NULL,
12427 ffestorag_accretion:
5ff904cd 12428
c7e4ee3a
CB
12429 ffestorag_init may contain an opCONTER or opARRTER. opCONTER may occur
12430 even for an array if the array is one element in length!
5ff904cd 12431
c7e4ee3a
CB
12432 ffestorag_accretion will contain an opACCTER. It is much like an
12433 opARRTER except it has an ffebit object in it instead of just a size.
12434 The back end can use the info in the ffebit object, if it wants, to
12435 reduce the amount of actual initialization, but in any case it should
12436 kill the ffebit object when done. Also, set accretion to NULL but
12437 init to a non-NULL value.
5ff904cd 12438
c7e4ee3a
CB
12439 After performing initialization, DO NOT set init to NULL, because that'll
12440 tell the front end it is ok for more initialization to happen. Instead,
12441 set init to an opANY expression or some such thing that you can use to
12442 tell that you've already initialized the object.
5ff904cd 12443
c7e4ee3a
CB
12444 27-Oct-91 JCB 1.1
12445 Support two-pass FFE. */
5ff904cd 12446
c7e4ee3a
CB
12447void
12448ffecom_notify_init_storage (ffestorag st)
12449{
12450 ffebld init; /* The initialization expression. */
12451#if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12452 ffetargetOffset size; /* The size of the entity. */
12453 ffetargetAlign pad; /* Its initial padding. */
12454#endif
12455
12456 if (ffestorag_init (st) == NULL)
5ff904cd 12457 {
c7e4ee3a
CB
12458 init = ffestorag_accretion (st);
12459 assert (init != NULL);
12460 ffestorag_set_accretion (st, NULL);
12461 ffestorag_set_accretes (st, 0);
12462
12463#if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12464 /* For GNU backend, just turn ACCTER into ARRTER and proceed. */
12465 size = ffebld_accter_size (init);
12466 pad = ffebld_accter_pad (init);
12467 ffebit_kill (ffebld_accter_bits (init));
12468 ffebld_set_op (init, FFEBLD_opARRTER);
12469 ffebld_set_arrter (init, ffebld_accter (init));
12470 ffebld_arrter_set_size (init, size);
12471 ffebld_arrter_set_pad (init, size);
12472#endif
12473
12474#if FFECOM_TWOPASS
12475 ffestorag_set_init (st, init);
12476#endif
5ff904cd 12477 }
c7e4ee3a
CB
12478#if FFECOM_ONEPASS
12479 else
12480 init = ffestorag_init (st);
5ff904cd
JL
12481#endif
12482
c7e4ee3a
CB
12483#if FFECOM_ONEPASS /* Process the inits, wipe 'em out. */
12484 ffestorag_set_init (st, ffebld_new_any ());
5ff904cd 12485
c7e4ee3a
CB
12486 if (ffebld_op (init) == FFEBLD_opANY)
12487 return; /* Oh, we already did this! */
5ff904cd 12488
c7e4ee3a
CB
12489#if FFECOM_targetCURRENT == FFECOM_targetFFE
12490 {
12491 ffesymbol s;
5ff904cd 12492
c7e4ee3a
CB
12493 if (ffestorag_symbol (st) != NULL)
12494 s = ffestorag_symbol (st);
12495 else
12496 s = ffestorag_typesymbol (st);
5ff904cd 12497
c7e4ee3a
CB
12498 fprintf (dmpout, "= initialize_storage \"%s\" ",
12499 (s != NULL) ? ffesymbol_text (s) : "(unnamed)");
12500 ffebld_dump (init);
12501 fputc ('\n', dmpout);
12502 }
12503#endif
5ff904cd 12504
c7e4ee3a
CB
12505#endif /* if FFECOM_ONEPASS */
12506}
5ff904cd 12507
c7e4ee3a 12508/* ffecom_notify_init_symbol -- A symbol is now fully init'ed
5ff904cd 12509
c7e4ee3a
CB
12510 ffesymbol s;
12511 ffecom_notify_init_symbol(s);
5ff904cd 12512
c7e4ee3a
CB
12513 Gets called when all possible units in a symbol (not placed in COMMON
12514 or involved in EQUIVALENCE, unless it as yet has no ffestorag object)
12515 have been initialized. The initialization info either is in
12516 ffesymbol_init or, if that is NULL, ffesymbol_accretion:
5ff904cd 12517
c7e4ee3a
CB
12518 ffesymbol_init may contain an opCONTER or opARRTER. opCONTER may occur
12519 even for an array if the array is one element in length!
5ff904cd 12520
c7e4ee3a
CB
12521 ffesymbol_accretion will contain an opACCTER. It is much like an
12522 opARRTER except it has an ffebit object in it instead of just a size.
12523 The back end can use the info in the ffebit object, if it wants, to
12524 reduce the amount of actual initialization, but in any case it should
12525 kill the ffebit object when done. Also, set accretion to NULL but
12526 init to a non-NULL value.
5ff904cd 12527
c7e4ee3a
CB
12528 After performing initialization, DO NOT set init to NULL, because that'll
12529 tell the front end it is ok for more initialization to happen. Instead,
12530 set init to an opANY expression or some such thing that you can use to
12531 tell that you've already initialized the object.
5ff904cd 12532
c7e4ee3a
CB
12533 27-Oct-91 JCB 1.1
12534 Support two-pass FFE. */
5ff904cd 12535
c7e4ee3a
CB
12536void
12537ffecom_notify_init_symbol (ffesymbol s)
12538{
12539 ffebld init; /* The initialization expression. */
12540#if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12541 ffetargetOffset size; /* The size of the entity. */
12542 ffetargetAlign pad; /* Its initial padding. */
12543#endif
5ff904cd 12544
c7e4ee3a
CB
12545 if (ffesymbol_storage (s) == NULL)
12546 return; /* Do nothing until COMMON/EQUIVALENCE
12547 possibilities checked. */
5ff904cd 12548
c7e4ee3a
CB
12549 if ((ffesymbol_init (s) == NULL)
12550 && ((init = ffesymbol_accretion (s)) != NULL))
12551 {
12552 ffesymbol_set_accretion (s, NULL);
12553 ffesymbol_set_accretes (s, 0);
5ff904cd 12554
c7e4ee3a
CB
12555#if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12556 /* For GNU backend, just turn ACCTER into ARRTER and proceed. */
12557 size = ffebld_accter_size (init);
12558 pad = ffebld_accter_pad (init);
12559 ffebit_kill (ffebld_accter_bits (init));
12560 ffebld_set_op (init, FFEBLD_opARRTER);
12561 ffebld_set_arrter (init, ffebld_accter (init));
12562 ffebld_arrter_set_size (init, size);
12563 ffebld_arrter_set_pad (init, size);
12564#endif
5ff904cd 12565
c7e4ee3a
CB
12566#if FFECOM_TWOPASS
12567 ffesymbol_set_init (s, init);
12568#endif
12569 }
12570#if FFECOM_ONEPASS
12571 else
12572 init = ffesymbol_init (s);
12573#endif
5ff904cd 12574
c7e4ee3a
CB
12575#if FFECOM_ONEPASS
12576 ffesymbol_set_init (s, ffebld_new_any ());
5ff904cd 12577
c7e4ee3a
CB
12578 if (ffebld_op (init) == FFEBLD_opANY)
12579 return; /* Oh, we already did this! */
5ff904cd 12580
c7e4ee3a
CB
12581#if FFECOM_targetCURRENT == FFECOM_targetFFE
12582 fprintf (dmpout, "= initialize_symbol \"%s\" ", ffesymbol_text (s));
12583 ffebld_dump (init);
12584 fputc ('\n', dmpout);
12585#endif
5ff904cd 12586
c7e4ee3a
CB
12587#endif /* if FFECOM_ONEPASS */
12588}
5ff904cd 12589
c7e4ee3a 12590/* ffecom_notify_primary_entry -- Learn which is the primary entry point
5ff904cd 12591
c7e4ee3a
CB
12592 ffesymbol s;
12593 ffecom_notify_primary_entry(s);
5ff904cd 12594
c7e4ee3a
CB
12595 Gets called when implicit or explicit PROGRAM statement seen or when
12596 FUNCTION, SUBROUTINE, or BLOCK DATA statement seen, with the primary
12597 global symbol that serves as the entry point. */
5ff904cd 12598
c7e4ee3a
CB
12599void
12600ffecom_notify_primary_entry (ffesymbol s)
12601{
12602 ffecom_primary_entry_ = s;
12603 ffecom_primary_entry_kind_ = ffesymbol_kind (s);
5ff904cd 12604
c7e4ee3a
CB
12605 if ((ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
12606 || (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE))
12607 ffecom_primary_entry_is_proc_ = TRUE;
12608 else
12609 ffecom_primary_entry_is_proc_ = FALSE;
5ff904cd 12610
c7e4ee3a
CB
12611 if (!ffe_is_silent ())
12612 {
12613 if (ffecom_primary_entry_kind_ == FFEINFO_kindPROGRAM)
12614 fprintf (stderr, "%s:\n", ffesymbol_text (s));
12615 else
12616 fprintf (stderr, " %s:\n", ffesymbol_text (s));
12617 }
5ff904cd 12618
c7e4ee3a
CB
12619#if FFECOM_targetCURRENT == FFECOM_targetGCC
12620 if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
12621 {
12622 ffebld list;
12623 ffebld arg;
5ff904cd 12624
c7e4ee3a
CB
12625 for (list = ffesymbol_dummyargs (s);
12626 list != NULL;
12627 list = ffebld_trail (list))
12628 {
12629 arg = ffebld_head (list);
12630 if (ffebld_op (arg) == FFEBLD_opSTAR)
12631 {
12632 ffecom_is_altreturning_ = TRUE;
12633 break;
12634 }
12635 }
12636 }
12637#endif
12638}
5ff904cd 12639
c7e4ee3a
CB
12640FILE *
12641ffecom_open_include (char *name, ffewhereLine l, ffewhereColumn c)
12642{
12643#if FFECOM_GCC_INCLUDE
12644 return ffecom_open_include_ (name, l, c);
12645#else
12646 return fopen (name, "r");
5ff904cd 12647#endif
c7e4ee3a 12648}
5ff904cd 12649
c7e4ee3a 12650/* ffecom_ptr_to_expr -- Transform expr into gcc tree with & in front
5ff904cd 12651
c7e4ee3a
CB
12652 tree t;
12653 ffebld expr; // FFE expression.
12654 tree = ffecom_ptr_to_expr(expr);
5ff904cd 12655
c7e4ee3a 12656 Like ffecom_expr, but sticks address-of in front of most things. */
5ff904cd 12657
c7e4ee3a
CB
12658#if FFECOM_targetCURRENT == FFECOM_targetGCC
12659tree
12660ffecom_ptr_to_expr (ffebld expr)
12661{
12662 tree item;
12663 ffeinfoBasictype bt;
12664 ffeinfoKindtype kt;
12665 ffesymbol s;
5ff904cd 12666
c7e4ee3a 12667 assert (expr != NULL);
5ff904cd 12668
c7e4ee3a
CB
12669 switch (ffebld_op (expr))
12670 {
12671 case FFEBLD_opSYMTER:
12672 s = ffebld_symter (expr);
12673 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
12674 {
12675 ffecomGfrt ix;
5ff904cd 12676
c7e4ee3a
CB
12677 ix = ffeintrin_gfrt_indirect (ffebld_symter_implementation (expr));
12678 assert (ix != FFECOM_gfrt);
12679 if ((item = ffecom_gfrt_[ix]) == NULL_TREE)
12680 {
12681 ffecom_make_gfrt_ (ix);
12682 item = ffecom_gfrt_[ix];
12683 }
12684 }
12685 else
12686 {
12687 item = ffesymbol_hook (s).decl_tree;
12688 if (item == NULL_TREE)
12689 {
12690 s = ffecom_sym_transform_ (s);
12691 item = ffesymbol_hook (s).decl_tree;
12692 }
12693 }
12694 assert (item != NULL);
12695 if (item == error_mark_node)
12696 return item;
12697 if (!ffesymbol_hook (s).addr)
12698 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12699 item);
12700 return item;
5ff904cd 12701
c7e4ee3a 12702 case FFEBLD_opARRAYREF:
ff852b44 12703 return ffecom_arrayref_ (NULL_TREE, expr, 1);
5ff904cd 12704
c7e4ee3a 12705 case FFEBLD_opCONTER:
5ff904cd 12706
c7e4ee3a
CB
12707 bt = ffeinfo_basictype (ffebld_info (expr));
12708 kt = ffeinfo_kindtype (ffebld_info (expr));
5ff904cd 12709
c7e4ee3a
CB
12710 item = ffecom_constantunion (&ffebld_constant_union
12711 (ffebld_conter (expr)), bt, kt,
12712 ffecom_tree_type[bt][kt]);
12713 if (item == error_mark_node)
12714 return error_mark_node;
12715 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12716 item);
12717 return item;
5ff904cd 12718
c7e4ee3a
CB
12719 case FFEBLD_opANY:
12720 return error_mark_node;
5ff904cd 12721
c7e4ee3a
CB
12722 default:
12723 bt = ffeinfo_basictype (ffebld_info (expr));
12724 kt = ffeinfo_kindtype (ffebld_info (expr));
12725
12726 item = ffecom_expr (expr);
12727 if (item == error_mark_node)
12728 return error_mark_node;
12729
12730 /* The back end currently optimizes a bit too zealously for us, in that
12731 we fail JCB001 if the following block of code is omitted. It checks
12732 to see if the transformed expression is a symbol or array reference,
12733 and encloses it in a SAVE_EXPR if that is the case. */
12734
12735 STRIP_NOPS (item);
12736 if ((TREE_CODE (item) == VAR_DECL)
12737 || (TREE_CODE (item) == PARM_DECL)
12738 || (TREE_CODE (item) == RESULT_DECL)
12739 || (TREE_CODE (item) == INDIRECT_REF)
12740 || (TREE_CODE (item) == ARRAY_REF)
12741 || (TREE_CODE (item) == COMPONENT_REF)
12742#ifdef OFFSET_REF
12743 || (TREE_CODE (item) == OFFSET_REF)
12744#endif
12745 || (TREE_CODE (item) == BUFFER_REF)
12746 || (TREE_CODE (item) == REALPART_EXPR)
12747 || (TREE_CODE (item) == IMAGPART_EXPR))
12748 {
12749 item = ffecom_save_tree (item);
12750 }
12751
12752 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12753 item);
12754 return item;
12755 }
12756
12757 assert ("fall-through error" == NULL);
12758 return error_mark_node;
5ff904cd
JL
12759}
12760
12761#endif
c7e4ee3a 12762/* Obtain a temp var with given data type.
5ff904cd 12763
c7e4ee3a
CB
12764 size is FFETARGET_charactersizeNONE for a non-CHARACTER type
12765 or >= 0 for a CHARACTER type.
5ff904cd 12766
c7e4ee3a 12767 elements is -1 for a scalar or > 0 for an array of type. */
5ff904cd
JL
12768
12769#if FFECOM_targetCURRENT == FFECOM_targetGCC
12770tree
c7e4ee3a
CB
12771ffecom_make_tempvar (const char *commentary, tree type,
12772 ffetargetCharacterSize size, int elements)
5ff904cd 12773{
c7e4ee3a
CB
12774 int yes;
12775 tree t;
12776 static int mynumber;
5ff904cd 12777
c7e4ee3a 12778 assert (current_binding_level->prep_state < 2);
702edf1d 12779
c7e4ee3a
CB
12780 if (type == error_mark_node)
12781 return error_mark_node;
702edf1d 12782
c7e4ee3a 12783 yes = suspend_momentary ();
5ff904cd 12784
c7e4ee3a
CB
12785 if (size != FFETARGET_charactersizeNONE)
12786 type = build_array_type (type,
12787 build_range_type (ffecom_f2c_ftnlen_type_node,
12788 ffecom_f2c_ftnlen_one_node,
12789 build_int_2 (size, 0)));
12790 if (elements != -1)
12791 type = build_array_type (type,
12792 build_range_type (integer_type_node,
12793 integer_zero_node,
12794 build_int_2 (elements - 1,
12795 0)));
12796 t = build_decl (VAR_DECL,
12797 ffecom_get_invented_identifier ("__g77_%s_%d",
12798 commentary,
12799 mynumber++),
12800 type);
5ff904cd 12801
c7e4ee3a
CB
12802 t = start_decl (t, FALSE);
12803 finish_decl (t, NULL_TREE, FALSE);
12804
12805 resume_momentary (yes);
5ff904cd 12806
c7e4ee3a
CB
12807 return t;
12808}
5ff904cd 12809#endif
5ff904cd 12810
c7e4ee3a 12811/* Prepare argument pointer to expression.
5ff904cd 12812
c7e4ee3a
CB
12813 Like ffecom_prepare_expr, except for expressions to be evaluated
12814 via ffecom_arg_ptr_to_expr. */
5ff904cd 12815
c7e4ee3a
CB
12816void
12817ffecom_prepare_arg_ptr_to_expr (ffebld expr)
5ff904cd 12818{
c7e4ee3a
CB
12819 /* ~~For now, it seems to be the same thing. */
12820 ffecom_prepare_expr (expr);
12821 return;
12822}
702edf1d 12823
c7e4ee3a 12824/* End of preparations. */
702edf1d 12825
c7e4ee3a
CB
12826bool
12827ffecom_prepare_end (void)
12828{
12829 int prep_state = current_binding_level->prep_state;
5ff904cd 12830
c7e4ee3a
CB
12831 assert (prep_state < 2);
12832 current_binding_level->prep_state = 2;
5ff904cd 12833
c7e4ee3a 12834 return (prep_state == 1) ? TRUE : FALSE;
5ff904cd
JL
12835}
12836
c7e4ee3a 12837/* Prepare expression.
5ff904cd 12838
c7e4ee3a
CB
12839 This is called before any code is generated for the current block.
12840 It scans the expression, declares any temporaries that might be needed
12841 during evaluation of the expression, and stores those temporaries in
12842 the appropriate "hook" fields of the expression. `dest', if not NULL,
12843 specifies the destination that ffecom_expr_ will see, in case that
12844 helps avoid generating unused temporaries.
12845
12846 ~~Improve to avoid allocating unused temporaries by taking `dest'
12847 into account vis-a-vis aliasing requirements of complex/character
12848 functions. */
12849
12850void
12851ffecom_prepare_expr_ (ffebld expr, ffebld dest UNUSED)
5ff904cd 12852{
c7e4ee3a
CB
12853 ffeinfoBasictype bt;
12854 ffeinfoKindtype kt;
12855 ffetargetCharacterSize sz;
12856 tree tempvar = NULL_TREE;
5ff904cd 12857
c7e4ee3a
CB
12858 assert (current_binding_level->prep_state < 2);
12859
12860 if (! expr)
12861 return;
12862
12863 bt = ffeinfo_basictype (ffebld_info (expr));
12864 kt = ffeinfo_kindtype (ffebld_info (expr));
12865 sz = ffeinfo_size (ffebld_info (expr));
12866
12867 /* Generate whatever temporaries are needed to represent the result
12868 of the expression. */
12869
47d98fa2
CB
12870 if (bt == FFEINFO_basictypeCHARACTER)
12871 {
12872 while (ffebld_op (expr) == FFEBLD_opPAREN)
12873 expr = ffebld_left (expr);
12874 }
12875
c7e4ee3a 12876 switch (ffebld_op (expr))
5ff904cd 12877 {
c7e4ee3a
CB
12878 default:
12879 /* Don't make temps for SYMTER, CONTER, etc. */
12880 if (ffebld_arity (expr) == 0)
12881 break;
5ff904cd 12882
c7e4ee3a 12883 switch (bt)
5ff904cd 12884 {
c7e4ee3a
CB
12885 case FFEINFO_basictypeCOMPLEX:
12886 if (ffebld_op (expr) == FFEBLD_opFUNCREF)
12887 {
12888 ffesymbol s;
5ff904cd 12889
c7e4ee3a
CB
12890 if (ffebld_op (ffebld_left (expr)) != FFEBLD_opSYMTER)
12891 break;
5ff904cd 12892
c7e4ee3a
CB
12893 s = ffebld_symter (ffebld_left (expr));
12894 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT
68779408
CB
12895 || (ffesymbol_where (s) != FFEINFO_whereINTRINSIC
12896 && ! ffesymbol_is_f2c (s))
12897 || (ffesymbol_where (s) == FFEINFO_whereINTRINSIC
12898 && ! ffe_is_f2c_library ()))
c7e4ee3a
CB
12899 break;
12900 }
12901 else if (ffebld_op (expr) == FFEBLD_opPOWER)
12902 {
12903 /* Requires special treatment. There's no POW_CC function
12904 in libg2c, so POW_ZZ is used, which means we always
12905 need a double-complex temp, not a single-complex. */
12906 kt = FFEINFO_kindtypeREAL2;
12907 }
12908 else if (ffebld_op (expr) != FFEBLD_opDIVIDE)
12909 /* The other ops don't need temps for complex operands. */
12910 break;
5ff904cd 12911
c7e4ee3a
CB
12912 /* ~~~Avoid making temps for some intrinsics, such as AIMAG(C),
12913 REAL(C). See 19990325-0.f, routine `check', for cases. */
12914 tempvar = ffecom_make_tempvar ("complex",
12915 ffecom_tree_type
12916 [FFEINFO_basictypeCOMPLEX][kt],
12917 FFETARGET_charactersizeNONE,
12918 -1);
5ff904cd
JL
12919 break;
12920
c7e4ee3a
CB
12921 case FFEINFO_basictypeCHARACTER:
12922 if (ffebld_op (expr) != FFEBLD_opFUNCREF)
12923 break;
12924
12925 if (sz == FFETARGET_charactersizeNONE)
12926 /* ~~Kludge alert! This should someday be fixed. */
12927 sz = 24;
12928
12929 tempvar = ffecom_make_tempvar ("char", char_type_node, sz, -1);
5ff904cd
JL
12930 break;
12931
12932 default:
5ff904cd
JL
12933 break;
12934 }
c7e4ee3a 12935 break;
5ff904cd 12936
c7e4ee3a
CB
12937#ifdef HAHA
12938 case FFEBLD_opPOWER:
12939 {
12940 tree rtype, ltype;
12941 tree rtmp, ltmp, result;
5ff904cd 12942
c7e4ee3a
CB
12943 ltype = ffecom_type_expr (ffebld_left (expr));
12944 rtype = ffecom_type_expr (ffebld_right (expr));
5ff904cd 12945
c7e4ee3a
CB
12946 rtmp = ffecom_make_tempvar (rtype, FFETARGET_charactersizeNONE, -1);
12947 ltmp = ffecom_make_tempvar (ltype, FFETARGET_charactersizeNONE, -1);
12948 result = ffecom_make_tempvar (ltype, FFETARGET_charactersizeNONE, -1);
5ff904cd 12949
c7e4ee3a
CB
12950 tempvar = make_tree_vec (3);
12951 TREE_VEC_ELT (tempvar, 0) = rtmp;
12952 TREE_VEC_ELT (tempvar, 1) = ltmp;
12953 TREE_VEC_ELT (tempvar, 2) = result;
12954 }
12955 break;
12956#endif /* HAHA */
5ff904cd 12957
c7e4ee3a
CB
12958 case FFEBLD_opCONCATENATE:
12959 {
12960 /* This gets special handling, because only one set of temps
12961 is needed for a tree of these -- the tree is treated as
12962 a flattened list of concatenations when generating code. */
5ff904cd 12963
c7e4ee3a
CB
12964 ffecomConcatList_ catlist;
12965 tree ltmp, itmp, result;
12966 int count;
12967 int i;
5ff904cd 12968
c7e4ee3a
CB
12969 catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
12970 count = ffecom_concat_list_count_ (catlist);
5ff904cd 12971
c7e4ee3a
CB
12972 if (count >= 2)
12973 {
12974 ltmp
12975 = ffecom_make_tempvar ("concat_len",
12976 ffecom_f2c_ftnlen_type_node,
12977 FFETARGET_charactersizeNONE, count);
12978 itmp
12979 = ffecom_make_tempvar ("concat_item",
12980 ffecom_f2c_address_type_node,
12981 FFETARGET_charactersizeNONE, count);
12982 result
12983 = ffecom_make_tempvar ("concat_res",
12984 char_type_node,
12985 ffecom_concat_list_maxlen_ (catlist),
12986 -1);
12987
12988 tempvar = make_tree_vec (3);
12989 TREE_VEC_ELT (tempvar, 0) = ltmp;
12990 TREE_VEC_ELT (tempvar, 1) = itmp;
12991 TREE_VEC_ELT (tempvar, 2) = result;
12992 }
5ff904cd 12993
c7e4ee3a
CB
12994 for (i = 0; i < count; ++i)
12995 ffecom_prepare_arg_ptr_to_expr (ffecom_concat_list_expr_ (catlist,
12996 i));
5ff904cd 12997
c7e4ee3a 12998 ffecom_concat_list_kill_ (catlist);
5ff904cd 12999
c7e4ee3a
CB
13000 if (tempvar)
13001 {
13002 ffebld_nonter_set_hook (expr, tempvar);
13003 current_binding_level->prep_state = 1;
13004 }
13005 }
13006 return;
5ff904cd 13007
c7e4ee3a
CB
13008 case FFEBLD_opCONVERT:
13009 if (bt == FFEINFO_basictypeCHARACTER
13010 && ((ffebld_size_known (ffebld_left (expr))
13011 == FFETARGET_charactersizeNONE)
13012 || (ffebld_size_known (ffebld_left (expr)) >= sz)))
13013 tempvar = ffecom_make_tempvar ("convert", char_type_node, sz, -1);
13014 break;
13015 }
5ff904cd 13016
c7e4ee3a
CB
13017 if (tempvar)
13018 {
13019 ffebld_nonter_set_hook (expr, tempvar);
13020 current_binding_level->prep_state = 1;
13021 }
5ff904cd 13022
c7e4ee3a 13023 /* Prepare subexpressions for this expr. */
5ff904cd 13024
c7e4ee3a 13025 switch (ffebld_op (expr))
5ff904cd 13026 {
c7e4ee3a
CB
13027 case FFEBLD_opPERCENT_LOC:
13028 ffecom_prepare_ptr_to_expr (ffebld_left (expr));
13029 break;
5ff904cd 13030
c7e4ee3a
CB
13031 case FFEBLD_opPERCENT_VAL:
13032 case FFEBLD_opPERCENT_REF:
13033 ffecom_prepare_expr (ffebld_left (expr));
13034 break;
5ff904cd 13035
c7e4ee3a
CB
13036 case FFEBLD_opPERCENT_DESCR:
13037 ffecom_prepare_arg_ptr_to_expr (ffebld_left (expr));
13038 break;
5ff904cd 13039
c7e4ee3a
CB
13040 case FFEBLD_opITEM:
13041 {
13042 ffebld item;
5ff904cd 13043
c7e4ee3a
CB
13044 for (item = expr;
13045 item != NULL;
13046 item = ffebld_trail (item))
13047 if (ffebld_head (item) != NULL)
13048 ffecom_prepare_expr (ffebld_head (item));
13049 }
13050 break;
5ff904cd 13051
c7e4ee3a
CB
13052 default:
13053 /* Need to handle character conversion specially. */
13054 switch (ffebld_arity (expr))
13055 {
13056 case 2:
13057 ffecom_prepare_expr (ffebld_left (expr));
13058 ffecom_prepare_expr (ffebld_right (expr));
13059 break;
5ff904cd 13060
c7e4ee3a
CB
13061 case 1:
13062 ffecom_prepare_expr (ffebld_left (expr));
13063 break;
5ff904cd 13064
c7e4ee3a
CB
13065 default:
13066 break;
13067 }
13068 }
5ff904cd 13069
c7e4ee3a 13070 return;
5ff904cd
JL
13071}
13072
c7e4ee3a 13073/* Prepare expression for reading and writing.
5ff904cd 13074
c7e4ee3a
CB
13075 Like ffecom_prepare_expr, except for expressions to be evaluated
13076 via ffecom_expr_rw. */
5ff904cd 13077
c7e4ee3a
CB
13078void
13079ffecom_prepare_expr_rw (tree type, ffebld expr)
13080{
13081 /* This is all we support for now. */
13082 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
5ff904cd 13083
c7e4ee3a
CB
13084 /* ~~For now, it seems to be the same thing. */
13085 ffecom_prepare_expr (expr);
13086 return;
13087}
5ff904cd 13088
c7e4ee3a 13089/* Prepare expression for writing.
5ff904cd 13090
c7e4ee3a
CB
13091 Like ffecom_prepare_expr, except for expressions to be evaluated
13092 via ffecom_expr_w. */
5ff904cd
JL
13093
13094void
c7e4ee3a 13095ffecom_prepare_expr_w (tree type, ffebld expr)
5ff904cd 13096{
c7e4ee3a
CB
13097 /* This is all we support for now. */
13098 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
5ff904cd 13099
c7e4ee3a
CB
13100 /* ~~For now, it seems to be the same thing. */
13101 ffecom_prepare_expr (expr);
13102 return;
13103}
5ff904cd 13104
c7e4ee3a 13105/* Prepare expression for returning.
5ff904cd 13106
c7e4ee3a
CB
13107 Like ffecom_prepare_expr, except for expressions to be evaluated
13108 via ffecom_return_expr. */
5ff904cd 13109
c7e4ee3a
CB
13110void
13111ffecom_prepare_return_expr (ffebld expr)
13112{
13113 assert (current_binding_level->prep_state < 2);
5ff904cd 13114
c7e4ee3a
CB
13115 if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE
13116 && ffecom_is_altreturning_
13117 && expr != NULL)
13118 ffecom_prepare_expr (expr);
13119}
5ff904cd 13120
c7e4ee3a 13121/* Prepare pointer to expression.
5ff904cd 13122
c7e4ee3a
CB
13123 Like ffecom_prepare_expr, except for expressions to be evaluated
13124 via ffecom_ptr_to_expr. */
5ff904cd 13125
c7e4ee3a
CB
13126void
13127ffecom_prepare_ptr_to_expr (ffebld expr)
13128{
13129 /* ~~For now, it seems to be the same thing. */
13130 ffecom_prepare_expr (expr);
13131 return;
5ff904cd
JL
13132}
13133
c7e4ee3a 13134/* Transform expression into constant pointer-to-expression tree.
5ff904cd 13135
c7e4ee3a
CB
13136 If the expression can be transformed into a pointer-to-expression tree
13137 that is constant, that is done, and the tree returned. Else NULL_TREE
13138 is returned.
5ff904cd 13139
c7e4ee3a
CB
13140 That way, a caller can attempt to provide compile-time initialization
13141 of a variable and, if that fails, *then* choose to start a new block
13142 and resort to using temporaries, as appropriate. */
5ff904cd 13143
c7e4ee3a
CB
13144tree
13145ffecom_ptr_to_const_expr (ffebld expr)
5ff904cd 13146{
c7e4ee3a
CB
13147 if (! expr)
13148 return integer_zero_node;
5ff904cd 13149
c7e4ee3a
CB
13150 if (ffebld_op (expr) == FFEBLD_opANY)
13151 return error_mark_node;
5ff904cd 13152
c7e4ee3a
CB
13153 if (ffebld_arity (expr) == 0
13154 && (ffebld_op (expr) != FFEBLD_opSYMTER
13155 || ffebld_where (expr) == FFEINFO_whereCOMMON
13156 || ffebld_where (expr) == FFEINFO_whereGLOBAL
13157 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
5ff904cd 13158 {
c7e4ee3a
CB
13159 tree t;
13160
13161 t = ffecom_ptr_to_expr (expr);
13162 assert (TREE_CONSTANT (t));
13163 return t;
5ff904cd
JL
13164 }
13165
c7e4ee3a
CB
13166 return NULL_TREE;
13167}
13168
13169/* ffecom_return_expr -- Returns return-value expr given alt return expr
13170
13171 tree rtn; // NULL_TREE means use expand_null_return()
13172 ffebld expr; // NULL if no alt return expr to RETURN stmt
13173 rtn = ffecom_return_expr(expr);
13174
13175 Based on the program unit type and other info (like return function
13176 type, return master function type when alternate ENTRY points,
13177 whether subroutine has any alternate RETURN points, etc), returns the
13178 appropriate expression to be returned to the caller, or NULL_TREE
13179 meaning no return value or the caller expects it to be returned somewhere
13180 else (which is handled by other parts of this module). */
13181
5ff904cd 13182#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
13183tree
13184ffecom_return_expr (ffebld expr)
13185{
13186 tree rtn;
13187
13188 switch (ffecom_primary_entry_kind_)
5ff904cd 13189 {
c7e4ee3a
CB
13190 case FFEINFO_kindPROGRAM:
13191 case FFEINFO_kindBLOCKDATA:
13192 rtn = NULL_TREE;
13193 break;
5ff904cd 13194
c7e4ee3a
CB
13195 case FFEINFO_kindSUBROUTINE:
13196 if (!ffecom_is_altreturning_)
13197 rtn = NULL_TREE; /* No alt returns, never an expr. */
13198 else if (expr == NULL)
13199 rtn = integer_zero_node;
13200 else
13201 rtn = ffecom_expr (expr);
13202 break;
13203
13204 case FFEINFO_kindFUNCTION:
13205 if ((ffecom_multi_retval_ != NULL_TREE)
13206 || (ffesymbol_basictype (ffecom_primary_entry_)
13207 == FFEINFO_basictypeCHARACTER)
13208 || ((ffesymbol_basictype (ffecom_primary_entry_)
13209 == FFEINFO_basictypeCOMPLEX)
13210 && (ffecom_num_entrypoints_ == 0)
13211 && ffesymbol_is_f2c (ffecom_primary_entry_)))
13212 { /* Value is returned by direct assignment
13213 into (implicit) dummy. */
13214 rtn = NULL_TREE;
13215 break;
5ff904cd 13216 }
c7e4ee3a
CB
13217 rtn = ffecom_func_result_;
13218#if 0
13219 /* Spurious error if RETURN happens before first reference! So elide
13220 this code. In particular, for debugging registry, rtn should always
13221 be non-null after all, but TREE_USED won't be set until we encounter
13222 a reference in the code. Perfectly okay (but weird) code that,
13223 e.g., has "GOTO 20;10 RETURN;20 RTN=0;GOTO 10", would result in
13224 this diagnostic for no reason. Have people use -O -Wuninitialized
13225 and leave it to the back end to find obviously weird cases. */
5ff904cd 13226
c7e4ee3a
CB
13227 /* Used to "assert(rtn != NULL_TREE);" here, but it's kind of a valid
13228 situation; if the return value has never been referenced, it won't
13229 have a tree under 2pass mode. */
13230 if ((rtn == NULL_TREE)
13231 || !TREE_USED (rtn))
13232 {
13233 ffebad_start (FFEBAD_RETURN_VALUE_UNSET);
13234 ffebad_here (0, ffesymbol_where_line (ffecom_primary_entry_),
13235 ffesymbol_where_column (ffecom_primary_entry_));
13236 ffebad_string (ffesymbol_text (ffesymbol_funcresult
13237 (ffecom_primary_entry_)));
13238 ffebad_finish ();
13239 }
5ff904cd 13240#endif
c7e4ee3a 13241 break;
5ff904cd 13242
c7e4ee3a
CB
13243 default:
13244 assert ("bad unit kind" == NULL);
13245 case FFEINFO_kindANY:
13246 rtn = error_mark_node;
13247 break;
13248 }
5ff904cd 13249
c7e4ee3a
CB
13250 return rtn;
13251}
5ff904cd 13252
c7e4ee3a
CB
13253#endif
13254/* Do save_expr only if tree is not error_mark_node. */
5ff904cd
JL
13255
13256#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
13257tree
13258ffecom_save_tree (tree t)
5ff904cd 13259{
c7e4ee3a 13260 return save_expr (t);
5ff904cd 13261}
5ff904cd 13262#endif
c7e4ee3a
CB
13263
13264/* Start a compound statement (block). */
5ff904cd
JL
13265
13266#if FFECOM_targetCURRENT == FFECOM_targetGCC
13267void
c7e4ee3a 13268ffecom_start_compstmt (void)
5ff904cd 13269{
c7e4ee3a 13270 bison_rule_pushlevel_ ();
5ff904cd 13271}
c7e4ee3a 13272#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
5ff904cd 13273
c7e4ee3a 13274/* Public entry point for front end to access start_decl. */
5ff904cd
JL
13275
13276#if FFECOM_targetCURRENT == FFECOM_targetGCC
13277tree
c7e4ee3a 13278ffecom_start_decl (tree decl, bool is_initialized)
5ff904cd 13279{
c7e4ee3a
CB
13280 DECL_INITIAL (decl) = is_initialized ? error_mark_node : NULL_TREE;
13281 return start_decl (decl, FALSE);
13282}
5ff904cd 13283
c7e4ee3a
CB
13284#endif
13285/* ffecom_sym_commit -- Symbol's state being committed to reality
5ff904cd 13286
c7e4ee3a
CB
13287 ffesymbol s;
13288 ffecom_sym_commit(s);
5ff904cd 13289
c7e4ee3a
CB
13290 Does whatever the backend needs when a symbol is committed after having
13291 been backtrackable for a period of time. */
5ff904cd 13292
c7e4ee3a
CB
13293#if FFECOM_targetCURRENT == FFECOM_targetGCC
13294void
13295ffecom_sym_commit (ffesymbol s UNUSED)
13296{
13297 assert (!ffesymbol_retractable ());
13298}
5ff904cd 13299
c7e4ee3a
CB
13300#endif
13301/* ffecom_sym_end_transition -- Perform end transition on all symbols
5ff904cd 13302
c7e4ee3a 13303 ffecom_sym_end_transition();
5ff904cd 13304
c7e4ee3a
CB
13305 Does backend-specific stuff and also calls ffest_sym_end_transition
13306 to do the necessary FFE stuff.
5ff904cd 13307
c7e4ee3a
CB
13308 Backtracking is never enabled when this fn is called, so don't worry
13309 about it. */
5ff904cd 13310
c7e4ee3a
CB
13311ffesymbol
13312ffecom_sym_end_transition (ffesymbol s)
13313{
13314 ffestorag st;
5ff904cd 13315
c7e4ee3a 13316 assert (!ffesymbol_retractable ());
5ff904cd 13317
c7e4ee3a 13318 s = ffest_sym_end_transition (s);
5ff904cd 13319
c7e4ee3a
CB
13320#if FFECOM_targetCURRENT == FFECOM_targetGCC
13321 if ((ffesymbol_kind (s) == FFEINFO_kindBLOCKDATA)
13322 && (ffesymbol_where (s) == FFEINFO_whereGLOBAL))
13323 {
13324 ffecom_list_blockdata_
13325 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
13326 FFEINTRIN_specNONE,
13327 FFEINTRIN_impNONE),
13328 ffecom_list_blockdata_);
5ff904cd 13329 }
5ff904cd 13330#endif
5ff904cd 13331
c7e4ee3a
CB
13332 /* This is where we finally notice that a symbol has partial initialization
13333 and finalize it. */
5ff904cd 13334
c7e4ee3a
CB
13335 if (ffesymbol_accretion (s) != NULL)
13336 {
13337 assert (ffesymbol_init (s) == NULL);
13338 ffecom_notify_init_symbol (s);
13339 }
13340 else if (((st = ffesymbol_storage (s)) != NULL)
13341 && ((st = ffestorag_parent (st)) != NULL)
13342 && (ffestorag_accretion (st) != NULL))
13343 {
13344 assert (ffestorag_init (st) == NULL);
13345 ffecom_notify_init_storage (st);
13346 }
5ff904cd
JL
13347
13348#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
13349 if ((ffesymbol_kind (s) == FFEINFO_kindCOMMON)
13350 && (ffesymbol_where (s) == FFEINFO_whereLOCAL)
13351 && (ffesymbol_storage (s) != NULL))
13352 {
13353 ffecom_list_common_
13354 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
13355 FFEINTRIN_specNONE,
13356 FFEINTRIN_impNONE),
13357 ffecom_list_common_);
13358 }
13359#endif
5ff904cd 13360
c7e4ee3a
CB
13361 return s;
13362}
5ff904cd 13363
c7e4ee3a 13364/* ffecom_sym_exec_transition -- Perform exec transition on all symbols
5ff904cd 13365
c7e4ee3a 13366 ffecom_sym_exec_transition();
5ff904cd 13367
c7e4ee3a
CB
13368 Does backend-specific stuff and also calls ffest_sym_exec_transition
13369 to do the necessary FFE stuff.
5ff904cd 13370
c7e4ee3a
CB
13371 See the long-winded description in ffecom_sym_learned for info
13372 on handling the situation where backtracking is inhibited. */
5ff904cd 13373
c7e4ee3a
CB
13374ffesymbol
13375ffecom_sym_exec_transition (ffesymbol s)
13376{
13377 s = ffest_sym_exec_transition (s);
5ff904cd 13378
c7e4ee3a
CB
13379 return s;
13380}
5ff904cd 13381
c7e4ee3a 13382/* ffecom_sym_learned -- Initial or more info gained on symbol after exec
5ff904cd 13383
c7e4ee3a
CB
13384 ffesymbol s;
13385 s = ffecom_sym_learned(s);
5ff904cd 13386
c7e4ee3a
CB
13387 Called when a new symbol is seen after the exec transition or when more
13388 info (perhaps) is gained for an UNCERTAIN symbol. The symbol state when
13389 it arrives here is that all its latest info is updated already, so its
13390 state may be UNCERTAIN or UNDERSTOOD, it might already have the hook
13391 field filled in if its gone through here or exec_transition first, and
13392 so on.
5ff904cd 13393
c7e4ee3a
CB
13394 The backend probably wants to check ffesymbol_retractable() to see if
13395 backtracking is in effect. If so, the FFE's changes to the symbol may
13396 be retracted (undone) or committed (ratified), at which time the
13397 appropriate ffecom_sym_retract or _commit function will be called
13398 for that function.
5ff904cd 13399
c7e4ee3a
CB
13400 If the backend has its own backtracking mechanism, great, use it so that
13401 committal is a simple operation. Though it doesn't make much difference,
13402 I suppose: the reason for tentative symbol evolution in the FFE is to
13403 enable error detection in weird incorrect statements early and to disable
13404 incorrect error detection on a correct statement. The backend is not
13405 likely to introduce any information that'll get involved in these
13406 considerations, so it is probably just fine that the implementation
13407 model for this fn and for _exec_transition is to not do anything
13408 (besides the required FFE stuff) if ffesymbol_retractable() returns TRUE
13409 and instead wait until ffecom_sym_commit is called (which it never
13410 will be as long as we're using ambiguity-detecting statement analysis in
13411 the FFE, which we are initially to shake out the code, but don't depend
13412 on this), otherwise go ahead and do whatever is needed.
5ff904cd 13413
c7e4ee3a
CB
13414 In essence, then, when this fn and _exec_transition get called while
13415 backtracking is enabled, a general mechanism would be to flag which (or
13416 both) of these were called (and in what order? neat question as to what
13417 might happen that I'm too lame to think through right now) and then when
13418 _commit is called reproduce the original calling sequence, if any, for
13419 the two fns (at which point backtracking will, of course, be disabled). */
5ff904cd 13420
c7e4ee3a
CB
13421ffesymbol
13422ffecom_sym_learned (ffesymbol s)
13423{
13424 ffestorag_exec_layout (s);
5ff904cd 13425
c7e4ee3a 13426 return s;
5ff904cd
JL
13427}
13428
c7e4ee3a 13429/* ffecom_sym_retract -- Symbol's state being retracted from reality
5ff904cd 13430
c7e4ee3a
CB
13431 ffesymbol s;
13432 ffecom_sym_retract(s);
5ff904cd 13433
c7e4ee3a
CB
13434 Does whatever the backend needs when a symbol is retracted after having
13435 been backtrackable for a period of time. */
5ff904cd
JL
13436
13437#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
13438void
13439ffecom_sym_retract (ffesymbol s UNUSED)
5ff904cd 13440{
c7e4ee3a 13441 assert (!ffesymbol_retractable ());
5ff904cd 13442
c7e4ee3a
CB
13443#if 0 /* GCC doesn't commit any backtrackable sins,
13444 so nothing needed here. */
13445 switch (ffesymbol_hook (s).state)
5ff904cd 13446 {
c7e4ee3a 13447 case 0: /* nothing happened yet. */
5ff904cd
JL
13448 break;
13449
c7e4ee3a 13450 case 1: /* exec transition happened. */
5ff904cd
JL
13451 break;
13452
c7e4ee3a
CB
13453 case 2: /* learned happened. */
13454 break;
5ff904cd 13455
c7e4ee3a
CB
13456 case 3: /* learned then exec. */
13457 break;
13458
13459 case 4: /* exec then learned. */
5ff904cd
JL
13460 break;
13461
13462 default:
c7e4ee3a 13463 assert ("bad hook state" == NULL);
5ff904cd
JL
13464 break;
13465 }
c7e4ee3a
CB
13466#endif
13467}
5ff904cd 13468
c7e4ee3a
CB
13469#endif
13470/* Create temporary gcc label. */
13471
13472#if FFECOM_targetCURRENT == FFECOM_targetGCC
13473tree
13474ffecom_temp_label ()
13475{
13476 tree glabel;
13477 static int mynumber = 0;
13478
13479 glabel = build_decl (LABEL_DECL,
13480 ffecom_get_invented_identifier ("__g77_label_%d",
c7e4ee3a
CB
13481 mynumber++),
13482 void_type_node);
13483 DECL_CONTEXT (glabel) = current_function_decl;
13484 DECL_MODE (glabel) = VOIDmode;
13485
13486 return glabel;
5ff904cd
JL
13487}
13488
13489#endif
c7e4ee3a
CB
13490/* Return an expression that is usable as an arg in a conditional context
13491 (IF, DO WHILE, .NOT., and so on).
13492
13493 Use the one provided for the back end as of >2.6.0. */
5ff904cd
JL
13494
13495#if FFECOM_targetCURRENT == FFECOM_targetGCC
a2977d2d 13496tree
c7e4ee3a 13497ffecom_truth_value (tree expr)
5ff904cd 13498{
c7e4ee3a 13499 return truthvalue_conversion (expr);
5ff904cd 13500}
c7e4ee3a 13501
5ff904cd 13502#endif
c7e4ee3a
CB
13503/* Return the inversion of a truth value (the inversion of what
13504 ffecom_truth_value builds).
5ff904cd 13505
c7e4ee3a
CB
13506 Apparently invert_truthvalue, which is properly in the back end, is
13507 enough for now, so just use it. */
5ff904cd
JL
13508
13509#if FFECOM_targetCURRENT == FFECOM_targetGCC
13510tree
c7e4ee3a 13511ffecom_truth_value_invert (tree expr)
5ff904cd 13512{
c7e4ee3a 13513 return invert_truthvalue (ffecom_truth_value (expr));
5ff904cd
JL
13514}
13515
13516#endif
5ff904cd 13517
c7e4ee3a
CB
13518/* Return the tree that is the type of the expression, as would be
13519 returned in TREE_TYPE(ffecom_expr(expr)), without otherwise
13520 transforming the expression, generating temporaries, etc. */
5ff904cd 13521
c7e4ee3a
CB
13522tree
13523ffecom_type_expr (ffebld expr)
13524{
13525 ffeinfoBasictype bt;
13526 ffeinfoKindtype kt;
13527 tree tree_type;
13528
13529 assert (expr != NULL);
13530
13531 bt = ffeinfo_basictype (ffebld_info (expr));
13532 kt = ffeinfo_kindtype (ffebld_info (expr));
13533 tree_type = ffecom_tree_type[bt][kt];
13534
13535 switch (ffebld_op (expr))
13536 {
13537 case FFEBLD_opCONTER:
13538 case FFEBLD_opSYMTER:
13539 case FFEBLD_opARRAYREF:
13540 case FFEBLD_opUPLUS:
13541 case FFEBLD_opPAREN:
13542 case FFEBLD_opUMINUS:
13543 case FFEBLD_opADD:
13544 case FFEBLD_opSUBTRACT:
13545 case FFEBLD_opMULTIPLY:
13546 case FFEBLD_opDIVIDE:
13547 case FFEBLD_opPOWER:
13548 case FFEBLD_opNOT:
13549 case FFEBLD_opFUNCREF:
13550 case FFEBLD_opSUBRREF:
13551 case FFEBLD_opAND:
13552 case FFEBLD_opOR:
13553 case FFEBLD_opXOR:
13554 case FFEBLD_opNEQV:
13555 case FFEBLD_opEQV:
13556 case FFEBLD_opCONVERT:
13557 case FFEBLD_opLT:
13558 case FFEBLD_opLE:
13559 case FFEBLD_opEQ:
13560 case FFEBLD_opNE:
13561 case FFEBLD_opGT:
13562 case FFEBLD_opGE:
13563 case FFEBLD_opPERCENT_LOC:
13564 return tree_type;
13565
13566 case FFEBLD_opACCTER:
13567 case FFEBLD_opARRTER:
13568 case FFEBLD_opITEM:
13569 case FFEBLD_opSTAR:
13570 case FFEBLD_opBOUNDS:
13571 case FFEBLD_opREPEAT:
13572 case FFEBLD_opLABTER:
13573 case FFEBLD_opLABTOK:
13574 case FFEBLD_opIMPDO:
13575 case FFEBLD_opCONCATENATE:
13576 case FFEBLD_opSUBSTR:
13577 default:
13578 assert ("bad op for ffecom_type_expr" == NULL);
13579 /* Fall through. */
13580 case FFEBLD_opANY:
13581 return error_mark_node;
13582 }
13583}
13584
13585/* Return PARM_DECL for arg#1 of master fn containing alternate ENTRY points
13586
13587 If the PARM_DECL already exists, return it, else create it. It's an
13588 integer_type_node argument for the master function that implements a
13589 subroutine or function with more than one entrypoint and is bound at
13590 run time with the entrypoint number (0 for SUBROUTINE/FUNCTION, 1 for
13591 first ENTRY statement, and so on). */
5ff904cd
JL
13592
13593#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
13594tree
13595ffecom_which_entrypoint_decl ()
5ff904cd 13596{
c7e4ee3a
CB
13597 assert (ffecom_which_entrypoint_decl_ != NULL_TREE);
13598
13599 return ffecom_which_entrypoint_decl_;
5ff904cd
JL
13600}
13601
13602#endif
c7e4ee3a
CB
13603\f
13604/* The following sections consists of private and public functions
13605 that have the same names and perform roughly the same functions
13606 as counterparts in the C front end. Changes in the C front end
13607 might affect how things should be done here. Only functions
13608 needed by the back end should be public here; the rest should
13609 be private (static in the C sense). Functions needed by other
13610 g77 front-end modules should be accessed by them via public
13611 ffecom_* names, which should themselves call private versions
13612 in this section so the private versions are easy to recognize
13613 when upgrading to a new gcc and finding interesting changes
13614 in the front end.
5ff904cd 13615
c7e4ee3a
CB
13616 Functions named after rule "foo:" in c-parse.y are named
13617 "bison_rule_foo_" so they are easy to find. */
5ff904cd 13618
c7e4ee3a 13619#if FFECOM_targetCURRENT == FFECOM_targetGCC
5ff904cd 13620
c7e4ee3a
CB
13621static void
13622bison_rule_pushlevel_ ()
13623{
13624 emit_line_note (input_filename, lineno);
13625 pushlevel (0);
13626 clear_last_expr ();
13627 push_momentary ();
13628 expand_start_bindings (0);
13629}
5ff904cd 13630
c7e4ee3a
CB
13631static tree
13632bison_rule_compstmt_ ()
5ff904cd 13633{
c7e4ee3a
CB
13634 tree t;
13635 int keep = kept_level_p ();
5ff904cd 13636
c7e4ee3a
CB
13637 /* Make the temps go away. */
13638 if (! keep)
13639 current_binding_level->names = NULL_TREE;
5ff904cd 13640
c7e4ee3a
CB
13641 emit_line_note (input_filename, lineno);
13642 expand_end_bindings (getdecls (), keep, 0);
13643 t = poplevel (keep, 1, 0);
13644 pop_momentary ();
5ff904cd 13645
c7e4ee3a
CB
13646 return t;
13647}
5ff904cd 13648
c7e4ee3a
CB
13649/* Return a definition for a builtin function named NAME and whose data type
13650 is TYPE. TYPE should be a function type with argument types.
13651 FUNCTION_CODE tells later passes how to compile calls to this function.
13652 See tree.h for its possible values.
5ff904cd 13653
c7e4ee3a
CB
13654 If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME,
13655 the name to be called if we can't opencode the function. */
5ff904cd 13656
26db82d8
BS
13657tree
13658builtin_function (const char *name, tree type, int function_code,
13659 enum built_in_class class,
c7e4ee3a
CB
13660 const char *library_name)
13661{
13662 tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
13663 DECL_EXTERNAL (decl) = 1;
13664 TREE_PUBLIC (decl) = 1;
13665 if (library_name)
13666 DECL_ASSEMBLER_NAME (decl) = get_identifier (library_name);
13667 make_decl_rtl (decl, NULL_PTR, 1);
13668 pushdecl (decl);
26db82d8
BS
13669 DECL_BUILT_IN_CLASS (decl) = class;
13670 DECL_FUNCTION_CODE (decl) = function_code;
5ff904cd 13671
c7e4ee3a 13672 return decl;
5ff904cd
JL
13673}
13674
c7e4ee3a
CB
13675/* Handle when a new declaration NEWDECL
13676 has the same name as an old one OLDDECL
13677 in the same binding contour.
13678 Prints an error message if appropriate.
5ff904cd 13679
c7e4ee3a
CB
13680 If safely possible, alter OLDDECL to look like NEWDECL, and return 1.
13681 Otherwise, return 0. */
5ff904cd 13682
c7e4ee3a
CB
13683static int
13684duplicate_decls (tree newdecl, tree olddecl)
5ff904cd 13685{
c7e4ee3a
CB
13686 int types_match = 1;
13687 int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
13688 && DECL_INITIAL (newdecl) != 0);
13689 tree oldtype = TREE_TYPE (olddecl);
13690 tree newtype = TREE_TYPE (newdecl);
5ff904cd 13691
c7e4ee3a
CB
13692 if (olddecl == newdecl)
13693 return 1;
5ff904cd 13694
c7e4ee3a
CB
13695 if (TREE_CODE (newtype) == ERROR_MARK
13696 || TREE_CODE (oldtype) == ERROR_MARK)
13697 types_match = 0;
5ff904cd 13698
c7e4ee3a
CB
13699 /* New decl is completely inconsistent with the old one =>
13700 tell caller to replace the old one.
13701 This is always an error except in the case of shadowing a builtin. */
13702 if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
13703 return 0;
5ff904cd 13704
c7e4ee3a
CB
13705 /* For real parm decl following a forward decl,
13706 return 1 so old decl will be reused. */
13707 if (types_match && TREE_CODE (newdecl) == PARM_DECL
13708 && TREE_ASM_WRITTEN (olddecl) && ! TREE_ASM_WRITTEN (newdecl))
13709 return 1;
5ff904cd 13710
c7e4ee3a
CB
13711 /* The new declaration is the same kind of object as the old one.
13712 The declarations may partially match. Print warnings if they don't
13713 match enough. Ultimately, copy most of the information from the new
13714 decl to the old one, and keep using the old one. */
5ff904cd 13715
c7e4ee3a
CB
13716 if (TREE_CODE (olddecl) == FUNCTION_DECL
13717 && DECL_BUILT_IN (olddecl))
13718 {
13719 /* A function declaration for a built-in function. */
13720 if (!TREE_PUBLIC (newdecl))
13721 return 0;
13722 else if (!types_match)
13723 {
13724 /* Accept the return type of the new declaration if same modes. */
13725 tree oldreturntype = TREE_TYPE (TREE_TYPE (olddecl));
13726 tree newreturntype = TREE_TYPE (TREE_TYPE (newdecl));
5ff904cd 13727
c7e4ee3a
CB
13728 if (TYPE_MODE (oldreturntype) == TYPE_MODE (newreturntype))
13729 {
13730 /* Function types may be shared, so we can't just modify
13731 the return type of olddecl's function type. */
13732 tree newtype
13733 = build_function_type (newreturntype,
13734 TYPE_ARG_TYPES (TREE_TYPE (olddecl)));
5ff904cd 13735
c7e4ee3a
CB
13736 types_match = 1;
13737 if (types_match)
13738 TREE_TYPE (olddecl) = newtype;
13739 }
c7e4ee3a
CB
13740 }
13741 if (!types_match)
13742 return 0;
13743 }
13744 else if (TREE_CODE (olddecl) == FUNCTION_DECL
13745 && DECL_SOURCE_LINE (olddecl) == 0)
5ff904cd 13746 {
c7e4ee3a
CB
13747 /* A function declaration for a predeclared function
13748 that isn't actually built in. */
13749 if (!TREE_PUBLIC (newdecl))
13750 return 0;
13751 else if (!types_match)
13752 {
13753 /* If the types don't match, preserve volatility indication.
13754 Later on, we will discard everything else about the
13755 default declaration. */
13756 TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
13757 }
13758 }
5ff904cd 13759
c7e4ee3a
CB
13760 /* Copy all the DECL_... slots specified in the new decl
13761 except for any that we copy here from the old type.
5ff904cd 13762
c7e4ee3a
CB
13763 Past this point, we don't change OLDTYPE and NEWTYPE
13764 even if we change the types of NEWDECL and OLDDECL. */
5ff904cd 13765
c7e4ee3a
CB
13766 if (types_match)
13767 {
c7e4ee3a
CB
13768 /* Merge the data types specified in the two decls. */
13769 if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl))
13770 TREE_TYPE (newdecl)
13771 = TREE_TYPE (olddecl)
13772 = TREE_TYPE (newdecl);
5ff904cd 13773
c7e4ee3a
CB
13774 /* Lay the type out, unless already done. */
13775 if (oldtype != TREE_TYPE (newdecl))
13776 {
13777 if (TREE_TYPE (newdecl) != error_mark_node)
13778 layout_type (TREE_TYPE (newdecl));
13779 if (TREE_CODE (newdecl) != FUNCTION_DECL
13780 && TREE_CODE (newdecl) != TYPE_DECL
13781 && TREE_CODE (newdecl) != CONST_DECL)
13782 layout_decl (newdecl, 0);
13783 }
13784 else
13785 {
13786 /* Since the type is OLDDECL's, make OLDDECL's size go with. */
13787 DECL_SIZE (newdecl) = DECL_SIZE (olddecl);
06ceef4e 13788 DECL_SIZE_UNIT (newdecl) = DECL_SIZE_UNIT (olddecl);
c7e4ee3a
CB
13789 if (TREE_CODE (olddecl) != FUNCTION_DECL)
13790 if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
11cf4d18
JJ
13791 {
13792 DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
13793 DECL_USER_ALIGN (newdecl) |= DECL_USER_ALIGN (olddecl);
13794 }
c7e4ee3a 13795 }
5ff904cd 13796
c7e4ee3a
CB
13797 /* Keep the old rtl since we can safely use it. */
13798 DECL_RTL (newdecl) = DECL_RTL (olddecl);
5ff904cd 13799
c7e4ee3a
CB
13800 /* Merge the type qualifiers. */
13801 if (DECL_BUILT_IN_NONANSI (olddecl) && TREE_THIS_VOLATILE (olddecl)
13802 && !TREE_THIS_VOLATILE (newdecl))
13803 TREE_THIS_VOLATILE (olddecl) = 0;
13804 if (TREE_READONLY (newdecl))
13805 TREE_READONLY (olddecl) = 1;
13806 if (TREE_THIS_VOLATILE (newdecl))
13807 {
13808 TREE_THIS_VOLATILE (olddecl) = 1;
13809 if (TREE_CODE (newdecl) == VAR_DECL)
13810 make_var_volatile (newdecl);
13811 }
5ff904cd 13812
c7e4ee3a
CB
13813 /* Keep source location of definition rather than declaration.
13814 Likewise, keep decl at outer scope. */
13815 if ((DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0)
13816 || (DECL_CONTEXT (newdecl) != 0 && DECL_CONTEXT (olddecl) == 0))
13817 {
13818 DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl);
13819 DECL_SOURCE_FILE (newdecl) = DECL_SOURCE_FILE (olddecl);
5ff904cd 13820
c7e4ee3a
CB
13821 if (DECL_CONTEXT (olddecl) == 0
13822 && TREE_CODE (newdecl) != FUNCTION_DECL)
13823 DECL_CONTEXT (newdecl) = 0;
13824 }
5ff904cd 13825
c7e4ee3a
CB
13826 /* Merge the unused-warning information. */
13827 if (DECL_IN_SYSTEM_HEADER (olddecl))
13828 DECL_IN_SYSTEM_HEADER (newdecl) = 1;
13829 else if (DECL_IN_SYSTEM_HEADER (newdecl))
13830 DECL_IN_SYSTEM_HEADER (olddecl) = 1;
5ff904cd 13831
c7e4ee3a
CB
13832 /* Merge the initialization information. */
13833 if (DECL_INITIAL (newdecl) == 0)
13834 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
5ff904cd 13835
c7e4ee3a
CB
13836 /* Merge the section attribute.
13837 We want to issue an error if the sections conflict but that must be
13838 done later in decl_attributes since we are called before attributes
13839 are assigned. */
13840 if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
13841 DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
5ff904cd 13842
c7e4ee3a
CB
13843#if BUILT_FOR_270
13844 if (TREE_CODE (newdecl) == FUNCTION_DECL)
13845 {
13846 DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
13847 DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
13848 }
5ff904cd 13849#endif
c7e4ee3a
CB
13850 }
13851 /* If cannot merge, then use the new type and qualifiers,
13852 and don't preserve the old rtl. */
13853 else
13854 {
13855 TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
13856 TREE_READONLY (olddecl) = TREE_READONLY (newdecl);
13857 TREE_THIS_VOLATILE (olddecl) = TREE_THIS_VOLATILE (newdecl);
13858 TREE_SIDE_EFFECTS (olddecl) = TREE_SIDE_EFFECTS (newdecl);
13859 }
5ff904cd 13860
c7e4ee3a
CB
13861 /* Merge the storage class information. */
13862 /* For functions, static overrides non-static. */
13863 if (TREE_CODE (newdecl) == FUNCTION_DECL)
13864 {
13865 TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl);
13866 /* This is since we don't automatically
13867 copy the attributes of NEWDECL into OLDDECL. */
13868 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
13869 /* If this clears `static', clear it in the identifier too. */
13870 if (! TREE_PUBLIC (olddecl))
13871 TREE_PUBLIC (DECL_NAME (olddecl)) = 0;
13872 }
13873 if (DECL_EXTERNAL (newdecl))
13874 {
13875 TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
13876 DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
13877 /* An extern decl does not override previous storage class. */
13878 TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
13879 }
13880 else
13881 {
13882 TREE_STATIC (olddecl) = TREE_STATIC (newdecl);
13883 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
13884 }
5ff904cd 13885
c7e4ee3a
CB
13886 /* If either decl says `inline', this fn is inline,
13887 unless its definition was passed already. */
13888 if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == 0)
13889 DECL_INLINE (olddecl) = 1;
13890 DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
5ff904cd 13891
c7e4ee3a
CB
13892 /* Get rid of any built-in function if new arg types don't match it
13893 or if we have a function definition. */
13894 if (TREE_CODE (newdecl) == FUNCTION_DECL
13895 && DECL_BUILT_IN (olddecl)
13896 && (!types_match || new_is_definition))
13897 {
13898 TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
26db82d8 13899 DECL_BUILT_IN_CLASS (olddecl) = NOT_BUILT_IN;
c7e4ee3a 13900 }
5ff904cd 13901
c7e4ee3a
CB
13902 /* If redeclaring a builtin function, and not a definition,
13903 it stays built in.
13904 Also preserve various other info from the definition. */
13905 if (TREE_CODE (newdecl) == FUNCTION_DECL && !new_is_definition)
13906 {
13907 if (DECL_BUILT_IN (olddecl))
13908 {
26db82d8 13909 DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
c7e4ee3a
CB
13910 DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
13911 }
13912 else
13913 DECL_FRAME_SIZE (newdecl) = DECL_FRAME_SIZE (olddecl);
5ff904cd 13914
c7e4ee3a
CB
13915 DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
13916 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
13917 DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
13918 DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
13919 }
5ff904cd 13920
c7e4ee3a
CB
13921 /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
13922 But preserve olddecl's DECL_UID. */
13923 {
13924 register unsigned olddecl_uid = DECL_UID (olddecl);
5ff904cd 13925
c7e4ee3a
CB
13926 memcpy ((char *) olddecl + sizeof (struct tree_common),
13927 (char *) newdecl + sizeof (struct tree_common),
13928 sizeof (struct tree_decl) - sizeof (struct tree_common));
13929 DECL_UID (olddecl) = olddecl_uid;
13930 }
5ff904cd 13931
c7e4ee3a 13932 return 1;
5ff904cd
JL
13933}
13934
c7e4ee3a
CB
13935/* Finish processing of a declaration;
13936 install its initial value.
13937 If the length of an array type is not known before,
13938 it must be determined now, from the initial value, or it is an error. */
13939
5ff904cd 13940static void
c7e4ee3a 13941finish_decl (tree decl, tree init, bool is_top_level)
5ff904cd 13942{
c7e4ee3a
CB
13943 register tree type = TREE_TYPE (decl);
13944 int was_incomplete = (DECL_SIZE (decl) == 0);
13945 int temporary = allocation_temporary_p ();
13946 bool at_top_level = (current_binding_level == global_binding_level);
13947 bool top_level = is_top_level || at_top_level;
5ff904cd 13948
c7e4ee3a
CB
13949 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
13950 level anyway. */
13951 assert (!is_top_level || !at_top_level);
5ff904cd 13952
c7e4ee3a
CB
13953 if (TREE_CODE (decl) == PARM_DECL)
13954 assert (init == NULL_TREE);
13955 /* Remember that PARM_DECL doesn't have a DECL_INITIAL field per se -- it
13956 overlaps DECL_ARG_TYPE. */
13957 else if (init == NULL_TREE)
13958 assert (DECL_INITIAL (decl) == NULL_TREE);
13959 else
13960 assert (DECL_INITIAL (decl) == error_mark_node);
5ff904cd 13961
c7e4ee3a 13962 if (init != NULL_TREE)
5ff904cd 13963 {
c7e4ee3a
CB
13964 if (TREE_CODE (decl) != TYPE_DECL)
13965 DECL_INITIAL (decl) = init;
13966 else
13967 {
13968 /* typedef foo = bar; store the type of bar as the type of foo. */
13969 TREE_TYPE (decl) = TREE_TYPE (init);
13970 DECL_INITIAL (decl) = init = 0;
13971 }
5ff904cd
JL
13972 }
13973
c7e4ee3a
CB
13974 /* Pop back to the obstack that is current for this binding level. This is
13975 because MAXINDEX, rtl, etc. to be made below must go in the permanent
13976 obstack. But don't discard the temporary data yet. */
13977 pop_obstacks ();
5ff904cd 13978
c7e4ee3a 13979 /* Deduce size of array from initialization, if not already known */
5ff904cd 13980
c7e4ee3a
CB
13981 if (TREE_CODE (type) == ARRAY_TYPE
13982 && TYPE_DOMAIN (type) == 0
13983 && TREE_CODE (decl) != TYPE_DECL)
13984 {
13985 assert (top_level);
13986 assert (was_incomplete);
5ff904cd 13987
c7e4ee3a
CB
13988 layout_decl (decl, 0);
13989 }
5ff904cd 13990
c7e4ee3a
CB
13991 if (TREE_CODE (decl) == VAR_DECL)
13992 {
13993 if (DECL_SIZE (decl) == NULL_TREE
13994 && TYPE_SIZE (TREE_TYPE (decl)) != NULL_TREE)
13995 layout_decl (decl, 0);
5ff904cd 13996
c7e4ee3a
CB
13997 if (DECL_SIZE (decl) == NULL_TREE
13998 && (TREE_STATIC (decl)
13999 ?
14000 /* A static variable with an incomplete type is an error if it is
14001 initialized. Also if it is not file scope. Otherwise, let it
14002 through, but if it is not `extern' then it may cause an error
14003 message later. */
14004 (DECL_INITIAL (decl) != 0 || DECL_CONTEXT (decl) != 0)
14005 :
14006 /* An automatic variable with an incomplete type is an error. */
14007 !DECL_EXTERNAL (decl)))
14008 {
14009 assert ("storage size not known" == NULL);
14010 abort ();
14011 }
5ff904cd 14012
c7e4ee3a
CB
14013 if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
14014 && (DECL_SIZE (decl) != 0)
14015 && (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST))
14016 {
14017 assert ("storage size not constant" == NULL);
14018 abort ();
14019 }
14020 }
5ff904cd 14021
c7e4ee3a
CB
14022 /* Output the assembler code and/or RTL code for variables and functions,
14023 unless the type is an undefined structure or union. If not, it will get
14024 done when the type is completed. */
5ff904cd 14025
c7e4ee3a 14026 if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
5ff904cd 14027 {
c7e4ee3a
CB
14028 rest_of_decl_compilation (decl, NULL,
14029 DECL_CONTEXT (decl) == 0,
14030 0);
5ff904cd 14031
c7e4ee3a
CB
14032 if (DECL_CONTEXT (decl) != 0)
14033 {
14034 /* Recompute the RTL of a local array now if it used to be an
14035 incomplete type. */
14036 if (was_incomplete
14037 && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
5ff904cd 14038 {
c7e4ee3a
CB
14039 /* If we used it already as memory, it must stay in memory. */
14040 TREE_ADDRESSABLE (decl) = TREE_USED (decl);
14041 /* If it's still incomplete now, no init will save it. */
14042 if (DECL_SIZE (decl) == 0)
14043 DECL_INITIAL (decl) = 0;
14044 expand_decl (decl);
5ff904cd 14045 }
c7e4ee3a
CB
14046 /* Compute and store the initial value. */
14047 if (TREE_CODE (decl) != FUNCTION_DECL)
14048 expand_decl_init (decl);
14049 }
14050 }
14051 else if (TREE_CODE (decl) == TYPE_DECL)
14052 {
14053 rest_of_decl_compilation (decl, NULL_PTR,
14054 DECL_CONTEXT (decl) == 0,
14055 0);
14056 }
5ff904cd 14057
c7e4ee3a
CB
14058 if (!(TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl))
14059 && temporary
14060 /* DECL_INITIAL is not defined in PARM_DECLs, since it shares space with
14061 DECL_ARG_TYPE. */
14062 && TREE_CODE (decl) != PARM_DECL)
14063 {
14064 /* We need to remember that this array HAD an initialization, but
14065 discard the actual temporary nodes, since we can't have a permanent
14066 node keep pointing to them. */
14067 /* We make an exception for inline functions, since it's normal for a
14068 local extern redeclaration of an inline function to have a copy of
14069 the top-level decl's DECL_INLINE. */
14070 if ((DECL_INITIAL (decl) != 0)
14071 && (DECL_INITIAL (decl) != error_mark_node))
14072 {
14073 /* If this is a const variable, then preserve the
14074 initializer instead of discarding it so that we can optimize
14075 references to it. */
14076 /* This test used to include TREE_STATIC, but this won't be set
14077 for function level initializers. */
14078 if (TREE_READONLY (decl))
5ff904cd 14079 {
c7e4ee3a 14080 preserve_initializer ();
5ff904cd 14081
c7e4ee3a
CB
14082 /* The initializer and DECL must have the same (or equivalent
14083 types), but if the initializer is a STRING_CST, its type
14084 might not be on the right obstack, so copy the type
14085 of DECL. */
14086 TREE_TYPE (DECL_INITIAL (decl)) = type;
5ff904cd 14087 }
c7e4ee3a
CB
14088 else
14089 DECL_INITIAL (decl) = error_mark_node;
5ff904cd 14090 }
5ff904cd 14091 }
c7e4ee3a 14092
c7e4ee3a
CB
14093 /* If we have gone back from temporary to permanent allocation, actually
14094 free the temporary space that we no longer need. */
14095 if (temporary && !allocation_temporary_p ())
14096 permanent_allocation (0);
5ff904cd 14097
c7e4ee3a
CB
14098 /* At the end of a declaration, throw away any variable type sizes of types
14099 defined inside that declaration. There is no use computing them in the
14100 following function definition. */
14101 if (current_binding_level == global_binding_level)
14102 get_pending_sizes ();
14103}
5ff904cd 14104
c7e4ee3a
CB
14105/* Finish up a function declaration and compile that function
14106 all the way to assembler language output. The free the storage
14107 for the function definition.
5ff904cd 14108
c7e4ee3a 14109 This is called after parsing the body of the function definition.
5ff904cd 14110
c7e4ee3a
CB
14111 NESTED is nonzero if the function being finished is nested in another. */
14112
14113static void
14114finish_function (int nested)
14115{
14116 register tree fndecl = current_function_decl;
14117
14118 assert (fndecl != NULL_TREE);
14119 if (TREE_CODE (fndecl) != ERROR_MARK)
14120 {
14121 if (nested)
14122 assert (DECL_CONTEXT (fndecl) != NULL_TREE);
5ff904cd 14123 else
c7e4ee3a
CB
14124 assert (DECL_CONTEXT (fndecl) == NULL_TREE);
14125 }
5ff904cd 14126
c7e4ee3a
CB
14127/* TREE_READONLY (fndecl) = 1;
14128 This caused &foo to be of type ptr-to-const-function
14129 which then got a warning when stored in a ptr-to-function variable. */
5ff904cd 14130
c7e4ee3a 14131 poplevel (1, 0, 1);
5ff904cd 14132
c7e4ee3a
CB
14133 if (TREE_CODE (fndecl) != ERROR_MARK)
14134 {
14135 BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
5ff904cd 14136
c7e4ee3a 14137 /* Must mark the RESULT_DECL as being in this function. */
5ff904cd 14138
c7e4ee3a 14139 DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
5ff904cd 14140
c7e4ee3a
CB
14141 /* Obey `register' declarations if `setjmp' is called in this fn. */
14142 /* Generate rtl for function exit. */
14143 expand_function_end (input_filename, lineno, 0);
5ff904cd 14144
c7e4ee3a
CB
14145 /* So we can tell if jump_optimize sets it to 1. */
14146 can_reach_end = 0;
5ff904cd 14147
7189a4b0
GK
14148 /* If this is a nested function, protect the local variables in the stack
14149 above us from being collected while we're compiling this function. */
14150 if (ggc_p && nested)
14151 ggc_push_context ();
14152
c7e4ee3a
CB
14153 /* Run the optimizers and output the assembler code for this function. */
14154 rest_of_compilation (fndecl);
7189a4b0
GK
14155
14156 /* Undo the GC context switch. */
14157 if (ggc_p && nested)
14158 ggc_pop_context ();
c7e4ee3a 14159 }
5ff904cd 14160
c7e4ee3a
CB
14161 /* Free all the tree nodes making up this function. */
14162 /* Switch back to allocating nodes permanently until we start another
14163 function. */
14164 if (!nested)
14165 permanent_allocation (1);
14166
14167 if (TREE_CODE (fndecl) != ERROR_MARK
14168 && !nested
14169 && DECL_SAVED_INSNS (fndecl) == 0)
14170 {
14171 /* Stop pointing to the local nodes about to be freed. */
14172 /* But DECL_INITIAL must remain nonzero so we know this was an actual
14173 function definition. */
14174 /* For a nested function, this is done in pop_f_function_context. */
14175 /* If rest_of_compilation set this to 0, leave it 0. */
14176 if (DECL_INITIAL (fndecl) != 0)
14177 DECL_INITIAL (fndecl) = error_mark_node;
14178 DECL_ARGUMENTS (fndecl) = 0;
5ff904cd 14179 }
c7e4ee3a
CB
14180
14181 if (!nested)
5ff904cd 14182 {
c7e4ee3a
CB
14183 /* Let the error reporting routines know that we're outside a function.
14184 For a nested function, this value is used in pop_c_function_context
14185 and then reset via pop_function_context. */
14186 ffecom_outer_function_decl_ = current_function_decl = NULL;
5ff904cd 14187 }
c7e4ee3a 14188}
5ff904cd 14189
c7e4ee3a
CB
14190/* Plug-in replacement for identifying the name of a decl and, for a
14191 function, what we call it in diagnostics. For now, "program unit"
14192 should suffice, since it's a bit of a hassle to figure out which
14193 of several kinds of things it is. Note that it could conceivably
14194 be a statement function, which probably isn't really a program unit
14195 per se, but if that comes up, it should be easy to check (being a
14196 nested function and all). */
14197
4b731ffa 14198static const char *
c7e4ee3a
CB
14199lang_printable_name (tree decl, int v)
14200{
14201 /* Just to keep GCC quiet about the unused variable.
14202 In theory, differing values of V should produce different
14203 output. */
14204 switch (v)
5ff904cd 14205 {
c7e4ee3a
CB
14206 default:
14207 if (TREE_CODE (decl) == ERROR_MARK)
14208 return "erroneous code";
14209 return IDENTIFIER_POINTER (DECL_NAME (decl));
5ff904cd 14210 }
c7e4ee3a
CB
14211}
14212
14213/* g77's function to print out name of current function that caused
14214 an error. */
14215
14216#if BUILT_FOR_270
b0791fa9
KG
14217static void
14218lang_print_error_function (const char *file)
c7e4ee3a
CB
14219{
14220 static ffeglobal last_g = NULL;
14221 static ffesymbol last_s = NULL;
14222 ffeglobal g;
14223 ffesymbol s;
14224 const char *kind;
14225
14226 if ((ffecom_primary_entry_ == NULL)
14227 || (ffesymbol_global (ffecom_primary_entry_) == NULL))
5ff904cd 14228 {
c7e4ee3a
CB
14229 g = NULL;
14230 s = NULL;
14231 kind = NULL;
5ff904cd
JL
14232 }
14233 else
14234 {
c7e4ee3a
CB
14235 g = ffesymbol_global (ffecom_primary_entry_);
14236 if (ffecom_nested_entry_ == NULL)
14237 {
14238 s = ffecom_primary_entry_;
14239 switch (ffesymbol_kind (s))
14240 {
14241 case FFEINFO_kindFUNCTION:
14242 kind = "function";
14243 break;
5ff904cd 14244
c7e4ee3a
CB
14245 case FFEINFO_kindSUBROUTINE:
14246 kind = "subroutine";
14247 break;
5ff904cd 14248
c7e4ee3a
CB
14249 case FFEINFO_kindPROGRAM:
14250 kind = "program";
14251 break;
14252
14253 case FFEINFO_kindBLOCKDATA:
14254 kind = "block-data";
14255 break;
14256
14257 default:
14258 kind = ffeinfo_kind_message (ffesymbol_kind (s));
14259 break;
14260 }
14261 }
14262 else
14263 {
14264 s = ffecom_nested_entry_;
14265 kind = "statement function";
14266 }
5ff904cd
JL
14267 }
14268
c7e4ee3a 14269 if ((last_g != g) || (last_s != s))
5ff904cd 14270 {
c7e4ee3a
CB
14271 if (file)
14272 fprintf (stderr, "%s: ", file);
14273
14274 if (s == NULL)
14275 fprintf (stderr, "Outside of any program unit:\n");
14276 else
5ff904cd 14277 {
c7e4ee3a
CB
14278 const char *name = ffesymbol_text (s);
14279
14280 fprintf (stderr, "In %s `%s':\n", kind, name);
5ff904cd 14281 }
5ff904cd 14282
c7e4ee3a
CB
14283 last_g = g;
14284 last_s = s;
5ff904cd 14285 }
c7e4ee3a
CB
14286}
14287#endif
5ff904cd 14288
c7e4ee3a 14289/* Similar to `lookup_name' but look only at current binding level. */
5ff904cd 14290
c7e4ee3a
CB
14291static tree
14292lookup_name_current_level (tree name)
14293{
14294 register tree t;
5ff904cd 14295
c7e4ee3a
CB
14296 if (current_binding_level == global_binding_level)
14297 return IDENTIFIER_GLOBAL_VALUE (name);
14298
14299 if (IDENTIFIER_LOCAL_VALUE (name) == 0)
14300 return 0;
14301
14302 for (t = current_binding_level->names; t; t = TREE_CHAIN (t))
14303 if (DECL_NAME (t) == name)
14304 break;
14305
14306 return t;
5ff904cd
JL
14307}
14308
c7e4ee3a 14309/* Create a new `struct binding_level'. */
5ff904cd 14310
c7e4ee3a
CB
14311static struct binding_level *
14312make_binding_level ()
5ff904cd 14313{
c7e4ee3a
CB
14314 /* NOSTRICT */
14315 return (struct binding_level *) xmalloc (sizeof (struct binding_level));
14316}
5ff904cd 14317
c7e4ee3a
CB
14318/* Save and restore the variables in this file and elsewhere
14319 that keep track of the progress of compilation of the current function.
14320 Used for nested functions. */
5ff904cd 14321
c7e4ee3a
CB
14322struct f_function
14323{
14324 struct f_function *next;
14325 tree named_labels;
14326 tree shadowed_labels;
14327 struct binding_level *binding_level;
14328};
5ff904cd 14329
c7e4ee3a 14330struct f_function *f_function_chain;
5ff904cd 14331
c7e4ee3a 14332/* Restore the variables used during compilation of a C function. */
5ff904cd 14333
c7e4ee3a
CB
14334static void
14335pop_f_function_context ()
14336{
14337 struct f_function *p = f_function_chain;
14338 tree link;
5ff904cd 14339
c7e4ee3a
CB
14340 /* Bring back all the labels that were shadowed. */
14341 for (link = shadowed_labels; link; link = TREE_CHAIN (link))
14342 if (DECL_NAME (TREE_VALUE (link)) != 0)
14343 IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)))
14344 = TREE_VALUE (link);
5ff904cd 14345
c7e4ee3a
CB
14346 if (current_function_decl != error_mark_node
14347 && DECL_SAVED_INSNS (current_function_decl) == 0)
14348 {
14349 /* Stop pointing to the local nodes about to be freed. */
14350 /* But DECL_INITIAL must remain nonzero so we know this was an actual
14351 function definition. */
14352 DECL_INITIAL (current_function_decl) = error_mark_node;
14353 DECL_ARGUMENTS (current_function_decl) = 0;
5ff904cd
JL
14354 }
14355
c7e4ee3a 14356 pop_function_context ();
5ff904cd 14357
c7e4ee3a 14358 f_function_chain = p->next;
5ff904cd 14359
c7e4ee3a
CB
14360 named_labels = p->named_labels;
14361 shadowed_labels = p->shadowed_labels;
14362 current_binding_level = p->binding_level;
5ff904cd 14363
c7e4ee3a
CB
14364 free (p);
14365}
5ff904cd 14366
c7e4ee3a
CB
14367/* Save and reinitialize the variables
14368 used during compilation of a C function. */
5ff904cd 14369
c7e4ee3a
CB
14370static void
14371push_f_function_context ()
14372{
14373 struct f_function *p
14374 = (struct f_function *) xmalloc (sizeof (struct f_function));
5ff904cd 14375
c7e4ee3a
CB
14376 push_function_context ();
14377
14378 p->next = f_function_chain;
14379 f_function_chain = p;
14380
14381 p->named_labels = named_labels;
14382 p->shadowed_labels = shadowed_labels;
14383 p->binding_level = current_binding_level;
14384}
5ff904cd 14385
c7e4ee3a
CB
14386static void
14387push_parm_decl (tree parm)
14388{
14389 int old_immediate_size_expand = immediate_size_expand;
5ff904cd 14390
c7e4ee3a 14391 /* Don't try computing parm sizes now -- wait till fn is called. */
5ff904cd 14392
c7e4ee3a 14393 immediate_size_expand = 0;
5ff904cd 14394
c7e4ee3a 14395 push_obstacks_nochange ();
5ff904cd 14396
c7e4ee3a 14397 /* Fill in arg stuff. */
5ff904cd 14398
c7e4ee3a
CB
14399 DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
14400 DECL_ARG_TYPE_AS_WRITTEN (parm) = TREE_TYPE (parm);
14401 TREE_READONLY (parm) = 1; /* All implementation args are read-only. */
5ff904cd 14402
c7e4ee3a
CB
14403 parm = pushdecl (parm);
14404
14405 immediate_size_expand = old_immediate_size_expand;
14406
14407 finish_decl (parm, NULL_TREE, FALSE);
5ff904cd
JL
14408}
14409
c7e4ee3a 14410/* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL, if appropriate. */
5ff904cd 14411
c7e4ee3a
CB
14412static tree
14413pushdecl_top_level (x)
14414 tree x;
14415{
14416 register tree t;
14417 register struct binding_level *b = current_binding_level;
14418 register tree f = current_function_decl;
5ff904cd 14419
c7e4ee3a
CB
14420 current_binding_level = global_binding_level;
14421 current_function_decl = NULL_TREE;
14422 t = pushdecl (x);
14423 current_binding_level = b;
14424 current_function_decl = f;
14425 return t;
14426}
14427
14428/* Store the list of declarations of the current level.
14429 This is done for the parameter declarations of a function being defined,
14430 after they are modified in the light of any missing parameters. */
14431
14432static tree
14433storedecls (decls)
14434 tree decls;
14435{
14436 return current_binding_level->names = decls;
14437}
14438
14439/* Store the parameter declarations into the current function declaration.
14440 This is called after parsing the parameter declarations, before
14441 digesting the body of the function.
14442
14443 For an old-style definition, modify the function's type
14444 to specify at least the number of arguments. */
5ff904cd
JL
14445
14446static void
c7e4ee3a 14447store_parm_decls (int is_main_program UNUSED)
5ff904cd
JL
14448{
14449 register tree fndecl = current_function_decl;
14450
c7e4ee3a
CB
14451 if (fndecl == error_mark_node)
14452 return;
5ff904cd 14453
c7e4ee3a
CB
14454 /* This is a chain of PARM_DECLs from old-style parm declarations. */
14455 DECL_ARGUMENTS (fndecl) = storedecls (nreverse (getdecls ()));
5ff904cd 14456
c7e4ee3a 14457 /* Initialize the RTL code for the function. */
5ff904cd 14458
c7e4ee3a 14459 init_function_start (fndecl, input_filename, lineno);
56a0044b 14460
c7e4ee3a 14461 /* Set up parameters and prepare for return, for the function. */
5ff904cd 14462
c7e4ee3a
CB
14463 expand_function_start (fndecl, 0);
14464}
5ff904cd 14465
c7e4ee3a
CB
14466static tree
14467start_decl (tree decl, bool is_top_level)
14468{
14469 register tree tem;
14470 bool at_top_level = (current_binding_level == global_binding_level);
14471 bool top_level = is_top_level || at_top_level;
5ff904cd 14472
c7e4ee3a
CB
14473 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
14474 level anyway. */
14475 assert (!is_top_level || !at_top_level);
5ff904cd 14476
c7e4ee3a
CB
14477 /* The corresponding pop_obstacks is in finish_decl. */
14478 push_obstacks_nochange ();
14479
14480 if (DECL_INITIAL (decl) != NULL_TREE)
14481 {
14482 assert (DECL_INITIAL (decl) == error_mark_node);
14483 assert (!DECL_EXTERNAL (decl));
56a0044b 14484 }
c7e4ee3a
CB
14485 else if (top_level)
14486 assert ((TREE_STATIC (decl) == 1) || DECL_EXTERNAL (decl) == 1);
5ff904cd 14487
c7e4ee3a
CB
14488 /* For Fortran, we by default put things in .common when possible. */
14489 DECL_COMMON (decl) = 1;
5ff904cd 14490
c7e4ee3a
CB
14491 /* Add this decl to the current binding level. TEM may equal DECL or it may
14492 be a previous decl of the same name. */
14493 if (is_top_level)
14494 tem = pushdecl_top_level (decl);
14495 else
14496 tem = pushdecl (decl);
14497
14498 /* For a local variable, define the RTL now. */
14499 if (!top_level
14500 /* But not if this is a duplicate decl and we preserved the rtl from the
14501 previous one (which may or may not happen). */
14502 && DECL_RTL (tem) == 0)
5ff904cd 14503 {
c7e4ee3a
CB
14504 if (TYPE_SIZE (TREE_TYPE (tem)) != 0)
14505 expand_decl (tem);
14506 else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
14507 && DECL_INITIAL (tem) != 0)
14508 expand_decl (tem);
5ff904cd
JL
14509 }
14510
c7e4ee3a 14511 if (DECL_INITIAL (tem) != NULL_TREE)
5ff904cd 14512 {
c7e4ee3a
CB
14513 /* When parsing and digesting the initializer, use temporary storage.
14514 Do this even if we will ignore the value. */
14515 if (at_top_level)
14516 temporary_allocation ();
5ff904cd 14517 }
c7e4ee3a
CB
14518
14519 return tem;
5ff904cd
JL
14520}
14521
c7e4ee3a
CB
14522/* Create the FUNCTION_DECL for a function definition.
14523 DECLSPECS and DECLARATOR are the parts of the declaration;
14524 they describe the function's name and the type it returns,
14525 but twisted together in a fashion that parallels the syntax of C.
5ff904cd 14526
c7e4ee3a
CB
14527 This function creates a binding context for the function body
14528 as well as setting up the FUNCTION_DECL in current_function_decl.
5ff904cd 14529
c7e4ee3a
CB
14530 Returns 1 on success. If the DECLARATOR is not suitable for a function
14531 (it defines a datum instead), we return 0, which tells
14532 yyparse to report a parse error.
5ff904cd 14533
c7e4ee3a
CB
14534 NESTED is nonzero for a function nested within another function. */
14535
14536static void
14537start_function (tree name, tree type, int nested, int public)
5ff904cd 14538{
c7e4ee3a
CB
14539 tree decl1;
14540 tree restype;
14541 int old_immediate_size_expand = immediate_size_expand;
5ff904cd 14542
c7e4ee3a
CB
14543 named_labels = 0;
14544 shadowed_labels = 0;
14545
14546 /* Don't expand any sizes in the return type of the function. */
14547 immediate_size_expand = 0;
14548
14549 if (nested)
5ff904cd 14550 {
c7e4ee3a
CB
14551 assert (!public);
14552 assert (current_function_decl != NULL_TREE);
14553 assert (DECL_CONTEXT (current_function_decl) == NULL_TREE);
14554 }
14555 else
14556 {
14557 assert (current_function_decl == NULL_TREE);
5ff904cd 14558 }
c7e4ee3a
CB
14559
14560 if (TREE_CODE (type) == ERROR_MARK)
14561 decl1 = current_function_decl = error_mark_node;
56a0044b 14562 else
5ff904cd 14563 {
c7e4ee3a
CB
14564 decl1 = build_decl (FUNCTION_DECL,
14565 name,
14566 type);
14567 TREE_PUBLIC (decl1) = public ? 1 : 0;
14568 if (nested)
14569 DECL_INLINE (decl1) = 1;
14570 TREE_STATIC (decl1) = 1;
14571 DECL_EXTERNAL (decl1) = 0;
5ff904cd 14572
c7e4ee3a 14573 announce_function (decl1);
5ff904cd 14574
c7e4ee3a
CB
14575 /* Make the init_value nonzero so pushdecl knows this is not tentative.
14576 error_mark_node is replaced below (in poplevel) with the BLOCK. */
14577 DECL_INITIAL (decl1) = error_mark_node;
5ff904cd 14578
c7e4ee3a
CB
14579 /* Record the decl so that the function name is defined. If we already have
14580 a decl for this name, and it is a FUNCTION_DECL, use the old decl. */
5ff904cd 14581
c7e4ee3a 14582 current_function_decl = pushdecl (decl1);
5ff904cd
JL
14583 }
14584
c7e4ee3a
CB
14585 if (!nested)
14586 ffecom_outer_function_decl_ = current_function_decl;
5ff904cd 14587
c7e4ee3a
CB
14588 pushlevel (0);
14589 current_binding_level->prep_state = 2;
5ff904cd 14590
c7e4ee3a
CB
14591 if (TREE_CODE (current_function_decl) != ERROR_MARK)
14592 {
14593 make_function_rtl (current_function_decl);
5ff904cd 14594
c7e4ee3a
CB
14595 restype = TREE_TYPE (TREE_TYPE (current_function_decl));
14596 DECL_RESULT (current_function_decl)
14597 = build_decl (RESULT_DECL, NULL_TREE, restype);
5ff904cd 14598 }
5ff904cd 14599
c7e4ee3a
CB
14600 if (!nested)
14601 /* Allocate further tree nodes temporarily during compilation of this
14602 function only. */
14603 temporary_allocation ();
5ff904cd 14604
c7e4ee3a
CB
14605 if (!nested && (TREE_CODE (current_function_decl) != ERROR_MARK))
14606 TREE_ADDRESSABLE (current_function_decl) = 1;
14607
14608 immediate_size_expand = old_immediate_size_expand;
14609}
14610\f
14611/* Here are the public functions the GNU back end needs. */
14612
14613tree
14614convert (type, expr)
14615 tree type, expr;
5ff904cd 14616{
c7e4ee3a
CB
14617 register tree e = expr;
14618 register enum tree_code code = TREE_CODE (type);
5ff904cd 14619
c7e4ee3a
CB
14620 if (type == TREE_TYPE (e)
14621 || TREE_CODE (e) == ERROR_MARK)
14622 return e;
14623 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
14624 return fold (build1 (NOP_EXPR, type, e));
14625 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
14626 || code == ERROR_MARK)
14627 return error_mark_node;
14628 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
14629 {
14630 assert ("void value not ignored as it ought to be" == NULL);
14631 return error_mark_node;
14632 }
14633 if (code == VOID_TYPE)
14634 return build1 (CONVERT_EXPR, type, e);
14635 if ((code != RECORD_TYPE)
14636 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
14637 e = ffecom_1 (REALPART_EXPR, TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e))),
14638 e);
14639 if (code == INTEGER_TYPE || code == ENUMERAL_TYPE)
14640 return fold (convert_to_integer (type, e));
14641 if (code == POINTER_TYPE)
14642 return fold (convert_to_pointer (type, e));
14643 if (code == REAL_TYPE)
14644 return fold (convert_to_real (type, e));
14645 if (code == COMPLEX_TYPE)
14646 return fold (convert_to_complex (type, e));
14647 if (code == RECORD_TYPE)
14648 return fold (ffecom_convert_to_complex_ (type, e));
5ff904cd 14649
c7e4ee3a
CB
14650 assert ("conversion to non-scalar type requested" == NULL);
14651 return error_mark_node;
14652}
5ff904cd 14653
c7e4ee3a
CB
14654/* integrate_decl_tree calls this function, but since we don't use the
14655 DECL_LANG_SPECIFIC field, this is a no-op. */
5ff904cd 14656
c7e4ee3a
CB
14657void
14658copy_lang_decl (node)
14659 tree node UNUSED;
14660{
5ff904cd
JL
14661}
14662
c7e4ee3a
CB
14663/* Return the list of declarations of the current level.
14664 Note that this list is in reverse order unless/until
14665 you nreverse it; and when you do nreverse it, you must
14666 store the result back using `storedecls' or you will lose. */
5ff904cd 14667
c7e4ee3a
CB
14668tree
14669getdecls ()
5ff904cd 14670{
c7e4ee3a 14671 return current_binding_level->names;
5ff904cd
JL
14672}
14673
c7e4ee3a 14674/* Nonzero if we are currently in the global binding level. */
5ff904cd 14675
c7e4ee3a
CB
14676int
14677global_bindings_p ()
5ff904cd 14678{
c7e4ee3a
CB
14679 return current_binding_level == global_binding_level;
14680}
5ff904cd 14681
c7e4ee3a
CB
14682/* Print an error message for invalid use of an incomplete type.
14683 VALUE is the expression that was used (or 0 if that isn't known)
14684 and TYPE is the type that was invalid. */
5ff904cd 14685
c7e4ee3a
CB
14686void
14687incomplete_type_error (value, type)
14688 tree value UNUSED;
14689 tree type;
14690{
14691 if (TREE_CODE (type) == ERROR_MARK)
14692 return;
5ff904cd 14693
c7e4ee3a
CB
14694 assert ("incomplete type?!?" == NULL);
14695}
14696
7189a4b0
GK
14697/* Mark ARG for GC. */
14698static void
54551044 14699mark_binding_level (void *arg)
7189a4b0
GK
14700{
14701 struct binding_level *level = *(struct binding_level **) arg;
14702
14703 while (level)
14704 {
14705 ggc_mark_tree (level->names);
14706 ggc_mark_tree (level->blocks);
14707 ggc_mark_tree (level->this_block);
14708 level = level->level_chain;
14709 }
14710}
14711
c7e4ee3a
CB
14712void
14713init_decl_processing ()
5ff904cd 14714{
7189a4b0
GK
14715 static tree *const tree_roots[] = {
14716 &current_function_decl,
14717 &string_type_node,
14718 &ffecom_tree_fun_type_void,
14719 &ffecom_integer_zero_node,
14720 &ffecom_integer_one_node,
14721 &ffecom_tree_subr_type,
14722 &ffecom_tree_ptr_to_subr_type,
14723 &ffecom_tree_blockdata_type,
14724 &ffecom_tree_xargc_,
14725 &ffecom_f2c_integer_type_node,
14726 &ffecom_f2c_ptr_to_integer_type_node,
14727 &ffecom_f2c_address_type_node,
14728 &ffecom_f2c_real_type_node,
14729 &ffecom_f2c_ptr_to_real_type_node,
14730 &ffecom_f2c_doublereal_type_node,
14731 &ffecom_f2c_complex_type_node,
14732 &ffecom_f2c_doublecomplex_type_node,
14733 &ffecom_f2c_longint_type_node,
14734 &ffecom_f2c_logical_type_node,
14735 &ffecom_f2c_flag_type_node,
14736 &ffecom_f2c_ftnlen_type_node,
14737 &ffecom_f2c_ftnlen_zero_node,
14738 &ffecom_f2c_ftnlen_one_node,
14739 &ffecom_f2c_ftnlen_two_node,
14740 &ffecom_f2c_ptr_to_ftnlen_type_node,
14741 &ffecom_f2c_ftnint_type_node,
14742 &ffecom_f2c_ptr_to_ftnint_type_node,
14743 &ffecom_outer_function_decl_,
14744 &ffecom_previous_function_decl_,
14745 &ffecom_which_entrypoint_decl_,
14746 &ffecom_float_zero_,
14747 &ffecom_float_half_,
14748 &ffecom_double_zero_,
14749 &ffecom_double_half_,
14750 &ffecom_func_result_,
14751 &ffecom_func_length_,
14752 &ffecom_multi_type_node_,
14753 &ffecom_multi_retval_,
14754 &named_labels,
14755 &shadowed_labels
14756 };
14757 size_t i;
14758
c7e4ee3a 14759 malloc_init ();
7189a4b0
GK
14760
14761 /* Record our roots. */
14762 for (i = 0; i < sizeof(tree_roots)/sizeof(tree_roots[0]); i++)
14763 ggc_add_tree_root (tree_roots[i], 1);
14764 ggc_add_tree_root (&ffecom_tree_type[0][0],
14765 FFEINFO_basictype*FFEINFO_kindtype);
14766 ggc_add_tree_root (&ffecom_tree_fun_type[0][0],
14767 FFEINFO_basictype*FFEINFO_kindtype);
14768 ggc_add_tree_root (&ffecom_tree_ptr_to_fun_type[0][0],
14769 FFEINFO_basictype*FFEINFO_kindtype);
14770 ggc_add_tree_root (ffecom_gfrt_, FFECOM_gfrt);
14771 ggc_add_root (&current_binding_level, 1, sizeof current_binding_level,
14772 mark_binding_level);
14773 ggc_add_root (&free_binding_level, 1, sizeof current_binding_level,
14774 mark_binding_level);
14775 ggc_add_root (&tracker_head, 1, sizeof tracker_head, mark_tracker_head);
14776
c7e4ee3a
CB
14777 ffe_init_0 ();
14778}
5ff904cd 14779
3b304f5b 14780const char *
c7e4ee3a 14781init_parse (filename)
3b304f5b 14782 const char *filename;
c7e4ee3a 14783{
c7e4ee3a
CB
14784 /* Open input file. */
14785 if (filename == 0 || !strcmp (filename, "-"))
5ff904cd 14786 {
c7e4ee3a
CB
14787 finput = stdin;
14788 filename = "stdin";
5ff904cd 14789 }
c7e4ee3a
CB
14790 else
14791 finput = fopen (filename, "r");
14792 if (finput == 0)
14793 pfatal_with_name (filename);
5ff904cd 14794
c7e4ee3a
CB
14795#ifdef IO_BUFFER_SIZE
14796 setvbuf (finput, (char *) xmalloc (IO_BUFFER_SIZE), _IOFBF, IO_BUFFER_SIZE);
14797#endif
5ff904cd 14798
c7e4ee3a
CB
14799 /* Make identifier nodes long enough for the language-specific slots. */
14800 set_identifier_size (sizeof (struct lang_identifier));
14801 decl_printable_name = lang_printable_name;
14802#if BUILT_FOR_270
14803 print_error_function = lang_print_error_function;
14804#endif
5ff904cd 14805
c7e4ee3a
CB
14806 return filename;
14807}
5ff904cd 14808
c7e4ee3a
CB
14809void
14810finish_parse ()
14811{
14812 fclose (finput);
14813}
14814
14815/* Delete the node BLOCK from the current binding level.
14816 This is used for the block inside a stmt expr ({...})
14817 so that the block can be reinserted where appropriate. */
14818
14819static void
14820delete_block (block)
14821 tree block;
14822{
14823 tree t;
14824 if (current_binding_level->blocks == block)
14825 current_binding_level->blocks = TREE_CHAIN (block);
14826 for (t = current_binding_level->blocks; t;)
14827 {
14828 if (TREE_CHAIN (t) == block)
14829 TREE_CHAIN (t) = TREE_CHAIN (block);
14830 else
14831 t = TREE_CHAIN (t);
14832 }
14833 TREE_CHAIN (block) = NULL;
14834 /* Clear TREE_USED which is always set by poplevel.
14835 The flag is set again if insert_block is called. */
14836 TREE_USED (block) = 0;
14837}
14838
14839void
14840insert_block (block)
14841 tree block;
14842{
14843 TREE_USED (block) = 1;
14844 current_binding_level->blocks
14845 = chainon (current_binding_level->blocks, block);
14846}
14847
14848int
14849lang_decode_option (argc, argv)
14850 int argc;
14851 char **argv;
14852{
14853 return ffe_decode_option (argc, argv);
5ff904cd
JL
14854}
14855
c7e4ee3a 14856/* used by print-tree.c */
5ff904cd 14857
c7e4ee3a
CB
14858void
14859lang_print_xnode (file, node, indent)
14860 FILE *file UNUSED;
14861 tree node UNUSED;
14862 int indent UNUSED;
5ff904cd 14863{
c7e4ee3a 14864}
5ff904cd 14865
c7e4ee3a
CB
14866void
14867lang_finish ()
14868{
14869 ffe_terminate_0 ();
5ff904cd 14870
c7e4ee3a
CB
14871 if (ffe_is_ffedebug ())
14872 malloc_pool_display (malloc_pool_image ());
5ff904cd
JL
14873}
14874
dafbd854 14875const char *
c7e4ee3a 14876lang_identify ()
5ff904cd 14877{
c7e4ee3a
CB
14878 return "f77";
14879}
5ff904cd 14880
2e761e49
RH
14881/* Return the typed-based alias set for T, which may be an expression
14882 or a type. Return -1 if we don't do anything special. */
14883
14884HOST_WIDE_INT
14885lang_get_alias_set (t)
5ac9118e 14886 tree t ATTRIBUTE_UNUSED;
2e761e49
RH
14887{
14888 /* We do not wish to use alias-set based aliasing at all. Used in the
14889 extreme (every object with its own set, with equivalences recorded)
14890 it might be helpful, but there are problems when it comes to inlining.
14891 We get on ok with flag_argument_noalias, and alias-set aliasing does
14892 currently limit how stack slots can be reused, which is a lose. */
14893 return 0;
14894}
14895
c7e4ee3a
CB
14896void
14897lang_init_options ()
14898{
14899 /* Set default options for Fortran. */
14900 flag_move_all_movables = 1;
14901 flag_reduce_all_givs = 1;
14902 flag_argument_noalias = 2;
41af162c 14903 flag_errno_math = 0;
c64f913e 14904 flag_complex_divide_method = 1;
c7e4ee3a 14905}
5ff904cd 14906
c7e4ee3a
CB
14907void
14908lang_init ()
14909{
14910 /* If the file is output from cpp, it should contain a first line
14911 `# 1 "real-filename"', and the current design of gcc (toplev.c
14912 in particular and the way it sets up information relied on by
14913 INCLUDE) requires that we read this now, and store the
14914 "real-filename" info in master_input_filename. Ask the lexer
14915 to try doing this. */
14916 ffelex_hash_kludge (finput);
14917}
5ff904cd 14918
c7e4ee3a
CB
14919int
14920mark_addressable (exp)
14921 tree exp;
14922{
14923 register tree x = exp;
14924 while (1)
14925 switch (TREE_CODE (x))
14926 {
14927 case ADDR_EXPR:
14928 case COMPONENT_REF:
14929 case ARRAY_REF:
14930 x = TREE_OPERAND (x, 0);
14931 break;
5ff904cd 14932
c7e4ee3a
CB
14933 case CONSTRUCTOR:
14934 TREE_ADDRESSABLE (x) = 1;
14935 return 1;
5ff904cd 14936
c7e4ee3a
CB
14937 case VAR_DECL:
14938 case CONST_DECL:
14939 case PARM_DECL:
14940 case RESULT_DECL:
14941 if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x)
14942 && DECL_NONLOCAL (x))
14943 {
14944 if (TREE_PUBLIC (x))
14945 {
14946 assert ("address of global register var requested" == NULL);
14947 return 0;
14948 }
14949 assert ("address of register variable requested" == NULL);
14950 }
14951 else if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x))
14952 {
14953 if (TREE_PUBLIC (x))
14954 {
14955 assert ("address of global register var requested" == NULL);
14956 return 0;
14957 }
14958 assert ("address of register var requested" == NULL);
14959 }
14960 put_var_into_stack (x);
5ff904cd 14961
c7e4ee3a
CB
14962 /* drops in */
14963 case FUNCTION_DECL:
14964 TREE_ADDRESSABLE (x) = 1;
14965#if 0 /* poplevel deals with this now. */
14966 if (DECL_CONTEXT (x) == 0)
14967 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;
14968#endif
5ff904cd 14969
c7e4ee3a
CB
14970 default:
14971 return 1;
14972 }
5ff904cd
JL
14973}
14974
c7e4ee3a
CB
14975/* If DECL has a cleanup, build and return that cleanup here.
14976 This is a callback called by expand_expr. */
5ff904cd 14977
c7e4ee3a
CB
14978tree
14979maybe_build_cleanup (decl)
14980 tree decl UNUSED;
5ff904cd 14981{
c7e4ee3a
CB
14982 /* There are no cleanups in Fortran. */
14983 return NULL_TREE;
5ff904cd
JL
14984}
14985
c7e4ee3a
CB
14986/* Exit a binding level.
14987 Pop the level off, and restore the state of the identifier-decl mappings
14988 that were in effect when this level was entered.
5ff904cd 14989
c7e4ee3a
CB
14990 If KEEP is nonzero, this level had explicit declarations, so
14991 and create a "block" (a BLOCK node) for the level
14992 to record its declarations and subblocks for symbol table output.
5ff904cd 14993
c7e4ee3a
CB
14994 If FUNCTIONBODY is nonzero, this level is the body of a function,
14995 so create a block as if KEEP were set and also clear out all
14996 label names.
5ff904cd 14997
c7e4ee3a
CB
14998 If REVERSE is nonzero, reverse the order of decls before putting
14999 them into the BLOCK. */
5ff904cd 15000
c7e4ee3a
CB
15001tree
15002poplevel (keep, reverse, functionbody)
15003 int keep;
15004 int reverse;
15005 int functionbody;
5ff904cd 15006{
c7e4ee3a
CB
15007 register tree link;
15008 /* The chain of decls was accumulated in reverse order.
15009 Put it into forward order, just for cleanliness. */
15010 tree decls;
15011 tree subblocks = current_binding_level->blocks;
15012 tree block = 0;
15013 tree decl;
15014 int block_previously_created;
5ff904cd 15015
c7e4ee3a
CB
15016 /* Get the decls in the order they were written.
15017 Usually current_binding_level->names is in reverse order.
15018 But parameter decls were previously put in forward order. */
702edf1d 15019
c7e4ee3a
CB
15020 if (reverse)
15021 current_binding_level->names
15022 = decls = nreverse (current_binding_level->names);
15023 else
15024 decls = current_binding_level->names;
5ff904cd 15025
c7e4ee3a
CB
15026 /* Output any nested inline functions within this block
15027 if they weren't already output. */
5ff904cd 15028
c7e4ee3a
CB
15029 for (decl = decls; decl; decl = TREE_CHAIN (decl))
15030 if (TREE_CODE (decl) == FUNCTION_DECL
15031 && ! TREE_ASM_WRITTEN (decl)
15032 && DECL_INITIAL (decl) != 0
15033 && TREE_ADDRESSABLE (decl))
15034 {
15035 /* If this decl was copied from a file-scope decl
15036 on account of a block-scope extern decl,
15037 propagate TREE_ADDRESSABLE to the file-scope decl.
15038
15039 DECL_ABSTRACT_ORIGIN can be set to itself if warn_return_type is
15040 true, since then the decl goes through save_for_inline_copying. */
15041 if (DECL_ABSTRACT_ORIGIN (decl) != 0
15042 && DECL_ABSTRACT_ORIGIN (decl) != decl)
15043 TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
15044 else if (DECL_SAVED_INSNS (decl) != 0)
15045 {
15046 push_function_context ();
15047 output_inline_function (decl);
15048 pop_function_context ();
15049 }
15050 }
5ff904cd 15051
c7e4ee3a
CB
15052 /* If there were any declarations or structure tags in that level,
15053 or if this level is a function body,
15054 create a BLOCK to record them for the life of this function. */
5ff904cd 15055
c7e4ee3a
CB
15056 block = 0;
15057 block_previously_created = (current_binding_level->this_block != 0);
15058 if (block_previously_created)
15059 block = current_binding_level->this_block;
15060 else if (keep || functionbody)
15061 block = make_node (BLOCK);
15062 if (block != 0)
15063 {
15064 BLOCK_VARS (block) = decls;
15065 BLOCK_SUBBLOCKS (block) = subblocks;
c7e4ee3a 15066 }
5ff904cd 15067
c7e4ee3a 15068 /* In each subblock, record that this is its superior. */
5ff904cd 15069
c7e4ee3a
CB
15070 for (link = subblocks; link; link = TREE_CHAIN (link))
15071 BLOCK_SUPERCONTEXT (link) = block;
5ff904cd 15072
c7e4ee3a 15073 /* Clear out the meanings of the local variables of this level. */
5ff904cd 15074
c7e4ee3a 15075 for (link = decls; link; link = TREE_CHAIN (link))
5ff904cd 15076 {
c7e4ee3a
CB
15077 if (DECL_NAME (link) != 0)
15078 {
15079 /* If the ident. was used or addressed via a local extern decl,
15080 don't forget that fact. */
15081 if (DECL_EXTERNAL (link))
15082 {
15083 if (TREE_USED (link))
15084 TREE_USED (DECL_NAME (link)) = 1;
15085 if (TREE_ADDRESSABLE (link))
15086 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1;
15087 }
15088 IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = 0;
15089 }
5ff904cd 15090 }
5ff904cd 15091
c7e4ee3a
CB
15092 /* If the level being exited is the top level of a function,
15093 check over all the labels, and clear out the current
15094 (function local) meanings of their names. */
5ff904cd 15095
c7e4ee3a 15096 if (functionbody)
5ff904cd 15097 {
c7e4ee3a
CB
15098 /* If this is the top level block of a function,
15099 the vars are the function's parameters.
15100 Don't leave them in the BLOCK because they are
15101 found in the FUNCTION_DECL instead. */
15102
15103 BLOCK_VARS (block) = 0;
5ff904cd
JL
15104 }
15105
c7e4ee3a
CB
15106 /* Pop the current level, and free the structure for reuse. */
15107
15108 {
15109 register struct binding_level *level = current_binding_level;
15110 current_binding_level = current_binding_level->level_chain;
15111
15112 level->level_chain = free_binding_level;
15113 free_binding_level = level;
15114 }
15115
15116 /* Dispose of the block that we just made inside some higher level. */
15117 if (functionbody
15118 && current_function_decl != error_mark_node)
15119 DECL_INITIAL (current_function_decl) = block;
15120 else if (block)
5ff904cd 15121 {
c7e4ee3a
CB
15122 if (!block_previously_created)
15123 current_binding_level->blocks
15124 = chainon (current_binding_level->blocks, block);
5ff904cd 15125 }
c7e4ee3a
CB
15126 /* If we did not make a block for the level just exited,
15127 any blocks made for inner levels
15128 (since they cannot be recorded as subblocks in that level)
15129 must be carried forward so they will later become subblocks
15130 of something else. */
15131 else if (subblocks)
15132 current_binding_level->blocks
15133 = chainon (current_binding_level->blocks, subblocks);
5ff904cd 15134
c7e4ee3a
CB
15135 if (block)
15136 TREE_USED (block) = 1;
15137 return block;
5ff904cd
JL
15138}
15139
c7e4ee3a
CB
15140void
15141print_lang_decl (file, node, indent)
15142 FILE *file UNUSED;
15143 tree node UNUSED;
15144 int indent UNUSED;
15145{
15146}
5ff904cd 15147
c7e4ee3a
CB
15148void
15149print_lang_identifier (file, node, indent)
15150 FILE *file;
15151 tree node;
15152 int indent;
15153{
15154 print_node (file, "global", IDENTIFIER_GLOBAL_VALUE (node), indent + 4);
15155 print_node (file, "local", IDENTIFIER_LOCAL_VALUE (node), indent + 4);
15156}
5ff904cd 15157
c7e4ee3a
CB
15158void
15159print_lang_statistics ()
15160{
15161}
5ff904cd 15162
c7e4ee3a
CB
15163void
15164print_lang_type (file, node, indent)
15165 FILE *file UNUSED;
15166 tree node UNUSED;
15167 int indent UNUSED;
5ff904cd 15168{
c7e4ee3a 15169}
5ff904cd 15170
c7e4ee3a
CB
15171/* Record a decl-node X as belonging to the current lexical scope.
15172 Check for errors (such as an incompatible declaration for the same
15173 name already seen in the same scope).
5ff904cd 15174
c7e4ee3a
CB
15175 Returns either X or an old decl for the same name.
15176 If an old decl is returned, it may have been smashed
15177 to agree with what X says. */
5ff904cd 15178
c7e4ee3a
CB
15179tree
15180pushdecl (x)
15181 tree x;
15182{
15183 register tree t;
15184 register tree name = DECL_NAME (x);
15185 register struct binding_level *b = current_binding_level;
5ff904cd 15186
c7e4ee3a
CB
15187 if ((TREE_CODE (x) == FUNCTION_DECL)
15188 && (DECL_INITIAL (x) == 0)
15189 && DECL_EXTERNAL (x))
15190 DECL_CONTEXT (x) = NULL_TREE;
56a0044b 15191 else
c7e4ee3a
CB
15192 DECL_CONTEXT (x) = current_function_decl;
15193
15194 if (name)
56a0044b 15195 {
c7e4ee3a
CB
15196 if (IDENTIFIER_INVENTED (name))
15197 {
15198#if BUILT_FOR_270
15199 DECL_ARTIFICIAL (x) = 1;
15200#endif
15201 DECL_IN_SYSTEM_HEADER (x) = 1;
15202 }
5ff904cd 15203
c7e4ee3a 15204 t = lookup_name_current_level (name);
5ff904cd 15205
c7e4ee3a 15206 assert ((t == NULL_TREE) || (DECL_CONTEXT (x) == NULL_TREE));
5ff904cd 15207
c7e4ee3a
CB
15208 /* Don't push non-parms onto list for parms until we understand
15209 why we're doing this and whether it works. */
56a0044b 15210
c7e4ee3a
CB
15211 assert ((b == global_binding_level)
15212 || !ffecom_transform_only_dummies_
15213 || TREE_CODE (x) == PARM_DECL);
5ff904cd 15214
c7e4ee3a
CB
15215 if ((t != NULL_TREE) && duplicate_decls (x, t))
15216 return t;
5ff904cd 15217
c7e4ee3a
CB
15218 /* If we are processing a typedef statement, generate a whole new
15219 ..._TYPE node (which will be just an variant of the existing
15220 ..._TYPE node with identical properties) and then install the
15221 TYPE_DECL node generated to represent the typedef name as the
15222 TYPE_NAME of this brand new (duplicate) ..._TYPE node.
5ff904cd 15223
c7e4ee3a
CB
15224 The whole point here is to end up with a situation where each and every
15225 ..._TYPE node the compiler creates will be uniquely associated with
15226 AT MOST one node representing a typedef name. This way, even though
15227 the compiler substitutes corresponding ..._TYPE nodes for TYPE_DECL
15228 (i.e. "typedef name") nodes very early on, later parts of the
15229 compiler can always do the reverse translation and get back the
15230 corresponding typedef name. For example, given:
5ff904cd 15231
c7e4ee3a 15232 typedef struct S MY_TYPE; MY_TYPE object;
5ff904cd 15233
c7e4ee3a
CB
15234 Later parts of the compiler might only know that `object' was of type
15235 `struct S' if it were not for code just below. With this code
15236 however, later parts of the compiler see something like:
5ff904cd 15237
c7e4ee3a 15238 struct S' == struct S typedef struct S' MY_TYPE; struct S' object;
5ff904cd 15239
c7e4ee3a
CB
15240 And they can then deduce (from the node for type struct S') that the
15241 original object declaration was:
5ff904cd 15242
c7e4ee3a 15243 MY_TYPE object;
5ff904cd 15244
c7e4ee3a
CB
15245 Being able to do this is important for proper support of protoize, and
15246 also for generating precise symbolic debugging information which
15247 takes full account of the programmer's (typedef) vocabulary.
5ff904cd 15248
c7e4ee3a
CB
15249 Obviously, we don't want to generate a duplicate ..._TYPE node if the
15250 TYPE_DECL node that we are now processing really represents a
15251 standard built-in type.
5ff904cd 15252
c7e4ee3a
CB
15253 Since all standard types are effectively declared at line zero in the
15254 source file, we can easily check to see if we are working on a
15255 standard type by checking the current value of lineno. */
15256
15257 if (TREE_CODE (x) == TYPE_DECL)
15258 {
15259 if (DECL_SOURCE_LINE (x) == 0)
15260 {
15261 if (TYPE_NAME (TREE_TYPE (x)) == 0)
15262 TYPE_NAME (TREE_TYPE (x)) = x;
15263 }
15264 else if (TREE_TYPE (x) != error_mark_node)
15265 {
15266 tree tt = TREE_TYPE (x);
15267
15268 tt = build_type_copy (tt);
15269 TYPE_NAME (tt) = x;
15270 TREE_TYPE (x) = tt;
15271 }
15272 }
5ff904cd 15273
c7e4ee3a
CB
15274 /* This name is new in its binding level. Install the new declaration
15275 and return it. */
15276 if (b == global_binding_level)
15277 IDENTIFIER_GLOBAL_VALUE (name) = x;
15278 else
15279 IDENTIFIER_LOCAL_VALUE (name) = x;
15280 }
5ff904cd 15281
c7e4ee3a
CB
15282 /* Put decls on list in reverse order. We will reverse them later if
15283 necessary. */
15284 TREE_CHAIN (x) = b->names;
15285 b->names = x;
5ff904cd 15286
c7e4ee3a 15287 return x;
5ff904cd
JL
15288}
15289
c7e4ee3a 15290/* Nonzero if the current level needs to have a BLOCK made. */
5ff904cd 15291
c7e4ee3a
CB
15292static int
15293kept_level_p ()
5ff904cd 15294{
c7e4ee3a
CB
15295 tree decl;
15296
15297 for (decl = current_binding_level->names;
15298 decl;
15299 decl = TREE_CHAIN (decl))
15300 {
15301 if (TREE_USED (decl) || TREE_CODE (decl) != VAR_DECL
15302 || (DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl)))
15303 /* Currently, there aren't supposed to be non-artificial names
15304 at other than the top block for a function -- they're
15305 believed to always be temps. But it's wise to check anyway. */
15306 return 1;
15307 }
15308 return 0;
5ff904cd
JL
15309}
15310
c7e4ee3a
CB
15311/* Enter a new binding level.
15312 If TAG_TRANSPARENT is nonzero, do so only for the name space of variables,
15313 not for that of tags. */
5ff904cd
JL
15314
15315void
c7e4ee3a
CB
15316pushlevel (tag_transparent)
15317 int tag_transparent;
5ff904cd 15318{
c7e4ee3a 15319 register struct binding_level *newlevel = NULL_BINDING_LEVEL;
5ff904cd 15320
c7e4ee3a 15321 assert (! tag_transparent);
5ff904cd 15322
c7e4ee3a
CB
15323 if (current_binding_level == global_binding_level)
15324 {
15325 named_labels = 0;
15326 }
5ff904cd 15327
c7e4ee3a 15328 /* Reuse or create a struct for this binding level. */
5ff904cd 15329
c7e4ee3a 15330 if (free_binding_level)
77f77701 15331 {
c7e4ee3a
CB
15332 newlevel = free_binding_level;
15333 free_binding_level = free_binding_level->level_chain;
77f77701
DB
15334 }
15335 else
c7e4ee3a
CB
15336 {
15337 newlevel = make_binding_level ();
15338 }
77f77701 15339
c7e4ee3a
CB
15340 /* Add this level to the front of the chain (stack) of levels that
15341 are active. */
71b5e532 15342
c7e4ee3a
CB
15343 *newlevel = clear_binding_level;
15344 newlevel->level_chain = current_binding_level;
15345 current_binding_level = newlevel;
5ff904cd
JL
15346}
15347
c7e4ee3a
CB
15348/* Set the BLOCK node for the innermost scope
15349 (the one we are currently in). */
77f77701 15350
5ff904cd 15351void
c7e4ee3a
CB
15352set_block (block)
15353 register tree block;
5ff904cd 15354{
c7e4ee3a 15355 current_binding_level->this_block = block;
5ff904cd
JL
15356}
15357
c7e4ee3a 15358/* ~~gcc/tree.h *should* declare this, because toplev.c references it. */
5ff904cd 15359
c7e4ee3a 15360/* Can't 'yydebug' a front end not generated by yacc/bison! */
bc289659
ML
15361
15362void
c7e4ee3a
CB
15363set_yydebug (value)
15364 int value;
bc289659 15365{
c7e4ee3a
CB
15366 if (value)
15367 fprintf (stderr, "warning: no yacc/bison-generated output to debug!\n");
bc289659
ML
15368}
15369
c7e4ee3a
CB
15370tree
15371signed_or_unsigned_type (unsignedp, type)
15372 int unsignedp;
15373 tree type;
5ff904cd 15374{
c7e4ee3a 15375 tree type2;
5ff904cd 15376
c7e4ee3a
CB
15377 if (! INTEGRAL_TYPE_P (type))
15378 return type;
15379 if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node))
15380 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15381 if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
15382 return unsignedp ? unsigned_type_node : integer_type_node;
15383 if (TYPE_PRECISION (type) == TYPE_PRECISION (short_integer_type_node))
15384 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15385 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_integer_type_node))
15386 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15387 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_long_integer_type_node))
15388 return (unsignedp ? long_long_unsigned_type_node
15389 : long_long_integer_type_node);
5ff904cd 15390
c7e4ee3a
CB
15391 type2 = type_for_size (TYPE_PRECISION (type), unsignedp);
15392 if (type2 == NULL_TREE)
15393 return type;
f84639ba 15394
c7e4ee3a 15395 return type2;
5ff904cd
JL
15396}
15397
c7e4ee3a
CB
15398tree
15399signed_type (type)
15400 tree type;
5ff904cd 15401{
c7e4ee3a
CB
15402 tree type1 = TYPE_MAIN_VARIANT (type);
15403 ffeinfoKindtype kt;
15404 tree type2;
5ff904cd 15405
c7e4ee3a
CB
15406 if (type1 == unsigned_char_type_node || type1 == char_type_node)
15407 return signed_char_type_node;
15408 if (type1 == unsigned_type_node)
15409 return integer_type_node;
15410 if (type1 == short_unsigned_type_node)
15411 return short_integer_type_node;
15412 if (type1 == long_unsigned_type_node)
15413 return long_integer_type_node;
15414 if (type1 == long_long_unsigned_type_node)
15415 return long_long_integer_type_node;
15416#if 0 /* gcc/c-* files only */
15417 if (type1 == unsigned_intDI_type_node)
15418 return intDI_type_node;
15419 if (type1 == unsigned_intSI_type_node)
15420 return intSI_type_node;
15421 if (type1 == unsigned_intHI_type_node)
15422 return intHI_type_node;
15423 if (type1 == unsigned_intQI_type_node)
15424 return intQI_type_node;
15425#endif
5ff904cd 15426
c7e4ee3a
CB
15427 type2 = type_for_size (TYPE_PRECISION (type1), 0);
15428 if (type2 != NULL_TREE)
15429 return type2;
5ff904cd 15430
c7e4ee3a
CB
15431 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15432 {
15433 type2 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
5ff904cd 15434
c7e4ee3a
CB
15435 if (type1 == type2)
15436 return ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15437 }
15438
15439 return type;
5ff904cd
JL
15440}
15441
c7e4ee3a
CB
15442/* Prepare expr to be an argument of a TRUTH_NOT_EXPR,
15443 or validate its data type for an `if' or `while' statement or ?..: exp.
15444
15445 This preparation consists of taking the ordinary
15446 representation of an expression expr and producing a valid tree
15447 boolean expression describing whether expr is nonzero. We could
15448 simply always do build_binary_op (NE_EXPR, expr, integer_zero_node, 1),
15449 but we optimize comparisons, &&, ||, and !.
15450
15451 The resulting type should always be `integer_type_node'. */
5ff904cd
JL
15452
15453tree
c7e4ee3a
CB
15454truthvalue_conversion (expr)
15455 tree expr;
5ff904cd 15456{
c7e4ee3a
CB
15457 if (TREE_CODE (expr) == ERROR_MARK)
15458 return expr;
5ff904cd 15459
c7e4ee3a
CB
15460#if 0 /* This appears to be wrong for C++. */
15461 /* These really should return error_mark_node after 2.4 is stable.
15462 But not all callers handle ERROR_MARK properly. */
15463 switch (TREE_CODE (TREE_TYPE (expr)))
15464 {
15465 case RECORD_TYPE:
15466 error ("struct type value used where scalar is required");
15467 return integer_zero_node;
5ff904cd 15468
c7e4ee3a
CB
15469 case UNION_TYPE:
15470 error ("union type value used where scalar is required");
15471 return integer_zero_node;
5ff904cd 15472
c7e4ee3a
CB
15473 case ARRAY_TYPE:
15474 error ("array type value used where scalar is required");
15475 return integer_zero_node;
5ff904cd 15476
c7e4ee3a
CB
15477 default:
15478 break;
15479 }
15480#endif /* 0 */
5ff904cd 15481
c7e4ee3a
CB
15482 switch (TREE_CODE (expr))
15483 {
15484 /* It is simpler and generates better code to have only TRUTH_*_EXPR
15485 or comparison expressions as truth values at this level. */
15486#if 0
15487 case COMPONENT_REF:
15488 /* A one-bit unsigned bit-field is already acceptable. */
15489 if (1 == TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (expr, 1)))
15490 && TREE_UNSIGNED (TREE_OPERAND (expr, 1)))
15491 return expr;
15492 break;
15493#endif
15494
15495 case EQ_EXPR:
15496 /* It is simpler and generates better code to have only TRUTH_*_EXPR
15497 or comparison expressions as truth values at this level. */
15498#if 0
15499 if (integer_zerop (TREE_OPERAND (expr, 1)))
15500 return build_unary_op (TRUTH_NOT_EXPR, TREE_OPERAND (expr, 0), 0);
15501#endif
15502 case NE_EXPR: case LE_EXPR: case GE_EXPR: case LT_EXPR: case GT_EXPR:
15503 case TRUTH_ANDIF_EXPR:
15504 case TRUTH_ORIF_EXPR:
15505 case TRUTH_AND_EXPR:
15506 case TRUTH_OR_EXPR:
15507 case TRUTH_XOR_EXPR:
15508 TREE_TYPE (expr) = integer_type_node;
15509 return expr;
5ff904cd 15510
c7e4ee3a
CB
15511 case ERROR_MARK:
15512 return expr;
5ff904cd 15513
c7e4ee3a
CB
15514 case INTEGER_CST:
15515 return integer_zerop (expr) ? integer_zero_node : integer_one_node;
5ff904cd 15516
c7e4ee3a
CB
15517 case REAL_CST:
15518 return real_zerop (expr) ? integer_zero_node : integer_one_node;
5ff904cd 15519
c7e4ee3a
CB
15520 case ADDR_EXPR:
15521 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 0)))
15522 return build (COMPOUND_EXPR, integer_type_node,
15523 TREE_OPERAND (expr, 0), integer_one_node);
15524 else
15525 return integer_one_node;
5ff904cd 15526
c7e4ee3a
CB
15527 case COMPLEX_EXPR:
15528 return ffecom_2 ((TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
15529 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
15530 integer_type_node,
15531 truthvalue_conversion (TREE_OPERAND (expr, 0)),
15532 truthvalue_conversion (TREE_OPERAND (expr, 1)));
5ff904cd 15533
c7e4ee3a
CB
15534 case NEGATE_EXPR:
15535 case ABS_EXPR:
15536 case FLOAT_EXPR:
15537 case FFS_EXPR:
15538 /* These don't change whether an object is non-zero or zero. */
15539 return truthvalue_conversion (TREE_OPERAND (expr, 0));
5ff904cd 15540
c7e4ee3a
CB
15541 case LROTATE_EXPR:
15542 case RROTATE_EXPR:
15543 /* These don't change whether an object is zero or non-zero, but
15544 we can't ignore them if their second arg has side-effects. */
15545 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
15546 return build (COMPOUND_EXPR, integer_type_node, TREE_OPERAND (expr, 1),
15547 truthvalue_conversion (TREE_OPERAND (expr, 0)));
15548 else
15549 return truthvalue_conversion (TREE_OPERAND (expr, 0));
5ff904cd 15550
c7e4ee3a
CB
15551 case COND_EXPR:
15552 /* Distribute the conversion into the arms of a COND_EXPR. */
15553 return fold (build (COND_EXPR, integer_type_node, TREE_OPERAND (expr, 0),
15554 truthvalue_conversion (TREE_OPERAND (expr, 1)),
15555 truthvalue_conversion (TREE_OPERAND (expr, 2))));
5ff904cd 15556
c7e4ee3a
CB
15557 case CONVERT_EXPR:
15558 /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
15559 since that affects how `default_conversion' will behave. */
15560 if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE
15561 || TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE)
15562 break;
15563 /* fall through... */
15564 case NOP_EXPR:
15565 /* If this is widening the argument, we can ignore it. */
15566 if (TYPE_PRECISION (TREE_TYPE (expr))
15567 >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))
15568 return truthvalue_conversion (TREE_OPERAND (expr, 0));
15569 break;
5ff904cd 15570
c7e4ee3a
CB
15571 case MINUS_EXPR:
15572 /* With IEEE arithmetic, x - x may not equal 0, so we can't optimize
15573 this case. */
15574 if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
15575 && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE)
15576 break;
15577 /* fall through... */
15578 case BIT_XOR_EXPR:
15579 /* This and MINUS_EXPR can be changed into a comparison of the
15580 two objects. */
15581 if (TREE_TYPE (TREE_OPERAND (expr, 0))
15582 == TREE_TYPE (TREE_OPERAND (expr, 1)))
15583 return ffecom_2 (NE_EXPR, integer_type_node,
15584 TREE_OPERAND (expr, 0),
15585 TREE_OPERAND (expr, 1));
15586 return ffecom_2 (NE_EXPR, integer_type_node,
15587 TREE_OPERAND (expr, 0),
15588 fold (build1 (NOP_EXPR,
15589 TREE_TYPE (TREE_OPERAND (expr, 0)),
15590 TREE_OPERAND (expr, 1))));
15591
15592 case BIT_AND_EXPR:
15593 if (integer_onep (TREE_OPERAND (expr, 1)))
15594 return expr;
15595 break;
15596
15597 case MODIFY_EXPR:
15598#if 0 /* No such thing in Fortran. */
15599 if (warn_parentheses && C_EXP_ORIGINAL_CODE (expr) == MODIFY_EXPR)
15600 warning ("suggest parentheses around assignment used as truth value");
15601#endif
15602 break;
15603
15604 default:
15605 break;
5ff904cd
JL
15606 }
15607
c7e4ee3a
CB
15608 if (TREE_CODE (TREE_TYPE (expr)) == COMPLEX_TYPE)
15609 return (ffecom_2
15610 ((TREE_SIDE_EFFECTS (expr)
15611 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
15612 integer_type_node,
15613 truthvalue_conversion (ffecom_1 (REALPART_EXPR,
15614 TREE_TYPE (TREE_TYPE (expr)),
15615 expr)),
15616 truthvalue_conversion (ffecom_1 (IMAGPART_EXPR,
15617 TREE_TYPE (TREE_TYPE (expr)),
15618 expr))));
15619
15620 return ffecom_2 (NE_EXPR, integer_type_node,
15621 expr,
15622 convert (TREE_TYPE (expr), integer_zero_node));
15623}
15624
15625tree
15626type_for_mode (mode, unsignedp)
15627 enum machine_mode mode;
15628 int unsignedp;
15629{
15630 int i;
15631 int j;
15632 tree t;
5ff904cd 15633
c7e4ee3a
CB
15634 if (mode == TYPE_MODE (integer_type_node))
15635 return unsignedp ? unsigned_type_node : integer_type_node;
5ff904cd 15636
c7e4ee3a
CB
15637 if (mode == TYPE_MODE (signed_char_type_node))
15638 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
5ff904cd 15639
c7e4ee3a
CB
15640 if (mode == TYPE_MODE (short_integer_type_node))
15641 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
5ff904cd 15642
c7e4ee3a
CB
15643 if (mode == TYPE_MODE (long_integer_type_node))
15644 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
5ff904cd 15645
c7e4ee3a
CB
15646 if (mode == TYPE_MODE (long_long_integer_type_node))
15647 return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
5ff904cd 15648
fed3cef0
RK
15649#if HOST_BITS_PER_WIDE_INT >= 64
15650 if (mode == TYPE_MODE (intTI_type_node))
15651 return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
15652#endif
15653
c7e4ee3a
CB
15654 if (mode == TYPE_MODE (float_type_node))
15655 return float_type_node;
5ff904cd 15656
c7e4ee3a
CB
15657 if (mode == TYPE_MODE (double_type_node))
15658 return double_type_node;
5ff904cd 15659
c7e4ee3a
CB
15660 if (mode == TYPE_MODE (build_pointer_type (char_type_node)))
15661 return build_pointer_type (char_type_node);
5ff904cd 15662
c7e4ee3a
CB
15663 if (mode == TYPE_MODE (build_pointer_type (integer_type_node)))
15664 return build_pointer_type (integer_type_node);
5ff904cd 15665
c7e4ee3a
CB
15666 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
15667 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
15668 {
15669 if (((t = ffecom_tree_type[i][j]) != NULL_TREE)
15670 && (mode == TYPE_MODE (t)))
15671 {
15672 if ((i == FFEINFO_basictypeINTEGER) && unsignedp)
15673 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][j];
15674 else
15675 return t;
15676 }
15677 }
5ff904cd 15678
c7e4ee3a 15679 return 0;
5ff904cd
JL
15680}
15681
c7e4ee3a
CB
15682tree
15683type_for_size (bits, unsignedp)
15684 unsigned bits;
15685 int unsignedp;
5ff904cd 15686{
c7e4ee3a
CB
15687 ffeinfoKindtype kt;
15688 tree type_node;
5ff904cd 15689
c7e4ee3a
CB
15690 if (bits == TYPE_PRECISION (integer_type_node))
15691 return unsignedp ? unsigned_type_node : integer_type_node;
5ff904cd 15692
c7e4ee3a
CB
15693 if (bits == TYPE_PRECISION (signed_char_type_node))
15694 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
5ff904cd 15695
c7e4ee3a
CB
15696 if (bits == TYPE_PRECISION (short_integer_type_node))
15697 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
5ff904cd 15698
c7e4ee3a
CB
15699 if (bits == TYPE_PRECISION (long_integer_type_node))
15700 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
5ff904cd 15701
c7e4ee3a
CB
15702 if (bits == TYPE_PRECISION (long_long_integer_type_node))
15703 return (unsignedp ? long_long_unsigned_type_node
15704 : long_long_integer_type_node);
5ff904cd 15705
c7e4ee3a 15706 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
5ff904cd 15707 {
c7e4ee3a 15708 type_node = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
5ff904cd 15709
c7e4ee3a
CB
15710 if ((type_node != NULL_TREE) && (bits == TYPE_PRECISION (type_node)))
15711 return unsignedp ? ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt]
15712 : type_node;
15713 }
5ff904cd 15714
c7e4ee3a
CB
15715 return 0;
15716}
5ff904cd 15717
c7e4ee3a
CB
15718tree
15719unsigned_type (type)
15720 tree type;
15721{
15722 tree type1 = TYPE_MAIN_VARIANT (type);
15723 ffeinfoKindtype kt;
15724 tree type2;
5ff904cd 15725
c7e4ee3a
CB
15726 if (type1 == signed_char_type_node || type1 == char_type_node)
15727 return unsigned_char_type_node;
15728 if (type1 == integer_type_node)
15729 return unsigned_type_node;
15730 if (type1 == short_integer_type_node)
15731 return short_unsigned_type_node;
15732 if (type1 == long_integer_type_node)
15733 return long_unsigned_type_node;
15734 if (type1 == long_long_integer_type_node)
15735 return long_long_unsigned_type_node;
15736#if 0 /* gcc/c-* files only */
15737 if (type1 == intDI_type_node)
15738 return unsigned_intDI_type_node;
15739 if (type1 == intSI_type_node)
15740 return unsigned_intSI_type_node;
15741 if (type1 == intHI_type_node)
15742 return unsigned_intHI_type_node;
15743 if (type1 == intQI_type_node)
15744 return unsigned_intQI_type_node;
15745#endif
5ff904cd 15746
c7e4ee3a
CB
15747 type2 = type_for_size (TYPE_PRECISION (type1), 1);
15748 if (type2 != NULL_TREE)
15749 return type2;
5ff904cd 15750
c7e4ee3a
CB
15751 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15752 {
15753 type2 = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
5ff904cd 15754
c7e4ee3a
CB
15755 if (type1 == type2)
15756 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
15757 }
5ff904cd 15758
c7e4ee3a
CB
15759 return type;
15760}
5ff904cd 15761
7189a4b0
GK
15762/* Callback routines for garbage collection. */
15763
15764int ggc_p = 1;
15765
15766void
15767lang_mark_tree (t)
15768 union tree_node *t ATTRIBUTE_UNUSED;
15769{
15770 if (TREE_CODE (t) == IDENTIFIER_NODE)
15771 {
15772 struct lang_identifier *i = (struct lang_identifier *) t;
15773 ggc_mark_tree (IDENTIFIER_GLOBAL_VALUE (i));
15774 ggc_mark_tree (IDENTIFIER_LOCAL_VALUE (i));
15775 ggc_mark_tree (IDENTIFIER_LABEL_VALUE (i));
15776 }
15777 else if (TYPE_P (t) && TYPE_LANG_SPECIFIC (t))
15778 ggc_mark (TYPE_LANG_SPECIFIC (t));
15779}
15780
15781void
15782lang_mark_false_label_stack (l)
15783 struct label_node *l;
15784{
15785 /* Fortran doesn't use false_label_stack. It better be NULL. */
15786 if (l != NULL)
15787 abort();
15788}
15789
c7e4ee3a
CB
15790#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
15791\f
15792#if FFECOM_GCC_INCLUDE
5ff904cd 15793
c7e4ee3a 15794/* From gcc/cccp.c, the code to handle -I. */
5ff904cd 15795
c7e4ee3a
CB
15796/* Skip leading "./" from a directory name.
15797 This may yield the empty string, which represents the current directory. */
5ff904cd 15798
c7e4ee3a
CB
15799static const char *
15800skip_redundant_dir_prefix (const char *dir)
15801{
15802 while (dir[0] == '.' && dir[1] == '/')
15803 for (dir += 2; *dir == '/'; dir++)
15804 continue;
15805 if (dir[0] == '.' && !dir[1])
15806 dir++;
15807 return dir;
15808}
5ff904cd 15809
c7e4ee3a
CB
15810/* The file_name_map structure holds a mapping of file names for a
15811 particular directory. This mapping is read from the file named
15812 FILE_NAME_MAP_FILE in that directory. Such a file can be used to
15813 map filenames on a file system with severe filename restrictions,
15814 such as DOS. The format of the file name map file is just a series
15815 of lines with two tokens on each line. The first token is the name
15816 to map, and the second token is the actual name to use. */
5ff904cd 15817
c7e4ee3a
CB
15818struct file_name_map
15819{
15820 struct file_name_map *map_next;
15821 char *map_from;
15822 char *map_to;
15823};
5ff904cd 15824
c7e4ee3a 15825#define FILE_NAME_MAP_FILE "header.gcc"
5ff904cd 15826
c7e4ee3a
CB
15827/* Current maximum length of directory names in the search path
15828 for include files. (Altered as we get more of them.) */
5ff904cd 15829
c7e4ee3a 15830static int max_include_len = 0;
5ff904cd 15831
c7e4ee3a
CB
15832struct file_name_list
15833 {
15834 struct file_name_list *next;
15835 char *fname;
15836 /* Mapping of file names for this directory. */
15837 struct file_name_map *name_map;
15838 /* Non-zero if name_map is valid. */
15839 int got_name_map;
15840 };
5ff904cd 15841
c7e4ee3a
CB
15842static struct file_name_list *include = NULL; /* First dir to search */
15843static struct file_name_list *last_include = NULL; /* Last in chain */
5ff904cd 15844
c7e4ee3a
CB
15845/* I/O buffer structure.
15846 The `fname' field is nonzero for source files and #include files
15847 and for the dummy text used for -D and -U.
15848 It is zero for rescanning results of macro expansion
15849 and for expanding macro arguments. */
15850#define INPUT_STACK_MAX 400
15851static struct file_buf {
b0791fa9 15852 const char *fname;
c7e4ee3a 15853 /* Filename specified with #line command. */
b0791fa9 15854 const char *nominal_fname;
c7e4ee3a
CB
15855 /* Record where in the search path this file was found.
15856 For #include_next. */
15857 struct file_name_list *dir;
15858 ffewhereLine line;
15859 ffewhereColumn column;
15860} instack[INPUT_STACK_MAX];
5ff904cd 15861
c7e4ee3a
CB
15862static int last_error_tick = 0; /* Incremented each time we print it. */
15863static int input_file_stack_tick = 0; /* Incremented when status changes. */
5ff904cd 15864
c7e4ee3a
CB
15865/* Current nesting level of input sources.
15866 `instack[indepth]' is the level currently being read. */
15867static int indepth = -1;
5ff904cd 15868
c7e4ee3a 15869typedef struct file_buf FILE_BUF;
5ff904cd 15870
c7e4ee3a 15871typedef unsigned char U_CHAR;
5ff904cd 15872
c7e4ee3a
CB
15873/* table to tell if char can be part of a C identifier. */
15874U_CHAR is_idchar[256];
15875/* table to tell if char can be first char of a c identifier. */
15876U_CHAR is_idstart[256];
15877/* table to tell if c is horizontal space. */
15878U_CHAR is_hor_space[256];
15879/* table to tell if c is horizontal or vertical space. */
15880static U_CHAR is_space[256];
5ff904cd 15881
c7e4ee3a
CB
15882#define SKIP_WHITE_SPACE(p) do { while (is_hor_space[*p]) p++; } while (0)
15883#define SKIP_ALL_WHITE_SPACE(p) do { while (is_space[*p]) p++; } while (0)
5ff904cd 15884
c7e4ee3a
CB
15885/* Nonzero means -I- has been seen,
15886 so don't look for #include "foo" the source-file directory. */
15887static int ignore_srcdir;
5ff904cd 15888
c7e4ee3a
CB
15889#ifndef INCLUDE_LEN_FUDGE
15890#define INCLUDE_LEN_FUDGE 0
15891#endif
5ff904cd 15892
c7e4ee3a
CB
15893static void append_include_chain (struct file_name_list *first,
15894 struct file_name_list *last);
15895static FILE *open_include_file (char *filename,
15896 struct file_name_list *searchptr);
15897static void print_containing_files (ffebadSeverity sev);
15898static const char *skip_redundant_dir_prefix (const char *);
15899static char *read_filename_string (int ch, FILE *f);
15900static struct file_name_map *read_name_map (const char *dirname);
5ff904cd 15901
c7e4ee3a
CB
15902/* Append a chain of `struct file_name_list's
15903 to the end of the main include chain.
15904 FIRST is the beginning of the chain to append, and LAST is the end. */
5ff904cd 15905
c7e4ee3a
CB
15906static void
15907append_include_chain (first, last)
15908 struct file_name_list *first, *last;
5ff904cd 15909{
c7e4ee3a 15910 struct file_name_list *dir;
5ff904cd 15911
c7e4ee3a
CB
15912 if (!first || !last)
15913 return;
5ff904cd 15914
c7e4ee3a
CB
15915 if (include == 0)
15916 include = first;
15917 else
15918 last_include->next = first;
5ff904cd 15919
c7e4ee3a
CB
15920 for (dir = first; ; dir = dir->next) {
15921 int len = strlen (dir->fname) + INCLUDE_LEN_FUDGE;
15922 if (len > max_include_len)
15923 max_include_len = len;
15924 if (dir == last)
15925 break;
15926 }
15927
15928 last->next = NULL;
15929 last_include = last;
5ff904cd
JL
15930}
15931
c7e4ee3a
CB
15932/* Try to open include file FILENAME. SEARCHPTR is the directory
15933 being tried from the include file search path. This function maps
15934 filenames on file systems based on information read by
15935 read_name_map. */
15936
15937static FILE *
15938open_include_file (filename, searchptr)
15939 char *filename;
15940 struct file_name_list *searchptr;
5ff904cd 15941{
c7e4ee3a
CB
15942 register struct file_name_map *map;
15943 register char *from;
15944 char *p, *dir;
5ff904cd 15945
c7e4ee3a
CB
15946 if (searchptr && ! searchptr->got_name_map)
15947 {
15948 searchptr->name_map = read_name_map (searchptr->fname
15949 ? searchptr->fname : ".");
15950 searchptr->got_name_map = 1;
15951 }
5ff904cd 15952
c7e4ee3a
CB
15953 /* First check the mapping for the directory we are using. */
15954 if (searchptr && searchptr->name_map)
15955 {
15956 from = filename;
15957 if (searchptr->fname)
15958 from += strlen (searchptr->fname) + 1;
15959 for (map = searchptr->name_map; map; map = map->map_next)
15960 {
15961 if (! strcmp (map->map_from, from))
15962 {
15963 /* Found a match. */
15964 return fopen (map->map_to, "r");
15965 }
15966 }
15967 }
5ff904cd 15968
c7e4ee3a
CB
15969 /* Try to find a mapping file for the particular directory we are
15970 looking in. Thus #include <sys/types.h> will look up sys/types.h
15971 in /usr/include/header.gcc and look up types.h in
15972 /usr/include/sys/header.gcc. */
15973 p = rindex (filename, '/');
15974#ifdef DIR_SEPARATOR
15975 if (! p) p = rindex (filename, DIR_SEPARATOR);
15976 else {
15977 char *tmp = rindex (filename, DIR_SEPARATOR);
15978 if (tmp != NULL && tmp > p) p = tmp;
15979 }
15980#endif
15981 if (! p)
15982 p = filename;
15983 if (searchptr
15984 && searchptr->fname
15985 && strlen (searchptr->fname) == (size_t) (p - filename)
15986 && ! strncmp (searchptr->fname, filename, (int) (p - filename)))
15987 {
15988 /* FILENAME is in SEARCHPTR, which we've already checked. */
15989 return fopen (filename, "r");
15990 }
15991
15992 if (p == filename)
15993 {
15994 from = filename;
15995 map = read_name_map (".");
15996 }
15997 else
5ff904cd 15998 {
c7e4ee3a
CB
15999 dir = (char *) xmalloc (p - filename + 1);
16000 memcpy (dir, filename, p - filename);
16001 dir[p - filename] = '\0';
16002 from = p + 1;
16003 map = read_name_map (dir);
16004 free (dir);
5ff904cd 16005 }
c7e4ee3a
CB
16006 for (; map; map = map->map_next)
16007 if (! strcmp (map->map_from, from))
16008 return fopen (map->map_to, "r");
5ff904cd 16009
c7e4ee3a 16010 return fopen (filename, "r");
5ff904cd
JL
16011}
16012
c7e4ee3a
CB
16013/* Print the file names and line numbers of the #include
16014 commands which led to the current file. */
5ff904cd 16015
c7e4ee3a
CB
16016static void
16017print_containing_files (ffebadSeverity sev)
16018{
16019 FILE_BUF *ip = NULL;
16020 int i;
16021 int first = 1;
16022 const char *str1;
16023 const char *str2;
5ff904cd 16024
c7e4ee3a
CB
16025 /* If stack of files hasn't changed since we last printed
16026 this info, don't repeat it. */
16027 if (last_error_tick == input_file_stack_tick)
16028 return;
5ff904cd 16029
c7e4ee3a
CB
16030 for (i = indepth; i >= 0; i--)
16031 if (instack[i].fname != NULL) {
16032 ip = &instack[i];
16033 break;
16034 }
5ff904cd 16035
c7e4ee3a
CB
16036 /* Give up if we don't find a source file. */
16037 if (ip == NULL)
16038 return;
5ff904cd 16039
c7e4ee3a
CB
16040 /* Find the other, outer source files. */
16041 for (i--; i >= 0; i--)
16042 if (instack[i].fname != NULL)
16043 {
16044 ip = &instack[i];
16045 if (first)
16046 {
16047 first = 0;
16048 str1 = "In file included";
16049 }
16050 else
16051 {
16052 str1 = "... ...";
16053 }
5ff904cd 16054
c7e4ee3a
CB
16055 if (i == 1)
16056 str2 = ":";
16057 else
16058 str2 = "";
5ff904cd 16059
c7e4ee3a
CB
16060 ffebad_start_msg ("%A from %B at %0%C", sev);
16061 ffebad_here (0, ip->line, ip->column);
16062 ffebad_string (str1);
16063 ffebad_string (ip->nominal_fname);
16064 ffebad_string (str2);
16065 ffebad_finish ();
16066 }
5ff904cd 16067
c7e4ee3a
CB
16068 /* Record we have printed the status as of this time. */
16069 last_error_tick = input_file_stack_tick;
16070}
5ff904cd 16071
c7e4ee3a
CB
16072/* Read a space delimited string of unlimited length from a stdio
16073 file. */
5ff904cd 16074
c7e4ee3a
CB
16075static char *
16076read_filename_string (ch, f)
16077 int ch;
16078 FILE *f;
16079{
16080 char *alloc, *set;
16081 int len;
5ff904cd 16082
c7e4ee3a
CB
16083 len = 20;
16084 set = alloc = xmalloc (len + 1);
16085 if (! is_space[ch])
16086 {
16087 *set++ = ch;
16088 while ((ch = getc (f)) != EOF && ! is_space[ch])
16089 {
16090 if (set - alloc == len)
16091 {
16092 len *= 2;
16093 alloc = xrealloc (alloc, len + 1);
16094 set = alloc + len / 2;
16095 }
16096 *set++ = ch;
16097 }
16098 }
16099 *set = '\0';
16100 ungetc (ch, f);
16101 return alloc;
16102}
5ff904cd 16103
c7e4ee3a 16104/* Read the file name map file for DIRNAME. */
5ff904cd 16105
c7e4ee3a
CB
16106static struct file_name_map *
16107read_name_map (dirname)
16108 const char *dirname;
16109{
16110 /* This structure holds a linked list of file name maps, one per
16111 directory. */
16112 struct file_name_map_list
16113 {
16114 struct file_name_map_list *map_list_next;
16115 char *map_list_name;
16116 struct file_name_map *map_list_map;
16117 };
16118 static struct file_name_map_list *map_list;
16119 register struct file_name_map_list *map_list_ptr;
16120 char *name;
16121 FILE *f;
16122 size_t dirlen;
16123 int separator_needed;
5ff904cd 16124
c7e4ee3a 16125 dirname = skip_redundant_dir_prefix (dirname);
5ff904cd 16126
c7e4ee3a
CB
16127 for (map_list_ptr = map_list; map_list_ptr;
16128 map_list_ptr = map_list_ptr->map_list_next)
16129 if (! strcmp (map_list_ptr->map_list_name, dirname))
16130 return map_list_ptr->map_list_map;
5ff904cd 16131
c7e4ee3a
CB
16132 map_list_ptr = ((struct file_name_map_list *)
16133 xmalloc (sizeof (struct file_name_map_list)));
16134 map_list_ptr->map_list_name = xstrdup (dirname);
16135 map_list_ptr->map_list_map = NULL;
5ff904cd 16136
c7e4ee3a
CB
16137 dirlen = strlen (dirname);
16138 separator_needed = dirlen != 0 && dirname[dirlen - 1] != '/';
16139 name = (char *) xmalloc (dirlen + strlen (FILE_NAME_MAP_FILE) + 2);
16140 strcpy (name, dirname);
16141 name[dirlen] = '/';
16142 strcpy (name + dirlen + separator_needed, FILE_NAME_MAP_FILE);
16143 f = fopen (name, "r");
16144 free (name);
16145 if (!f)
16146 map_list_ptr->map_list_map = NULL;
16147 else
16148 {
16149 int ch;
5ff904cd 16150
c7e4ee3a
CB
16151 while ((ch = getc (f)) != EOF)
16152 {
16153 char *from, *to;
16154 struct file_name_map *ptr;
16155
16156 if (is_space[ch])
16157 continue;
16158 from = read_filename_string (ch, f);
16159 while ((ch = getc (f)) != EOF && is_hor_space[ch])
16160 ;
16161 to = read_filename_string (ch, f);
5ff904cd 16162
c7e4ee3a
CB
16163 ptr = ((struct file_name_map *)
16164 xmalloc (sizeof (struct file_name_map)));
16165 ptr->map_from = from;
5ff904cd 16166
c7e4ee3a
CB
16167 /* Make the real filename absolute. */
16168 if (*to == '/')
16169 ptr->map_to = to;
16170 else
16171 {
16172 ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
16173 strcpy (ptr->map_to, dirname);
16174 ptr->map_to[dirlen] = '/';
16175 strcpy (ptr->map_to + dirlen + separator_needed, to);
16176 free (to);
16177 }
5ff904cd 16178
c7e4ee3a
CB
16179 ptr->map_next = map_list_ptr->map_list_map;
16180 map_list_ptr->map_list_map = ptr;
5ff904cd 16181
c7e4ee3a
CB
16182 while ((ch = getc (f)) != '\n')
16183 if (ch == EOF)
16184 break;
16185 }
16186 fclose (f);
5ff904cd
JL
16187 }
16188
c7e4ee3a
CB
16189 map_list_ptr->map_list_next = map_list;
16190 map_list = map_list_ptr;
5ff904cd 16191
c7e4ee3a 16192 return map_list_ptr->map_list_map;
5ff904cd
JL
16193}
16194
c7e4ee3a 16195static void
b0791fa9 16196ffecom_file_ (const char *name)
5ff904cd 16197{
c7e4ee3a 16198 FILE_BUF *fp;
5ff904cd 16199
c7e4ee3a
CB
16200 /* Do partial setup of input buffer for the sake of generating
16201 early #line directives (when -g is in effect). */
5ff904cd 16202
c7e4ee3a
CB
16203 fp = &instack[++indepth];
16204 memset ((char *) fp, 0, sizeof (FILE_BUF));
16205 if (name == NULL)
16206 name = "";
16207 fp->nominal_fname = fp->fname = name;
16208}
5ff904cd 16209
c7e4ee3a 16210/* Initialize syntactic classifications of characters. */
5ff904cd 16211
c7e4ee3a
CB
16212static void
16213ffecom_initialize_char_syntax_ ()
16214{
16215 register int i;
5ff904cd 16216
c7e4ee3a
CB
16217 /*
16218 * Set up is_idchar and is_idstart tables. These should be
16219 * faster than saying (is_alpha (c) || c == '_'), etc.
16220 * Set up these things before calling any routines tthat
16221 * refer to them.
16222 */
16223 for (i = 'a'; i <= 'z'; i++) {
16224 is_idchar[i - 'a' + 'A'] = 1;
16225 is_idchar[i] = 1;
16226 is_idstart[i - 'a' + 'A'] = 1;
16227 is_idstart[i] = 1;
16228 }
16229 for (i = '0'; i <= '9'; i++)
16230 is_idchar[i] = 1;
16231 is_idchar['_'] = 1;
16232 is_idstart['_'] = 1;
5ff904cd 16233
c7e4ee3a
CB
16234 /* horizontal space table */
16235 is_hor_space[' '] = 1;
16236 is_hor_space['\t'] = 1;
16237 is_hor_space['\v'] = 1;
16238 is_hor_space['\f'] = 1;
16239 is_hor_space['\r'] = 1;
5ff904cd 16240
c7e4ee3a
CB
16241 is_space[' '] = 1;
16242 is_space['\t'] = 1;
16243 is_space['\v'] = 1;
16244 is_space['\f'] = 1;
16245 is_space['\n'] = 1;
16246 is_space['\r'] = 1;
16247}
5ff904cd 16248
c7e4ee3a
CB
16249static void
16250ffecom_close_include_ (FILE *f)
16251{
16252 fclose (f);
5ff904cd 16253
c7e4ee3a
CB
16254 indepth--;
16255 input_file_stack_tick++;
5ff904cd 16256
c7e4ee3a
CB
16257 ffewhere_line_kill (instack[indepth].line);
16258 ffewhere_column_kill (instack[indepth].column);
16259}
5ff904cd 16260
c7e4ee3a
CB
16261static int
16262ffecom_decode_include_option_ (char *spec)
16263{
16264 struct file_name_list *dirtmp;
16265
16266 if (! ignore_srcdir && !strcmp (spec, "-"))
16267 ignore_srcdir = 1;
16268 else
16269 {
16270 dirtmp = (struct file_name_list *)
16271 xmalloc (sizeof (struct file_name_list));
16272 dirtmp->next = 0; /* New one goes on the end */
16273 if (spec[0] != 0)
16274 dirtmp->fname = spec;
16275 else
16276 fatal ("Directory name must immediately follow -I option with no intervening spaces, as in `-Idir', not `-I dir'");
16277 dirtmp->got_name_map = 0;
16278 append_include_chain (dirtmp, dirtmp);
16279 }
16280 return 1;
5ff904cd
JL
16281}
16282
c7e4ee3a
CB
16283/* Open INCLUDEd file. */
16284
16285static FILE *
16286ffecom_open_include_ (char *name, ffewhereLine l, ffewhereColumn c)
5ff904cd 16287{
c7e4ee3a
CB
16288 char *fbeg = name;
16289 size_t flen = strlen (fbeg);
16290 struct file_name_list *search_start = include; /* Chain of dirs to search */
16291 struct file_name_list dsp[1]; /* First in chain, if #include "..." */
16292 struct file_name_list *searchptr = 0;
16293 char *fname; /* Dynamically allocated fname buffer */
16294 FILE *f;
16295 FILE_BUF *fp;
5ff904cd 16296
c7e4ee3a
CB
16297 if (flen == 0)
16298 return NULL;
5ff904cd 16299
c7e4ee3a 16300 dsp[0].fname = NULL;
5ff904cd 16301
c7e4ee3a
CB
16302 /* If -I- was specified, don't search current dir, only spec'd ones. */
16303 if (!ignore_srcdir)
16304 {
16305 for (fp = &instack[indepth]; fp >= instack; fp--)
16306 {
16307 int n;
16308 char *ep;
b0791fa9 16309 const char *nam;
5ff904cd 16310
c7e4ee3a
CB
16311 if ((nam = fp->nominal_fname) != NULL)
16312 {
16313 /* Found a named file. Figure out dir of the file,
16314 and put it in front of the search list. */
16315 dsp[0].next = search_start;
16316 search_start = dsp;
16317#ifndef VMS
16318 ep = rindex (nam, '/');
16319#ifdef DIR_SEPARATOR
16320 if (ep == NULL) ep = rindex (nam, DIR_SEPARATOR);
16321 else {
16322 char *tmp = rindex (nam, DIR_SEPARATOR);
16323 if (tmp != NULL && tmp > ep) ep = tmp;
16324 }
16325#endif
16326#else /* VMS */
16327 ep = rindex (nam, ']');
16328 if (ep == NULL) ep = rindex (nam, '>');
16329 if (ep == NULL) ep = rindex (nam, ':');
16330 if (ep != NULL) ep++;
16331#endif /* VMS */
16332 if (ep != NULL)
16333 {
16334 n = ep - nam;
16335 dsp[0].fname = (char *) xmalloc (n + 1);
16336 strncpy (dsp[0].fname, nam, n);
16337 dsp[0].fname[n] = '\0';
16338 if (n + INCLUDE_LEN_FUDGE > max_include_len)
16339 max_include_len = n + INCLUDE_LEN_FUDGE;
16340 }
16341 else
16342 dsp[0].fname = NULL; /* Current directory */
16343 dsp[0].got_name_map = 0;
16344 break;
16345 }
16346 }
16347 }
5ff904cd 16348
c7e4ee3a
CB
16349 /* Allocate this permanently, because it gets stored in the definitions
16350 of macros. */
16351 fname = xmalloc (max_include_len + flen + 4);
16352 /* + 2 above for slash and terminating null. */
16353 /* + 2 added for '.h' on VMS (to support '#include filename') (NOT USED
16354 for g77 yet). */
5ff904cd 16355
c7e4ee3a 16356 /* If specified file name is absolute, just open it. */
5ff904cd 16357
c7e4ee3a
CB
16358 if (*fbeg == '/'
16359#ifdef DIR_SEPARATOR
16360 || *fbeg == DIR_SEPARATOR
16361#endif
16362 )
16363 {
16364 strncpy (fname, (char *) fbeg, flen);
16365 fname[flen] = 0;
16366 f = open_include_file (fname, NULL_PTR);
5ff904cd 16367 }
c7e4ee3a
CB
16368 else
16369 {
16370 f = NULL;
5ff904cd 16371
c7e4ee3a
CB
16372 /* Search directory path, trying to open the file.
16373 Copy each filename tried into FNAME. */
5ff904cd 16374
c7e4ee3a
CB
16375 for (searchptr = search_start; searchptr; searchptr = searchptr->next)
16376 {
16377 if (searchptr->fname)
16378 {
16379 /* The empty string in a search path is ignored.
16380 This makes it possible to turn off entirely
16381 a standard piece of the list. */
16382 if (searchptr->fname[0] == 0)
16383 continue;
16384 strcpy (fname, skip_redundant_dir_prefix (searchptr->fname));
16385 if (fname[0] && fname[strlen (fname) - 1] != '/')
16386 strcat (fname, "/");
16387 fname[strlen (fname) + flen] = 0;
16388 }
16389 else
16390 fname[0] = 0;
5ff904cd 16391
c7e4ee3a
CB
16392 strncat (fname, fbeg, flen);
16393#ifdef VMS
16394 /* Change this 1/2 Unix 1/2 VMS file specification into a
16395 full VMS file specification */
16396 if (searchptr->fname && (searchptr->fname[0] != 0))
16397 {
16398 /* Fix up the filename */
16399 hack_vms_include_specification (fname);
16400 }
16401 else
16402 {
16403 /* This is a normal VMS filespec, so use it unchanged. */
16404 strncpy (fname, (char *) fbeg, flen);
16405 fname[flen] = 0;
16406#if 0 /* Not for g77. */
16407 /* if it's '#include filename', add the missing .h */
16408 if (index (fname, '.') == NULL)
16409 strcat (fname, ".h");
5ff904cd 16410#endif
c7e4ee3a
CB
16411 }
16412#endif /* VMS */
16413 f = open_include_file (fname, searchptr);
16414#ifdef EACCES
16415 if (f == NULL && errno == EACCES)
16416 {
16417 print_containing_files (FFEBAD_severityWARNING);
16418 ffebad_start_msg ("At %0, INCLUDE file %A exists, but is not readable",
16419 FFEBAD_severityWARNING);
16420 ffebad_string (fname);
16421 ffebad_here (0, l, c);
16422 ffebad_finish ();
16423 }
16424#endif
16425 if (f != NULL)
16426 break;
16427 }
16428 }
5ff904cd 16429
c7e4ee3a 16430 if (f == NULL)
5ff904cd 16431 {
c7e4ee3a 16432 /* A file that was not found. */
5ff904cd 16433
c7e4ee3a
CB
16434 strncpy (fname, (char *) fbeg, flen);
16435 fname[flen] = 0;
16436 print_containing_files (ffebad_severity (FFEBAD_OPEN_INCLUDE));
16437 ffebad_start (FFEBAD_OPEN_INCLUDE);
16438 ffebad_here (0, l, c);
16439 ffebad_string (fname);
16440 ffebad_finish ();
5ff904cd
JL
16441 }
16442
c7e4ee3a
CB
16443 if (dsp[0].fname != NULL)
16444 free (dsp[0].fname);
5ff904cd 16445
c7e4ee3a
CB
16446 if (f == NULL)
16447 return NULL;
5ff904cd 16448
c7e4ee3a
CB
16449 if (indepth >= (INPUT_STACK_MAX - 1))
16450 {
16451 print_containing_files (FFEBAD_severityFATAL);
16452 ffebad_start_msg ("At %0, INCLUDE nesting too deep",
16453 FFEBAD_severityFATAL);
16454 ffebad_string (fname);
16455 ffebad_here (0, l, c);
16456 ffebad_finish ();
16457 return NULL;
16458 }
5ff904cd 16459
c7e4ee3a
CB
16460 instack[indepth].line = ffewhere_line_use (l);
16461 instack[indepth].column = ffewhere_column_use (c);
5ff904cd 16462
c7e4ee3a
CB
16463 fp = &instack[indepth + 1];
16464 memset ((char *) fp, 0, sizeof (FILE_BUF));
16465 fp->nominal_fname = fp->fname = fname;
16466 fp->dir = searchptr;
5ff904cd 16467
c7e4ee3a
CB
16468 indepth++;
16469 input_file_stack_tick++;
5ff904cd 16470
c7e4ee3a
CB
16471 return f;
16472}
16473#endif /* FFECOM_GCC_INCLUDE */
5ff904cd 16474
c7e4ee3a
CB
16475/**INDENT* (Do not reformat this comment even with -fca option.)
16476 Data-gathering files: Given the source file listed below, compiled with
16477 f2c I obtained the output file listed after that, and from the output
16478 file I derived the above code.
5ff904cd 16479
c7e4ee3a
CB
16480-------- (begin input file to f2c)
16481 implicit none
16482 character*10 A1,A2
16483 complex C1,C2
16484 integer I1,I2
16485 real R1,R2
16486 double precision D1,D2
16487C
16488 call getem(A1,A2,C1,C2,I1,I2,R1,R2,D1,D2)
16489c /
16490 call fooI(I1/I2)
16491 call fooR(R1/I1)
16492 call fooD(D1/I1)
16493 call fooC(C1/I1)
16494 call fooR(R1/R2)
16495 call fooD(R1/D1)
16496 call fooD(D1/D2)
16497 call fooD(D1/R1)
16498 call fooC(C1/C2)
16499 call fooC(C1/R1)
16500 call fooZ(C1/D1)
16501c **
16502 call fooI(I1**I2)
16503 call fooR(R1**I1)
16504 call fooD(D1**I1)
16505 call fooC(C1**I1)
16506 call fooR(R1**R2)
16507 call fooD(R1**D1)
16508 call fooD(D1**D2)
16509 call fooD(D1**R1)
16510 call fooC(C1**C2)
16511 call fooC(C1**R1)
16512 call fooZ(C1**D1)
16513c FFEINTRIN_impABS
16514 call fooR(ABS(R1))
16515c FFEINTRIN_impACOS
16516 call fooR(ACOS(R1))
16517c FFEINTRIN_impAIMAG
16518 call fooR(AIMAG(C1))
16519c FFEINTRIN_impAINT
16520 call fooR(AINT(R1))
16521c FFEINTRIN_impALOG
16522 call fooR(ALOG(R1))
16523c FFEINTRIN_impALOG10
16524 call fooR(ALOG10(R1))
16525c FFEINTRIN_impAMAX0
16526 call fooR(AMAX0(I1,I2))
16527c FFEINTRIN_impAMAX1
16528 call fooR(AMAX1(R1,R2))
16529c FFEINTRIN_impAMIN0
16530 call fooR(AMIN0(I1,I2))
16531c FFEINTRIN_impAMIN1
16532 call fooR(AMIN1(R1,R2))
16533c FFEINTRIN_impAMOD
16534 call fooR(AMOD(R1,R2))
16535c FFEINTRIN_impANINT
16536 call fooR(ANINT(R1))
16537c FFEINTRIN_impASIN
16538 call fooR(ASIN(R1))
16539c FFEINTRIN_impATAN
16540 call fooR(ATAN(R1))
16541c FFEINTRIN_impATAN2
16542 call fooR(ATAN2(R1,R2))
16543c FFEINTRIN_impCABS
16544 call fooR(CABS(C1))
16545c FFEINTRIN_impCCOS
16546 call fooC(CCOS(C1))
16547c FFEINTRIN_impCEXP
16548 call fooC(CEXP(C1))
16549c FFEINTRIN_impCHAR
16550 call fooA(CHAR(I1))
16551c FFEINTRIN_impCLOG
16552 call fooC(CLOG(C1))
16553c FFEINTRIN_impCONJG
16554 call fooC(CONJG(C1))
16555c FFEINTRIN_impCOS
16556 call fooR(COS(R1))
16557c FFEINTRIN_impCOSH
16558 call fooR(COSH(R1))
16559c FFEINTRIN_impCSIN
16560 call fooC(CSIN(C1))
16561c FFEINTRIN_impCSQRT
16562 call fooC(CSQRT(C1))
16563c FFEINTRIN_impDABS
16564 call fooD(DABS(D1))
16565c FFEINTRIN_impDACOS
16566 call fooD(DACOS(D1))
16567c FFEINTRIN_impDASIN
16568 call fooD(DASIN(D1))
16569c FFEINTRIN_impDATAN
16570 call fooD(DATAN(D1))
16571c FFEINTRIN_impDATAN2
16572 call fooD(DATAN2(D1,D2))
16573c FFEINTRIN_impDCOS
16574 call fooD(DCOS(D1))
16575c FFEINTRIN_impDCOSH
16576 call fooD(DCOSH(D1))
16577c FFEINTRIN_impDDIM
16578 call fooD(DDIM(D1,D2))
16579c FFEINTRIN_impDEXP
16580 call fooD(DEXP(D1))
16581c FFEINTRIN_impDIM
16582 call fooR(DIM(R1,R2))
16583c FFEINTRIN_impDINT
16584 call fooD(DINT(D1))
16585c FFEINTRIN_impDLOG
16586 call fooD(DLOG(D1))
16587c FFEINTRIN_impDLOG10
16588 call fooD(DLOG10(D1))
16589c FFEINTRIN_impDMAX1
16590 call fooD(DMAX1(D1,D2))
16591c FFEINTRIN_impDMIN1
16592 call fooD(DMIN1(D1,D2))
16593c FFEINTRIN_impDMOD
16594 call fooD(DMOD(D1,D2))
16595c FFEINTRIN_impDNINT
16596 call fooD(DNINT(D1))
16597c FFEINTRIN_impDPROD
16598 call fooD(DPROD(R1,R2))
16599c FFEINTRIN_impDSIGN
16600 call fooD(DSIGN(D1,D2))
16601c FFEINTRIN_impDSIN
16602 call fooD(DSIN(D1))
16603c FFEINTRIN_impDSINH
16604 call fooD(DSINH(D1))
16605c FFEINTRIN_impDSQRT
16606 call fooD(DSQRT(D1))
16607c FFEINTRIN_impDTAN
16608 call fooD(DTAN(D1))
16609c FFEINTRIN_impDTANH
16610 call fooD(DTANH(D1))
16611c FFEINTRIN_impEXP
16612 call fooR(EXP(R1))
16613c FFEINTRIN_impIABS
16614 call fooI(IABS(I1))
16615c FFEINTRIN_impICHAR
16616 call fooI(ICHAR(A1))
16617c FFEINTRIN_impIDIM
16618 call fooI(IDIM(I1,I2))
16619c FFEINTRIN_impIDNINT
16620 call fooI(IDNINT(D1))
16621c FFEINTRIN_impINDEX
16622 call fooI(INDEX(A1,A2))
16623c FFEINTRIN_impISIGN
16624 call fooI(ISIGN(I1,I2))
16625c FFEINTRIN_impLEN
16626 call fooI(LEN(A1))
16627c FFEINTRIN_impLGE
16628 call fooL(LGE(A1,A2))
16629c FFEINTRIN_impLGT
16630 call fooL(LGT(A1,A2))
16631c FFEINTRIN_impLLE
16632 call fooL(LLE(A1,A2))
16633c FFEINTRIN_impLLT
16634 call fooL(LLT(A1,A2))
16635c FFEINTRIN_impMAX0
16636 call fooI(MAX0(I1,I2))
16637c FFEINTRIN_impMAX1
16638 call fooI(MAX1(R1,R2))
16639c FFEINTRIN_impMIN0
16640 call fooI(MIN0(I1,I2))
16641c FFEINTRIN_impMIN1
16642 call fooI(MIN1(R1,R2))
16643c FFEINTRIN_impMOD
16644 call fooI(MOD(I1,I2))
16645c FFEINTRIN_impNINT
16646 call fooI(NINT(R1))
16647c FFEINTRIN_impSIGN
16648 call fooR(SIGN(R1,R2))
16649c FFEINTRIN_impSIN
16650 call fooR(SIN(R1))
16651c FFEINTRIN_impSINH
16652 call fooR(SINH(R1))
16653c FFEINTRIN_impSQRT
16654 call fooR(SQRT(R1))
16655c FFEINTRIN_impTAN
16656 call fooR(TAN(R1))
16657c FFEINTRIN_impTANH
16658 call fooR(TANH(R1))
16659c FFEINTRIN_imp_CMPLX_C
16660 call fooC(cmplx(C1,C2))
16661c FFEINTRIN_imp_CMPLX_D
16662 call fooZ(cmplx(D1,D2))
16663c FFEINTRIN_imp_CMPLX_I
16664 call fooC(cmplx(I1,I2))
16665c FFEINTRIN_imp_CMPLX_R
16666 call fooC(cmplx(R1,R2))
16667c FFEINTRIN_imp_DBLE_C
16668 call fooD(dble(C1))
16669c FFEINTRIN_imp_DBLE_D
16670 call fooD(dble(D1))
16671c FFEINTRIN_imp_DBLE_I
16672 call fooD(dble(I1))
16673c FFEINTRIN_imp_DBLE_R
16674 call fooD(dble(R1))
16675c FFEINTRIN_imp_INT_C
16676 call fooI(int(C1))
16677c FFEINTRIN_imp_INT_D
16678 call fooI(int(D1))
16679c FFEINTRIN_imp_INT_I
16680 call fooI(int(I1))
16681c FFEINTRIN_imp_INT_R
16682 call fooI(int(R1))
16683c FFEINTRIN_imp_REAL_C
16684 call fooR(real(C1))
16685c FFEINTRIN_imp_REAL_D
16686 call fooR(real(D1))
16687c FFEINTRIN_imp_REAL_I
16688 call fooR(real(I1))
16689c FFEINTRIN_imp_REAL_R
16690 call fooR(real(R1))
16691c
16692c FFEINTRIN_imp_INT_D:
16693c
16694c FFEINTRIN_specIDINT
16695 call fooI(IDINT(D1))
16696c
16697c FFEINTRIN_imp_INT_R:
16698c
16699c FFEINTRIN_specIFIX
16700 call fooI(IFIX(R1))
16701c FFEINTRIN_specINT
16702 call fooI(INT(R1))
16703c
16704c FFEINTRIN_imp_REAL_D:
16705c
16706c FFEINTRIN_specSNGL
16707 call fooR(SNGL(D1))
16708c
16709c FFEINTRIN_imp_REAL_I:
16710c
16711c FFEINTRIN_specFLOAT
16712 call fooR(FLOAT(I1))
16713c FFEINTRIN_specREAL
16714 call fooR(REAL(I1))
16715c
16716 end
16717-------- (end input file to f2c)
5ff904cd 16718
c7e4ee3a
CB
16719-------- (begin output from providing above input file as input to:
16720-------- `f2c | gcc -E -C - | sed -e "s:/[*]*://:g" -e "s:[*]*[/]://:g" \
16721-------- -e "s:^#.*$::g"')
5ff904cd 16722
c7e4ee3a
CB
16723// -- translated by f2c (version 19950223).
16724 You must link the resulting object file with the libraries:
16725 -lf2c -lm (in that order)
16726//
5ff904cd 16727
5ff904cd 16728
c7e4ee3a 16729// f2c.h -- Standard Fortran to C header file //
5ff904cd 16730
c7e4ee3a 16731/// barf [ba:rf] 2. "He suggested using FORTRAN, and everybody barfed."
5ff904cd 16732
c7e4ee3a 16733 - From The Shogakukan DICTIONARY OF NEW ENGLISH (Second edition) //
5ff904cd 16734
5ff904cd 16735
5ff904cd 16736
5ff904cd 16737
c7e4ee3a
CB
16738// F2C_INTEGER will normally be `int' but would be `long' on 16-bit systems //
16739// we assume short, float are OK //
16740typedef long int // long int // integer;
16741typedef char *address;
16742typedef short int shortint;
16743typedef float real;
16744typedef double doublereal;
16745typedef struct { real r, i; } complex;
16746typedef struct { doublereal r, i; } doublecomplex;
16747typedef long int // long int // logical;
16748typedef short int shortlogical;
16749typedef char logical1;
16750typedef char integer1;
16751// typedef long long longint; // // system-dependent //
5ff904cd 16752
5ff904cd 16753
5ff904cd 16754
5ff904cd 16755
c7e4ee3a 16756// Extern is for use with -E //
5ff904cd 16757
5ff904cd 16758
5ff904cd 16759
5ff904cd 16760
c7e4ee3a 16761// I/O stuff //
5ff904cd 16762
5ff904cd 16763
5ff904cd 16764
5ff904cd 16765
5ff904cd 16766
5ff904cd 16767
5ff904cd 16768
5ff904cd 16769
c7e4ee3a
CB
16770typedef long int // int or long int // flag;
16771typedef long int // int or long int // ftnlen;
16772typedef long int // int or long int // ftnint;
5ff904cd 16773
5ff904cd 16774
c7e4ee3a
CB
16775//external read, write//
16776typedef struct
16777{ flag cierr;
16778 ftnint ciunit;
16779 flag ciend;
16780 char *cifmt;
16781 ftnint cirec;
16782} cilist;
5ff904cd 16783
c7e4ee3a
CB
16784//internal read, write//
16785typedef struct
16786{ flag icierr;
16787 char *iciunit;
16788 flag iciend;
16789 char *icifmt;
16790 ftnint icirlen;
16791 ftnint icirnum;
16792} icilist;
5ff904cd 16793
c7e4ee3a
CB
16794//open//
16795typedef struct
16796{ flag oerr;
16797 ftnint ounit;
16798 char *ofnm;
16799 ftnlen ofnmlen;
16800 char *osta;
16801 char *oacc;
16802 char *ofm;
16803 ftnint orl;
16804 char *oblnk;
16805} olist;
5ff904cd 16806
c7e4ee3a
CB
16807//close//
16808typedef struct
16809{ flag cerr;
16810 ftnint cunit;
16811 char *csta;
16812} cllist;
5ff904cd 16813
c7e4ee3a
CB
16814//rewind, backspace, endfile//
16815typedef struct
16816{ flag aerr;
16817 ftnint aunit;
16818} alist;
5ff904cd 16819
c7e4ee3a
CB
16820// inquire //
16821typedef struct
16822{ flag inerr;
16823 ftnint inunit;
16824 char *infile;
16825 ftnlen infilen;
16826 ftnint *inex; //parameters in standard's order//
16827 ftnint *inopen;
16828 ftnint *innum;
16829 ftnint *innamed;
16830 char *inname;
16831 ftnlen innamlen;
16832 char *inacc;
16833 ftnlen inacclen;
16834 char *inseq;
16835 ftnlen inseqlen;
16836 char *indir;
16837 ftnlen indirlen;
16838 char *infmt;
16839 ftnlen infmtlen;
16840 char *inform;
16841 ftnint informlen;
16842 char *inunf;
16843 ftnlen inunflen;
16844 ftnint *inrecl;
16845 ftnint *innrec;
16846 char *inblank;
16847 ftnlen inblanklen;
16848} inlist;
5ff904cd 16849
5ff904cd 16850
5ff904cd 16851
c7e4ee3a
CB
16852union Multitype { // for multiple entry points //
16853 integer1 g;
16854 shortint h;
16855 integer i;
16856 // longint j; //
16857 real r;
16858 doublereal d;
16859 complex c;
16860 doublecomplex z;
16861 };
16862
16863typedef union Multitype Multitype;
5ff904cd 16864
c7e4ee3a 16865typedef long Long; // No longer used; formerly in Namelist //
5ff904cd 16866
c7e4ee3a
CB
16867struct Vardesc { // for Namelist //
16868 char *name;
16869 char *addr;
16870 ftnlen *dims;
16871 int type;
16872 };
16873typedef struct Vardesc Vardesc;
5ff904cd 16874
c7e4ee3a
CB
16875struct Namelist {
16876 char *name;
16877 Vardesc **vars;
16878 int nvars;
16879 };
16880typedef struct Namelist Namelist;
5ff904cd 16881
5ff904cd 16882
5ff904cd 16883
5ff904cd 16884
5ff904cd 16885
5ff904cd 16886
5ff904cd 16887
5ff904cd 16888
c7e4ee3a 16889// procedure parameter types for -A and -C++ //
5ff904cd 16890
5ff904cd 16891
5ff904cd 16892
5ff904cd 16893
c7e4ee3a
CB
16894typedef int // Unknown procedure type // (*U_fp)();
16895typedef shortint (*J_fp)();
16896typedef integer (*I_fp)();
16897typedef real (*R_fp)();
16898typedef doublereal (*D_fp)(), (*E_fp)();
16899typedef // Complex // void (*C_fp)();
16900typedef // Double Complex // void (*Z_fp)();
16901typedef logical (*L_fp)();
16902typedef shortlogical (*K_fp)();
16903typedef // Character // void (*H_fp)();
16904typedef // Subroutine // int (*S_fp)();
5ff904cd 16905
c7e4ee3a
CB
16906// E_fp is for real functions when -R is not specified //
16907typedef void C_f; // complex function //
16908typedef void H_f; // character function //
16909typedef void Z_f; // double complex function //
16910typedef doublereal E_f; // real function with -R not specified //
5ff904cd 16911
c7e4ee3a 16912// undef any lower-case symbols that your C compiler predefines, e.g.: //
5ff904cd 16913
5ff904cd 16914
c7e4ee3a
CB
16915// (No such symbols should be defined in a strict ANSI C compiler.
16916 We can avoid trouble with f2c-translated code by using
16917 gcc -ansi [-traditional].) //
16918
5ff904cd 16919
5ff904cd 16920
5ff904cd 16921
5ff904cd 16922
5ff904cd 16923
5ff904cd 16924
5ff904cd 16925
5ff904cd 16926
5ff904cd 16927
5ff904cd 16928
5ff904cd 16929
5ff904cd 16930
5ff904cd 16931
5ff904cd 16932
5ff904cd 16933
5ff904cd 16934
5ff904cd 16935
5ff904cd 16936
5ff904cd 16937
5ff904cd 16938
5ff904cd 16939
5ff904cd 16940
c7e4ee3a
CB
16941// Main program // MAIN__()
16942{
16943 // System generated locals //
16944 integer i__1;
16945 real r__1, r__2;
16946 doublereal d__1, d__2;
16947 complex q__1;
16948 doublecomplex z__1, z__2, z__3;
16949 logical L__1;
16950 char ch__1[1];
16951
16952 // Builtin functions //
16953 void c_div();
16954 integer pow_ii();
16955 double pow_ri(), pow_di();
16956 void pow_ci();
16957 double pow_dd();
16958 void pow_zz();
16959 double acos(), r_imag(), r_int(), log(), r_lg10(), r_mod(), r_nint(),
16960 asin(), atan(), atan2(), c_abs();
16961 void c_cos(), c_exp(), c_log(), r_cnjg();
16962 double cos(), cosh();
16963 void c_sin(), c_sqrt();
16964 double d_dim(), exp(), r_dim(), d_int(), d_lg10(), d_mod(), d_nint(),
16965 d_sign(), sin(), sinh(), sqrt(), tan(), tanh();
16966 integer i_dim(), i_dnnt(), i_indx(), i_sign(), i_len();
16967 logical l_ge(), l_gt(), l_le(), l_lt();
16968 integer i_nint();
16969 double r_sign();
16970
16971 // Local variables //
16972 extern // Subroutine // int fooa_(), fooc_(), food_(), fooi_(), foor_(),
16973 fool_(), fooz_(), getem_();
16974 static char a1[10], a2[10];
16975 static complex c1, c2;
16976 static doublereal d1, d2;
16977 static integer i1, i2;
16978 static real r1, r2;
16979
16980
16981 getem_(a1, a2, &c1, &c2, &i1, &i2, &r1, &r2, &d1, &d2, 10L, 10L);
16982// / //
16983 i__1 = i1 / i2;
16984 fooi_(&i__1);
16985 r__1 = r1 / i1;
16986 foor_(&r__1);
16987 d__1 = d1 / i1;
16988 food_(&d__1);
16989 d__1 = (doublereal) i1;
16990 q__1.r = c1.r / d__1, q__1.i = c1.i / d__1;
16991 fooc_(&q__1);
16992 r__1 = r1 / r2;
16993 foor_(&r__1);
16994 d__1 = r1 / d1;
16995 food_(&d__1);
16996 d__1 = d1 / d2;
16997 food_(&d__1);
16998 d__1 = d1 / r1;
16999 food_(&d__1);
17000 c_div(&q__1, &c1, &c2);
17001 fooc_(&q__1);
17002 q__1.r = c1.r / r1, q__1.i = c1.i / r1;
17003 fooc_(&q__1);
17004 z__1.r = c1.r / d1, z__1.i = c1.i / d1;
17005 fooz_(&z__1);
17006// ** //
17007 i__1 = pow_ii(&i1, &i2);
17008 fooi_(&i__1);
17009 r__1 = pow_ri(&r1, &i1);
17010 foor_(&r__1);
17011 d__1 = pow_di(&d1, &i1);
17012 food_(&d__1);
17013 pow_ci(&q__1, &c1, &i1);
17014 fooc_(&q__1);
17015 d__1 = (doublereal) r1;
17016 d__2 = (doublereal) r2;
17017 r__1 = pow_dd(&d__1, &d__2);
17018 foor_(&r__1);
17019 d__2 = (doublereal) r1;
17020 d__1 = pow_dd(&d__2, &d1);
17021 food_(&d__1);
17022 d__1 = pow_dd(&d1, &d2);
17023 food_(&d__1);
17024 d__2 = (doublereal) r1;
17025 d__1 = pow_dd(&d1, &d__2);
17026 food_(&d__1);
17027 z__2.r = c1.r, z__2.i = c1.i;
17028 z__3.r = c2.r, z__3.i = c2.i;
17029 pow_zz(&z__1, &z__2, &z__3);
17030 q__1.r = z__1.r, q__1.i = z__1.i;
17031 fooc_(&q__1);
17032 z__2.r = c1.r, z__2.i = c1.i;
17033 z__3.r = r1, z__3.i = 0.;
17034 pow_zz(&z__1, &z__2, &z__3);
17035 q__1.r = z__1.r, q__1.i = z__1.i;
17036 fooc_(&q__1);
17037 z__2.r = c1.r, z__2.i = c1.i;
17038 z__3.r = d1, z__3.i = 0.;
17039 pow_zz(&z__1, &z__2, &z__3);
17040 fooz_(&z__1);
17041// FFEINTRIN_impABS //
17042 r__1 = (doublereal)(( r1 ) >= 0 ? ( r1 ) : -( r1 )) ;
17043 foor_(&r__1);
17044// FFEINTRIN_impACOS //
17045 r__1 = acos(r1);
17046 foor_(&r__1);
17047// FFEINTRIN_impAIMAG //
17048 r__1 = r_imag(&c1);
17049 foor_(&r__1);
17050// FFEINTRIN_impAINT //
17051 r__1 = r_int(&r1);
17052 foor_(&r__1);
17053// FFEINTRIN_impALOG //
17054 r__1 = log(r1);
17055 foor_(&r__1);
17056// FFEINTRIN_impALOG10 //
17057 r__1 = r_lg10(&r1);
17058 foor_(&r__1);
17059// FFEINTRIN_impAMAX0 //
17060 r__1 = (real) (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
17061 foor_(&r__1);
17062// FFEINTRIN_impAMAX1 //
17063 r__1 = (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
17064 foor_(&r__1);
17065// FFEINTRIN_impAMIN0 //
17066 r__1 = (real) (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
17067 foor_(&r__1);
17068// FFEINTRIN_impAMIN1 //
17069 r__1 = (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
17070 foor_(&r__1);
17071// FFEINTRIN_impAMOD //
17072 r__1 = r_mod(&r1, &r2);
17073 foor_(&r__1);
17074// FFEINTRIN_impANINT //
17075 r__1 = r_nint(&r1);
17076 foor_(&r__1);
17077// FFEINTRIN_impASIN //
17078 r__1 = asin(r1);
17079 foor_(&r__1);
17080// FFEINTRIN_impATAN //
17081 r__1 = atan(r1);
17082 foor_(&r__1);
17083// FFEINTRIN_impATAN2 //
17084 r__1 = atan2(r1, r2);
17085 foor_(&r__1);
17086// FFEINTRIN_impCABS //
17087 r__1 = c_abs(&c1);
17088 foor_(&r__1);
17089// FFEINTRIN_impCCOS //
17090 c_cos(&q__1, &c1);
17091 fooc_(&q__1);
17092// FFEINTRIN_impCEXP //
17093 c_exp(&q__1, &c1);
17094 fooc_(&q__1);
17095// FFEINTRIN_impCHAR //
17096 *(unsigned char *)&ch__1[0] = i1;
17097 fooa_(ch__1, 1L);
17098// FFEINTRIN_impCLOG //
17099 c_log(&q__1, &c1);
17100 fooc_(&q__1);
17101// FFEINTRIN_impCONJG //
17102 r_cnjg(&q__1, &c1);
17103 fooc_(&q__1);
17104// FFEINTRIN_impCOS //
17105 r__1 = cos(r1);
17106 foor_(&r__1);
17107// FFEINTRIN_impCOSH //
17108 r__1 = cosh(r1);
17109 foor_(&r__1);
17110// FFEINTRIN_impCSIN //
17111 c_sin(&q__1, &c1);
17112 fooc_(&q__1);
17113// FFEINTRIN_impCSQRT //
17114 c_sqrt(&q__1, &c1);
17115 fooc_(&q__1);
17116// FFEINTRIN_impDABS //
17117 d__1 = (( d1 ) >= 0 ? ( d1 ) : -( d1 )) ;
17118 food_(&d__1);
17119// FFEINTRIN_impDACOS //
17120 d__1 = acos(d1);
17121 food_(&d__1);
17122// FFEINTRIN_impDASIN //
17123 d__1 = asin(d1);
17124 food_(&d__1);
17125// FFEINTRIN_impDATAN //
17126 d__1 = atan(d1);
17127 food_(&d__1);
17128// FFEINTRIN_impDATAN2 //
17129 d__1 = atan2(d1, d2);
17130 food_(&d__1);
17131// FFEINTRIN_impDCOS //
17132 d__1 = cos(d1);
17133 food_(&d__1);
17134// FFEINTRIN_impDCOSH //
17135 d__1 = cosh(d1);
17136 food_(&d__1);
17137// FFEINTRIN_impDDIM //
17138 d__1 = d_dim(&d1, &d2);
17139 food_(&d__1);
17140// FFEINTRIN_impDEXP //
17141 d__1 = exp(d1);
17142 food_(&d__1);
17143// FFEINTRIN_impDIM //
17144 r__1 = r_dim(&r1, &r2);
17145 foor_(&r__1);
17146// FFEINTRIN_impDINT //
17147 d__1 = d_int(&d1);
17148 food_(&d__1);
17149// FFEINTRIN_impDLOG //
17150 d__1 = log(d1);
17151 food_(&d__1);
17152// FFEINTRIN_impDLOG10 //
17153 d__1 = d_lg10(&d1);
17154 food_(&d__1);
17155// FFEINTRIN_impDMAX1 //
17156 d__1 = (( d1 ) >= ( d2 ) ? ( d1 ) : ( d2 )) ;
17157 food_(&d__1);
17158// FFEINTRIN_impDMIN1 //
17159 d__1 = (( d1 ) <= ( d2 ) ? ( d1 ) : ( d2 )) ;
17160 food_(&d__1);
17161// FFEINTRIN_impDMOD //
17162 d__1 = d_mod(&d1, &d2);
17163 food_(&d__1);
17164// FFEINTRIN_impDNINT //
17165 d__1 = d_nint(&d1);
17166 food_(&d__1);
17167// FFEINTRIN_impDPROD //
17168 d__1 = (doublereal) r1 * r2;
17169 food_(&d__1);
17170// FFEINTRIN_impDSIGN //
17171 d__1 = d_sign(&d1, &d2);
17172 food_(&d__1);
17173// FFEINTRIN_impDSIN //
17174 d__1 = sin(d1);
17175 food_(&d__1);
17176// FFEINTRIN_impDSINH //
17177 d__1 = sinh(d1);
17178 food_(&d__1);
17179// FFEINTRIN_impDSQRT //
17180 d__1 = sqrt(d1);
17181 food_(&d__1);
17182// FFEINTRIN_impDTAN //
17183 d__1 = tan(d1);
17184 food_(&d__1);
17185// FFEINTRIN_impDTANH //
17186 d__1 = tanh(d1);
17187 food_(&d__1);
17188// FFEINTRIN_impEXP //
17189 r__1 = exp(r1);
17190 foor_(&r__1);
17191// FFEINTRIN_impIABS //
17192 i__1 = (( i1 ) >= 0 ? ( i1 ) : -( i1 )) ;
17193 fooi_(&i__1);
17194// FFEINTRIN_impICHAR //
17195 i__1 = *(unsigned char *)a1;
17196 fooi_(&i__1);
17197// FFEINTRIN_impIDIM //
17198 i__1 = i_dim(&i1, &i2);
17199 fooi_(&i__1);
17200// FFEINTRIN_impIDNINT //
17201 i__1 = i_dnnt(&d1);
17202 fooi_(&i__1);
17203// FFEINTRIN_impINDEX //
17204 i__1 = i_indx(a1, a2, 10L, 10L);
17205 fooi_(&i__1);
17206// FFEINTRIN_impISIGN //
17207 i__1 = i_sign(&i1, &i2);
17208 fooi_(&i__1);
17209// FFEINTRIN_impLEN //
17210 i__1 = i_len(a1, 10L);
17211 fooi_(&i__1);
17212// FFEINTRIN_impLGE //
17213 L__1 = l_ge(a1, a2, 10L, 10L);
17214 fool_(&L__1);
17215// FFEINTRIN_impLGT //
17216 L__1 = l_gt(a1, a2, 10L, 10L);
17217 fool_(&L__1);
17218// FFEINTRIN_impLLE //
17219 L__1 = l_le(a1, a2, 10L, 10L);
17220 fool_(&L__1);
17221// FFEINTRIN_impLLT //
17222 L__1 = l_lt(a1, a2, 10L, 10L);
17223 fool_(&L__1);
17224// FFEINTRIN_impMAX0 //
17225 i__1 = (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
17226 fooi_(&i__1);
17227// FFEINTRIN_impMAX1 //
17228 i__1 = (integer) (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
17229 fooi_(&i__1);
17230// FFEINTRIN_impMIN0 //
17231 i__1 = (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
17232 fooi_(&i__1);
17233// FFEINTRIN_impMIN1 //
17234 i__1 = (integer) (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
17235 fooi_(&i__1);
17236// FFEINTRIN_impMOD //
17237 i__1 = i1 % i2;
17238 fooi_(&i__1);
17239// FFEINTRIN_impNINT //
17240 i__1 = i_nint(&r1);
17241 fooi_(&i__1);
17242// FFEINTRIN_impSIGN //
17243 r__1 = r_sign(&r1, &r2);
17244 foor_(&r__1);
17245// FFEINTRIN_impSIN //
17246 r__1 = sin(r1);
17247 foor_(&r__1);
17248// FFEINTRIN_impSINH //
17249 r__1 = sinh(r1);
17250 foor_(&r__1);
17251// FFEINTRIN_impSQRT //
17252 r__1 = sqrt(r1);
17253 foor_(&r__1);
17254// FFEINTRIN_impTAN //
17255 r__1 = tan(r1);
17256 foor_(&r__1);
17257// FFEINTRIN_impTANH //
17258 r__1 = tanh(r1);
17259 foor_(&r__1);
17260// FFEINTRIN_imp_CMPLX_C //
17261 r__1 = c1.r;
17262 r__2 = c2.r;
17263 q__1.r = r__1, q__1.i = r__2;
17264 fooc_(&q__1);
17265// FFEINTRIN_imp_CMPLX_D //
17266 z__1.r = d1, z__1.i = d2;
17267 fooz_(&z__1);
17268// FFEINTRIN_imp_CMPLX_I //
17269 r__1 = (real) i1;
17270 r__2 = (real) i2;
17271 q__1.r = r__1, q__1.i = r__2;
17272 fooc_(&q__1);
17273// FFEINTRIN_imp_CMPLX_R //
17274 q__1.r = r1, q__1.i = r2;
17275 fooc_(&q__1);
17276// FFEINTRIN_imp_DBLE_C //
17277 d__1 = (doublereal) c1.r;
17278 food_(&d__1);
17279// FFEINTRIN_imp_DBLE_D //
17280 d__1 = d1;
17281 food_(&d__1);
17282// FFEINTRIN_imp_DBLE_I //
17283 d__1 = (doublereal) i1;
17284 food_(&d__1);
17285// FFEINTRIN_imp_DBLE_R //
17286 d__1 = (doublereal) r1;
17287 food_(&d__1);
17288// FFEINTRIN_imp_INT_C //
17289 i__1 = (integer) c1.r;
17290 fooi_(&i__1);
17291// FFEINTRIN_imp_INT_D //
17292 i__1 = (integer) d1;
17293 fooi_(&i__1);
17294// FFEINTRIN_imp_INT_I //
17295 i__1 = i1;
17296 fooi_(&i__1);
17297// FFEINTRIN_imp_INT_R //
17298 i__1 = (integer) r1;
17299 fooi_(&i__1);
17300// FFEINTRIN_imp_REAL_C //
17301 r__1 = c1.r;
17302 foor_(&r__1);
17303// FFEINTRIN_imp_REAL_D //
17304 r__1 = (real) d1;
17305 foor_(&r__1);
17306// FFEINTRIN_imp_REAL_I //
17307 r__1 = (real) i1;
17308 foor_(&r__1);
17309// FFEINTRIN_imp_REAL_R //
17310 r__1 = r1;
17311 foor_(&r__1);
17312
17313// FFEINTRIN_imp_INT_D: //
17314
17315// FFEINTRIN_specIDINT //
17316 i__1 = (integer) d1;
17317 fooi_(&i__1);
17318
17319// FFEINTRIN_imp_INT_R: //
17320
17321// FFEINTRIN_specIFIX //
17322 i__1 = (integer) r1;
17323 fooi_(&i__1);
17324// FFEINTRIN_specINT //
17325 i__1 = (integer) r1;
17326 fooi_(&i__1);
17327
17328// FFEINTRIN_imp_REAL_D: //
5ff904cd 17329
c7e4ee3a
CB
17330// FFEINTRIN_specSNGL //
17331 r__1 = (real) d1;
17332 foor_(&r__1);
5ff904cd 17333
c7e4ee3a 17334// FFEINTRIN_imp_REAL_I: //
5ff904cd 17335
c7e4ee3a
CB
17336// FFEINTRIN_specFLOAT //
17337 r__1 = (real) i1;
17338 foor_(&r__1);
17339// FFEINTRIN_specREAL //
17340 r__1 = (real) i1;
17341 foor_(&r__1);
5ff904cd 17342
c7e4ee3a 17343} // MAIN__ //
5ff904cd 17344
c7e4ee3a 17345-------- (end output file from f2c)
5ff904cd 17346
c7e4ee3a 17347*/
This page took 2.750472 seconds and 5 git commands to generate.