]> gcc.gnu.org Git - gcc.git/blame - gcc/f/com.c
Update to Netlib version of 1999-06-28, doc fix
[gcc.git] / gcc / f / com.c
CommitLineData
5ff904cd 1/* com.c -- Implementation File (module.c template V1.0)
44d2eabc 2 Copyright (C) 1995-1998 Free Software Foundation, Inc.
25d7717e 3 Contributed by James Craig Burley.
5ff904cd
JL
4
5This file is part of GNU Fortran.
6
7GNU Fortran is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU Fortran is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Fortran; see the file COPYING. If not, write to
19the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
2002111-1307, USA.
21
22 Related Modules:
23 None
24
25 Description:
26 Contains compiler-specific functions.
27
28 Modifications:
29*/
30
31/* Understanding this module means understanding the interface between
32 the g77 front end and the gcc back end (or, perhaps, some other
33 back end). In here are the functions called by the front end proper
34 to notify whatever back end is in place about certain things, and
35 also the back-end-specific functions. It's a bear to deal with, so
36 lately I've been trying to simplify things, especially with regard
37 to the gcc-back-end-specific stuff.
38
39 Building expressions generally seems quite easy, but building decls
40 has been challenging and is undergoing revision. gcc has several
41 kinds of decls:
42
43 TYPE_DECL -- a type (int, float, struct, function, etc.)
44 CONST_DECL -- a constant of some type other than function
45 LABEL_DECL -- a variable or a constant?
46 PARM_DECL -- an argument to a function (a variable that is a dummy)
47 RESULT_DECL -- the return value of a function (a variable)
48 VAR_DECL -- other variable (can hold a ptr-to-function, struct, int, etc.)
49 FUNCTION_DECL -- a function (either the actual function or an extern ref)
50 FIELD_DECL -- a field in a struct or union (goes into types)
51
52 g77 has a set of functions that somewhat parallels the gcc front end
53 when it comes to building decls:
54
55 Internal Function (one we define, not just declare as extern):
56 int yes;
57 yes = suspend_momentary ();
58 if (is_nested) push_f_function_context ();
59 start_function (get_identifier ("function_name"), function_type,
60 is_nested, is_public);
61 // for each arg, build PARM_DECL and call push_parm_decl (decl) with it;
62 store_parm_decls (is_main_program);
c7e4ee3a 63 ffecom_start_compstmt ();
5ff904cd 64 // for stmts and decls inside function, do appropriate things;
c7e4ee3a 65 ffecom_end_compstmt ();
5ff904cd
JL
66 finish_function (is_nested);
67 if (is_nested) pop_f_function_context ();
68 if (is_nested) resume_momentary (yes);
69
70 Everything Else:
71 int yes;
72 tree d;
73 tree init;
74 yes = suspend_momentary ();
75 // fill in external, public, static, &c for decl, and
76 // set DECL_INITIAL to error_mark_node if going to initialize
77 // set is_top_level TRUE only if not at top level and decl
78 // must go in top level (i.e. not within current function decl context)
79 d = start_decl (decl, is_top_level);
80 init = ...; // if have initializer
81 finish_decl (d, init, is_top_level);
82 resume_momentary (yes);
83
84*/
85
86/* Include files. */
87
95a1b676 88#include "proj.h"
5ff904cd 89#if FFECOM_targetCURRENT == FFECOM_targetGCC
5ff904cd
JL
90#include "flags.j"
91#include "rtl.j"
8b45da67 92#include "toplev.j"
5ff904cd 93#include "tree.j"
95a1b676 94#include "output.j" /* Must follow tree.j so TREE_CODE is defined! */
5ff904cd
JL
95#include "convert.j"
96#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
97
98#define FFECOM_GCC_INCLUDE 1 /* Enable -I. */
99
100/* BEGIN stuff from gcc/cccp.c. */
101
102/* The following symbols should be autoconfigured:
103 HAVE_FCNTL_H
104 HAVE_STDLIB_H
105 HAVE_SYS_TIME_H
106 HAVE_UNISTD_H
107 STDC_HEADERS
108 TIME_WITH_SYS_TIME
109 In the mean time, we'll get by with approximations based
110 on existing GCC configuration symbols. */
111
112#ifdef POSIX
113# ifndef HAVE_STDLIB_H
114# define HAVE_STDLIB_H 1
115# endif
116# ifndef HAVE_UNISTD_H
117# define HAVE_UNISTD_H 1
118# endif
119# ifndef STDC_HEADERS
120# define STDC_HEADERS 1
121# endif
122#endif /* defined (POSIX) */
123
124#if defined (POSIX) || (defined (USG) && !defined (VMS))
125# ifndef HAVE_FCNTL_H
126# define HAVE_FCNTL_H 1
127# endif
128#endif
129
130#ifndef RLIMIT_STACK
131# include <time.h>
132#else
133# if TIME_WITH_SYS_TIME
134# include <sys/time.h>
135# include <time.h>
136# else
137# if HAVE_SYS_TIME_H
138# include <sys/time.h>
139# else
140# include <time.h>
141# endif
142# endif
143# include <sys/resource.h>
144#endif
145
146#if HAVE_FCNTL_H
147# include <fcntl.h>
148#endif
149
150/* This defines "errno" properly for VMS, and gives us EACCES. */
151#include <errno.h>
152
153#if HAVE_STDLIB_H
154# include <stdlib.h>
155#else
156char *getenv ();
157#endif
158
5ff904cd
JL
159#if HAVE_UNISTD_H
160# include <unistd.h>
161#endif
162
163/* VMS-specific definitions */
164#ifdef VMS
165#include <descrip.h>
166#define O_RDONLY 0 /* Open arg for Read/Only */
167#define O_WRONLY 1 /* Open arg for Write/Only */
168#define read(fd,buf,size) VMS_read (fd,buf,size)
169#define write(fd,buf,size) VMS_write (fd,buf,size)
170#define open(fname,mode,prot) VMS_open (fname,mode,prot)
171#define fopen(fname,mode) VMS_fopen (fname,mode)
172#define freopen(fname,mode,ofile) VMS_freopen (fname,mode,ofile)
173#define strncat(dst,src,cnt) VMS_strncat (dst,src,cnt)
174#define fstat(fd,stbuf) VMS_fstat (fd,stbuf)
175static int VMS_fstat (), VMS_stat ();
176static char * VMS_strncat ();
177static int VMS_read ();
178static int VMS_write ();
179static int VMS_open ();
180static FILE * VMS_fopen ();
181static FILE * VMS_freopen ();
182static void hack_vms_include_specification ();
183typedef struct { unsigned :16, :16, :16; } vms_ino_t;
184#define ino_t vms_ino_t
185#define INCLUDE_LEN_FUDGE 10 /* leave room for VMS syntax conversion */
186#ifdef __GNUC__
187#define BSTRING /* VMS/GCC supplies the bstring routines */
188#endif /* __GNUC__ */
189#endif /* VMS */
190
191#ifndef O_RDONLY
192#define O_RDONLY 0
193#endif
194
195/* END stuff from gcc/cccp.c. */
196
5ff904cd
JL
197#define FFECOM_DETERMINE_TYPES 1 /* for com.h */
198#include "com.h"
199#include "bad.h"
200#include "bld.h"
201#include "equiv.h"
202#include "expr.h"
203#include "implic.h"
204#include "info.h"
205#include "malloc.h"
206#include "src.h"
207#include "st.h"
208#include "storag.h"
209#include "symbol.h"
210#include "target.h"
211#include "top.h"
212#include "type.h"
213
214/* Externals defined here. */
215
5ff904cd
JL
216#if FFECOM_targetCURRENT == FFECOM_targetGCC
217
218/* tree.h declares a bunch of stuff that it expects the front end to
219 define. Here are the definitions, which in the C front end are
220 found in the file c-decl.c. */
221
222tree integer_zero_node;
223tree integer_one_node;
224tree null_pointer_node;
225tree error_mark_node;
226tree void_type_node;
227tree integer_type_node;
228tree unsigned_type_node;
229tree char_type_node;
230tree current_function_decl;
231
c7e4ee3a
CB
232/* ~~gcc/tree.h *should* declare this, because toplev.c and dwarfout.c
233 reference it. */
5ff904cd
JL
234
235char *language_string = "GNU F77";
236
77f77701
DB
237/* Stream for reading from the input file. */
238FILE *finput;
239
5ff904cd
JL
240/* These definitions parallel those in c-decl.c so that code from that
241 module can be used pretty much as is. Much of these defs aren't
242 otherwise used, i.e. by g77 code per se, except some of them are used
243 to build some of them that are. The ones that are global (i.e. not
244 "static") are those that ste.c and such might use (directly
245 or by using com macros that reference them in their definitions). */
246
247static tree short_integer_type_node;
248tree long_integer_type_node;
249static tree long_long_integer_type_node;
250
251static tree short_unsigned_type_node;
252static tree long_unsigned_type_node;
253static tree long_long_unsigned_type_node;
254
255static tree unsigned_char_type_node;
256static tree signed_char_type_node;
257
258static tree float_type_node;
259static tree double_type_node;
260static tree complex_float_type_node;
261tree complex_double_type_node;
262static tree long_double_type_node;
263static tree complex_integer_type_node;
264static tree complex_long_double_type_node;
265
266tree string_type_node;
267
268static tree double_ftype_double;
269static tree float_ftype_float;
270static tree ldouble_ftype_ldouble;
271
272/* The rest of these are inventions for g77, though there might be
273 similar things in the C front end. As they are found, these
274 inventions should be renamed to be canonical. Note that only
275 the ones currently required to be global are so. */
276
277static tree ffecom_tree_fun_type_void;
278static tree ffecom_tree_ptr_to_fun_type_void;
279
280tree ffecom_integer_type_node; /* Abbrev for _tree_type[blah][blah]. */
281tree ffecom_integer_zero_node; /* Like *_*_* with g77's integer type. */
282tree ffecom_integer_one_node; /* " */
283tree ffecom_tree_type[FFEINFO_basictype][FFEINFO_kindtype];
284
285/* _fun_type things are the f2c-specific versions. For -fno-f2c,
286 just use build_function_type and build_pointer_type on the
287 appropriate _tree_type array element. */
288
289static tree ffecom_tree_fun_type[FFEINFO_basictype][FFEINFO_kindtype];
290static tree ffecom_tree_ptr_to_fun_type[FFEINFO_basictype][FFEINFO_kindtype];
291static tree ffecom_tree_subr_type;
292static tree ffecom_tree_ptr_to_subr_type;
293static tree ffecom_tree_blockdata_type;
294
295static tree ffecom_tree_xargc_;
296
297ffecomSymbol ffecom_symbol_null_
298=
299{
300 NULL_TREE,
301 NULL_TREE,
302 NULL_TREE,
0816ebdd
KG
303 NULL_TREE,
304 false
5ff904cd
JL
305};
306ffeinfoKindtype ffecom_pointer_kind_ = FFEINFO_basictypeNONE;
307ffeinfoKindtype ffecom_label_kind_ = FFEINFO_basictypeNONE;
308
309int ffecom_f2c_typecode_[FFEINFO_basictype][FFEINFO_kindtype];
310tree ffecom_f2c_integer_type_node;
311tree ffecom_f2c_ptr_to_integer_type_node;
312tree ffecom_f2c_address_type_node;
313tree ffecom_f2c_real_type_node;
314tree ffecom_f2c_ptr_to_real_type_node;
315tree ffecom_f2c_doublereal_type_node;
316tree ffecom_f2c_complex_type_node;
317tree ffecom_f2c_doublecomplex_type_node;
318tree ffecom_f2c_longint_type_node;
319tree ffecom_f2c_logical_type_node;
320tree ffecom_f2c_flag_type_node;
321tree ffecom_f2c_ftnlen_type_node;
322tree ffecom_f2c_ftnlen_zero_node;
323tree ffecom_f2c_ftnlen_one_node;
324tree ffecom_f2c_ftnlen_two_node;
325tree ffecom_f2c_ptr_to_ftnlen_type_node;
326tree ffecom_f2c_ftnint_type_node;
327tree ffecom_f2c_ptr_to_ftnint_type_node;
328#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
329
330/* Simple definitions and enumerations. */
331
332#ifndef FFECOM_sizeMAXSTACKITEM
333#define FFECOM_sizeMAXSTACKITEM 32*1024 /* Keep user-declared things
334 larger than this # bytes
335 off stack if possible. */
336#endif
337
338/* For systems that have large enough stacks, they should define
339 this to 0, and here, for ease of use later on, we just undefine
340 it if it is 0. */
341
342#if FFECOM_sizeMAXSTACKITEM == 0
343#undef FFECOM_sizeMAXSTACKITEM
344#endif
345
346typedef enum
347 {
348 FFECOM_rttypeVOID_,
6d433196 349 FFECOM_rttypeVOIDSTAR_, /* C's `void *' type. */
795232f7
JL
350 FFECOM_rttypeFTNINT_, /* f2c's `ftnint' type. */
351 FFECOM_rttypeINTEGER_, /* f2c's `integer' type. */
352 FFECOM_rttypeLONGINT_, /* f2c's `longint' type. */
353 FFECOM_rttypeLOGICAL_, /* f2c's `logical' type. */
354 FFECOM_rttypeREAL_F2C_, /* f2c's `real' returned as `double'. */
355 FFECOM_rttypeREAL_GNU_, /* `real' returned as such. */
5ff904cd 356 FFECOM_rttypeCOMPLEX_F2C_, /* f2c's `complex' returned via 1st arg. */
795232f7 357 FFECOM_rttypeCOMPLEX_GNU_, /* f2c's `complex' returned directly. */
5ff904cd 358 FFECOM_rttypeDOUBLE_, /* C's `double' type. */
795232f7 359 FFECOM_rttypeDOUBLEREAL_, /* f2c's `doublereal' type. */
5ff904cd 360 FFECOM_rttypeDBLCMPLX_F2C_, /* f2c's `doublecomplex' returned via 1st arg. */
795232f7 361 FFECOM_rttypeDBLCMPLX_GNU_, /* f2c's `doublecomplex' returned directly. */
5ff904cd
JL
362 FFECOM_rttypeCHARACTER_, /* f2c `char *'/`ftnlen' pair. */
363 FFECOM_rttype_
364 } ffecomRttype_;
365
366/* Internal typedefs. */
367
368#if FFECOM_targetCURRENT == FFECOM_targetGCC
369typedef struct _ffecom_concat_list_ ffecomConcatList_;
5ff904cd
JL
370#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
371
372/* Private include files. */
373
374
375/* Internal structure definitions. */
376
377#if FFECOM_targetCURRENT == FFECOM_targetGCC
378struct _ffecom_concat_list_
379 {
380 ffebld *exprs;
381 int count;
382 int max;
383 ffetargetCharacterSize minlen;
384 ffetargetCharacterSize maxlen;
385 };
5ff904cd
JL
386#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
387
388/* Static functions (internal). */
389
390#if FFECOM_targetCURRENT == FFECOM_targetGCC
26f096f9 391static tree ffecom_arglist_expr_ (const char *argstring, ffebld args);
5ff904cd
JL
392static tree ffecom_widest_expr_type_ (ffebld list);
393static bool ffecom_overlap_ (tree dest_decl, tree dest_offset,
394 tree dest_size, tree source_tree,
395 ffebld source, bool scalar_arg);
396static bool ffecom_args_overlapping_ (tree dest_tree, ffebld dest,
397 tree args, tree callee_commons,
398 bool scalar_args);
26f096f9 399static tree ffecom_build_f2c_string_ (int i, const char *s);
5ff904cd
JL
400static tree ffecom_call_ (tree fn, ffeinfoKindtype kt,
401 bool is_f2c_complex, tree type,
402 tree args, tree dest_tree,
403 ffebld dest, bool *dest_used,
c7e4ee3a 404 tree callee_commons, bool scalar_args, tree hook);
5ff904cd
JL
405static tree ffecom_call_binop_ (tree fn, ffeinfoKindtype kt,
406 bool is_f2c_complex, tree type,
407 ffebld left, ffebld right,
408 tree dest_tree, ffebld dest,
409 bool *dest_used, tree callee_commons,
c7e4ee3a 410 bool scalar_args, tree hook);
86fc7a6c
CB
411static void ffecom_char_args_x_ (tree *xitem, tree *length,
412 ffebld expr, bool with_null);
5ff904cd
JL
413static tree ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy);
414static tree ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s);
415static ffecomConcatList_
416 ffecom_concat_list_gather_ (ffecomConcatList_ catlist,
417 ffebld expr,
418 ffetargetCharacterSize max);
419static void ffecom_concat_list_kill_ (ffecomConcatList_ catlist);
420static ffecomConcatList_ ffecom_concat_list_new_ (ffebld expr,
421 ffetargetCharacterSize max);
26f096f9
KG
422static void ffecom_debug_kludge_ (tree aggr, const char *aggr_type,
423 ffesymbol member, tree member_type,
424 ffetargetOffset offset);
5ff904cd 425static void ffecom_do_entry_ (ffesymbol fn, int entrynum);
092a4ef8
RH
426static tree ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
427 bool *dest_used, bool assignp, bool widenp);
5ff904cd
JL
428static tree ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
429 ffebld dest, bool *dest_used);
c7e4ee3a 430static tree ffecom_expr_power_integer_ (ffebld expr);
5ff904cd 431static void ffecom_expr_transform_ (ffebld expr);
26f096f9 432static void ffecom_f2c_make_type_ (tree *type, int tcode, const char *name);
5ff904cd
JL
433static void ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size,
434 int code);
435static ffeglobal ffecom_finish_global_ (ffeglobal global);
436static ffesymbol ffecom_finish_symbol_transform_ (ffesymbol s);
26f096f9 437static tree ffecom_get_appended_identifier_ (char us, const char *text);
5ff904cd 438static tree ffecom_get_external_identifier_ (ffesymbol s);
26f096f9 439static tree ffecom_get_identifier_ (const char *text);
5ff904cd
JL
440static tree ffecom_gen_sfuncdef_ (ffesymbol s,
441 ffeinfoBasictype bt,
442 ffeinfoKindtype kt);
26f096f9 443static const char *ffecom_gfrt_args_ (ffecomGfrt ix);
5ff904cd
JL
444static tree ffecom_gfrt_tree_ (ffecomGfrt ix);
445static tree ffecom_init_zero_ (tree decl);
446static tree ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg,
447 tree *maybe_tree);
448static tree ffecom_intrinsic_len_ (ffebld expr);
449static void ffecom_let_char_ (tree dest_tree,
450 tree dest_length,
451 ffetargetCharacterSize dest_size,
452 ffebld source);
453static void ffecom_make_gfrt_ (ffecomGfrt ix);
454static void ffecom_member_phase1_ (ffestorag mst, ffestorag st);
455#ifdef SOMEONE_GETS_DEBUG_SUPPORT_WORKING
456static void ffecom_member_phase2_ (ffestorag mst, ffestorag st);
457#endif
c7e4ee3a
CB
458static void ffecom_prepare_let_char_ (ffetargetCharacterSize dest_size,
459 ffebld source);
5ff904cd
JL
460static void ffecom_push_dummy_decls_ (ffebld dumlist,
461 bool stmtfunc);
462static void ffecom_start_progunit_ (void);
463static ffesymbol ffecom_sym_transform_ (ffesymbol s);
464static ffesymbol ffecom_sym_transform_assign_ (ffesymbol s);
465static void ffecom_transform_common_ (ffesymbol s);
466static void ffecom_transform_equiv_ (ffestorag st);
467static tree ffecom_transform_namelist_ (ffesymbol s);
468static void ffecom_tree_canonize_ptr_ (tree *decl, tree *offset,
469 tree t);
470static void ffecom_tree_canonize_ref_ (tree *decl, tree *offset,
471 tree *size, tree tree);
472static tree ffecom_tree_divide_ (tree tree_type, tree left, tree right,
473 tree dest_tree, ffebld dest,
c7e4ee3a 474 bool *dest_used, tree hook);
5ff904cd
JL
475static tree ffecom_type_localvar_ (ffesymbol s,
476 ffeinfoBasictype bt,
477 ffeinfoKindtype kt);
478static tree ffecom_type_namelist_ (void);
479#if 0
480static tree ffecom_type_permanent_copy_ (tree t);
481#endif
482static tree ffecom_type_vardesc_ (void);
483static tree ffecom_vardesc_ (ffebld expr);
484static tree ffecom_vardesc_array_ (ffesymbol s);
485static tree ffecom_vardesc_dims_ (ffesymbol s);
26f096f9
KG
486static tree ffecom_convert_narrow_ (tree type, tree expr);
487static tree ffecom_convert_widen_ (tree type, tree expr);
5ff904cd
JL
488#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
489
490/* These are static functions that parallel those found in the C front
491 end and thus have the same names. */
492
493#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a 494static tree bison_rule_compstmt_ (void);
5ff904cd 495static void bison_rule_pushlevel_ (void);
26f096f9 496static tree builtin_function (const char *name, tree type,
5ff904cd 497 enum built_in_function function_code,
26f096f9 498 const char *library_name);
c7e4ee3a 499static void delete_block (tree block);
5ff904cd
JL
500static int duplicate_decls (tree newdecl, tree olddecl);
501static void finish_decl (tree decl, tree init, bool is_top_level);
502static void finish_function (int nested);
8f87a563 503static char *lang_printable_name (tree decl, int v);
5ff904cd
JL
504static tree lookup_name_current_level (tree name);
505static struct binding_level *make_binding_level (void);
506static void pop_f_function_context (void);
507static void push_f_function_context (void);
508static void push_parm_decl (tree parm);
509static tree pushdecl_top_level (tree decl);
c7e4ee3a 510static int kept_level_p (void);
5ff904cd
JL
511static tree storedecls (tree decls);
512static void store_parm_decls (int is_main_program);
513static tree start_decl (tree decl, bool is_top_level);
514static void start_function (tree name, tree type, int nested, int public);
515#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
516#if FFECOM_GCC_INCLUDE
517static void ffecom_file_ (char *name);
518static void ffecom_initialize_char_syntax_ (void);
519static void ffecom_close_include_ (FILE *f);
520static int ffecom_decode_include_option_ (char *spec);
521static FILE *ffecom_open_include_ (char *name, ffewhereLine l,
522 ffewhereColumn c);
523#endif /* FFECOM_GCC_INCLUDE */
524
525/* Static objects accessed by functions in this module. */
526
527static ffesymbol ffecom_primary_entry_ = NULL;
528static ffesymbol ffecom_nested_entry_ = NULL;
529static ffeinfoKind ffecom_primary_entry_kind_;
530static bool ffecom_primary_entry_is_proc_;
531#if FFECOM_targetCURRENT == FFECOM_targetGCC
532static tree ffecom_outer_function_decl_;
533static tree ffecom_previous_function_decl_;
534static tree ffecom_which_entrypoint_decl_;
5ff904cd
JL
535static tree ffecom_float_zero_ = NULL_TREE;
536static tree ffecom_float_half_ = NULL_TREE;
537static tree ffecom_double_zero_ = NULL_TREE;
538static tree ffecom_double_half_ = NULL_TREE;
539static tree ffecom_func_result_;/* For functions. */
540static tree ffecom_func_length_;/* For CHARACTER fns. */
541static ffebld ffecom_list_blockdata_;
542static ffebld ffecom_list_common_;
543static ffebld ffecom_master_arglist_;
544static ffeinfoBasictype ffecom_master_bt_;
545static ffeinfoKindtype ffecom_master_kt_;
546static ffetargetCharacterSize ffecom_master_size_;
547static int ffecom_num_fns_ = 0;
548static int ffecom_num_entrypoints_ = 0;
549static bool ffecom_is_altreturning_ = FALSE;
550static tree ffecom_multi_type_node_;
551static tree ffecom_multi_retval_;
552static tree
553 ffecom_multi_fields_[FFEINFO_basictype][FFEINFO_kindtype];
554static bool ffecom_member_namelisted_; /* _member_phase1_ namelisted? */
555static bool ffecom_doing_entry_ = FALSE;
556static bool ffecom_transform_only_dummies_ = FALSE;
ff852b44
CB
557static int ffecom_typesize_pointer_;
558static int ffecom_typesize_integer1_;
5ff904cd
JL
559
560/* Holds pointer-to-function expressions. */
561
562static tree ffecom_gfrt_[FFECOM_gfrt]
563=
564{
565#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) NULL_TREE,
566#include "com-rt.def"
567#undef DEFGFRT
568};
569
570/* Holds the external names of the functions. */
571
26f096f9 572static const char *ffecom_gfrt_name_[FFECOM_gfrt]
5ff904cd
JL
573=
574{
575#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) NAME,
576#include "com-rt.def"
577#undef DEFGFRT
578};
579
580/* Whether the function returns. */
581
582static bool ffecom_gfrt_volatile_[FFECOM_gfrt]
583=
584{
585#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) VOLATILE,
586#include "com-rt.def"
587#undef DEFGFRT
588};
589
590/* Whether the function returns type complex. */
591
592static bool ffecom_gfrt_complex_[FFECOM_gfrt]
593=
594{
595#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) COMPLEX,
596#include "com-rt.def"
597#undef DEFGFRT
598};
599
600/* Type code for the function return value. */
601
602static ffecomRttype_ ffecom_gfrt_type_[FFECOM_gfrt]
603=
604{
605#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) TYPE,
606#include "com-rt.def"
607#undef DEFGFRT
608};
609
610/* String of codes for the function's arguments. */
611
26f096f9 612static const char *ffecom_gfrt_argstring_[FFECOM_gfrt]
5ff904cd
JL
613=
614{
615#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) ARGS,
616#include "com-rt.def"
617#undef DEFGFRT
618};
619#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
620
621/* Internal macros. */
622
623#if FFECOM_targetCURRENT == FFECOM_targetGCC
624
625/* We let tm.h override the types used here, to handle trivial differences
626 such as the choice of unsigned int or long unsigned int for size_t.
627 When machines start needing nontrivial differences in the size type,
628 it would be best to do something here to figure out automatically
629 from other information what type to use. */
630
ff852b44
CB
631#ifndef SIZE_TYPE
632#define SIZE_TYPE "long unsigned int"
633#endif
5ff904cd 634
5ff904cd
JL
635#define ffecom_concat_list_count_(catlist) ((catlist).count)
636#define ffecom_concat_list_expr_(catlist,i) ((catlist).exprs[(i)])
637#define ffecom_concat_list_maxlen_(catlist) ((catlist).maxlen)
638#define ffecom_concat_list_minlen_(catlist) ((catlist).minlen)
639
86fc7a6c
CB
640#define ffecom_char_args_(i,l,e) ffecom_char_args_x_((i),(l),(e),FALSE)
641#define ffecom_char_args_with_null_(i,l,e) ffecom_char_args_x_((i),(l),(e),TRUE)
642
5ff904cd
JL
643/* For each binding contour we allocate a binding_level structure
644 * which records the names defined in that contour.
645 * Contours include:
646 * 0) the global one
647 * 1) one for each function definition,
648 * where internal declarations of the parameters appear.
649 *
650 * The current meaning of a name can be found by searching the levels from
651 * the current one out to the global one.
652 */
653
654/* Note that the information in the `names' component of the global contour
655 is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers. */
656
657struct binding_level
658 {
c7e4ee3a
CB
659 /* A chain of _DECL nodes for all variables, constants, functions,
660 and typedef types. These are in the reverse of the order supplied.
661 */
5ff904cd
JL
662 tree names;
663
c7e4ee3a
CB
664 /* For each level (except not the global one),
665 a chain of BLOCK nodes for all the levels
666 that were entered and exited one level down. */
5ff904cd
JL
667 tree blocks;
668
c7e4ee3a
CB
669 /* The BLOCK node for this level, if one has been preallocated.
670 If 0, the BLOCK is allocated (if needed) when the level is popped. */
5ff904cd
JL
671 tree this_block;
672
673 /* The binding level which this one is contained in (inherits from). */
674 struct binding_level *level_chain;
c7e4ee3a
CB
675
676 /* 0: no ffecom_prepare_* functions called at this level yet;
677 1: ffecom_prepare* functions called, except not ffecom_prepare_end;
678 2: ffecom_prepare_end called. */
679 int prep_state;
5ff904cd
JL
680 };
681
682#define NULL_BINDING_LEVEL (struct binding_level *) NULL
683
684/* The binding level currently in effect. */
685
686static struct binding_level *current_binding_level;
687
688/* A chain of binding_level structures awaiting reuse. */
689
690static struct binding_level *free_binding_level;
691
692/* The outermost binding level, for names of file scope.
693 This is created when the compiler is started and exists
694 through the entire run. */
695
696static struct binding_level *global_binding_level;
697
698/* Binding level structures are initialized by copying this one. */
699
700static struct binding_level clear_binding_level
701=
c7e4ee3a 702{NULL, NULL, NULL, NULL_BINDING_LEVEL, 0};
5ff904cd
JL
703
704/* Language-dependent contents of an identifier. */
705
706struct lang_identifier
707 {
708 struct tree_identifier ignore;
709 tree global_value, local_value, label_value;
710 bool invented;
711 };
712
713/* Macros for access to language-specific slots in an identifier. */
714/* Each of these slots contains a DECL node or null. */
715
716/* This represents the value which the identifier has in the
717 file-scope namespace. */
718#define IDENTIFIER_GLOBAL_VALUE(NODE) \
719 (((struct lang_identifier *)(NODE))->global_value)
720/* This represents the value which the identifier has in the current
721 scope. */
722#define IDENTIFIER_LOCAL_VALUE(NODE) \
723 (((struct lang_identifier *)(NODE))->local_value)
724/* This represents the value which the identifier has as a label in
725 the current label scope. */
726#define IDENTIFIER_LABEL_VALUE(NODE) \
727 (((struct lang_identifier *)(NODE))->label_value)
728/* This is nonzero if the identifier was "made up" by g77 code. */
729#define IDENTIFIER_INVENTED(NODE) \
730 (((struct lang_identifier *)(NODE))->invented)
731
732/* In identifiers, C uses the following fields in a special way:
733 TREE_PUBLIC to record that there was a previous local extern decl.
734 TREE_USED to record that such a decl was used.
735 TREE_ADDRESSABLE to record that the address of such a decl was used. */
736
737/* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
738 that have names. Here so we can clear out their names' definitions
739 at the end of the function. */
740
741static tree named_labels;
742
743/* A list of LABEL_DECLs from outer contexts that are currently shadowed. */
744
745static tree shadowed_labels;
746
747#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
748\f
6b55276e
CB
749/* Return the subscript expression, modified to do range-checking.
750
751 `array' is the array to be checked against.
752 `element' is the subscript expression to check.
753 `dim' is the dimension number (starting at 0).
754 `total_dims' is the total number of dimensions (0 for CHARACTER substring).
755*/
756
757static tree
758ffecom_subscript_check_ (tree array, tree element, int dim, int total_dims,
759 char *array_name)
760{
761 tree low = TYPE_MIN_VALUE (TYPE_DOMAIN (array));
762 tree high = TYPE_MAX_VALUE (TYPE_DOMAIN (array));
763 tree cond;
764 tree die;
765 tree args;
766
767 if (element == error_mark_node)
768 return element;
769
ff852b44
CB
770 if (TREE_TYPE (low) != TREE_TYPE (element))
771 {
772 if (TYPE_PRECISION (TREE_TYPE (low))
773 > TYPE_PRECISION (TREE_TYPE (element)))
774 element = convert (TREE_TYPE (low), element);
775 else
776 {
777 low = convert (TREE_TYPE (element), low);
778 if (high)
779 high = convert (TREE_TYPE (element), high);
780 }
781 }
782
6b55276e
CB
783 element = ffecom_save_tree (element);
784 cond = ffecom_2 (LE_EXPR, integer_type_node,
785 low,
786 element);
787 if (high)
788 {
789 cond = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
790 cond,
791 ffecom_2 (LE_EXPR, integer_type_node,
792 element,
793 high));
794 }
795
796 {
797 int len;
798 char *proc;
799 char *var;
800 tree arg3;
801 tree arg2;
802 tree arg1;
803 tree arg4;
804
805 switch (total_dims)
806 {
807 case 0:
808 var = xmalloc (strlen (array_name) + 20);
809 sprintf (&var[0], "%s[%s-substring]",
810 array_name,
811 dim ? "end" : "start");
812 len = strlen (var) + 1;
813 break;
814
815 case 1:
816 len = strlen (array_name) + 1;
817 var = array_name;
818 break;
819
820 default:
821 var = xmalloc (strlen (array_name) + 40);
822 sprintf (&var[0], "%s[subscript-%d-of-%d]",
823 array_name,
824 dim + 1, total_dims);
825 len = strlen (var) + 1;
826 break;
827 }
828
829 arg1 = build_string (len, var);
830
831 if (total_dims != 1)
832 free (var);
833
834 TREE_TYPE (arg1)
835 = build_type_variant (build_array_type (char_type_node,
836 build_range_type
837 (integer_type_node,
838 integer_one_node,
839 build_int_2 (len, 0))),
840 1, 0);
841 TREE_CONSTANT (arg1) = 1;
842 TREE_STATIC (arg1) = 1;
843 arg1 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg1)),
844 arg1);
845
846 /* s_rnge adds one to the element to print it, so bias against
847 that -- want to print a faithful *subscript* value. */
848 arg2 = convert (ffecom_f2c_ftnint_type_node,
849 ffecom_2 (MINUS_EXPR,
850 TREE_TYPE (element),
851 element,
852 convert (TREE_TYPE (element),
853 integer_one_node)));
854
855 proc = xmalloc ((len = strlen (input_filename)
856 + IDENTIFIER_LENGTH (DECL_NAME (current_function_decl))
857 + 2));
858
859 sprintf (&proc[0], "%s/%s",
860 input_filename,
861 IDENTIFIER_POINTER (DECL_NAME (current_function_decl)));
862 arg3 = build_string (len, proc);
863
864 free (proc);
865
866 TREE_TYPE (arg3)
867 = build_type_variant (build_array_type (char_type_node,
868 build_range_type
869 (integer_type_node,
870 integer_one_node,
871 build_int_2 (len, 0))),
872 1, 0);
873 TREE_CONSTANT (arg3) = 1;
874 TREE_STATIC (arg3) = 1;
875 arg3 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg3)),
876 arg3);
877
878 arg4 = convert (ffecom_f2c_ftnint_type_node,
879 build_int_2 (lineno, 0));
880
881 arg1 = build_tree_list (NULL_TREE, arg1);
882 arg2 = build_tree_list (NULL_TREE, arg2);
883 arg3 = build_tree_list (NULL_TREE, arg3);
884 arg4 = build_tree_list (NULL_TREE, arg4);
885 TREE_CHAIN (arg3) = arg4;
886 TREE_CHAIN (arg2) = arg3;
887 TREE_CHAIN (arg1) = arg2;
888
889 args = arg1;
890 }
891 die = ffecom_call_gfrt (FFECOM_gfrtRANGE,
892 args, NULL_TREE);
893 TREE_SIDE_EFFECTS (die) = 1;
894
895 element = ffecom_3 (COND_EXPR,
896 TREE_TYPE (element),
897 cond,
898 element,
899 die);
900
901 return element;
902}
903
904/* Return the computed element of an array reference.
905
ff852b44
CB
906 `item' is NULL_TREE, or the transformed pointer to the array.
907 `expr' is the original opARRAYREF expression, which is transformed
908 if `item' is NULL_TREE.
909 `want_ptr' is non-zero if a pointer to the element, instead of
6b55276e
CB
910 the element itself, is to be returned. */
911
912static tree
913ffecom_arrayref_ (tree item, ffebld expr, int want_ptr)
914{
915 ffebld dims[FFECOM_dimensionsMAX];
916 int i;
917 int total_dims;
ff852b44
CB
918 int flatten = ffe_is_flatten_arrays ();
919 int need_ptr;
6b55276e
CB
920 tree array;
921 tree element;
ff852b44
CB
922 tree tree_type;
923 tree tree_type_x;
6b55276e 924 char *array_name;
ff852b44
CB
925 ffetype type;
926 ffebld list;
6b55276e
CB
927
928 if (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER)
929 array_name = ffesymbol_text (ffebld_symter (ffebld_left (expr)));
930 else
931 array_name = "[expr?]";
932
933 /* Build up ARRAY_REFs in reverse order (since we're column major
934 here in Fortran land). */
935
ff852b44
CB
936 for (i = 0, list = ffebld_right (expr);
937 list != NULL;
938 ++i, list = ffebld_trail (list))
939 {
940 dims[i] = ffebld_head (list);
941 type = ffeinfo_type (ffebld_basictype (dims[i]),
942 ffebld_kindtype (dims[i]));
943 if (! flatten
944 && ffecom_typesize_pointer_ > ffecom_typesize_integer1_
945 && ffetype_size (type) > ffecom_typesize_integer1_)
946 /* E.g. ARRAY(INDEX), given INTEGER*8 INDEX, on a system with 64-bit
947 pointers and 32-bit integers. Do the full 64-bit pointer
948 arithmetic, for codes using arrays for nonstandard heap-like
949 work. */
950 flatten = 1;
951 }
6b55276e
CB
952
953 total_dims = i;
954
ff852b44
CB
955 need_ptr = want_ptr || flatten;
956
957 if (! item)
958 {
959 if (need_ptr)
960 item = ffecom_ptr_to_expr (ffebld_left (expr));
961 else
962 item = ffecom_expr (ffebld_left (expr));
963
964 if (item == error_mark_node)
965 return item;
966
967 if (ffeinfo_where (ffebld_info (expr)) == FFEINFO_whereFLEETING
968 && ! mark_addressable (item))
969 return error_mark_node;
970 }
971
972 if (item == error_mark_node)
973 return item;
974
6b55276e
CB
975 if (need_ptr)
976 {
ff852b44
CB
977 tree min;
978
6b55276e
CB
979 for (--i, array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
980 i >= 0;
981 --i, array = TYPE_MAIN_VARIANT (TREE_TYPE (array)))
982 {
ff852b44
CB
983 min = TYPE_MIN_VALUE (TYPE_DOMAIN (array));
984 element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
6b55276e
CB
985 if (ffe_is_subscript_check ())
986 element = ffecom_subscript_check_ (array, element, i, total_dims,
987 array_name);
ff852b44
CB
988 if (element == error_mark_node)
989 return element;
990
991 /* Widen integral arithmetic as desired while preserving
992 signedness. */
993 tree_type = TREE_TYPE (element);
994 tree_type_x = tree_type;
995 if (tree_type
996 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
997 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
998 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
999
1000 if (TREE_TYPE (min) != tree_type_x)
1001 min = convert (tree_type_x, min);
1002 if (TREE_TYPE (element) != tree_type_x)
1003 element = convert (tree_type_x, element);
1004
6b55276e
CB
1005 item = ffecom_2 (PLUS_EXPR,
1006 build_pointer_type (TREE_TYPE (array)),
1007 item,
1008 size_binop (MULT_EXPR,
1009 size_in_bytes (TREE_TYPE (array)),
ff852b44
CB
1010 fold (build (MINUS_EXPR,
1011 tree_type_x,
1012 element,
1013 min))));
6b55276e
CB
1014 }
1015 if (! want_ptr)
1016 {
1017 item = ffecom_1 (INDIRECT_REF,
1018 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))),
1019 item);
1020 }
1021 }
1022 else
1023 {
1024 for (--i;
1025 i >= 0;
1026 --i)
1027 {
1028 array = TYPE_MAIN_VARIANT (TREE_TYPE (item));
1029
1030 element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
1031 if (ffe_is_subscript_check ())
1032 element = ffecom_subscript_check_ (array, element, i, total_dims,
1033 array_name);
ff852b44
CB
1034 if (element == error_mark_node)
1035 return element;
1036
1037 /* Widen integral arithmetic as desired while preserving
1038 signedness. */
1039 tree_type = TREE_TYPE (element);
1040 tree_type_x = tree_type;
1041 if (tree_type
1042 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
1043 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
1044 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
1045
1046 element = convert (tree_type_x, element);
1047
6b55276e
CB
1048 item = ffecom_2 (ARRAY_REF,
1049 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))),
1050 item,
1051 element);
1052 }
1053 }
1054
1055 return item;
1056}
1057
5ff904cd
JL
1058/* This is like gcc's stabilize_reference -- in fact, most of the code
1059 comes from that -- but it handles the situation where the reference
1060 is going to have its subparts picked at, and it shouldn't change
1061 (or trigger extra invocations of functions in the subtrees) due to
1062 this. save_expr is a bit overzealous, because we don't need the
1063 entire thing calculated and saved like a temp. So, for DECLs, no
1064 change is needed, because these are stable aggregates, and ARRAY_REF
1065 and such might well be stable too, but for things like calculations,
1066 we do need to calculate a snapshot of a value before picking at it. */
1067
1068#if FFECOM_targetCURRENT == FFECOM_targetGCC
1069static tree
1070ffecom_stabilize_aggregate_ (tree ref)
1071{
1072 tree result;
1073 enum tree_code code = TREE_CODE (ref);
1074
1075 switch (code)
1076 {
1077 case VAR_DECL:
1078 case PARM_DECL:
1079 case RESULT_DECL:
1080 /* No action is needed in this case. */
1081 return ref;
1082
1083 case NOP_EXPR:
1084 case CONVERT_EXPR:
1085 case FLOAT_EXPR:
1086 case FIX_TRUNC_EXPR:
1087 case FIX_FLOOR_EXPR:
1088 case FIX_ROUND_EXPR:
1089 case FIX_CEIL_EXPR:
1090 result = build_nt (code, stabilize_reference (TREE_OPERAND (ref, 0)));
1091 break;
1092
1093 case INDIRECT_REF:
1094 result = build_nt (INDIRECT_REF,
1095 stabilize_reference_1 (TREE_OPERAND (ref, 0)));
1096 break;
1097
1098 case COMPONENT_REF:
1099 result = build_nt (COMPONENT_REF,
1100 stabilize_reference (TREE_OPERAND (ref, 0)),
1101 TREE_OPERAND (ref, 1));
1102 break;
1103
1104 case BIT_FIELD_REF:
1105 result = build_nt (BIT_FIELD_REF,
1106 stabilize_reference (TREE_OPERAND (ref, 0)),
1107 stabilize_reference_1 (TREE_OPERAND (ref, 1)),
1108 stabilize_reference_1 (TREE_OPERAND (ref, 2)));
1109 break;
1110
1111 case ARRAY_REF:
1112 result = build_nt (ARRAY_REF,
1113 stabilize_reference (TREE_OPERAND (ref, 0)),
1114 stabilize_reference_1 (TREE_OPERAND (ref, 1)));
1115 break;
1116
1117 case COMPOUND_EXPR:
1118 result = build_nt (COMPOUND_EXPR,
1119 stabilize_reference_1 (TREE_OPERAND (ref, 0)),
1120 stabilize_reference (TREE_OPERAND (ref, 1)));
1121 break;
1122
1123 case RTL_EXPR:
1124 result = build1 (INDIRECT_REF, TREE_TYPE (ref),
1125 save_expr (build1 (ADDR_EXPR,
1126 build_pointer_type (TREE_TYPE (ref)),
1127 ref)));
1128 break;
1129
1130
1131 default:
1132 return save_expr (ref);
1133
1134 case ERROR_MARK:
1135 return error_mark_node;
1136 }
1137
1138 TREE_TYPE (result) = TREE_TYPE (ref);
1139 TREE_READONLY (result) = TREE_READONLY (ref);
1140 TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (ref);
1141 TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (ref);
1142 TREE_RAISES (result) = TREE_RAISES (ref);
1143
1144 return result;
1145}
1146#endif
1147
1148/* A rip-off of gcc's convert.c convert_to_complex function,
1149 reworked to handle complex implemented as C structures
1150 (RECORD_TYPE with two fields, real and imaginary `r' and `i'). */
1151
1152#if FFECOM_targetCURRENT == FFECOM_targetGCC
1153static tree
1154ffecom_convert_to_complex_ (tree type, tree expr)
1155{
1156 register enum tree_code form = TREE_CODE (TREE_TYPE (expr));
1157 tree subtype;
1158
1159 assert (TREE_CODE (type) == RECORD_TYPE);
1160
1161 subtype = TREE_TYPE (TYPE_FIELDS (type));
1162
1163 if (form == REAL_TYPE || form == INTEGER_TYPE || form == ENUMERAL_TYPE)
1164 {
1165 expr = convert (subtype, expr);
1166 return ffecom_2 (COMPLEX_EXPR, type, expr,
1167 convert (subtype, integer_zero_node));
1168 }
1169
1170 if (form == RECORD_TYPE)
1171 {
1172 tree elt_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr)));
1173 if (TYPE_MAIN_VARIANT (elt_type) == TYPE_MAIN_VARIANT (subtype))
1174 return expr;
1175 else
1176 {
1177 expr = save_expr (expr);
1178 return ffecom_2 (COMPLEX_EXPR,
1179 type,
1180 convert (subtype,
1181 ffecom_1 (REALPART_EXPR,
1182 TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))),
1183 expr)),
1184 convert (subtype,
1185 ffecom_1 (IMAGPART_EXPR,
1186 TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))),
1187 expr)));
1188 }
1189 }
1190
1191 if (form == POINTER_TYPE || form == REFERENCE_TYPE)
1192 error ("pointer value used where a complex was expected");
1193 else
1194 error ("aggregate value used where a complex was expected");
1195
1196 return ffecom_2 (COMPLEX_EXPR, type,
1197 convert (subtype, integer_zero_node),
1198 convert (subtype, integer_zero_node));
1199}
1200#endif
1201
1202/* Like gcc's convert(), but crashes if widening might happen. */
1203
1204#if FFECOM_targetCURRENT == FFECOM_targetGCC
1205static tree
1206ffecom_convert_narrow_ (type, expr)
1207 tree type, expr;
1208{
1209 register tree e = expr;
1210 register enum tree_code code = TREE_CODE (type);
1211
1212 if (type == TREE_TYPE (e)
1213 || TREE_CODE (e) == ERROR_MARK)
1214 return e;
1215 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
1216 return fold (build1 (NOP_EXPR, type, e));
1217 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
1218 || code == ERROR_MARK)
1219 return error_mark_node;
1220 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
1221 {
1222 assert ("void value not ignored as it ought to be" == NULL);
1223 return error_mark_node;
1224 }
1225 assert (code != VOID_TYPE);
1226 if ((code != RECORD_TYPE)
1227 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
1228 assert ("converting COMPLEX to REAL" == NULL);
1229 assert (code != ENUMERAL_TYPE);
1230 if (code == INTEGER_TYPE)
1231 {
a74de6ea
CB
1232 assert ((TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE
1233 && TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)))
1234 || (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
1235 && (TYPE_PRECISION (type)
1236 == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (e))))));
5ff904cd
JL
1237 return fold (convert_to_integer (type, e));
1238 }
1239 if (code == POINTER_TYPE)
1240 {
1241 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
1242 return fold (convert_to_pointer (type, e));
1243 }
1244 if (code == REAL_TYPE)
1245 {
1246 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
1247 assert (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)));
1248 return fold (convert_to_real (type, e));
1249 }
1250 if (code == COMPLEX_TYPE)
1251 {
1252 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
1253 assert (TYPE_PRECISION (TREE_TYPE (type)) <= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
1254 return fold (convert_to_complex (type, e));
1255 }
1256 if (code == RECORD_TYPE)
1257 {
1258 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
270fc4e8
CB
1259 /* Check that at least the first field name agrees. */
1260 assert (DECL_NAME (TYPE_FIELDS (type))
1261 == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e))));
5ff904cd
JL
1262 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1263 <= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
270fc4e8
CB
1264 if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1265 == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))))
1266 return e;
5ff904cd
JL
1267 return fold (ffecom_convert_to_complex_ (type, e));
1268 }
1269
1270 assert ("conversion to non-scalar type requested" == NULL);
1271 return error_mark_node;
1272}
1273#endif
1274
1275/* Like gcc's convert(), but crashes if narrowing might happen. */
1276
1277#if FFECOM_targetCURRENT == FFECOM_targetGCC
1278static tree
1279ffecom_convert_widen_ (type, expr)
1280 tree type, expr;
1281{
1282 register tree e = expr;
1283 register enum tree_code code = TREE_CODE (type);
1284
1285 if (type == TREE_TYPE (e)
1286 || TREE_CODE (e) == ERROR_MARK)
1287 return e;
1288 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
1289 return fold (build1 (NOP_EXPR, type, e));
1290 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
1291 || code == ERROR_MARK)
1292 return error_mark_node;
1293 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
1294 {
1295 assert ("void value not ignored as it ought to be" == NULL);
1296 return error_mark_node;
1297 }
1298 assert (code != VOID_TYPE);
1299 if ((code != RECORD_TYPE)
1300 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
1301 assert ("narrowing COMPLEX to REAL" == NULL);
1302 assert (code != ENUMERAL_TYPE);
1303 if (code == INTEGER_TYPE)
1304 {
a74de6ea
CB
1305 assert ((TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE
1306 && TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)))
1307 || (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
1308 && (TYPE_PRECISION (type)
1309 == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (e))))));
5ff904cd
JL
1310 return fold (convert_to_integer (type, e));
1311 }
1312 if (code == POINTER_TYPE)
1313 {
1314 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
1315 return fold (convert_to_pointer (type, e));
1316 }
1317 if (code == REAL_TYPE)
1318 {
1319 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
1320 assert (TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)));
1321 return fold (convert_to_real (type, e));
1322 }
1323 if (code == COMPLEX_TYPE)
1324 {
1325 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
1326 assert (TYPE_PRECISION (TREE_TYPE (type)) >= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
1327 return fold (convert_to_complex (type, e));
1328 }
1329 if (code == RECORD_TYPE)
1330 {
1331 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
270fc4e8
CB
1332 /* Check that at least the first field name agrees. */
1333 assert (DECL_NAME (TYPE_FIELDS (type))
1334 == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e))));
5ff904cd
JL
1335 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1336 >= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
270fc4e8
CB
1337 if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1338 == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))))
1339 return e;
5ff904cd
JL
1340 return fold (ffecom_convert_to_complex_ (type, e));
1341 }
1342
1343 assert ("conversion to non-scalar type requested" == NULL);
1344 return error_mark_node;
1345}
1346#endif
1347
1348/* Handles making a COMPLEX type, either the standard
1349 (but buggy?) gbe way, or the safer (but less elegant?)
1350 f2c way. */
1351
1352#if FFECOM_targetCURRENT == FFECOM_targetGCC
1353static tree
1354ffecom_make_complex_type_ (tree subtype)
1355{
1356 tree type;
1357 tree realfield;
1358 tree imagfield;
1359
1360 if (ffe_is_emulate_complex ())
1361 {
1362 type = make_node (RECORD_TYPE);
1363 realfield = ffecom_decl_field (type, NULL_TREE, "r", subtype);
1364 imagfield = ffecom_decl_field (type, realfield, "i", subtype);
1365 TYPE_FIELDS (type) = realfield;
1366 layout_type (type);
1367 }
1368 else
1369 {
1370 type = make_node (COMPLEX_TYPE);
1371 TREE_TYPE (type) = subtype;
1372 layout_type (type);
1373 }
1374
1375 return type;
1376}
1377#endif
1378
1379/* Chooses either the gbe or the f2c way to build a
1380 complex constant. */
1381
1382#if FFECOM_targetCURRENT == FFECOM_targetGCC
1383static tree
1384ffecom_build_complex_constant_ (tree type, tree realpart, tree imagpart)
1385{
1386 tree bothparts;
1387
1388 if (ffe_is_emulate_complex ())
1389 {
1390 bothparts = build_tree_list (TYPE_FIELDS (type), realpart);
1391 TREE_CHAIN (bothparts) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), imagpart);
1392 bothparts = build (CONSTRUCTOR, type, NULL_TREE, bothparts);
1393 }
1394 else
1395 {
1396 bothparts = build_complex (type, realpart, imagpart);
1397 }
1398
1399 return bothparts;
1400}
1401#endif
1402
1403#if FFECOM_targetCURRENT == FFECOM_targetGCC
1404static tree
26f096f9 1405ffecom_arglist_expr_ (const char *c, ffebld expr)
5ff904cd
JL
1406{
1407 tree list;
1408 tree *plist = &list;
1409 tree trail = NULL_TREE; /* Append char length args here. */
1410 tree *ptrail = &trail;
1411 tree length;
1412 ffebld exprh;
1413 tree item;
1414 bool ptr = FALSE;
1415 tree wanted = NULL_TREE;
e2fa159e
JL
1416 static char zed[] = "0";
1417
1418 if (c == NULL)
1419 c = &zed[0];
5ff904cd
JL
1420
1421 while (expr != NULL)
1422 {
1423 if (*c != '\0')
1424 {
1425 ptr = FALSE;
1426 if (*c == '&')
1427 {
1428 ptr = TRUE;
1429 ++c;
1430 }
1431 switch (*(c++))
1432 {
1433 case '\0':
1434 ptr = TRUE;
1435 wanted = NULL_TREE;
1436 break;
1437
1438 case 'a':
1439 assert (ptr);
1440 wanted = NULL_TREE;
1441 break;
1442
1443 case 'c':
1444 wanted = ffecom_f2c_complex_type_node;
1445 break;
1446
1447 case 'd':
1448 wanted = ffecom_f2c_doublereal_type_node;
1449 break;
1450
1451 case 'e':
1452 wanted = ffecom_f2c_doublecomplex_type_node;
1453 break;
1454
1455 case 'f':
1456 wanted = ffecom_f2c_real_type_node;
1457 break;
1458
1459 case 'i':
1460 wanted = ffecom_f2c_integer_type_node;
1461 break;
1462
1463 case 'j':
1464 wanted = ffecom_f2c_longint_type_node;
1465 break;
1466
1467 default:
1468 assert ("bad argstring code" == NULL);
1469 wanted = NULL_TREE;
1470 break;
1471 }
1472 }
1473
1474 exprh = ffebld_head (expr);
1475 if (exprh == NULL)
1476 wanted = NULL_TREE;
1477
1478 if ((wanted == NULL_TREE)
1479 || (ptr
1480 && (TYPE_MODE
1481 (ffecom_tree_type[ffeinfo_basictype (ffebld_info (exprh))]
1482 [ffeinfo_kindtype (ffebld_info (exprh))])
1483 == TYPE_MODE (wanted))))
1484 *plist
1485 = build_tree_list (NULL_TREE,
1486 ffecom_arg_ptr_to_expr (exprh,
1487 &length));
1488 else
1489 {
1490 item = ffecom_arg_expr (exprh, &length);
1491 item = ffecom_convert_widen_ (wanted, item);
1492 if (ptr)
1493 {
1494 item = ffecom_1 (ADDR_EXPR,
1495 build_pointer_type (TREE_TYPE (item)),
1496 item);
1497 }
1498 *plist
1499 = build_tree_list (NULL_TREE,
1500 item);
1501 }
1502
1503 plist = &TREE_CHAIN (*plist);
1504 expr = ffebld_trail (expr);
1505 if (length != NULL_TREE)
1506 {
1507 *ptrail = build_tree_list (NULL_TREE, length);
1508 ptrail = &TREE_CHAIN (*ptrail);
1509 }
1510 }
1511
e2fa159e
JL
1512 /* We've run out of args in the call; if the implementation expects
1513 more, supply null pointers for them, which the implementation can
1514 check to see if an arg was omitted. */
1515
1516 while (*c != '\0' && *c != '0')
1517 {
1518 if (*c == '&')
1519 ++c;
1520 else
1521 assert ("missing arg to run-time routine!" == NULL);
1522
1523 switch (*(c++))
1524 {
1525 case '\0':
1526 case 'a':
1527 case 'c':
1528 case 'd':
1529 case 'e':
1530 case 'f':
1531 case 'i':
1532 case 'j':
1533 break;
1534
1535 default:
1536 assert ("bad arg string code" == NULL);
1537 break;
1538 }
1539 *plist
1540 = build_tree_list (NULL_TREE,
1541 null_pointer_node);
1542 plist = &TREE_CHAIN (*plist);
1543 }
1544
5ff904cd
JL
1545 *plist = trail;
1546
1547 return list;
1548}
1549#endif
1550
1551#if FFECOM_targetCURRENT == FFECOM_targetGCC
1552static tree
1553ffecom_widest_expr_type_ (ffebld list)
1554{
1555 ffebld item;
1556 ffebld widest = NULL;
1557 ffetype type;
1558 ffetype widest_type = NULL;
1559 tree t;
1560
1561 for (; list != NULL; list = ffebld_trail (list))
1562 {
1563 item = ffebld_head (list);
1564 if (item == NULL)
1565 continue;
1566 if ((widest != NULL)
1567 && (ffeinfo_basictype (ffebld_info (item))
1568 != ffeinfo_basictype (ffebld_info (widest))))
1569 continue;
1570 type = ffeinfo_type (ffeinfo_basictype (ffebld_info (item)),
1571 ffeinfo_kindtype (ffebld_info (item)));
1572 if ((widest == FFEINFO_kindtypeNONE)
1573 || (ffetype_size (type)
1574 > ffetype_size (widest_type)))
1575 {
1576 widest = item;
1577 widest_type = type;
1578 }
1579 }
1580
1581 assert (widest != NULL);
1582 t = ffecom_tree_type[ffeinfo_basictype (ffebld_info (widest))]
1583 [ffeinfo_kindtype (ffebld_info (widest))];
1584 assert (t != NULL_TREE);
1585 return t;
1586}
1587#endif
1588
d6cd84e0
CB
1589/* Check whether a partial overlap between two expressions is possible.
1590
1591 Can *starting* to write a portion of expr1 change the value
1592 computed (perhaps already, *partially*) by expr2?
1593
1594 Currently, this is a concern only for a COMPLEX expr1. But if it
1595 isn't in COMMON or local EQUIVALENCE, since we don't support
1596 aliasing of arguments, it isn't a concern. */
1597
1598static bool
1599ffecom_possible_partial_overlap_ (ffebld expr1, ffebld expr2)
1600{
1601 ffesymbol sym;
1602 ffestorag st;
1603
1604 switch (ffebld_op (expr1))
1605 {
1606 case FFEBLD_opSYMTER:
1607 sym = ffebld_symter (expr1);
1608 break;
1609
1610 case FFEBLD_opARRAYREF:
1611 if (ffebld_op (ffebld_left (expr1)) != FFEBLD_opSYMTER)
1612 return FALSE;
1613 sym = ffebld_symter (ffebld_left (expr1));
1614 break;
1615
1616 default:
1617 return FALSE;
1618 }
1619
1620 if (ffesymbol_where (sym) != FFEINFO_whereCOMMON
1621 && (ffesymbol_where (sym) != FFEINFO_whereLOCAL
1622 || ! (st = ffesymbol_storage (sym))
1623 || ! ffestorag_parent (st)))
1624 return FALSE;
1625
1626 /* It's in COMMON or local EQUIVALENCE. */
1627
1628 return TRUE;
1629}
1630
5ff904cd
JL
1631/* Check whether dest and source might overlap. ffebld versions of these
1632 might or might not be passed, will be NULL if not.
1633
1634 The test is really whether source_tree is modifiable and, if modified,
1635 might overlap destination such that the value(s) in the destination might
1636 change before it is finally modified. dest_* are the canonized
1637 destination itself. */
1638
1639#if FFECOM_targetCURRENT == FFECOM_targetGCC
1640static bool
1641ffecom_overlap_ (tree dest_decl, tree dest_offset, tree dest_size,
1642 tree source_tree, ffebld source UNUSED,
1643 bool scalar_arg)
1644{
1645 tree source_decl;
1646 tree source_offset;
1647 tree source_size;
1648 tree t;
1649
1650 if (source_tree == NULL_TREE)
1651 return FALSE;
1652
1653 switch (TREE_CODE (source_tree))
1654 {
1655 case ERROR_MARK:
1656 case IDENTIFIER_NODE:
1657 case INTEGER_CST:
1658 case REAL_CST:
1659 case COMPLEX_CST:
1660 case STRING_CST:
1661 case CONST_DECL:
1662 case VAR_DECL:
1663 case RESULT_DECL:
1664 case FIELD_DECL:
1665 case MINUS_EXPR:
1666 case MULT_EXPR:
1667 case TRUNC_DIV_EXPR:
1668 case CEIL_DIV_EXPR:
1669 case FLOOR_DIV_EXPR:
1670 case ROUND_DIV_EXPR:
1671 case TRUNC_MOD_EXPR:
1672 case CEIL_MOD_EXPR:
1673 case FLOOR_MOD_EXPR:
1674 case ROUND_MOD_EXPR:
1675 case RDIV_EXPR:
1676 case EXACT_DIV_EXPR:
1677 case FIX_TRUNC_EXPR:
1678 case FIX_CEIL_EXPR:
1679 case FIX_FLOOR_EXPR:
1680 case FIX_ROUND_EXPR:
1681 case FLOAT_EXPR:
1682 case EXPON_EXPR:
1683 case NEGATE_EXPR:
1684 case MIN_EXPR:
1685 case MAX_EXPR:
1686 case ABS_EXPR:
1687 case FFS_EXPR:
1688 case LSHIFT_EXPR:
1689 case RSHIFT_EXPR:
1690 case LROTATE_EXPR:
1691 case RROTATE_EXPR:
1692 case BIT_IOR_EXPR:
1693 case BIT_XOR_EXPR:
1694 case BIT_AND_EXPR:
1695 case BIT_ANDTC_EXPR:
1696 case BIT_NOT_EXPR:
1697 case TRUTH_ANDIF_EXPR:
1698 case TRUTH_ORIF_EXPR:
1699 case TRUTH_AND_EXPR:
1700 case TRUTH_OR_EXPR:
1701 case TRUTH_XOR_EXPR:
1702 case TRUTH_NOT_EXPR:
1703 case LT_EXPR:
1704 case LE_EXPR:
1705 case GT_EXPR:
1706 case GE_EXPR:
1707 case EQ_EXPR:
1708 case NE_EXPR:
1709 case COMPLEX_EXPR:
1710 case CONJ_EXPR:
1711 case REALPART_EXPR:
1712 case IMAGPART_EXPR:
1713 case LABEL_EXPR:
1714 case COMPONENT_REF:
1715 return FALSE;
1716
1717 case COMPOUND_EXPR:
1718 return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1719 TREE_OPERAND (source_tree, 1), NULL,
1720 scalar_arg);
1721
1722 case MODIFY_EXPR:
1723 return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1724 TREE_OPERAND (source_tree, 0), NULL,
1725 scalar_arg);
1726
1727 case CONVERT_EXPR:
1728 case NOP_EXPR:
1729 case NON_LVALUE_EXPR:
1730 case PLUS_EXPR:
1731 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1732 return TRUE;
1733
1734 ffecom_tree_canonize_ptr_ (&source_decl, &source_offset,
1735 source_tree);
1736 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1737 break;
1738
1739 case COND_EXPR:
1740 return
1741 ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1742 TREE_OPERAND (source_tree, 1), NULL,
1743 scalar_arg)
1744 || ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1745 TREE_OPERAND (source_tree, 2), NULL,
1746 scalar_arg);
1747
1748
1749 case ADDR_EXPR:
1750 ffecom_tree_canonize_ref_ (&source_decl, &source_offset,
1751 &source_size,
1752 TREE_OPERAND (source_tree, 0));
1753 break;
1754
1755 case PARM_DECL:
1756 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1757 return TRUE;
1758
1759 source_decl = source_tree;
1760 source_offset = size_zero_node;
1761 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1762 break;
1763
1764 case SAVE_EXPR:
1765 case REFERENCE_EXPR:
1766 case PREDECREMENT_EXPR:
1767 case PREINCREMENT_EXPR:
1768 case POSTDECREMENT_EXPR:
1769 case POSTINCREMENT_EXPR:
1770 case INDIRECT_REF:
1771 case ARRAY_REF:
1772 case CALL_EXPR:
1773 default:
1774 return TRUE;
1775 }
1776
1777 /* Come here when source_decl, source_offset, and source_size filled
1778 in appropriately. */
1779
1780 if (source_decl == NULL_TREE)
1781 return FALSE; /* No decl involved, so no overlap. */
1782
1783 if (source_decl != dest_decl)
1784 return FALSE; /* Different decl, no overlap. */
1785
1786 if (TREE_CODE (dest_size) == ERROR_MARK)
1787 return TRUE; /* Assignment into entire assumed-size
1788 array? Shouldn't happen.... */
1789
1790 t = ffecom_2 (LE_EXPR, integer_type_node,
1791 ffecom_2 (PLUS_EXPR, TREE_TYPE (dest_offset),
1792 dest_offset,
1793 convert (TREE_TYPE (dest_offset),
1794 dest_size)),
1795 convert (TREE_TYPE (dest_offset),
1796 source_offset));
1797
1798 if (integer_onep (t))
1799 return FALSE; /* Destination precedes source. */
1800
1801 if (!scalar_arg
1802 || (source_size == NULL_TREE)
1803 || (TREE_CODE (source_size) == ERROR_MARK)
1804 || integer_zerop (source_size))
1805 return TRUE; /* No way to tell if dest follows source. */
1806
1807 t = ffecom_2 (LE_EXPR, integer_type_node,
1808 ffecom_2 (PLUS_EXPR, TREE_TYPE (source_offset),
1809 source_offset,
1810 convert (TREE_TYPE (source_offset),
1811 source_size)),
1812 convert (TREE_TYPE (source_offset),
1813 dest_offset));
1814
1815 if (integer_onep (t))
1816 return FALSE; /* Destination follows source. */
1817
1818 return TRUE; /* Destination and source overlap. */
1819}
1820#endif
1821
1822/* Check whether dest might overlap any of a list of arguments or is
1823 in a COMMON area the callee might know about (and thus modify). */
1824
1825#if FFECOM_targetCURRENT == FFECOM_targetGCC
1826static bool
1827ffecom_args_overlapping_ (tree dest_tree, ffebld dest UNUSED,
1828 tree args, tree callee_commons,
1829 bool scalar_args)
1830{
1831 tree arg;
1832 tree dest_decl;
1833 tree dest_offset;
1834 tree dest_size;
1835
1836 ffecom_tree_canonize_ref_ (&dest_decl, &dest_offset, &dest_size,
1837 dest_tree);
1838
1839 if (dest_decl == NULL_TREE)
1840 return FALSE; /* Seems unlikely! */
1841
1842 /* If the decl cannot be determined reliably, or if its in COMMON
1843 and the callee isn't known to not futz with COMMON via other
1844 means, overlap might happen. */
1845
1846 if ((TREE_CODE (dest_decl) == ERROR_MARK)
1847 || ((callee_commons != NULL_TREE)
1848 && TREE_PUBLIC (dest_decl)))
1849 return TRUE;
1850
1851 for (; args != NULL_TREE; args = TREE_CHAIN (args))
1852 {
1853 if (((arg = TREE_VALUE (args)) != NULL_TREE)
1854 && ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1855 arg, NULL, scalar_args))
1856 return TRUE;
1857 }
1858
1859 return FALSE;
1860}
1861#endif
1862
1863/* Build a string for a variable name as used by NAMELIST. This means that
1864 if we're using the f2c library, we build an uppercase string, since
1865 f2c does this. */
1866
1867#if FFECOM_targetCURRENT == FFECOM_targetGCC
1868static tree
26f096f9 1869ffecom_build_f2c_string_ (int i, const char *s)
5ff904cd
JL
1870{
1871 if (!ffe_is_f2c_library ())
1872 return build_string (i, s);
1873
1874 {
1875 char *tmp;
26f096f9 1876 const char *p;
5ff904cd
JL
1877 char *q;
1878 char space[34];
1879 tree t;
1880
1881 if (((size_t) i) > ARRAY_SIZE (space))
1882 tmp = malloc_new_ks (malloc_pool_image (), "f2c_string", i);
1883 else
1884 tmp = &space[0];
1885
1886 for (p = s, q = tmp; *p != '\0'; ++p, ++q)
1887 *q = ffesrc_toupper (*p);
1888 *q = '\0';
1889
1890 t = build_string (i, tmp);
1891
1892 if (((size_t) i) > ARRAY_SIZE (space))
1893 malloc_kill_ks (malloc_pool_image (), tmp, i);
1894
1895 return t;
1896 }
1897}
1898
1899#endif
1900/* Returns CALL_EXPR or equivalent with given type (pass NULL_TREE for
1901 type to just get whatever the function returns), handling the
1902 f2c value-returning convention, if required, by prepending
1903 to the arglist a pointer to a temporary to receive the return value. */
1904
1905#if FFECOM_targetCURRENT == FFECOM_targetGCC
1906static tree
1907ffecom_call_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1908 tree type, tree args, tree dest_tree,
1909 ffebld dest, bool *dest_used, tree callee_commons,
c7e4ee3a 1910 bool scalar_args, tree hook)
5ff904cd
JL
1911{
1912 tree item;
1913 tree tempvar;
1914
1915 if (dest_used != NULL)
1916 *dest_used = FALSE;
1917
1918 if (is_f2c_complex)
1919 {
1920 if ((dest_used == NULL)
1921 || (dest == NULL)
1922 || (ffeinfo_basictype (ffebld_info (dest))
1923 != FFEINFO_basictypeCOMPLEX)
1924 || (ffeinfo_kindtype (ffebld_info (dest)) != kt)
1925 || ((type != NULL_TREE) && (TREE_TYPE (dest_tree) != type))
1926 || ffecom_args_overlapping_ (dest_tree, dest, args,
1927 callee_commons,
1928 scalar_args))
1929 {
c7e4ee3a
CB
1930#ifdef HOHO
1931 tempvar = ffecom_make_tempvar (ffecom_tree_type
5ff904cd
JL
1932 [FFEINFO_basictypeCOMPLEX][kt],
1933 FFETARGET_charactersizeNONE,
c7e4ee3a
CB
1934 -1);
1935#else
1936 tempvar = hook;
1937 assert (tempvar);
1938#endif
5ff904cd
JL
1939 }
1940 else
1941 {
1942 *dest_used = TRUE;
1943 tempvar = dest_tree;
1944 type = NULL_TREE;
1945 }
1946
1947 item
1948 = build_tree_list (NULL_TREE,
1949 ffecom_1 (ADDR_EXPR,
c7e4ee3a 1950 build_pointer_type (TREE_TYPE (tempvar)),
5ff904cd
JL
1951 tempvar));
1952 TREE_CHAIN (item) = args;
1953
1954 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1955 item, NULL_TREE);
1956
1957 if (tempvar != dest_tree)
1958 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item, tempvar);
1959 }
1960 else
1961 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1962 args, NULL_TREE);
1963
1964 if ((type != NULL_TREE) && (TREE_TYPE (item) != type))
1965 item = ffecom_convert_narrow_ (type, item);
1966
1967 return item;
1968}
1969#endif
1970
1971/* Given two arguments, transform them and make a call to the given
1972 function via ffecom_call_. */
1973
1974#if FFECOM_targetCURRENT == FFECOM_targetGCC
1975static tree
1976ffecom_call_binop_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1977 tree type, ffebld left, ffebld right,
1978 tree dest_tree, ffebld dest, bool *dest_used,
c7e4ee3a 1979 tree callee_commons, bool scalar_args, tree hook)
5ff904cd
JL
1980{
1981 tree left_tree;
1982 tree right_tree;
1983 tree left_length;
1984 tree right_length;
1985
5ff904cd
JL
1986 left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
1987 right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
5ff904cd
JL
1988
1989 left_tree = build_tree_list (NULL_TREE, left_tree);
1990 right_tree = build_tree_list (NULL_TREE, right_tree);
1991 TREE_CHAIN (left_tree) = right_tree;
1992
1993 if (left_length != NULL_TREE)
1994 {
1995 left_length = build_tree_list (NULL_TREE, left_length);
1996 TREE_CHAIN (right_tree) = left_length;
1997 }
1998
1999 if (right_length != NULL_TREE)
2000 {
2001 right_length = build_tree_list (NULL_TREE, right_length);
2002 if (left_length != NULL_TREE)
2003 TREE_CHAIN (left_length) = right_length;
2004 else
2005 TREE_CHAIN (right_tree) = right_length;
2006 }
2007
2008 return ffecom_call_ (fn, kt, is_f2c_complex, type, left_tree,
2009 dest_tree, dest, dest_used, callee_commons,
c7e4ee3a 2010 scalar_args, hook);
5ff904cd
JL
2011}
2012#endif
2013
c7e4ee3a 2014/* Return ptr/length args for char subexpression
5ff904cd
JL
2015
2016 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
2017 subexpressions by constructing the appropriate trees for the ptr-to-
2018 character-text and length-of-character-text arguments in a calling
86fc7a6c
CB
2019 sequence.
2020
2021 Note that if with_null is TRUE, and the expression is an opCONTER,
2022 a null byte is appended to the string. */
5ff904cd
JL
2023
2024#if FFECOM_targetCURRENT == FFECOM_targetGCC
2025static void
86fc7a6c 2026ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
5ff904cd
JL
2027{
2028 tree item;
2029 tree high;
2030 ffetargetCharacter1 val;
86fc7a6c 2031 ffetargetCharacterSize newlen;
5ff904cd
JL
2032
2033 switch (ffebld_op (expr))
2034 {
2035 case FFEBLD_opCONTER:
2036 val = ffebld_constant_character1 (ffebld_conter (expr));
86fc7a6c
CB
2037 newlen = ffetarget_length_character1 (val);
2038 if (with_null)
2039 {
c7e4ee3a 2040 /* Begin FFETARGET-NULL-KLUDGE. */
86fc7a6c 2041 if (newlen != 0)
c7e4ee3a 2042 ++newlen;
86fc7a6c
CB
2043 }
2044 *length = build_int_2 (newlen, 0);
5ff904cd 2045 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
86fc7a6c 2046 high = build_int_2 (newlen, 0);
5ff904cd 2047 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
c7e4ee3a 2048 item = build_string (newlen,
5ff904cd 2049 ffetarget_text_character1 (val));
c7e4ee3a 2050 /* End FFETARGET-NULL-KLUDGE. */
5ff904cd
JL
2051 TREE_TYPE (item)
2052 = build_type_variant
2053 (build_array_type
2054 (char_type_node,
2055 build_range_type
2056 (ffecom_f2c_ftnlen_type_node,
2057 ffecom_f2c_ftnlen_one_node,
2058 high)),
2059 1, 0);
2060 TREE_CONSTANT (item) = 1;
2061 TREE_STATIC (item) = 1;
2062 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
2063 item);
2064 break;
2065
2066 case FFEBLD_opSYMTER:
2067 {
2068 ffesymbol s = ffebld_symter (expr);
2069
2070 item = ffesymbol_hook (s).decl_tree;
2071 if (item == NULL_TREE)
2072 {
2073 s = ffecom_sym_transform_ (s);
2074 item = ffesymbol_hook (s).decl_tree;
2075 }
2076 if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
2077 {
2078 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
2079 *length = ffesymbol_hook (s).length_tree;
2080 else
2081 {
2082 *length = build_int_2 (ffesymbol_size (s), 0);
2083 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2084 }
2085 }
2086 else if (item == error_mark_node)
2087 *length = error_mark_node;
c7e4ee3a
CB
2088 else
2089 /* FFEINFO_kindFUNCTION. */
5ff904cd
JL
2090 *length = NULL_TREE;
2091 if (!ffesymbol_hook (s).addr
2092 && (item != error_mark_node))
2093 item = ffecom_1 (ADDR_EXPR,
2094 build_pointer_type (TREE_TYPE (item)),
2095 item);
2096 }
2097 break;
2098
2099 case FFEBLD_opARRAYREF:
2100 {
5ff904cd 2101 ffecom_char_args_ (&item, length, ffebld_left (expr));
5ff904cd
JL
2102
2103 if (item == error_mark_node || *length == error_mark_node)
2104 {
2105 item = *length = error_mark_node;
2106 break;
2107 }
2108
6b55276e 2109 item = ffecom_arrayref_ (item, expr, 1);
5ff904cd
JL
2110 }
2111 break;
2112
2113 case FFEBLD_opSUBSTR:
2114 {
2115 ffebld start;
2116 ffebld end;
2117 ffebld thing = ffebld_right (expr);
2118 tree start_tree;
2119 tree end_tree;
6b55276e
CB
2120 char *char_name;
2121 ffebld left_symter;
2122 tree array;
5ff904cd
JL
2123
2124 assert (ffebld_op (thing) == FFEBLD_opITEM);
2125 start = ffebld_head (thing);
2126 thing = ffebld_trail (thing);
2127 assert (ffebld_trail (thing) == NULL);
2128 end = ffebld_head (thing);
2129
6b55276e
CB
2130 /* Determine name for pretty-printing range-check errors. */
2131 for (left_symter = ffebld_left (expr);
2132 left_symter && ffebld_op (left_symter) == FFEBLD_opARRAYREF;
2133 left_symter = ffebld_left (left_symter))
2134 ;
2135 if (ffebld_op (left_symter) == FFEBLD_opSYMTER)
2136 char_name = ffesymbol_text (ffebld_symter (left_symter));
2137 else
2138 char_name = "[expr?]";
2139
5ff904cd 2140 ffecom_char_args_ (&item, length, ffebld_left (expr));
5ff904cd
JL
2141
2142 if (item == error_mark_node || *length == error_mark_node)
2143 {
2144 item = *length = error_mark_node;
2145 break;
2146 }
2147
6b55276e
CB
2148 array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
2149
ff852b44
CB
2150 /* ~~~~Handle INTEGER*8 start/end, a la FFEBLD_opARRAYREF. */
2151
5ff904cd
JL
2152 if (start == NULL)
2153 {
2154 if (end == NULL)
2155 ;
2156 else
2157 {
6b55276e
CB
2158 end_tree = ffecom_expr (end);
2159 if (ffe_is_subscript_check ())
2160 end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
2161 char_name);
5ff904cd 2162 end_tree = convert (ffecom_f2c_ftnlen_type_node,
6b55276e 2163 end_tree);
5ff904cd
JL
2164
2165 if (end_tree == error_mark_node)
2166 {
2167 item = *length = error_mark_node;
2168 break;
2169 }
2170
2171 *length = end_tree;
2172 }
2173 }
2174 else
2175 {
6b55276e
CB
2176 start_tree = ffecom_expr (start);
2177 if (ffe_is_subscript_check ())
2178 start_tree = ffecom_subscript_check_ (array, start_tree, 0, 0,
2179 char_name);
5ff904cd 2180 start_tree = convert (ffecom_f2c_ftnlen_type_node,
6b55276e 2181 start_tree);
5ff904cd
JL
2182
2183 if (start_tree == error_mark_node)
2184 {
2185 item = *length = error_mark_node;
2186 break;
2187 }
2188
2189 start_tree = ffecom_save_tree (start_tree);
2190
2191 item = ffecom_2 (PLUS_EXPR, TREE_TYPE (item),
2192 item,
2193 ffecom_2 (MINUS_EXPR,
2194 TREE_TYPE (start_tree),
2195 start_tree,
2196 ffecom_f2c_ftnlen_one_node));
2197
2198 if (end == NULL)
2199 {
2200 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
2201 ffecom_f2c_ftnlen_one_node,
2202 ffecom_2 (MINUS_EXPR,
2203 ffecom_f2c_ftnlen_type_node,
2204 *length,
2205 start_tree));
2206 }
2207 else
2208 {
6b55276e
CB
2209 end_tree = ffecom_expr (end);
2210 if (ffe_is_subscript_check ())
2211 end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
2212 char_name);
5ff904cd 2213 end_tree = convert (ffecom_f2c_ftnlen_type_node,
6b55276e 2214 end_tree);
5ff904cd
JL
2215
2216 if (end_tree == error_mark_node)
2217 {
2218 item = *length = error_mark_node;
2219 break;
2220 }
2221
2222 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
2223 ffecom_f2c_ftnlen_one_node,
2224 ffecom_2 (MINUS_EXPR,
2225 ffecom_f2c_ftnlen_type_node,
2226 end_tree, start_tree));
2227 }
2228 }
2229 }
2230 break;
2231
2232 case FFEBLD_opFUNCREF:
2233 {
2234 ffesymbol s = ffebld_symter (ffebld_left (expr));
2235 tree tempvar;
2236 tree args;
2237 ffetargetCharacterSize size = ffeinfo_size (ffebld_info (expr));
2238 ffecomGfrt ix;
2239
2240 if (size == FFETARGET_charactersizeNONE)
c7e4ee3a
CB
2241 /* ~~Kludge alert! This should someday be fixed. */
2242 size = 24;
5ff904cd
JL
2243
2244 *length = build_int_2 (size, 0);
2245 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2246
2247 if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
2248 == FFEINFO_whereINTRINSIC)
2249 {
2250 if (size == 1)
c7e4ee3a
CB
2251 {
2252 /* Invocation of an intrinsic returning CHARACTER*1. */
5ff904cd
JL
2253 item = ffecom_expr_intrinsic_ (expr, NULL_TREE,
2254 NULL, NULL);
2255 break;
2256 }
2257 ix = ffeintrin_gfrt_direct (ffebld_symter_implementation (ffebld_left (expr)));
2258 assert (ix != FFECOM_gfrt);
2259 item = ffecom_gfrt_tree_ (ix);
2260 }
2261 else
2262 {
2263 ix = FFECOM_gfrt;
2264 item = ffesymbol_hook (s).decl_tree;
2265 if (item == NULL_TREE)
2266 {
2267 s = ffecom_sym_transform_ (s);
2268 item = ffesymbol_hook (s).decl_tree;
2269 }
2270 if (item == error_mark_node)
2271 {
2272 item = *length = error_mark_node;
2273 break;
2274 }
2275
2276 if (!ffesymbol_hook (s).addr)
2277 item = ffecom_1_fn (item);
2278 }
2279
c7e4ee3a 2280#ifdef HOHO
5ff904cd 2281 tempvar = ffecom_push_tempvar (char_type_node, size, -1, TRUE);
c7e4ee3a
CB
2282#else
2283 tempvar = ffebld_nonter_hook (expr);
2284 assert (tempvar);
2285#endif
5ff904cd
JL
2286 tempvar = ffecom_1 (ADDR_EXPR,
2287 build_pointer_type (TREE_TYPE (tempvar)),
2288 tempvar);
2289
5ff904cd
JL
2290 args = build_tree_list (NULL_TREE, tempvar);
2291
2292 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT) /* Sfunc args by value. */
2293 TREE_CHAIN (args) = ffecom_list_expr (ffebld_right (expr));
2294 else
2295 {
2296 TREE_CHAIN (args) = build_tree_list (NULL_TREE, *length);
2297 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
2298 {
2299 TREE_CHAIN (TREE_CHAIN (args))
2300 = ffecom_arglist_expr_ (ffecom_gfrt_args_ (ix),
2301 ffebld_right (expr));
2302 }
2303 else
2304 {
2305 TREE_CHAIN (TREE_CHAIN (args))
2306 = ffecom_list_ptr_to_expr (ffebld_right (expr));
2307 }
2308 }
2309
2310 item = ffecom_3s (CALL_EXPR,
2311 TREE_TYPE (TREE_TYPE (TREE_TYPE (item))),
2312 item, args, NULL_TREE);
2313 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item,
2314 tempvar);
5ff904cd
JL
2315 }
2316 break;
2317
2318 case FFEBLD_opCONVERT:
2319
5ff904cd 2320 ffecom_char_args_ (&item, length, ffebld_left (expr));
5ff904cd
JL
2321
2322 if (item == error_mark_node || *length == error_mark_node)
2323 {
2324 item = *length = error_mark_node;
2325 break;
2326 }
2327
2328 if ((ffebld_size_known (ffebld_left (expr))
2329 == FFETARGET_charactersizeNONE)
2330 || (ffebld_size_known (ffebld_left (expr)) < (ffebld_size (expr))))
2331 { /* Possible blank-padding needed, copy into
2332 temporary. */
2333 tree tempvar;
2334 tree args;
2335 tree newlen;
2336
c7e4ee3a
CB
2337#ifdef HOHO
2338 tempvar = ffecom_make_tempvar (char_type_node,
2339 ffebld_size (expr), -1);
2340#else
2341 tempvar = ffebld_nonter_hook (expr);
2342 assert (tempvar);
2343#endif
5ff904cd
JL
2344 tempvar = ffecom_1 (ADDR_EXPR,
2345 build_pointer_type (TREE_TYPE (tempvar)),
2346 tempvar);
2347
2348 newlen = build_int_2 (ffebld_size (expr), 0);
2349 TREE_TYPE (newlen) = ffecom_f2c_ftnlen_type_node;
2350
2351 args = build_tree_list (NULL_TREE, tempvar);
2352 TREE_CHAIN (args) = build_tree_list (NULL_TREE, item);
2353 TREE_CHAIN (TREE_CHAIN (args)) = build_tree_list (NULL_TREE, newlen);
2354 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (args)))
2355 = build_tree_list (NULL_TREE, *length);
2356
c7e4ee3a 2357 item = ffecom_call_gfrt (FFECOM_gfrtCOPY, args, NULL_TREE);
5ff904cd
JL
2358 TREE_SIDE_EFFECTS (item) = 1;
2359 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), fold (item),
2360 tempvar);
2361 *length = newlen;
2362 }
2363 else
2364 { /* Just truncate the length. */
2365 *length = build_int_2 (ffebld_size (expr), 0);
2366 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2367 }
2368 break;
2369
2370 default:
2371 assert ("bad op for single char arg expr" == NULL);
2372 item = NULL_TREE;
2373 break;
2374 }
2375
2376 *xitem = item;
2377}
2378#endif
2379
2380/* Check the size of the type to be sure it doesn't overflow the
2381 "portable" capacities of the compiler back end. `dummy' types
2382 can generally overflow the normal sizes as long as the computations
2383 themselves don't overflow. A particular target of the back end
2384 must still enforce its size requirements, though, and the back
2385 end takes care of this in stor-layout.c. */
2386
2387#if FFECOM_targetCURRENT == FFECOM_targetGCC
2388static tree
2389ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy)
2390{
2391 if (TREE_CODE (type) == ERROR_MARK)
2392 return type;
2393
2394 if (TYPE_SIZE (type) == NULL_TREE)
2395 return type;
2396
2397 if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
2398 return type;
2399
2400 if ((tree_int_cst_sgn (TYPE_SIZE (type)) < 0)
2b0c2df0
CB
2401 || (!dummy && (((TREE_INT_CST_HIGH (TYPE_SIZE (type)) != 0))
2402 || TREE_OVERFLOW (TYPE_SIZE (type)))))
5ff904cd
JL
2403 {
2404 ffebad_start (FFEBAD_ARRAY_LARGE);
2405 ffebad_string (ffesymbol_text (s));
2406 ffebad_here (0, ffesymbol_where_line (s), ffesymbol_where_column (s));
2407 ffebad_finish ();
2408
2409 return error_mark_node;
2410 }
2411
2412 return type;
2413}
2414#endif
2415
2416/* Builds a length argument (PARM_DECL). Also wraps type in an array type
2417 where the dimension info is (1:size) where <size> is ffesymbol_size(s) if
2418 known, length_arg if not known (FFETARGET_charactersizeNONE). */
2419
2420#if FFECOM_targetCURRENT == FFECOM_targetGCC
2421static tree
2422ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s)
2423{
2424 ffetargetCharacterSize sz = ffesymbol_size (s);
2425 tree highval;
2426 tree tlen;
2427 tree type = *xtype;
2428
2429 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
2430 tlen = NULL_TREE; /* A statement function, no length passed. */
2431 else
2432 {
2433 if (ffesymbol_where (s) == FFEINFO_whereDUMMY)
2434 tlen = ffecom_get_invented_identifier ("__g77_length_%s",
c7e4ee3a 2435 ffesymbol_text (s), -1);
5ff904cd
JL
2436 else
2437 tlen = ffecom_get_invented_identifier ("__g77_%s",
c7e4ee3a 2438 "length", -1);
5ff904cd
JL
2439 tlen = build_decl (PARM_DECL, tlen, ffecom_f2c_ftnlen_type_node);
2440#if BUILT_FOR_270
2441 DECL_ARTIFICIAL (tlen) = 1;
2442#endif
2443 }
2444
2445 if (sz == FFETARGET_charactersizeNONE)
2446 {
2447 assert (tlen != NULL_TREE);
2b0c2df0 2448 highval = variable_size (tlen);
5ff904cd
JL
2449 }
2450 else
2451 {
2452 highval = build_int_2 (sz, 0);
2453 TREE_TYPE (highval) = ffecom_f2c_ftnlen_type_node;
2454 }
2455
2456 type = build_array_type (type,
2457 build_range_type (ffecom_f2c_ftnlen_type_node,
2458 ffecom_f2c_ftnlen_one_node,
2459 highval));
2460
2461 *xtype = type;
2462 return tlen;
2463}
2464
2465#endif
2466/* ffecom_concat_list_gather_ -- Gather list of concatenated string exprs
2467
2468 ffecomConcatList_ catlist;
2469 ffebld expr; // expr of CHARACTER basictype.
2470 ffetargetCharacterSize max; // max chars to gather or _...NONE if no max
2471 catlist = ffecom_concat_list_gather_(catlist,expr,max);
2472
2473 Scans expr for character subexpressions, updates and returns catlist
2474 accordingly. */
2475
2476#if FFECOM_targetCURRENT == FFECOM_targetGCC
2477static ffecomConcatList_
2478ffecom_concat_list_gather_ (ffecomConcatList_ catlist, ffebld expr,
2479 ffetargetCharacterSize max)
2480{
2481 ffetargetCharacterSize sz;
2482
2483recurse: /* :::::::::::::::::::: */
2484
2485 if (expr == NULL)
2486 return catlist;
2487
2488 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen >= max))
2489 return catlist; /* Don't append any more items. */
2490
2491 switch (ffebld_op (expr))
2492 {
2493 case FFEBLD_opCONTER:
2494 case FFEBLD_opSYMTER:
2495 case FFEBLD_opARRAYREF:
2496 case FFEBLD_opFUNCREF:
2497 case FFEBLD_opSUBSTR:
2498 case FFEBLD_opCONVERT: /* Callers should strip this off beforehand
2499 if they don't need to preserve it. */
2500 if (catlist.count == catlist.max)
2501 { /* Make a (larger) list. */
2502 ffebld *newx;
2503 int newmax;
2504
2505 newmax = (catlist.max == 0) ? 8 : catlist.max * 2;
2506 newx = malloc_new_ks (malloc_pool_image (), "catlist",
2507 newmax * sizeof (newx[0]));
2508 if (catlist.max != 0)
2509 {
2510 memcpy (newx, catlist.exprs, catlist.max * sizeof (newx[0]));
2511 malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2512 catlist.max * sizeof (newx[0]));
2513 }
2514 catlist.max = newmax;
2515 catlist.exprs = newx;
2516 }
2517 if ((sz = ffebld_size_known (expr)) != FFETARGET_charactersizeNONE)
2518 catlist.minlen += sz;
2519 else
2520 ++catlist.minlen; /* Not true for F90; can be 0 length. */
2521 if ((sz = ffebld_size_max (expr)) == FFETARGET_charactersizeNONE)
2522 catlist.maxlen = sz;
2523 else
2524 catlist.maxlen += sz;
2525 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen > max))
2526 { /* This item overlaps (or is beyond) the end
2527 of the destination. */
2528 switch (ffebld_op (expr))
2529 {
2530 case FFEBLD_opCONTER:
2531 case FFEBLD_opSYMTER:
2532 case FFEBLD_opARRAYREF:
2533 case FFEBLD_opFUNCREF:
2534 case FFEBLD_opSUBSTR:
c7e4ee3a
CB
2535 /* ~~Do useful truncations here. */
2536 break;
5ff904cd
JL
2537
2538 default:
2539 assert ("op changed or inconsistent switches!" == NULL);
2540 break;
2541 }
2542 }
2543 catlist.exprs[catlist.count++] = expr;
2544 return catlist;
2545
2546 case FFEBLD_opPAREN:
2547 expr = ffebld_left (expr);
2548 goto recurse; /* :::::::::::::::::::: */
2549
2550 case FFEBLD_opCONCATENATE:
2551 catlist = ffecom_concat_list_gather_ (catlist, ffebld_left (expr), max);
2552 expr = ffebld_right (expr);
2553 goto recurse; /* :::::::::::::::::::: */
2554
2555#if 0 /* Breaks passing small actual arg to larger
2556 dummy arg of sfunc */
2557 case FFEBLD_opCONVERT:
2558 expr = ffebld_left (expr);
2559 {
2560 ffetargetCharacterSize cmax;
2561
2562 cmax = catlist.len + ffebld_size_known (expr);
2563
2564 if ((max == FFETARGET_charactersizeNONE) || (max > cmax))
2565 max = cmax;
2566 }
2567 goto recurse; /* :::::::::::::::::::: */
2568#endif
2569
2570 case FFEBLD_opANY:
2571 return catlist;
2572
2573 default:
2574 assert ("bad op in _gather_" == NULL);
2575 return catlist;
2576 }
2577}
2578
2579#endif
2580/* ffecom_concat_list_kill_ -- Kill list of concatenated string exprs
2581
2582 ffecomConcatList_ catlist;
2583 ffecom_concat_list_kill_(catlist);
2584
2585 Anything allocated within the list info is deallocated. */
2586
2587#if FFECOM_targetCURRENT == FFECOM_targetGCC
2588static void
2589ffecom_concat_list_kill_ (ffecomConcatList_ catlist)
2590{
2591 if (catlist.max != 0)
2592 malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2593 catlist.max * sizeof (catlist.exprs[0]));
2594}
2595
2596#endif
c7e4ee3a 2597/* Make list of concatenated string exprs.
5ff904cd
JL
2598
2599 Returns a flattened list of concatenated subexpressions given a
2600 tree of such expressions. */
2601
2602#if FFECOM_targetCURRENT == FFECOM_targetGCC
2603static ffecomConcatList_
2604ffecom_concat_list_new_ (ffebld expr, ffetargetCharacterSize max)
2605{
2606 ffecomConcatList_ catlist;
2607
2608 catlist.maxlen = catlist.minlen = catlist.max = catlist.count = 0;
2609 return ffecom_concat_list_gather_ (catlist, expr, max);
2610}
2611
2612#endif
2613
2614/* Provide some kind of useful info on member of aggregate area,
2615 since current g77/gcc technology does not provide debug info
2616 on these members. */
2617
2618#if FFECOM_targetCURRENT == FFECOM_targetGCC
2619static void
26f096f9 2620ffecom_debug_kludge_ (tree aggr, const char *aggr_type, ffesymbol member,
5ff904cd
JL
2621 tree member_type UNUSED, ffetargetOffset offset)
2622{
2623 tree value;
2624 tree decl;
2625 int len;
2626 char *buff;
2627 char space[120];
2628#if 0
2629 tree type_id;
2630
2631 for (type_id = member_type;
2632 TREE_CODE (type_id) != IDENTIFIER_NODE;
2633 )
2634 {
2635 switch (TREE_CODE (type_id))
2636 {
2637 case INTEGER_TYPE:
2638 case REAL_TYPE:
2639 type_id = TYPE_NAME (type_id);
2640 break;
2641
2642 case ARRAY_TYPE:
2643 case COMPLEX_TYPE:
2644 type_id = TREE_TYPE (type_id);
2645 break;
2646
2647 default:
2648 assert ("no IDENTIFIER_NODE for type!" == NULL);
2649 type_id = error_mark_node;
2650 break;
2651 }
2652 }
2653#endif
2654
2655 if (ffecom_transform_only_dummies_
2656 || !ffe_is_debug_kludge ())
2657 return; /* Can't do this yet, maybe later. */
2658
2659 len = 60
2660 + strlen (aggr_type)
2661 + IDENTIFIER_LENGTH (DECL_NAME (aggr));
2662#if 0
2663 + IDENTIFIER_LENGTH (type_id);
2664#endif
2665
2666 if (((size_t) len) >= ARRAY_SIZE (space))
2667 buff = malloc_new_ks (malloc_pool_image (), "debug_kludge", len + 1);
2668 else
2669 buff = &space[0];
2670
2671 sprintf (&buff[0], "At (%s) `%s' plus %ld bytes",
2672 aggr_type,
2673 IDENTIFIER_POINTER (DECL_NAME (aggr)),
2674 (long int) offset);
2675
2676 value = build_string (len, buff);
2677 TREE_TYPE (value)
2678 = build_type_variant (build_array_type (char_type_node,
2679 build_range_type
2680 (integer_type_node,
2681 integer_one_node,
2682 build_int_2 (strlen (buff), 0))),
2683 1, 0);
2684 decl = build_decl (VAR_DECL,
2685 ffecom_get_identifier_ (ffesymbol_text (member)),
2686 TREE_TYPE (value));
2687 TREE_CONSTANT (decl) = 1;
2688 TREE_STATIC (decl) = 1;
2689 DECL_INITIAL (decl) = error_mark_node;
2690 DECL_IN_SYSTEM_HEADER (decl) = 1; /* Don't let -Wunused complain. */
2691 decl = start_decl (decl, FALSE);
2692 finish_decl (decl, value, FALSE);
2693
2694 if (buff != &space[0])
2695 malloc_kill_ks (malloc_pool_image (), buff, len + 1);
2696}
2697#endif
2698
2699/* ffecom_do_entry_ -- Do compilation of a particular entrypoint
2700
2701 ffesymbol fn; // the SUBROUTINE, FUNCTION, or ENTRY symbol itself
2702 int i; // entry# for this entrypoint (used by master fn)
2703 ffecom_do_entrypoint_(s,i);
2704
2705 Makes a public entry point that calls our private master fn (already
2706 compiled). */
2707
2708#if FFECOM_targetCURRENT == FFECOM_targetGCC
2709static void
2710ffecom_do_entry_ (ffesymbol fn, int entrynum)
2711{
2712 ffebld item;
2713 tree type; /* Type of function. */
2714 tree multi_retval; /* Var holding return value (union). */
2715 tree result; /* Var holding result. */
2716 ffeinfoBasictype bt;
2717 ffeinfoKindtype kt;
2718 ffeglobal g;
2719 ffeglobalType gt;
2720 bool charfunc; /* All entry points return same type
2721 CHARACTER. */
2722 bool cmplxfunc; /* Use f2c way of returning COMPLEX. */
2723 bool multi; /* Master fn has multiple return types. */
2724 bool altreturning = FALSE; /* This entry point has alternate returns. */
2725 int yes;
44d2eabc
JL
2726 int old_lineno = lineno;
2727 char *old_input_filename = input_filename;
2728
2729 input_filename = ffesymbol_where_filename (fn);
2730 lineno = ffesymbol_where_filelinenum (fn);
5ff904cd
JL
2731
2732 /* c-parse.y indeed does call suspend_momentary and not only ignores the
2733 return value, but also never calls resume_momentary, when starting an
2734 outer function (see "fndef:", "setspecs:", and so on). So g77 does the
2735 same thing. It shouldn't be a problem since start_function calls
2736 temporary_allocation, but it might be necessary. If it causes a problem
2737 here, then maybe there's a bug lurking in gcc. NOTE: This identical
2738 comment appears twice in thist file. */
2739
2740 suspend_momentary ();
2741
2742 ffecom_doing_entry_ = TRUE; /* Don't bother with array dimensions. */
2743
2744 switch (ffecom_primary_entry_kind_)
2745 {
2746 case FFEINFO_kindFUNCTION:
2747
2748 /* Determine actual return type for function. */
2749
2750 gt = FFEGLOBAL_typeFUNC;
2751 bt = ffesymbol_basictype (fn);
2752 kt = ffesymbol_kindtype (fn);
2753 if (bt == FFEINFO_basictypeNONE)
2754 {
2755 ffeimplic_establish_symbol (fn);
2756 if (ffesymbol_funcresult (fn) != NULL)
2757 ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
2758 bt = ffesymbol_basictype (fn);
2759 kt = ffesymbol_kindtype (fn);
2760 }
2761
2762 if (bt == FFEINFO_basictypeCHARACTER)
2763 charfunc = TRUE, cmplxfunc = FALSE;
2764 else if ((bt == FFEINFO_basictypeCOMPLEX)
2765 && ffesymbol_is_f2c (fn))
2766 charfunc = FALSE, cmplxfunc = TRUE;
2767 else
2768 charfunc = cmplxfunc = FALSE;
2769
2770 if (charfunc)
2771 type = ffecom_tree_fun_type_void;
2772 else if (ffesymbol_is_f2c (fn))
2773 type = ffecom_tree_fun_type[bt][kt];
2774 else
2775 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
2776
2777 if ((type == NULL_TREE)
2778 || (TREE_TYPE (type) == NULL_TREE))
2779 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */
2780
2781 multi = (ffecom_master_bt_ == FFEINFO_basictypeNONE);
2782 break;
2783
2784 case FFEINFO_kindSUBROUTINE:
2785 gt = FFEGLOBAL_typeSUBR;
2786 bt = FFEINFO_basictypeNONE;
2787 kt = FFEINFO_kindtypeNONE;
2788 if (ffecom_is_altreturning_)
2789 { /* Am _I_ altreturning? */
2790 for (item = ffesymbol_dummyargs (fn);
2791 item != NULL;
2792 item = ffebld_trail (item))
2793 {
2794 if (ffebld_op (ffebld_head (item)) == FFEBLD_opSTAR)
2795 {
2796 altreturning = TRUE;
2797 break;
2798 }
2799 }
2800 if (altreturning)
2801 type = ffecom_tree_subr_type;
2802 else
2803 type = ffecom_tree_fun_type_void;
2804 }
2805 else
2806 type = ffecom_tree_fun_type_void;
2807 charfunc = FALSE;
2808 cmplxfunc = FALSE;
2809 multi = FALSE;
2810 break;
2811
2812 default:
2813 assert ("say what??" == NULL);
2814 /* Fall through. */
2815 case FFEINFO_kindANY:
2816 gt = FFEGLOBAL_typeANY;
2817 bt = FFEINFO_basictypeNONE;
2818 kt = FFEINFO_kindtypeNONE;
2819 type = error_mark_node;
2820 charfunc = FALSE;
2821 cmplxfunc = FALSE;
2822 multi = FALSE;
2823 break;
2824 }
2825
2826 /* build_decl uses the current lineno and input_filename to set the decl
2827 source info. So, I've putzed with ffestd and ffeste code to update that
2828 source info to point to the appropriate statement just before calling
2829 ffecom_do_entrypoint (which calls this fn). */
2830
2831 start_function (ffecom_get_external_identifier_ (fn),
2832 type,
2833 0, /* nested/inline */
2834 1); /* TREE_PUBLIC */
2835
2836 if (((g = ffesymbol_global (fn)) != NULL)
2837 && ((ffeglobal_type (g) == gt)
2838 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
2839 {
2840 ffeglobal_set_hook (g, current_function_decl);
2841 }
2842
2843 /* Reset args in master arg list so they get retransitioned. */
2844
2845 for (item = ffecom_master_arglist_;
2846 item != NULL;
2847 item = ffebld_trail (item))
2848 {
2849 ffebld arg;
2850 ffesymbol s;
2851
2852 arg = ffebld_head (item);
2853 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2854 continue; /* Alternate return or some such thing. */
2855 s = ffebld_symter (arg);
2856 ffesymbol_hook (s).decl_tree = NULL_TREE;
2857 ffesymbol_hook (s).length_tree = NULL_TREE;
2858 }
2859
2860 /* Build dummy arg list for this entry point. */
2861
2862 yes = suspend_momentary ();
2863
2864 if (charfunc || cmplxfunc)
2865 { /* Prepend arg for where result goes. */
2866 tree type;
2867 tree length;
2868
2869 if (charfunc)
2870 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
2871 else
2872 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
2873
2874 result = ffecom_get_invented_identifier ("__g77_%s",
c7e4ee3a 2875 "result", -1);
5ff904cd
JL
2876
2877 /* Make length arg _and_ enhance type info for CHAR arg itself. */
2878
2879 if (charfunc)
2880 length = ffecom_char_enhance_arg_ (&type, fn);
2881 else
2882 length = NULL_TREE; /* Not ref'd if !charfunc. */
2883
2884 type = build_pointer_type (type);
2885 result = build_decl (PARM_DECL, result, type);
2886
2887 push_parm_decl (result);
2888 ffecom_func_result_ = result;
2889
2890 if (charfunc)
2891 {
2892 push_parm_decl (length);
2893 ffecom_func_length_ = length;
2894 }
2895 }
2896 else
2897 result = DECL_RESULT (current_function_decl);
2898
2899 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (fn), FALSE);
2900
2901 resume_momentary (yes);
2902
2903 store_parm_decls (0);
2904
c7e4ee3a
CB
2905 ffecom_start_compstmt ();
2906 /* Disallow temp vars at this level. */
2907 current_binding_level->prep_state = 2;
5ff904cd
JL
2908
2909 /* Make local var to hold return type for multi-type master fn. */
2910
2911 if (multi)
2912 {
2913 yes = suspend_momentary ();
2914
2915 multi_retval = ffecom_get_invented_identifier ("__g77_%s",
c7e4ee3a 2916 "multi_retval", -1);
5ff904cd
JL
2917 multi_retval = build_decl (VAR_DECL, multi_retval,
2918 ffecom_multi_type_node_);
2919 multi_retval = start_decl (multi_retval, FALSE);
2920 finish_decl (multi_retval, NULL_TREE, FALSE);
2921
2922 resume_momentary (yes);
2923 }
2924 else
2925 multi_retval = NULL_TREE; /* Not actually ref'd if !multi. */
2926
2927 /* Here we emit the actual code for the entry point. */
2928
2929 {
2930 ffebld list;
2931 ffebld arg;
2932 ffesymbol s;
2933 tree arglist = NULL_TREE;
2934 tree *plist = &arglist;
2935 tree prepend;
2936 tree call;
2937 tree actarg;
2938 tree master_fn;
2939
2940 /* Prepare actual arg list based on master arg list. */
2941
2942 for (list = ffecom_master_arglist_;
2943 list != NULL;
2944 list = ffebld_trail (list))
2945 {
2946 arg = ffebld_head (list);
2947 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2948 continue;
2949 s = ffebld_symter (arg);
702edf1d
CB
2950 if (ffesymbol_hook (s).decl_tree == NULL_TREE
2951 || ffesymbol_hook (s).decl_tree == error_mark_node)
5ff904cd
JL
2952 actarg = null_pointer_node; /* We don't have this arg. */
2953 else
2954 actarg = ffesymbol_hook (s).decl_tree;
2955 *plist = build_tree_list (NULL_TREE, actarg);
2956 plist = &TREE_CHAIN (*plist);
2957 }
2958
2959 /* This code appends the length arguments for character
2960 variables/arrays. */
2961
2962 for (list = ffecom_master_arglist_;
2963 list != NULL;
2964 list = ffebld_trail (list))
2965 {
2966 arg = ffebld_head (list);
2967 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2968 continue;
2969 s = ffebld_symter (arg);
2970 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
2971 continue; /* Only looking for CHARACTER arguments. */
2972 if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
2973 continue; /* Only looking for variables and arrays. */
702edf1d
CB
2974 if (ffesymbol_hook (s).length_tree == NULL_TREE
2975 || ffesymbol_hook (s).length_tree == error_mark_node)
5ff904cd
JL
2976 actarg = ffecom_f2c_ftnlen_zero_node; /* We don't have this arg. */
2977 else
2978 actarg = ffesymbol_hook (s).length_tree;
2979 *plist = build_tree_list (NULL_TREE, actarg);
2980 plist = &TREE_CHAIN (*plist);
2981 }
2982
2983 /* Prepend character-value return info to actual arg list. */
2984
2985 if (charfunc)
2986 {
2987 prepend = build_tree_list (NULL_TREE, ffecom_func_result_);
2988 TREE_CHAIN (prepend)
2989 = build_tree_list (NULL_TREE, ffecom_func_length_);
2990 TREE_CHAIN (TREE_CHAIN (prepend)) = arglist;
2991 arglist = prepend;
2992 }
2993
2994 /* Prepend multi-type return value to actual arg list. */
2995
2996 if (multi)
2997 {
2998 prepend
2999 = build_tree_list (NULL_TREE,
3000 ffecom_1 (ADDR_EXPR,
3001 build_pointer_type (TREE_TYPE (multi_retval)),
3002 multi_retval));
3003 TREE_CHAIN (prepend) = arglist;
3004 arglist = prepend;
3005 }
3006
3007 /* Prepend my entry-point number to the actual arg list. */
3008
3009 prepend = build_tree_list (NULL_TREE, build_int_2 (entrynum, 0));
3010 TREE_CHAIN (prepend) = arglist;
3011 arglist = prepend;
3012
3013 /* Build the call to the master function. */
3014
3015 master_fn = ffecom_1_fn (ffecom_previous_function_decl_);
3016 call = ffecom_3s (CALL_EXPR,
3017 TREE_TYPE (TREE_TYPE (TREE_TYPE (master_fn))),
3018 master_fn, arglist, NULL_TREE);
3019
3020 /* Decide whether the master function is a function or subroutine, and
3021 handle the return value for my entry point. */
3022
3023 if (charfunc || ((ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
3024 && !altreturning))
3025 {
3026 expand_expr_stmt (call);
3027 expand_null_return ();
3028 }
3029 else if (multi && cmplxfunc)
3030 {
3031 expand_expr_stmt (call);
3032 result
3033 = ffecom_1 (INDIRECT_REF,
3034 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
3035 result);
3036 result = ffecom_modify (NULL_TREE, result,
3037 ffecom_2 (COMPONENT_REF, TREE_TYPE (result),
3038 multi_retval,
3039 ffecom_multi_fields_[bt][kt]));
3040 expand_expr_stmt (result);
3041 expand_null_return ();
3042 }
3043 else if (multi)
3044 {
3045 expand_expr_stmt (call);
3046 result
3047 = ffecom_modify (NULL_TREE, result,
3048 convert (TREE_TYPE (result),
3049 ffecom_2 (COMPONENT_REF,
3050 ffecom_tree_type[bt][kt],
3051 multi_retval,
3052 ffecom_multi_fields_[bt][kt])));
3053 expand_return (result);
3054 }
3055 else if (cmplxfunc)
3056 {
3057 result
3058 = ffecom_1 (INDIRECT_REF,
3059 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
3060 result);
3061 result = ffecom_modify (NULL_TREE, result, call);
3062 expand_expr_stmt (result);
3063 expand_null_return ();
3064 }
3065 else
3066 {
3067 result = ffecom_modify (NULL_TREE,
3068 result,
3069 convert (TREE_TYPE (result),
3070 call));
3071 expand_return (result);
3072 }
3073
3074 clear_momentary ();
3075 }
3076
c7e4ee3a 3077 ffecom_end_compstmt ();
5ff904cd
JL
3078
3079 finish_function (0);
3080
44d2eabc
JL
3081 lineno = old_lineno;
3082 input_filename = old_input_filename;
3083
5ff904cd
JL
3084 ffecom_doing_entry_ = FALSE;
3085}
3086
3087#endif
3088/* Transform expr into gcc tree with possible destination
3089
3090 Recursive descent on expr while making corresponding tree nodes and
3091 attaching type info and such. If destination supplied and compatible
3092 with temporary that would be made in certain cases, temporary isn't
092a4ef8 3093 made, destination used instead, and dest_used flag set TRUE. */
5ff904cd
JL
3094
3095#if FFECOM_targetCURRENT == FFECOM_targetGCC
3096static tree
092a4ef8
RH
3097ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
3098 bool *dest_used, bool assignp, bool widenp)
5ff904cd
JL
3099{
3100 tree item;
3101 tree list;
3102 tree args;
3103 ffeinfoBasictype bt;
3104 ffeinfoKindtype kt;
3105 tree t;
5ff904cd 3106 tree dt; /* decl_tree for an ffesymbol. */
092a4ef8 3107 tree tree_type, tree_type_x;
af752698 3108 tree left, right;
5ff904cd
JL
3109 ffesymbol s;
3110 enum tree_code code;
3111
3112 assert (expr != NULL);
3113
3114 if (dest_used != NULL)
3115 *dest_used = FALSE;
3116
3117 bt = ffeinfo_basictype (ffebld_info (expr));
3118 kt = ffeinfo_kindtype (ffebld_info (expr));
af752698 3119 tree_type = ffecom_tree_type[bt][kt];
5ff904cd 3120
092a4ef8
RH
3121 /* Widen integral arithmetic as desired while preserving signedness. */
3122 tree_type_x = NULL_TREE;
3123 if (widenp && tree_type
3124 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
3125 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
3126 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
3127
5ff904cd
JL
3128 switch (ffebld_op (expr))
3129 {
3130 case FFEBLD_opACCTER:
5ff904cd
JL
3131 {
3132 ffebitCount i;
3133 ffebit bits = ffebld_accter_bits (expr);
3134 ffetargetOffset source_offset = 0;
a6fa6420 3135 ffetargetOffset dest_offset = ffebld_accter_pad (expr);
5ff904cd
JL
3136 tree purpose;
3137
a6fa6420
CB
3138 assert (dest_offset == 0
3139 || (bt == FFEINFO_basictypeCHARACTER
3140 && kt == FFEINFO_kindtypeCHARACTER1));
5ff904cd
JL
3141
3142 list = item = NULL;
3143 for (;;)
3144 {
3145 ffebldConstantUnion cu;
3146 ffebitCount length;
3147 bool value;
3148 ffebldConstantArray ca = ffebld_accter (expr);
3149
3150 ffebit_test (bits, source_offset, &value, &length);
3151 if (length == 0)
3152 break;
3153
3154 if (value)
3155 {
3156 for (i = 0; i < length; ++i)
3157 {
3158 cu = ffebld_constantarray_get (ca, bt, kt,
3159 source_offset + i);
3160
3161 t = ffecom_constantunion (&cu, bt, kt, tree_type);
3162
a6fa6420
CB
3163 if (i == 0
3164 && dest_offset != 0)
3165 purpose = build_int_2 (dest_offset, 0);
5ff904cd
JL
3166 else
3167 purpose = NULL_TREE;
3168
3169 if (list == NULL_TREE)
3170 list = item = build_tree_list (purpose, t);
3171 else
3172 {
3173 TREE_CHAIN (item) = build_tree_list (purpose, t);
3174 item = TREE_CHAIN (item);
3175 }
3176 }
3177 }
3178 source_offset += length;
a6fa6420 3179 dest_offset += length;
5ff904cd
JL
3180 }
3181 }
3182
a6fa6420
CB
3183 item = build_int_2 ((ffebld_accter_size (expr)
3184 + ffebld_accter_pad (expr)) - 1, 0);
5ff904cd
JL
3185 ffebit_kill (ffebld_accter_bits (expr));
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,
3191 ffecom_integer_zero_node,
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_opARRTER:
5ff904cd
JL
3199 {
3200 ffetargetOffset i;
3201
a6fa6420
CB
3202 list = NULL_TREE;
3203 if (ffebld_arrter_pad (expr) == 0)
3204 item = NULL_TREE;
3205 else
3206 {
3207 assert (bt == FFEINFO_basictypeCHARACTER
3208 && kt == FFEINFO_kindtypeCHARACTER1);
3209
3210 /* Becomes PURPOSE first time through loop. */
3211 item = build_int_2 (ffebld_arrter_pad (expr), 0);
3212 }
3213
5ff904cd
JL
3214 for (i = 0; i < ffebld_arrter_size (expr); ++i)
3215 {
3216 ffebldConstantUnion cu
3217 = ffebld_constantarray_get (ffebld_arrter (expr), bt, kt, i);
3218
3219 t = ffecom_constantunion (&cu, bt, kt, tree_type);
3220
3221 if (list == NULL_TREE)
a6fa6420
CB
3222 /* Assume item is PURPOSE first time through loop. */
3223 list = item = build_tree_list (item, t);
5ff904cd
JL
3224 else
3225 {
3226 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
3227 item = TREE_CHAIN (item);
3228 }
3229 }
3230 }
3231
a6fa6420
CB
3232 item = build_int_2 ((ffebld_arrter_size (expr)
3233 + ffebld_arrter_pad (expr)) - 1, 0);
5ff904cd
JL
3234 TREE_TYPE (item) = ffecom_integer_type_node;
3235 item
3236 = build_array_type
3237 (tree_type,
3238 build_range_type (ffecom_integer_type_node,
a6fa6420 3239 ffecom_integer_zero_node,
5ff904cd
JL
3240 item));
3241 list = build (CONSTRUCTOR, item, NULL_TREE, list);
3242 TREE_CONSTANT (list) = 1;
3243 TREE_STATIC (list) = 1;
3244 return list;
3245
3246 case FFEBLD_opCONTER:
c264f113 3247 assert (ffebld_conter_pad (expr) == 0);
5ff904cd
JL
3248 item
3249 = ffecom_constantunion (&ffebld_constant_union (ffebld_conter (expr)),
3250 bt, kt, tree_type);
3251 return item;
3252
3253 case FFEBLD_opSYMTER:
3254 if ((ffebld_symter_generic (expr) != FFEINTRIN_genNONE)
3255 || (ffebld_symter_specific (expr) != FFEINTRIN_specNONE))
3256 return ffecom_ptr_to_expr (expr); /* Same as %REF(intrinsic). */
3257 s = ffebld_symter (expr);
3258 t = ffesymbol_hook (s).decl_tree;
3259
3260 if (assignp)
3261 { /* ASSIGN'ed-label expr. */
3262 if (ffe_is_ugly_assign ())
3263 {
3264 /* User explicitly wants ASSIGN'ed variables to be at the same
3265 memory address as the variables when used in non-ASSIGN
3266 contexts. That can make old, arcane, non-standard code
3267 work, but don't try to do it when a pointer wouldn't fit
3268 in the normal variable (take other approach, and warn,
3269 instead). */
3270
3271 if (t == NULL_TREE)
3272 {
3273 s = ffecom_sym_transform_ (s);
3274 t = ffesymbol_hook (s).decl_tree;
3275 assert (t != NULL_TREE);
3276 }
3277
3278 if (t == error_mark_node)
3279 return t;
3280
3281 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (t)))
3282 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
3283 {
3284 if (ffesymbol_hook (s).addr)
3285 t = ffecom_1 (INDIRECT_REF,
3286 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
3287 return t;
3288 }
3289
3290 if (ffesymbol_hook (s).assign_tree == NULL_TREE)
3291 {
3292 ffebad_start_msg ("ASSIGN'ed label cannot fit into `%A' at %0 -- using wider sibling",
3293 FFEBAD_severityWARNING);
3294 ffebad_string (ffesymbol_text (s));
3295 ffebad_here (0, ffesymbol_where_line (s),
3296 ffesymbol_where_column (s));
3297 ffebad_finish ();
3298 }
3299 }
3300
3301 /* Don't use the normal variable's tree for ASSIGN, though mark
3302 it as in the system header (housekeeping). Use an explicit,
3303 specially created sibling that is known to be wide enough
3304 to hold pointers to labels. */
3305
3306 if (t != NULL_TREE
3307 && TREE_CODE (t) == VAR_DECL)
3308 DECL_IN_SYSTEM_HEADER (t) = 1; /* Don't let -Wunused complain. */
3309
3310 t = ffesymbol_hook (s).assign_tree;
3311 if (t == NULL_TREE)
3312 {
3313 s = ffecom_sym_transform_assign_ (s);
3314 t = ffesymbol_hook (s).assign_tree;
3315 assert (t != NULL_TREE);
3316 }
3317 }
3318 else
3319 {
3320 if (t == NULL_TREE)
3321 {
3322 s = ffecom_sym_transform_ (s);
3323 t = ffesymbol_hook (s).decl_tree;
3324 assert (t != NULL_TREE);
3325 }
3326 if (ffesymbol_hook (s).addr)
3327 t = ffecom_1 (INDIRECT_REF,
3328 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
3329 }
3330 return t;
3331
3332 case FFEBLD_opARRAYREF:
ff852b44 3333 return ffecom_arrayref_ (NULL_TREE, expr, 0);
5ff904cd
JL
3334
3335 case FFEBLD_opUPLUS:
092a4ef8 3336 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
af752698 3337 return ffecom_1 (NOP_EXPR, tree_type, left);
5ff904cd 3338
c7e4ee3a
CB
3339 case FFEBLD_opPAREN:
3340 /* ~~~Make sure Fortran rules respected here */
092a4ef8 3341 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
af752698 3342 return ffecom_1 (NOP_EXPR, tree_type, left);
5ff904cd
JL
3343
3344 case FFEBLD_opUMINUS:
092a4ef8 3345 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3346 if (tree_type_x)
3347 {
3348 tree_type = tree_type_x;
3349 left = convert (tree_type, left);
3350 }
3351 return ffecom_1 (NEGATE_EXPR, tree_type, left);
5ff904cd
JL
3352
3353 case FFEBLD_opADD:
092a4ef8
RH
3354 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3355 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3356 if (tree_type_x)
3357 {
3358 tree_type = tree_type_x;
3359 left = convert (tree_type, left);
3360 right = convert (tree_type, right);
3361 }
3362 return ffecom_2 (PLUS_EXPR, tree_type, left, right);
5ff904cd
JL
3363
3364 case FFEBLD_opSUBTRACT:
092a4ef8
RH
3365 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3366 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3367 if (tree_type_x)
3368 {
3369 tree_type = tree_type_x;
3370 left = convert (tree_type, left);
3371 right = convert (tree_type, right);
3372 }
3373 return ffecom_2 (MINUS_EXPR, tree_type, left, right);
5ff904cd
JL
3374
3375 case FFEBLD_opMULTIPLY:
092a4ef8
RH
3376 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3377 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3378 if (tree_type_x)
3379 {
3380 tree_type = tree_type_x;
3381 left = convert (tree_type, left);
3382 right = convert (tree_type, right);
3383 }
3384 return ffecom_2 (MULT_EXPR, tree_type, left, right);
5ff904cd
JL
3385
3386 case FFEBLD_opDIVIDE:
092a4ef8
RH
3387 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3388 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3389 if (tree_type_x)
3390 {
3391 tree_type = tree_type_x;
3392 left = convert (tree_type, left);
3393 right = convert (tree_type, right);
3394 }
3395 return ffecom_tree_divide_ (tree_type, left, right,
c7e4ee3a
CB
3396 dest_tree, dest, dest_used,
3397 ffebld_nonter_hook (expr));
5ff904cd
JL
3398
3399 case FFEBLD_opPOWER:
5ff904cd
JL
3400 {
3401 ffebld left = ffebld_left (expr);
3402 ffebld right = ffebld_right (expr);
3403 ffecomGfrt code;
3404 ffeinfoKindtype rtkt;
270fc4e8 3405 ffeinfoKindtype ltkt;
5ff904cd
JL
3406
3407 switch (ffeinfo_basictype (ffebld_info (right)))
3408 {
3409 case FFEINFO_basictypeINTEGER:
3410 if (1 || optimize)
3411 {
c7e4ee3a 3412 item = ffecom_expr_power_integer_ (expr);
5ff904cd
JL
3413 if (item != NULL_TREE)
3414 return item;
3415 }
3416
3417 rtkt = FFEINFO_kindtypeINTEGER1;
3418 switch (ffeinfo_basictype (ffebld_info (left)))
3419 {
3420 case FFEINFO_basictypeINTEGER:
3421 if ((ffeinfo_kindtype (ffebld_info (left))
3422 == FFEINFO_kindtypeINTEGER4)
3423 || (ffeinfo_kindtype (ffebld_info (right))
3424 == FFEINFO_kindtypeINTEGER4))
3425 {
3426 code = FFECOM_gfrtPOW_QQ;
270fc4e8 3427 ltkt = FFEINFO_kindtypeINTEGER4;
5ff904cd
JL
3428 rtkt = FFEINFO_kindtypeINTEGER4;
3429 }
3430 else
6a047254
CB
3431 {
3432 code = FFECOM_gfrtPOW_II;
3433 ltkt = FFEINFO_kindtypeINTEGER1;
3434 }
5ff904cd
JL
3435 break;
3436
3437 case FFEINFO_basictypeREAL:
3438 if (ffeinfo_kindtype (ffebld_info (left))
3439 == FFEINFO_kindtypeREAL1)
6a047254
CB
3440 {
3441 code = FFECOM_gfrtPOW_RI;
3442 ltkt = FFEINFO_kindtypeREAL1;
3443 }
5ff904cd 3444 else
6a047254
CB
3445 {
3446 code = FFECOM_gfrtPOW_DI;
3447 ltkt = FFEINFO_kindtypeREAL2;
3448 }
5ff904cd
JL
3449 break;
3450
3451 case FFEINFO_basictypeCOMPLEX:
3452 if (ffeinfo_kindtype (ffebld_info (left))
3453 == FFEINFO_kindtypeREAL1)
6a047254
CB
3454 {
3455 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */
3456 ltkt = FFEINFO_kindtypeREAL1;
3457 }
5ff904cd 3458 else
6a047254
CB
3459 {
3460 code = FFECOM_gfrtPOW_ZI; /* Overlapping result okay. */
3461 ltkt = FFEINFO_kindtypeREAL2;
3462 }
5ff904cd
JL
3463 break;
3464
3465 default:
3466 assert ("bad pow_*i" == NULL);
3467 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */
6a047254 3468 ltkt = FFEINFO_kindtypeREAL1;
5ff904cd
JL
3469 break;
3470 }
270fc4e8 3471 if (ffeinfo_kindtype (ffebld_info (left)) != ltkt)
5ff904cd 3472 left = ffeexpr_convert (left, NULL, NULL,
6a047254 3473 ffeinfo_basictype (ffebld_info (left)),
270fc4e8 3474 ltkt, 0,
5ff904cd
JL
3475 FFETARGET_charactersizeNONE,
3476 FFEEXPR_contextLET);
3477 if (ffeinfo_kindtype (ffebld_info (right)) != rtkt)
3478 right = ffeexpr_convert (right, NULL, NULL,
3479 FFEINFO_basictypeINTEGER,
3480 rtkt, 0,
3481 FFETARGET_charactersizeNONE,
3482 FFEEXPR_contextLET);
3483 break;
3484
3485 case FFEINFO_basictypeREAL:
3486 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3487 left = ffeexpr_convert (left, NULL, NULL, FFEINFO_basictypeREAL,
3488 FFEINFO_kindtypeREALDOUBLE, 0,
3489 FFETARGET_charactersizeNONE,
3490 FFEEXPR_contextLET);
3491 if (ffeinfo_kindtype (ffebld_info (right))
3492 == FFEINFO_kindtypeREAL1)
3493 right = ffeexpr_convert (right, NULL, NULL,
3494 FFEINFO_basictypeREAL,
3495 FFEINFO_kindtypeREALDOUBLE, 0,
3496 FFETARGET_charactersizeNONE,
3497 FFEEXPR_contextLET);
3498 code = FFECOM_gfrtPOW_DD;
3499 break;
3500
3501 case FFEINFO_basictypeCOMPLEX:
3502 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3503 left = ffeexpr_convert (left, NULL, NULL,
3504 FFEINFO_basictypeCOMPLEX,
3505 FFEINFO_kindtypeREALDOUBLE, 0,
3506 FFETARGET_charactersizeNONE,
3507 FFEEXPR_contextLET);
3508 if (ffeinfo_kindtype (ffebld_info (right))
3509 == FFEINFO_kindtypeREAL1)
3510 right = ffeexpr_convert (right, NULL, NULL,
3511 FFEINFO_basictypeCOMPLEX,
3512 FFEINFO_kindtypeREALDOUBLE, 0,
3513 FFETARGET_charactersizeNONE,
3514 FFEEXPR_contextLET);
3515 code = FFECOM_gfrtPOW_ZZ; /* Overlapping result okay. */
3516 break;
3517
3518 default:
3519 assert ("bad pow_x*" == NULL);
3520 code = FFECOM_gfrtPOW_II;
3521 break;
3522 }
3523 return ffecom_call_binop_ (ffecom_gfrt_tree_ (code),
3524 ffecom_gfrt_kindtype (code),
3525 (ffe_is_f2c_library ()
3526 && ffecom_gfrt_complex_[code]),
3527 tree_type, left, right,
3528 dest_tree, dest, dest_used,
c7e4ee3a
CB
3529 NULL_TREE, FALSE,
3530 ffebld_nonter_hook (expr));
5ff904cd
JL
3531 }
3532
3533 case FFEBLD_opNOT:
5ff904cd
JL
3534 switch (bt)
3535 {
3536 case FFEINFO_basictypeLOGICAL:
83ffecd2 3537 item = ffecom_truth_value_invert (ffecom_expr (ffebld_left (expr)));
5ff904cd
JL
3538 return convert (tree_type, item);
3539
3540 case FFEINFO_basictypeINTEGER:
3541 return ffecom_1 (BIT_NOT_EXPR, tree_type,
3542 ffecom_expr (ffebld_left (expr)));
3543
3544 default:
3545 assert ("NOT bad basictype" == NULL);
3546 /* Fall through. */
3547 case FFEINFO_basictypeANY:
3548 return error_mark_node;
3549 }
3550 break;
3551
3552 case FFEBLD_opFUNCREF:
3553 assert (ffeinfo_basictype (ffebld_info (expr))
3554 != FFEINFO_basictypeCHARACTER);
3555 /* Fall through. */
3556 case FFEBLD_opSUBRREF:
5ff904cd
JL
3557 if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
3558 == FFEINFO_whereINTRINSIC)
3559 { /* Invocation of an intrinsic. */
3560 item = ffecom_expr_intrinsic_ (expr, dest_tree, dest,
3561 dest_used);
3562 return item;
3563 }
3564 s = ffebld_symter (ffebld_left (expr));
3565 dt = ffesymbol_hook (s).decl_tree;
3566 if (dt == NULL_TREE)
3567 {
3568 s = ffecom_sym_transform_ (s);
3569 dt = ffesymbol_hook (s).decl_tree;
3570 }
3571 if (dt == error_mark_node)
3572 return dt;
3573
3574 if (ffesymbol_hook (s).addr)
3575 item = dt;
3576 else
3577 item = ffecom_1_fn (dt);
3578
5ff904cd
JL
3579 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
3580 args = ffecom_list_expr (ffebld_right (expr));
3581 else
3582 args = ffecom_list_ptr_to_expr (ffebld_right (expr));
5ff904cd 3583
702edf1d
CB
3584 if (args == error_mark_node)
3585 return error_mark_node;
3586
5ff904cd
JL
3587 item = ffecom_call_ (item, kt,
3588 ffesymbol_is_f2c (s)
3589 && (bt == FFEINFO_basictypeCOMPLEX)
3590 && (ffesymbol_where (s)
3591 != FFEINFO_whereCONSTANT),
3592 tree_type,
3593 args,
3594 dest_tree, dest, dest_used,
c7e4ee3a
CB
3595 error_mark_node, FALSE,
3596 ffebld_nonter_hook (expr));
5ff904cd
JL
3597 TREE_SIDE_EFFECTS (item) = 1;
3598 return item;
3599
3600 case FFEBLD_opAND:
5ff904cd
JL
3601 switch (bt)
3602 {
3603 case FFEINFO_basictypeLOGICAL:
3604 item
3605 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3606 ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3607 ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3608 return convert (tree_type, item);
3609
3610 case FFEINFO_basictypeINTEGER:
3611 return ffecom_2 (BIT_AND_EXPR, tree_type,
3612 ffecom_expr (ffebld_left (expr)),
3613 ffecom_expr (ffebld_right (expr)));
3614
3615 default:
3616 assert ("AND bad basictype" == NULL);
3617 /* Fall through. */
3618 case FFEINFO_basictypeANY:
3619 return error_mark_node;
3620 }
3621 break;
3622
3623 case FFEBLD_opOR:
5ff904cd
JL
3624 switch (bt)
3625 {
3626 case FFEINFO_basictypeLOGICAL:
3627 item
3628 = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
3629 ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3630 ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3631 return convert (tree_type, item);
3632
3633 case FFEINFO_basictypeINTEGER:
3634 return ffecom_2 (BIT_IOR_EXPR, tree_type,
3635 ffecom_expr (ffebld_left (expr)),
3636 ffecom_expr (ffebld_right (expr)));
3637
3638 default:
3639 assert ("OR bad basictype" == NULL);
3640 /* Fall through. */
3641 case FFEINFO_basictypeANY:
3642 return error_mark_node;
3643 }
3644 break;
3645
3646 case FFEBLD_opXOR:
3647 case FFEBLD_opNEQV:
5ff904cd
JL
3648 switch (bt)
3649 {
3650 case FFEINFO_basictypeLOGICAL:
3651 item
3652 = ffecom_2 (NE_EXPR, integer_type_node,
3653 ffecom_expr (ffebld_left (expr)),
3654 ffecom_expr (ffebld_right (expr)));
3655 return convert (tree_type, ffecom_truth_value (item));
3656
3657 case FFEINFO_basictypeINTEGER:
3658 return ffecom_2 (BIT_XOR_EXPR, tree_type,
3659 ffecom_expr (ffebld_left (expr)),
3660 ffecom_expr (ffebld_right (expr)));
3661
3662 default:
3663 assert ("XOR/NEQV bad basictype" == NULL);
3664 /* Fall through. */
3665 case FFEINFO_basictypeANY:
3666 return error_mark_node;
3667 }
3668 break;
3669
3670 case FFEBLD_opEQV:
5ff904cd
JL
3671 switch (bt)
3672 {
3673 case FFEINFO_basictypeLOGICAL:
3674 item
3675 = ffecom_2 (EQ_EXPR, integer_type_node,
3676 ffecom_expr (ffebld_left (expr)),
3677 ffecom_expr (ffebld_right (expr)));
3678 return convert (tree_type, ffecom_truth_value (item));
3679
3680 case FFEINFO_basictypeINTEGER:
3681 return
3682 ffecom_1 (BIT_NOT_EXPR, tree_type,
3683 ffecom_2 (BIT_XOR_EXPR, tree_type,
3684 ffecom_expr (ffebld_left (expr)),
3685 ffecom_expr (ffebld_right (expr))));
3686
3687 default:
3688 assert ("EQV bad basictype" == NULL);
3689 /* Fall through. */
3690 case FFEINFO_basictypeANY:
3691 return error_mark_node;
3692 }
3693 break;
3694
3695 case FFEBLD_opCONVERT:
3696 if (ffebld_op (ffebld_left (expr)) == FFEBLD_opANY)
3697 return error_mark_node;
3698
5ff904cd
JL
3699 switch (bt)
3700 {
3701 case FFEINFO_basictypeLOGICAL:
3702 case FFEINFO_basictypeINTEGER:
3703 case FFEINFO_basictypeREAL:
3704 return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3705
3706 case FFEINFO_basictypeCOMPLEX:
3707 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3708 {
3709 case FFEINFO_basictypeINTEGER:
3710 case FFEINFO_basictypeLOGICAL:
3711 case FFEINFO_basictypeREAL:
3712 item = ffecom_expr (ffebld_left (expr));
3713 if (item == error_mark_node)
3714 return error_mark_node;
3715 /* convert() takes care of converting to the subtype first,
3716 at least in gcc-2.7.2. */
3717 item = convert (tree_type, item);
3718 return item;
3719
3720 case FFEINFO_basictypeCOMPLEX:
3721 return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3722
3723 default:
3724 assert ("CONVERT COMPLEX bad basictype" == NULL);
3725 /* Fall through. */
3726 case FFEINFO_basictypeANY:
3727 return error_mark_node;
3728 }
3729 break;
3730
3731 default:
3732 assert ("CONVERT bad basictype" == NULL);
3733 /* Fall through. */
3734 case FFEINFO_basictypeANY:
3735 return error_mark_node;
3736 }
3737 break;
3738
3739 case FFEBLD_opLT:
3740 code = LT_EXPR;
3741 goto relational; /* :::::::::::::::::::: */
3742
3743 case FFEBLD_opLE:
3744 code = LE_EXPR;
3745 goto relational; /* :::::::::::::::::::: */
3746
3747 case FFEBLD_opEQ:
3748 code = EQ_EXPR;
3749 goto relational; /* :::::::::::::::::::: */
3750
3751 case FFEBLD_opNE:
3752 code = NE_EXPR;
3753 goto relational; /* :::::::::::::::::::: */
3754
3755 case FFEBLD_opGT:
3756 code = GT_EXPR;
3757 goto relational; /* :::::::::::::::::::: */
3758
3759 case FFEBLD_opGE:
3760 code = GE_EXPR;
3761
3762 relational: /* :::::::::::::::::::: */
5ff904cd
JL
3763 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3764 {
3765 case FFEINFO_basictypeLOGICAL:
3766 case FFEINFO_basictypeINTEGER:
3767 case FFEINFO_basictypeREAL:
3768 item = ffecom_2 (code, integer_type_node,
3769 ffecom_expr (ffebld_left (expr)),
3770 ffecom_expr (ffebld_right (expr)));
3771 return convert (tree_type, item);
3772
3773 case FFEINFO_basictypeCOMPLEX:
3774 assert (code == EQ_EXPR || code == NE_EXPR);
3775 {
3776 tree real_type;
3777 tree arg1 = ffecom_expr (ffebld_left (expr));
3778 tree arg2 = ffecom_expr (ffebld_right (expr));
3779
3780 if (arg1 == error_mark_node || arg2 == error_mark_node)
3781 return error_mark_node;
3782
3783 arg1 = ffecom_save_tree (arg1);
3784 arg2 = ffecom_save_tree (arg2);
3785
3786 if (TREE_CODE (TREE_TYPE (arg1)) == COMPLEX_TYPE)
3787 {
3788 real_type = TREE_TYPE (TREE_TYPE (arg1));
3789 assert (real_type == TREE_TYPE (TREE_TYPE (arg2)));
3790 }
3791 else
3792 {
3793 real_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg1)));
3794 assert (real_type == TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg2))));
3795 }
3796
3797 item
3798 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3799 ffecom_2 (EQ_EXPR, integer_type_node,
3800 ffecom_1 (REALPART_EXPR, real_type, arg1),
3801 ffecom_1 (REALPART_EXPR, real_type, arg2)),
3802 ffecom_2 (EQ_EXPR, integer_type_node,
3803 ffecom_1 (IMAGPART_EXPR, real_type, arg1),
3804 ffecom_1 (IMAGPART_EXPR, real_type,
3805 arg2)));
3806 if (code == EQ_EXPR)
3807 item = ffecom_truth_value (item);
3808 else
3809 item = ffecom_truth_value_invert (item);
3810 return convert (tree_type, item);
3811 }
3812
3813 case FFEINFO_basictypeCHARACTER:
5ff904cd
JL
3814 {
3815 ffebld left = ffebld_left (expr);
3816 ffebld right = ffebld_right (expr);
3817 tree left_tree;
3818 tree right_tree;
3819 tree left_length;
3820 tree right_length;
3821
3822 /* f2c run-time functions do the implicit blank-padding for us,
3823 so we don't usually have to implement blank-padding ourselves.
3824 (The exception is when we pass an argument to a separately
3825 compiled statement function -- if we know the arg is not the
3826 same length as the dummy, we must truncate or extend it. If
3827 we "inline" statement functions, that necessity goes away as
3828 well.)
3829
3830 Strip off the CONVERT operators that blank-pad. (Truncation by
3831 CONVERT shouldn't happen here, but it can happen in
3832 assignments.) */
3833
3834 while (ffebld_op (left) == FFEBLD_opCONVERT)
3835 left = ffebld_left (left);
3836 while (ffebld_op (right) == FFEBLD_opCONVERT)
3837 right = ffebld_left (right);
3838
3839 left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
3840 right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
3841
3842 if (left_tree == error_mark_node || left_length == error_mark_node
3843 || right_tree == error_mark_node
3844 || right_length == error_mark_node)
c7e4ee3a 3845 return error_mark_node;
5ff904cd
JL
3846
3847 if ((ffebld_size_known (left) == 1)
3848 && (ffebld_size_known (right) == 1))
3849 {
3850 left_tree
3851 = ffecom_1 (INDIRECT_REF,
3852 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3853 left_tree);
3854 right_tree
3855 = ffecom_1 (INDIRECT_REF,
3856 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3857 right_tree);
3858
3859 item
3860 = ffecom_2 (code, integer_type_node,
3861 ffecom_2 (ARRAY_REF,
3862 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3863 left_tree,
3864 integer_one_node),
3865 ffecom_2 (ARRAY_REF,
3866 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3867 right_tree,
3868 integer_one_node));
3869 }
3870 else
3871 {
3872 item = build_tree_list (NULL_TREE, left_tree);
3873 TREE_CHAIN (item) = build_tree_list (NULL_TREE, right_tree);
3874 TREE_CHAIN (TREE_CHAIN (item)) = build_tree_list (NULL_TREE,
3875 left_length);
3876 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
3877 = build_tree_list (NULL_TREE, right_length);
c7e4ee3a 3878 item = ffecom_call_gfrt (FFECOM_gfrtCMP, item, NULL_TREE);
5ff904cd
JL
3879 item = ffecom_2 (code, integer_type_node,
3880 item,
3881 convert (TREE_TYPE (item),
3882 integer_zero_node));
3883 }
3884 item = convert (tree_type, item);
3885 }
3886
5ff904cd
JL
3887 return item;
3888
3889 default:
3890 assert ("relational bad basictype" == NULL);
3891 /* Fall through. */
3892 case FFEINFO_basictypeANY:
3893 return error_mark_node;
3894 }
3895 break;
3896
3897 case FFEBLD_opPERCENT_LOC:
5ff904cd
JL
3898 item = ffecom_arg_ptr_to_expr (ffebld_left (expr), &list);
3899 return convert (tree_type, item);
3900
3901 case FFEBLD_opITEM:
3902 case FFEBLD_opSTAR:
3903 case FFEBLD_opBOUNDS:
3904 case FFEBLD_opREPEAT:
3905 case FFEBLD_opLABTER:
3906 case FFEBLD_opLABTOK:
3907 case FFEBLD_opIMPDO:
3908 case FFEBLD_opCONCATENATE:
3909 case FFEBLD_opSUBSTR:
3910 default:
3911 assert ("bad op" == NULL);
3912 /* Fall through. */
3913 case FFEBLD_opANY:
3914 return error_mark_node;
3915 }
3916
3917#if 1
3918 assert ("didn't think anything got here anymore!!" == NULL);
3919#else
3920 switch (ffebld_arity (expr))
3921 {
3922 case 2:
3923 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3924 TREE_OPERAND (item, 1) = ffecom_expr (ffebld_right (expr));
3925 if (TREE_OPERAND (item, 0) == error_mark_node
3926 || TREE_OPERAND (item, 1) == error_mark_node)
3927 return error_mark_node;
3928 break;
3929
3930 case 1:
3931 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3932 if (TREE_OPERAND (item, 0) == error_mark_node)
3933 return error_mark_node;
3934 break;
3935
3936 default:
3937 break;
3938 }
3939
3940 return fold (item);
3941#endif
3942}
3943
3944#endif
3945/* Returns the tree that does the intrinsic invocation.
3946
3947 Note: this function applies only to intrinsics returning
3948 CHARACTER*1 or non-CHARACTER results, and to intrinsic
3949 subroutines. */
3950
3951#if FFECOM_targetCURRENT == FFECOM_targetGCC
3952static tree
3953ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
3954 ffebld dest, bool *dest_used)
3955{
3956 tree expr_tree;
3957 tree saved_expr1; /* For those who need it. */
3958 tree saved_expr2; /* For those who need it. */
3959 ffeinfoBasictype bt;
3960 ffeinfoKindtype kt;
3961 tree tree_type;
3962 tree arg1_type;
3963 tree real_type; /* REAL type corresponding to COMPLEX. */
3964 tree tempvar;
3965 ffebld list = ffebld_right (expr); /* List of (some) args. */
3966 ffebld arg1; /* For handy reference. */
3967 ffebld arg2;
3968 ffebld arg3;
3969 ffeintrinImp codegen_imp;
3970 ffecomGfrt gfrt;
3971
3972 assert (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER);
3973
3974 if (dest_used != NULL)
3975 *dest_used = FALSE;
3976
3977 bt = ffeinfo_basictype (ffebld_info (expr));
3978 kt = ffeinfo_kindtype (ffebld_info (expr));
3979 tree_type = ffecom_tree_type[bt][kt];
3980
3981 if (list != NULL)
3982 {
3983 arg1 = ffebld_head (list);
3984 if (arg1 != NULL && ffebld_op (arg1) == FFEBLD_opANY)
3985 return error_mark_node;
3986 if ((list = ffebld_trail (list)) != NULL)
3987 {
3988 arg2 = ffebld_head (list);
3989 if (arg2 != NULL && ffebld_op (arg2) == FFEBLD_opANY)
3990 return error_mark_node;
3991 if ((list = ffebld_trail (list)) != NULL)
3992 {
3993 arg3 = ffebld_head (list);
3994 if (arg3 != NULL && ffebld_op (arg3) == FFEBLD_opANY)
3995 return error_mark_node;
3996 }
3997 else
3998 arg3 = NULL;
3999 }
4000 else
4001 arg2 = arg3 = NULL;
4002 }
4003 else
4004 arg1 = arg2 = arg3 = NULL;
4005
4006 /* <list> ends up at the opITEM of the 3rd arg, or NULL if there are < 3
4007 args. This is used by the MAX/MIN expansions. */
4008
4009 if (arg1 != NULL)
4010 arg1_type = ffecom_tree_type
4011 [ffeinfo_basictype (ffebld_info (arg1))]
4012 [ffeinfo_kindtype (ffebld_info (arg1))];
4013 else
4014 arg1_type = NULL_TREE; /* Really not needed, but might catch bugs
4015 here. */
4016
4017 /* There are several ways for each of the cases in the following switch
4018 statements to exit (from simplest to use to most complicated):
4019
4020 break; (when expr_tree == NULL)
4021
4022 A standard call is made to the specific intrinsic just as if it had been
4023 passed in as a dummy procedure and called as any old procedure. This
4024 method can produce slower code but in some cases it's the easiest way for
4025 now. However, if a (presumably faster) direct call is available,
4026 that is used, so this is the easiest way in many more cases now.
4027
4028 gfrt = FFECOM_gfrtWHATEVER;
4029 break;
4030
4031 gfrt contains the gfrt index of a library function to call, passing the
4032 argument(s) by value rather than by reference. Used when a more
4033 careful choice of library function is needed than that provided
4034 by the vanilla `break;'.
4035
4036 return expr_tree;
4037
4038 The expr_tree has been completely set up and is ready to be returned
4039 as is. No further actions are taken. Use this when the tree is not
4040 in the simple form for one of the arity_n labels. */
4041
4042 /* For info on how the switch statement cases were written, see the files
4043 enclosed in comments below the switch statement. */
4044
4045 codegen_imp = ffebld_symter_implementation (ffebld_left (expr));
4046 gfrt = ffeintrin_gfrt_direct (codegen_imp);
4047 if (gfrt == FFECOM_gfrt)
4048 gfrt = ffeintrin_gfrt_indirect (codegen_imp);
4049
4050 switch (codegen_imp)
4051 {
4052 case FFEINTRIN_impABS:
4053 case FFEINTRIN_impCABS:
4054 case FFEINTRIN_impCDABS:
4055 case FFEINTRIN_impDABS:
4056 case FFEINTRIN_impIABS:
4057 if (ffeinfo_basictype (ffebld_info (arg1))
4058 == FFEINFO_basictypeCOMPLEX)
4059 {
4060 if (kt == FFEINFO_kindtypeREAL1)
4061 gfrt = FFECOM_gfrtCABS;
4062 else if (kt == FFEINFO_kindtypeREAL2)
4063 gfrt = FFECOM_gfrtCDABS;
4064 break;
4065 }
4066 return ffecom_1 (ABS_EXPR, tree_type,
4067 convert (tree_type, ffecom_expr (arg1)));
4068
4069 case FFEINTRIN_impACOS:
4070 case FFEINTRIN_impDACOS:
4071 break;
4072
4073 case FFEINTRIN_impAIMAG:
4074 case FFEINTRIN_impDIMAG:
4075 case FFEINTRIN_impIMAGPART:
4076 if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
4077 arg1_type = TREE_TYPE (arg1_type);
4078 else
4079 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
4080
4081 return
4082 convert (tree_type,
4083 ffecom_1 (IMAGPART_EXPR, arg1_type,
4084 ffecom_expr (arg1)));
4085
4086 case FFEINTRIN_impAINT:
4087 case FFEINTRIN_impDINT:
c7e4ee3a
CB
4088#if 0
4089 /* ~~Someday implement FIX_TRUNC_EXPR yielding same type as arg. */
5ff904cd
JL
4090 return ffecom_1 (FIX_TRUNC_EXPR, tree_type, ffecom_expr (arg1));
4091#else /* in the meantime, must use floor to avoid range problems with ints */
4092 /* r__1 = r1 >= 0 ? floor(r1) : -floor(-r1); */
4093 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4094 return
4095 convert (tree_type,
4096 ffecom_3 (COND_EXPR, double_type_node,
4097 ffecom_truth_value
4098 (ffecom_2 (GE_EXPR, integer_type_node,
4099 saved_expr1,
4100 convert (arg1_type,
4101 ffecom_float_zero_))),
4102 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4103 build_tree_list (NULL_TREE,
4104 convert (double_type_node,
c7e4ee3a
CB
4105 saved_expr1)),
4106 NULL_TREE),
5ff904cd
JL
4107 ffecom_1 (NEGATE_EXPR, double_type_node,
4108 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4109 build_tree_list (NULL_TREE,
4110 convert (double_type_node,
4111 ffecom_1 (NEGATE_EXPR,
4112 arg1_type,
c7e4ee3a
CB
4113 saved_expr1))),
4114 NULL_TREE)
5ff904cd
JL
4115 ))
4116 );
4117#endif
4118
4119 case FFEINTRIN_impANINT:
4120 case FFEINTRIN_impDNINT:
4121#if 0 /* This way of doing it won't handle real
4122 numbers of large magnitudes. */
4123 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4124 expr_tree = convert (tree_type,
4125 convert (integer_type_node,
4126 ffecom_3 (COND_EXPR, tree_type,
4127 ffecom_truth_value
4128 (ffecom_2 (GE_EXPR,
4129 integer_type_node,
4130 saved_expr1,
4131 ffecom_float_zero_)),
4132 ffecom_2 (PLUS_EXPR,
4133 tree_type,
4134 saved_expr1,
4135 ffecom_float_half_),
4136 ffecom_2 (MINUS_EXPR,
4137 tree_type,
4138 saved_expr1,
4139 ffecom_float_half_))));
4140 return expr_tree;
4141#else /* So we instead call floor. */
4142 /* r__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1) */
4143 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4144 return
4145 convert (tree_type,
4146 ffecom_3 (COND_EXPR, double_type_node,
4147 ffecom_truth_value
4148 (ffecom_2 (GE_EXPR, integer_type_node,
4149 saved_expr1,
4150 convert (arg1_type,
4151 ffecom_float_zero_))),
4152 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4153 build_tree_list (NULL_TREE,
4154 convert (double_type_node,
4155 ffecom_2 (PLUS_EXPR,
4156 arg1_type,
4157 saved_expr1,
4158 convert (arg1_type,
c7e4ee3a
CB
4159 ffecom_float_half_)))),
4160 NULL_TREE),
5ff904cd
JL
4161 ffecom_1 (NEGATE_EXPR, double_type_node,
4162 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4163 build_tree_list (NULL_TREE,
4164 convert (double_type_node,
4165 ffecom_2 (MINUS_EXPR,
4166 arg1_type,
4167 convert (arg1_type,
4168 ffecom_float_half_),
c7e4ee3a
CB
4169 saved_expr1))),
4170 NULL_TREE))
5ff904cd
JL
4171 )
4172 );
4173#endif
4174
4175 case FFEINTRIN_impASIN:
4176 case FFEINTRIN_impDASIN:
4177 case FFEINTRIN_impATAN:
4178 case FFEINTRIN_impDATAN:
4179 case FFEINTRIN_impATAN2:
4180 case FFEINTRIN_impDATAN2:
4181 break;
4182
4183 case FFEINTRIN_impCHAR:
4184 case FFEINTRIN_impACHAR:
c7e4ee3a
CB
4185#ifdef HOHO
4186 tempvar = ffecom_make_tempvar (char_type_node, 1, -1);
4187#else
4188 tempvar = ffebld_nonter_hook (expr);
4189 assert (tempvar);
4190#endif
5ff904cd
JL
4191 {
4192 tree tmv = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (tempvar)));
4193
4194 expr_tree = ffecom_modify (tmv,
4195 ffecom_2 (ARRAY_REF, tmv, tempvar,
4196 integer_one_node),
4197 convert (tmv, ffecom_expr (arg1)));
4198 }
4199 expr_tree = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar),
4200 expr_tree,
4201 tempvar);
4202 expr_tree = ffecom_1 (ADDR_EXPR,
4203 build_pointer_type (TREE_TYPE (expr_tree)),
4204 expr_tree);
4205 return expr_tree;
4206
4207 case FFEINTRIN_impCMPLX:
4208 case FFEINTRIN_impDCMPLX:
4209 if (arg2 == NULL)
4210 return
4211 convert (tree_type, ffecom_expr (arg1));
4212
4213 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
4214 return
4215 ffecom_2 (COMPLEX_EXPR, tree_type,
4216 convert (real_type, ffecom_expr (arg1)),
4217 convert (real_type,
4218 ffecom_expr (arg2)));
4219
4220 case FFEINTRIN_impCOMPLEX:
4221 return
4222 ffecom_2 (COMPLEX_EXPR, tree_type,
4223 ffecom_expr (arg1),
4224 ffecom_expr (arg2));
4225
4226 case FFEINTRIN_impCONJG:
4227 case FFEINTRIN_impDCONJG:
4228 {
4229 tree arg1_tree;
4230
4231 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
4232 arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4233 return
4234 ffecom_2 (COMPLEX_EXPR, tree_type,
4235 ffecom_1 (REALPART_EXPR, real_type, arg1_tree),
4236 ffecom_1 (NEGATE_EXPR, real_type,
4237 ffecom_1 (IMAGPART_EXPR, real_type, arg1_tree)));
4238 }
4239
4240 case FFEINTRIN_impCOS:
4241 case FFEINTRIN_impCCOS:
4242 case FFEINTRIN_impCDCOS:
4243 case FFEINTRIN_impDCOS:
4244 if (bt == FFEINFO_basictypeCOMPLEX)
4245 {
4246 if (kt == FFEINFO_kindtypeREAL1)
4247 gfrt = FFECOM_gfrtCCOS; /* Overlapping result okay. */
4248 else if (kt == FFEINFO_kindtypeREAL2)
4249 gfrt = FFECOM_gfrtCDCOS; /* Overlapping result okay. */
4250 }
4251 break;
4252
4253 case FFEINTRIN_impCOSH:
4254 case FFEINTRIN_impDCOSH:
4255 break;
4256
4257 case FFEINTRIN_impDBLE:
4258 case FFEINTRIN_impDFLOAT:
4259 case FFEINTRIN_impDREAL:
4260 case FFEINTRIN_impFLOAT:
4261 case FFEINTRIN_impIDINT:
4262 case FFEINTRIN_impIFIX:
4263 case FFEINTRIN_impINT2:
4264 case FFEINTRIN_impINT8:
4265 case FFEINTRIN_impINT:
4266 case FFEINTRIN_impLONG:
4267 case FFEINTRIN_impREAL:
4268 case FFEINTRIN_impSHORT:
4269 case FFEINTRIN_impSNGL:
4270 return convert (tree_type, ffecom_expr (arg1));
4271
4272 case FFEINTRIN_impDIM:
4273 case FFEINTRIN_impDDIM:
4274 case FFEINTRIN_impIDIM:
4275 saved_expr1 = ffecom_save_tree (convert (tree_type,
4276 ffecom_expr (arg1)));
4277 saved_expr2 = ffecom_save_tree (convert (tree_type,
4278 ffecom_expr (arg2)));
4279 return
4280 ffecom_3 (COND_EXPR, tree_type,
4281 ffecom_truth_value
4282 (ffecom_2 (GT_EXPR, integer_type_node,
4283 saved_expr1,
4284 saved_expr2)),
4285 ffecom_2 (MINUS_EXPR, tree_type,
4286 saved_expr1,
4287 saved_expr2),
4288 convert (tree_type, ffecom_float_zero_));
4289
4290 case FFEINTRIN_impDPROD:
4291 return
4292 ffecom_2 (MULT_EXPR, tree_type,
4293 convert (tree_type, ffecom_expr (arg1)),
4294 convert (tree_type, ffecom_expr (arg2)));
4295
4296 case FFEINTRIN_impEXP:
4297 case FFEINTRIN_impCDEXP:
4298 case FFEINTRIN_impCEXP:
4299 case FFEINTRIN_impDEXP:
4300 if (bt == FFEINFO_basictypeCOMPLEX)
4301 {
4302 if (kt == FFEINFO_kindtypeREAL1)
4303 gfrt = FFECOM_gfrtCEXP; /* Overlapping result okay. */
4304 else if (kt == FFEINFO_kindtypeREAL2)
4305 gfrt = FFECOM_gfrtCDEXP; /* Overlapping result okay. */
4306 }
4307 break;
4308
4309 case FFEINTRIN_impICHAR:
4310 case FFEINTRIN_impIACHAR:
4311#if 0 /* The simple approach. */
4312 ffecom_char_args_ (&expr_tree, &saved_expr1 /* Ignored */ , arg1);
4313 expr_tree
4314 = ffecom_1 (INDIRECT_REF,
4315 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
4316 expr_tree);
4317 expr_tree
4318 = ffecom_2 (ARRAY_REF,
4319 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
4320 expr_tree,
4321 integer_one_node);
4322 return convert (tree_type, expr_tree);
4323#else /* The more interesting (and more optimal) approach. */
4324 expr_tree = ffecom_intrinsic_ichar_ (tree_type, arg1, &saved_expr1);
4325 expr_tree = ffecom_3 (COND_EXPR, tree_type,
4326 saved_expr1,
4327 expr_tree,
4328 convert (tree_type, integer_zero_node));
4329 return expr_tree;
4330#endif
4331
4332 case FFEINTRIN_impINDEX:
4333 break;
4334
4335 case FFEINTRIN_impLEN:
4336#if 0
4337 break; /* The simple approach. */
4338#else
4339 return ffecom_intrinsic_len_ (arg1); /* The more optimal approach. */
4340#endif
4341
4342 case FFEINTRIN_impLGE:
4343 case FFEINTRIN_impLGT:
4344 case FFEINTRIN_impLLE:
4345 case FFEINTRIN_impLLT:
4346 break;
4347
4348 case FFEINTRIN_impLOG:
4349 case FFEINTRIN_impALOG:
4350 case FFEINTRIN_impCDLOG:
4351 case FFEINTRIN_impCLOG:
4352 case FFEINTRIN_impDLOG:
4353 if (bt == FFEINFO_basictypeCOMPLEX)
4354 {
4355 if (kt == FFEINFO_kindtypeREAL1)
4356 gfrt = FFECOM_gfrtCLOG; /* Overlapping result okay. */
4357 else if (kt == FFEINFO_kindtypeREAL2)
4358 gfrt = FFECOM_gfrtCDLOG; /* Overlapping result okay. */
4359 }
4360 break;
4361
4362 case FFEINTRIN_impLOG10:
4363 case FFEINTRIN_impALOG10:
4364 case FFEINTRIN_impDLOG10:
4365 if (gfrt != FFECOM_gfrt)
4366 break; /* Already picked one, stick with it. */
4367
4368 if (kt == FFEINFO_kindtypeREAL1)
4369 gfrt = FFECOM_gfrtALOG10;
4370 else if (kt == FFEINFO_kindtypeREAL2)
4371 gfrt = FFECOM_gfrtDLOG10;
4372 break;
4373
4374 case FFEINTRIN_impMAX:
4375 case FFEINTRIN_impAMAX0:
4376 case FFEINTRIN_impAMAX1:
4377 case FFEINTRIN_impDMAX1:
4378 case FFEINTRIN_impMAX0:
4379 case FFEINTRIN_impMAX1:
4380 if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4381 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4382 else
4383 arg1_type = tree_type;
4384 expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4385 convert (arg1_type, ffecom_expr (arg1)),
4386 convert (arg1_type, ffecom_expr (arg2)));
4387 for (; list != NULL; list = ffebld_trail (list))
4388 {
4389 if ((ffebld_head (list) == NULL)
4390 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4391 continue;
4392 expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4393 expr_tree,
4394 convert (arg1_type,
4395 ffecom_expr (ffebld_head (list))));
4396 }
4397 return convert (tree_type, expr_tree);
4398
4399 case FFEINTRIN_impMIN:
4400 case FFEINTRIN_impAMIN0:
4401 case FFEINTRIN_impAMIN1:
4402 case FFEINTRIN_impDMIN1:
4403 case FFEINTRIN_impMIN0:
4404 case FFEINTRIN_impMIN1:
4405 if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4406 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4407 else
4408 arg1_type = tree_type;
4409 expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4410 convert (arg1_type, ffecom_expr (arg1)),
4411 convert (arg1_type, ffecom_expr (arg2)));
4412 for (; list != NULL; list = ffebld_trail (list))
4413 {
4414 if ((ffebld_head (list) == NULL)
4415 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4416 continue;
4417 expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4418 expr_tree,
4419 convert (arg1_type,
4420 ffecom_expr (ffebld_head (list))));
4421 }
4422 return convert (tree_type, expr_tree);
4423
4424 case FFEINTRIN_impMOD:
4425 case FFEINTRIN_impAMOD:
4426 case FFEINTRIN_impDMOD:
4427 if (bt != FFEINFO_basictypeREAL)
4428 return ffecom_2 (TRUNC_MOD_EXPR, tree_type,
4429 convert (tree_type, ffecom_expr (arg1)),
4430 convert (tree_type, ffecom_expr (arg2)));
4431
4432 if (kt == FFEINFO_kindtypeREAL1)
4433 gfrt = FFECOM_gfrtAMOD;
4434 else if (kt == FFEINFO_kindtypeREAL2)
4435 gfrt = FFECOM_gfrtDMOD;
4436 break;
4437
4438 case FFEINTRIN_impNINT:
4439 case FFEINTRIN_impIDNINT:
c7e4ee3a
CB
4440#if 0
4441 /* ~~Ideally FIX_ROUND_EXPR would be implemented, but it ain't yet. */
5ff904cd
JL
4442 return ffecom_1 (FIX_ROUND_EXPR, tree_type, ffecom_expr (arg1));
4443#else
4444 /* i__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1); */
4445 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4446 return
4447 convert (ffecom_integer_type_node,
4448 ffecom_3 (COND_EXPR, arg1_type,
4449 ffecom_truth_value
4450 (ffecom_2 (GE_EXPR, integer_type_node,
4451 saved_expr1,
4452 convert (arg1_type,
4453 ffecom_float_zero_))),
4454 ffecom_2 (PLUS_EXPR, arg1_type,
4455 saved_expr1,
4456 convert (arg1_type,
4457 ffecom_float_half_)),
4458 ffecom_2 (MINUS_EXPR, arg1_type,
4459 saved_expr1,
4460 convert (arg1_type,
4461 ffecom_float_half_))));
4462#endif
4463
4464 case FFEINTRIN_impSIGN:
4465 case FFEINTRIN_impDSIGN:
4466 case FFEINTRIN_impISIGN:
4467 {
4468 tree arg2_tree = ffecom_expr (arg2);
4469
4470 saved_expr1
4471 = ffecom_save_tree
4472 (ffecom_1 (ABS_EXPR, tree_type,
4473 convert (tree_type,
4474 ffecom_expr (arg1))));
4475 expr_tree
4476 = ffecom_3 (COND_EXPR, tree_type,
4477 ffecom_truth_value
4478 (ffecom_2 (GE_EXPR, integer_type_node,
4479 arg2_tree,
4480 convert (TREE_TYPE (arg2_tree),
4481 integer_zero_node))),
4482 saved_expr1,
4483 ffecom_1 (NEGATE_EXPR, tree_type, saved_expr1));
4484 /* Make sure SAVE_EXPRs get referenced early enough. */
4485 expr_tree
4486 = ffecom_2 (COMPOUND_EXPR, tree_type,
4487 convert (void_type_node, saved_expr1),
4488 expr_tree);
4489 }
4490 return expr_tree;
4491
4492 case FFEINTRIN_impSIN:
4493 case FFEINTRIN_impCDSIN:
4494 case FFEINTRIN_impCSIN:
4495 case FFEINTRIN_impDSIN:
4496 if (bt == FFEINFO_basictypeCOMPLEX)
4497 {
4498 if (kt == FFEINFO_kindtypeREAL1)
4499 gfrt = FFECOM_gfrtCSIN; /* Overlapping result okay. */
4500 else if (kt == FFEINFO_kindtypeREAL2)
4501 gfrt = FFECOM_gfrtCDSIN; /* Overlapping result okay. */
4502 }
4503 break;
4504
4505 case FFEINTRIN_impSINH:
4506 case FFEINTRIN_impDSINH:
4507 break;
4508
4509 case FFEINTRIN_impSQRT:
4510 case FFEINTRIN_impCDSQRT:
4511 case FFEINTRIN_impCSQRT:
4512 case FFEINTRIN_impDSQRT:
4513 if (bt == FFEINFO_basictypeCOMPLEX)
4514 {
4515 if (kt == FFEINFO_kindtypeREAL1)
4516 gfrt = FFECOM_gfrtCSQRT; /* Overlapping result okay. */
4517 else if (kt == FFEINFO_kindtypeREAL2)
4518 gfrt = FFECOM_gfrtCDSQRT; /* Overlapping result okay. */
4519 }
4520 break;
4521
4522 case FFEINTRIN_impTAN:
4523 case FFEINTRIN_impDTAN:
4524 case FFEINTRIN_impTANH:
4525 case FFEINTRIN_impDTANH:
4526 break;
4527
4528 case FFEINTRIN_impREALPART:
4529 if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
4530 arg1_type = TREE_TYPE (arg1_type);
4531 else
4532 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
4533
4534 return
4535 convert (tree_type,
4536 ffecom_1 (REALPART_EXPR, arg1_type,
4537 ffecom_expr (arg1)));
4538
4539 case FFEINTRIN_impIAND:
4540 case FFEINTRIN_impAND:
4541 return ffecom_2 (BIT_AND_EXPR, tree_type,
4542 convert (tree_type,
4543 ffecom_expr (arg1)),
4544 convert (tree_type,
4545 ffecom_expr (arg2)));
4546
4547 case FFEINTRIN_impIOR:
4548 case FFEINTRIN_impOR:
4549 return ffecom_2 (BIT_IOR_EXPR, tree_type,
4550 convert (tree_type,
4551 ffecom_expr (arg1)),
4552 convert (tree_type,
4553 ffecom_expr (arg2)));
4554
4555 case FFEINTRIN_impIEOR:
4556 case FFEINTRIN_impXOR:
4557 return ffecom_2 (BIT_XOR_EXPR, tree_type,
4558 convert (tree_type,
4559 ffecom_expr (arg1)),
4560 convert (tree_type,
4561 ffecom_expr (arg2)));
4562
4563 case FFEINTRIN_impLSHIFT:
4564 return ffecom_2 (LSHIFT_EXPR, tree_type,
4565 ffecom_expr (arg1),
4566 convert (integer_type_node,
4567 ffecom_expr (arg2)));
4568
4569 case FFEINTRIN_impRSHIFT:
4570 return ffecom_2 (RSHIFT_EXPR, tree_type,
4571 ffecom_expr (arg1),
4572 convert (integer_type_node,
4573 ffecom_expr (arg2)));
4574
4575 case FFEINTRIN_impNOT:
4576 return ffecom_1 (BIT_NOT_EXPR, tree_type, ffecom_expr (arg1));
4577
4578 case FFEINTRIN_impBIT_SIZE:
4579 return convert (tree_type, TYPE_SIZE (arg1_type));
4580
4581 case FFEINTRIN_impBTEST:
4582 {
4583 ffetargetLogical1 true;
4584 ffetargetLogical1 false;
4585 tree true_tree;
4586 tree false_tree;
4587
4588 ffetarget_logical1 (&true, TRUE);
4589 ffetarget_logical1 (&false, FALSE);
4590 if (true == 1)
4591 true_tree = convert (tree_type, integer_one_node);
4592 else
4593 true_tree = convert (tree_type, build_int_2 (true, 0));
4594 if (false == 0)
4595 false_tree = convert (tree_type, integer_zero_node);
4596 else
4597 false_tree = convert (tree_type, build_int_2 (false, 0));
4598
4599 return
4600 ffecom_3 (COND_EXPR, tree_type,
4601 ffecom_truth_value
4602 (ffecom_2 (EQ_EXPR, integer_type_node,
4603 ffecom_2 (BIT_AND_EXPR, arg1_type,
4604 ffecom_expr (arg1),
4605 ffecom_2 (LSHIFT_EXPR, arg1_type,
4606 convert (arg1_type,
4607 integer_one_node),
4608 convert (integer_type_node,
4609 ffecom_expr (arg2)))),
4610 convert (arg1_type,
4611 integer_zero_node))),
4612 false_tree,
4613 true_tree);
4614 }
4615
4616 case FFEINTRIN_impIBCLR:
4617 return
4618 ffecom_2 (BIT_AND_EXPR, tree_type,
4619 ffecom_expr (arg1),
4620 ffecom_1 (BIT_NOT_EXPR, tree_type,
4621 ffecom_2 (LSHIFT_EXPR, tree_type,
4622 convert (tree_type,
4623 integer_one_node),
4624 convert (integer_type_node,
4625 ffecom_expr (arg2)))));
4626
4627 case FFEINTRIN_impIBITS:
4628 {
4629 tree arg3_tree = ffecom_save_tree (convert (integer_type_node,
4630 ffecom_expr (arg3)));
4631 tree uns_type
4632 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4633
4634 expr_tree
4635 = ffecom_2 (BIT_AND_EXPR, tree_type,
4636 ffecom_2 (RSHIFT_EXPR, tree_type,
4637 ffecom_expr (arg1),
4638 convert (integer_type_node,
4639 ffecom_expr (arg2))),
4640 convert (tree_type,
4641 ffecom_2 (RSHIFT_EXPR, uns_type,
4642 ffecom_1 (BIT_NOT_EXPR,
4643 uns_type,
4644 convert (uns_type,
4645 integer_zero_node)),
4646 ffecom_2 (MINUS_EXPR,
4647 integer_type_node,
4648 TYPE_SIZE (uns_type),
4649 arg3_tree))));
4650#if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4651 expr_tree
4652 = ffecom_3 (COND_EXPR, tree_type,
4653 ffecom_truth_value
4654 (ffecom_2 (NE_EXPR, integer_type_node,
4655 arg3_tree,
4656 integer_zero_node)),
4657 expr_tree,
4658 convert (tree_type, integer_zero_node));
4659#endif
4660 }
4661 return expr_tree;
4662
4663 case FFEINTRIN_impIBSET:
4664 return
4665 ffecom_2 (BIT_IOR_EXPR, tree_type,
4666 ffecom_expr (arg1),
4667 ffecom_2 (LSHIFT_EXPR, tree_type,
4668 convert (tree_type, integer_one_node),
4669 convert (integer_type_node,
4670 ffecom_expr (arg2))));
4671
4672 case FFEINTRIN_impISHFT:
4673 {
4674 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4675 tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4676 ffecom_expr (arg2)));
4677 tree uns_type
4678 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4679
4680 expr_tree
4681 = ffecom_3 (COND_EXPR, tree_type,
4682 ffecom_truth_value
4683 (ffecom_2 (GE_EXPR, integer_type_node,
4684 arg2_tree,
4685 integer_zero_node)),
4686 ffecom_2 (LSHIFT_EXPR, tree_type,
4687 arg1_tree,
4688 arg2_tree),
4689 convert (tree_type,
4690 ffecom_2 (RSHIFT_EXPR, uns_type,
4691 convert (uns_type, arg1_tree),
4692 ffecom_1 (NEGATE_EXPR,
4693 integer_type_node,
4694 arg2_tree))));
4695#if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4696 expr_tree
4697 = ffecom_3 (COND_EXPR, tree_type,
4698 ffecom_truth_value
4699 (ffecom_2 (NE_EXPR, integer_type_node,
4700 arg2_tree,
4701 TYPE_SIZE (uns_type))),
4702 expr_tree,
4703 convert (tree_type, integer_zero_node));
4704#endif
4705 /* Make sure SAVE_EXPRs get referenced early enough. */
4706 expr_tree
4707 = ffecom_2 (COMPOUND_EXPR, tree_type,
4708 convert (void_type_node, arg1_tree),
4709 ffecom_2 (COMPOUND_EXPR, tree_type,
4710 convert (void_type_node, arg2_tree),
4711 expr_tree));
4712 }
4713 return expr_tree;
4714
4715 case FFEINTRIN_impISHFTC:
4716 {
4717 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4718 tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4719 ffecom_expr (arg2)));
4720 tree arg3_tree = (arg3 == NULL) ? TYPE_SIZE (tree_type)
4721 : ffecom_save_tree (convert (integer_type_node, ffecom_expr (arg3)));
4722 tree shift_neg;
4723 tree shift_pos;
4724 tree mask_arg1;
4725 tree masked_arg1;
4726 tree uns_type
4727 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4728
4729 mask_arg1
4730 = ffecom_2 (LSHIFT_EXPR, tree_type,
4731 ffecom_1 (BIT_NOT_EXPR, tree_type,
4732 convert (tree_type, integer_zero_node)),
4733 arg3_tree);
4734#if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4735 mask_arg1
4736 = ffecom_3 (COND_EXPR, tree_type,
4737 ffecom_truth_value
4738 (ffecom_2 (NE_EXPR, integer_type_node,
4739 arg3_tree,
4740 TYPE_SIZE (uns_type))),
4741 mask_arg1,
4742 convert (tree_type, integer_zero_node));
4743#endif
4744 mask_arg1 = ffecom_save_tree (mask_arg1);
4745 masked_arg1
4746 = ffecom_2 (BIT_AND_EXPR, tree_type,
4747 arg1_tree,
4748 ffecom_1 (BIT_NOT_EXPR, tree_type,
4749 mask_arg1));
4750 masked_arg1 = ffecom_save_tree (masked_arg1);
4751 shift_neg
4752 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4753 convert (tree_type,
4754 ffecom_2 (RSHIFT_EXPR, uns_type,
4755 convert (uns_type, masked_arg1),
4756 ffecom_1 (NEGATE_EXPR,
4757 integer_type_node,
4758 arg2_tree))),
4759 ffecom_2 (LSHIFT_EXPR, tree_type,
4760 arg1_tree,
4761 ffecom_2 (PLUS_EXPR, integer_type_node,
4762 arg2_tree,
4763 arg3_tree)));
4764 shift_pos
4765 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4766 ffecom_2 (LSHIFT_EXPR, tree_type,
4767 arg1_tree,
4768 arg2_tree),
4769 convert (tree_type,
4770 ffecom_2 (RSHIFT_EXPR, uns_type,
4771 convert (uns_type, masked_arg1),
4772 ffecom_2 (MINUS_EXPR,
4773 integer_type_node,
4774 arg3_tree,
4775 arg2_tree))));
4776 expr_tree
4777 = ffecom_3 (COND_EXPR, tree_type,
4778 ffecom_truth_value
4779 (ffecom_2 (LT_EXPR, integer_type_node,
4780 arg2_tree,
4781 integer_zero_node)),
4782 shift_neg,
4783 shift_pos);
4784 expr_tree
4785 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4786 ffecom_2 (BIT_AND_EXPR, tree_type,
4787 mask_arg1,
4788 arg1_tree),
4789 ffecom_2 (BIT_AND_EXPR, tree_type,
4790 ffecom_1 (BIT_NOT_EXPR, tree_type,
4791 mask_arg1),
4792 expr_tree));
4793 expr_tree
4794 = ffecom_3 (COND_EXPR, tree_type,
4795 ffecom_truth_value
4796 (ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
4797 ffecom_2 (EQ_EXPR, integer_type_node,
4798 ffecom_1 (ABS_EXPR,
4799 integer_type_node,
4800 arg2_tree),
4801 arg3_tree),
4802 ffecom_2 (EQ_EXPR, integer_type_node,
4803 arg2_tree,
4804 integer_zero_node))),
4805 arg1_tree,
4806 expr_tree);
4807 /* Make sure SAVE_EXPRs get referenced early enough. */
4808 expr_tree
4809 = ffecom_2 (COMPOUND_EXPR, tree_type,
4810 convert (void_type_node, arg1_tree),
4811 ffecom_2 (COMPOUND_EXPR, tree_type,
4812 convert (void_type_node, arg2_tree),
4813 ffecom_2 (COMPOUND_EXPR, tree_type,
4814 convert (void_type_node,
4815 mask_arg1),
4816 ffecom_2 (COMPOUND_EXPR, tree_type,
4817 convert (void_type_node,
4818 masked_arg1),
4819 expr_tree))));
4820 expr_tree
4821 = ffecom_2 (COMPOUND_EXPR, tree_type,
4822 convert (void_type_node,
4823 arg3_tree),
4824 expr_tree);
4825 }
4826 return expr_tree;
4827
4828 case FFEINTRIN_impLOC:
4829 {
4830 tree arg1_tree = ffecom_expr (arg1);
4831
4832 expr_tree
4833 = convert (tree_type,
4834 ffecom_1 (ADDR_EXPR,
4835 build_pointer_type (TREE_TYPE (arg1_tree)),
4836 arg1_tree));
4837 }
4838 return expr_tree;
4839
4840 case FFEINTRIN_impMVBITS:
4841 {
4842 tree arg1_tree;
4843 tree arg2_tree;
4844 tree arg3_tree;
4845 ffebld arg4 = ffebld_head (ffebld_trail (list));
4846 tree arg4_tree;
4847 tree arg4_type;
4848 ffebld arg5 = ffebld_head (ffebld_trail (ffebld_trail (list)));
4849 tree arg5_tree;
4850 tree prep_arg1;
4851 tree prep_arg4;
4852 tree arg5_plus_arg3;
4853
5ff904cd
JL
4854 arg2_tree = convert (integer_type_node,
4855 ffecom_expr (arg2));
4856 arg3_tree = ffecom_save_tree (convert (integer_type_node,
4857 ffecom_expr (arg3)));
c7e4ee3a 4858 arg4_tree = ffecom_expr_rw (NULL_TREE, arg4);
5ff904cd
JL
4859 arg4_type = TREE_TYPE (arg4_tree);
4860
4861 arg1_tree = ffecom_save_tree (convert (arg4_type,
4862 ffecom_expr (arg1)));
4863
4864 arg5_tree = ffecom_save_tree (convert (integer_type_node,
4865 ffecom_expr (arg5)));
4866
5ff904cd
JL
4867 prep_arg1
4868 = ffecom_2 (LSHIFT_EXPR, arg4_type,
4869 ffecom_2 (BIT_AND_EXPR, arg4_type,
4870 ffecom_2 (RSHIFT_EXPR, arg4_type,
4871 arg1_tree,
4872 arg2_tree),
4873 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4874 ffecom_2 (LSHIFT_EXPR, arg4_type,
4875 ffecom_1 (BIT_NOT_EXPR,
4876 arg4_type,
4877 convert
4878 (arg4_type,
4879 integer_zero_node)),
4880 arg3_tree))),
4881 arg5_tree);
4882 arg5_plus_arg3
4883 = ffecom_save_tree (ffecom_2 (PLUS_EXPR, arg4_type,
4884 arg5_tree,
4885 arg3_tree));
4886 prep_arg4
4887 = ffecom_2 (LSHIFT_EXPR, arg4_type,
4888 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4889 convert (arg4_type,
4890 integer_zero_node)),
4891 arg5_plus_arg3);
4892#if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4893 prep_arg4
4894 = ffecom_3 (COND_EXPR, arg4_type,
4895 ffecom_truth_value
4896 (ffecom_2 (NE_EXPR, integer_type_node,
4897 arg5_plus_arg3,
4898 convert (TREE_TYPE (arg5_plus_arg3),
4899 TYPE_SIZE (arg4_type)))),
4900 prep_arg4,
4901 convert (arg4_type, integer_zero_node));
4902#endif
4903 prep_arg4
4904 = ffecom_2 (BIT_AND_EXPR, arg4_type,
4905 arg4_tree,
4906 ffecom_2 (BIT_IOR_EXPR, arg4_type,
4907 prep_arg4,
4908 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4909 ffecom_2 (LSHIFT_EXPR, arg4_type,
4910 ffecom_1 (BIT_NOT_EXPR,
4911 arg4_type,
4912 convert
4913 (arg4_type,
4914 integer_zero_node)),
4915 arg5_tree))));
4916 prep_arg1
4917 = ffecom_2 (BIT_IOR_EXPR, arg4_type,
4918 prep_arg1,
4919 prep_arg4);
4920#if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4921 prep_arg1
4922 = ffecom_3 (COND_EXPR, arg4_type,
4923 ffecom_truth_value
4924 (ffecom_2 (NE_EXPR, integer_type_node,
4925 arg3_tree,
4926 convert (TREE_TYPE (arg3_tree),
4927 integer_zero_node))),
4928 prep_arg1,
4929 arg4_tree);
4930 prep_arg1
4931 = ffecom_3 (COND_EXPR, arg4_type,
4932 ffecom_truth_value
4933 (ffecom_2 (NE_EXPR, integer_type_node,
4934 arg3_tree,
4935 convert (TREE_TYPE (arg3_tree),
4936 TYPE_SIZE (arg4_type)))),
4937 prep_arg1,
4938 arg1_tree);
4939#endif
4940 expr_tree
4941 = ffecom_2s (MODIFY_EXPR, void_type_node,
4942 arg4_tree,
4943 prep_arg1);
4944 /* Make sure SAVE_EXPRs get referenced early enough. */
4945 expr_tree
4946 = ffecom_2 (COMPOUND_EXPR, void_type_node,
4947 arg1_tree,
4948 ffecom_2 (COMPOUND_EXPR, void_type_node,
4949 arg3_tree,
4950 ffecom_2 (COMPOUND_EXPR, void_type_node,
4951 arg5_tree,
4952 ffecom_2 (COMPOUND_EXPR, void_type_node,
4953 arg5_plus_arg3,
4954 expr_tree))));
4955 expr_tree
4956 = ffecom_2 (COMPOUND_EXPR, void_type_node,
4957 arg4_tree,
4958 expr_tree);
4959
4960 }
4961 return expr_tree;
4962
4963 case FFEINTRIN_impDERF:
4964 case FFEINTRIN_impERF:
4965 case FFEINTRIN_impDERFC:
4966 case FFEINTRIN_impERFC:
4967 break;
4968
4969 case FFEINTRIN_impIARGC:
4970 /* extern int xargc; i__1 = xargc - 1; */
4971 expr_tree = ffecom_2 (MINUS_EXPR, TREE_TYPE (ffecom_tree_xargc_),
4972 ffecom_tree_xargc_,
4973 convert (TREE_TYPE (ffecom_tree_xargc_),
4974 integer_one_node));
4975 return expr_tree;
4976
4977 case FFEINTRIN_impSIGNAL_func:
4978 case FFEINTRIN_impSIGNAL_subr:
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 ((codegen_imp == FFEINTRIN_impSIGNAL_subr) ?
5012 NULL_TREE :
5013 tree_type),
5014 arg1_tree,
c7e4ee3a
CB
5015 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5016 ffebld_nonter_hook (expr));
5ff904cd
JL
5017
5018 if (arg3_tree != NULL_TREE)
5019 expr_tree
5020 = ffecom_modify (NULL_TREE, arg3_tree,
5021 convert (TREE_TYPE (arg3_tree),
5022 expr_tree));
5023 }
5024 return expr_tree;
5025
5026 case FFEINTRIN_impALARM:
5027 {
5028 tree arg1_tree;
5029 tree arg2_tree;
5030 tree arg3_tree;
5031
5ff904cd
JL
5032 arg1_tree = convert (ffecom_f2c_integer_type_node,
5033 ffecom_expr (arg1));
5034 arg1_tree = ffecom_1 (ADDR_EXPR,
5035 build_pointer_type (TREE_TYPE (arg1_tree)),
5036 arg1_tree);
5037
5038 /* Pass procedure as a pointer to it, anything else by value. */
5039 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
5040 arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
5041 else
5042 arg2_tree = ffecom_ptr_to_expr (arg2);
5043 arg2_tree = convert (TREE_TYPE (null_pointer_node),
5044 arg2_tree);
5045
5046 if (arg3 != NULL)
c7e4ee3a 5047 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
5048 else
5049 arg3_tree = NULL_TREE;
5050
5ff904cd
JL
5051 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5052 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5053 TREE_CHAIN (arg1_tree) = arg2_tree;
5054
5055 expr_tree
5056 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5057 ffecom_gfrt_kindtype (gfrt),
5058 FALSE,
5059 NULL_TREE,
5060 arg1_tree,
c7e4ee3a
CB
5061 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5062 ffebld_nonter_hook (expr));
5ff904cd
JL
5063
5064 if (arg3_tree != NULL_TREE)
5065 expr_tree
5066 = ffecom_modify (NULL_TREE, arg3_tree,
5067 convert (TREE_TYPE (arg3_tree),
5068 expr_tree));
5069 }
5070 return expr_tree;
5071
5072 case FFEINTRIN_impCHDIR_subr:
5073 case FFEINTRIN_impFDATE_subr:
5074 case FFEINTRIN_impFGET_subr:
5075 case FFEINTRIN_impFPUT_subr:
5076 case FFEINTRIN_impGETCWD_subr:
5077 case FFEINTRIN_impHOSTNM_subr:
5078 case FFEINTRIN_impSYSTEM_subr:
5079 case FFEINTRIN_impUNLINK_subr:
5080 {
5081 tree arg1_len = integer_zero_node;
5082 tree arg1_tree;
5083 tree arg2_tree;
5084
5ff904cd
JL
5085 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5086
5087 if (arg2 != NULL)
c7e4ee3a 5088 arg2_tree = ffecom_expr_w (NULL_TREE, arg2);
5ff904cd
JL
5089 else
5090 arg2_tree = NULL_TREE;
5091
5ff904cd
JL
5092 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5093 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5094 TREE_CHAIN (arg1_tree) = arg1_len;
5095
5096 expr_tree
5097 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5098 ffecom_gfrt_kindtype (gfrt),
5099 FALSE,
5100 NULL_TREE,
5101 arg1_tree,
c7e4ee3a
CB
5102 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5103 ffebld_nonter_hook (expr));
5ff904cd
JL
5104
5105 if (arg2_tree != NULL_TREE)
5106 expr_tree
5107 = ffecom_modify (NULL_TREE, arg2_tree,
5108 convert (TREE_TYPE (arg2_tree),
5109 expr_tree));
5110 }
5111 return expr_tree;
5112
5113 case FFEINTRIN_impEXIT:
5114 if (arg1 != NULL)
5115 break;
5116
5117 expr_tree = build_tree_list (NULL_TREE,
5118 ffecom_1 (ADDR_EXPR,
5119 build_pointer_type
5120 (ffecom_integer_type_node),
5121 integer_zero_node));
5122
5123 return
5124 ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5125 ffecom_gfrt_kindtype (gfrt),
5126 FALSE,
5127 void_type_node,
5128 expr_tree,
c7e4ee3a
CB
5129 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5130 ffebld_nonter_hook (expr));
5ff904cd
JL
5131
5132 case FFEINTRIN_impFLUSH:
5133 if (arg1 == NULL)
5134 gfrt = FFECOM_gfrtFLUSH;
5135 else
5136 gfrt = FFECOM_gfrtFLUSH1;
5137 break;
5138
5139 case FFEINTRIN_impCHMOD_subr:
5140 case FFEINTRIN_impLINK_subr:
5141 case FFEINTRIN_impRENAME_subr:
5142 case FFEINTRIN_impSYMLNK_subr:
5143 {
5144 tree arg1_len = integer_zero_node;
5145 tree arg1_tree;
5146 tree arg2_len = integer_zero_node;
5147 tree arg2_tree;
5148 tree arg3_tree;
5149
5ff904cd
JL
5150 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5151 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
5152 if (arg3 != NULL)
c7e4ee3a 5153 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
5154 else
5155 arg3_tree = NULL_TREE;
5156
5ff904cd
JL
5157 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5158 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5159 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5160 arg2_len = build_tree_list (NULL_TREE, arg2_len);
5161 TREE_CHAIN (arg1_tree) = arg2_tree;
5162 TREE_CHAIN (arg2_tree) = arg1_len;
5163 TREE_CHAIN (arg1_len) = arg2_len;
5164 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5165 ffecom_gfrt_kindtype (gfrt),
5166 FALSE,
5167 NULL_TREE,
5168 arg1_tree,
c7e4ee3a
CB
5169 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5170 ffebld_nonter_hook (expr));
5ff904cd
JL
5171 if (arg3_tree != NULL_TREE)
5172 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5173 convert (TREE_TYPE (arg3_tree),
5174 expr_tree));
5175 }
5176 return expr_tree;
5177
5178 case FFEINTRIN_impLSTAT_subr:
5179 case FFEINTRIN_impSTAT_subr:
5180 {
5181 tree arg1_len = integer_zero_node;
5182 tree arg1_tree;
5183 tree arg2_tree;
5184 tree arg3_tree;
5185
5ff904cd
JL
5186 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5187
5188 arg2_tree = ffecom_ptr_to_expr (arg2);
5189
5190 if (arg3 != NULL)
c7e4ee3a 5191 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
5192 else
5193 arg3_tree = NULL_TREE;
5194
5ff904cd
JL
5195 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5196 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5197 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5198 TREE_CHAIN (arg1_tree) = arg2_tree;
5199 TREE_CHAIN (arg2_tree) = arg1_len;
5200 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5201 ffecom_gfrt_kindtype (gfrt),
5202 FALSE,
5203 NULL_TREE,
5204 arg1_tree,
c7e4ee3a
CB
5205 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5206 ffebld_nonter_hook (expr));
5ff904cd
JL
5207 if (arg3_tree != NULL_TREE)
5208 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5209 convert (TREE_TYPE (arg3_tree),
5210 expr_tree));
5211 }
5212 return expr_tree;
5213
5214 case FFEINTRIN_impFGETC_subr:
5215 case FFEINTRIN_impFPUTC_subr:
5216 {
5217 tree arg1_tree;
5218 tree arg2_tree;
5219 tree arg2_len = integer_zero_node;
5220 tree arg3_tree;
5221
5ff904cd
JL
5222 arg1_tree = convert (ffecom_f2c_integer_type_node,
5223 ffecom_expr (arg1));
5224 arg1_tree = ffecom_1 (ADDR_EXPR,
5225 build_pointer_type (TREE_TYPE (arg1_tree)),
5226 arg1_tree);
5227
5228 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
c7e4ee3a 5229 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
5230
5231 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5232 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5233 arg2_len = build_tree_list (NULL_TREE, arg2_len);
5234 TREE_CHAIN (arg1_tree) = arg2_tree;
5235 TREE_CHAIN (arg2_tree) = arg2_len;
5236
5237 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5238 ffecom_gfrt_kindtype (gfrt),
5239 FALSE,
5240 NULL_TREE,
5241 arg1_tree,
c7e4ee3a
CB
5242 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5243 ffebld_nonter_hook (expr));
5ff904cd
JL
5244 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5245 convert (TREE_TYPE (arg3_tree),
5246 expr_tree));
5247 }
5248 return expr_tree;
5249
5250 case FFEINTRIN_impFSTAT_subr:
5251 {
5252 tree arg1_tree;
5253 tree arg2_tree;
5254 tree arg3_tree;
5255
5ff904cd
JL
5256 arg1_tree = convert (ffecom_f2c_integer_type_node,
5257 ffecom_expr (arg1));
5258 arg1_tree = ffecom_1 (ADDR_EXPR,
5259 build_pointer_type (TREE_TYPE (arg1_tree)),
5260 arg1_tree);
5261
5262 arg2_tree = convert (ffecom_f2c_ptr_to_integer_type_node,
5263 ffecom_ptr_to_expr (arg2));
5264
5265 if (arg3 == NULL)
5266 arg3_tree = NULL_TREE;
5267 else
c7e4ee3a 5268 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
5269
5270 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5271 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5272 TREE_CHAIN (arg1_tree) = arg2_tree;
5273 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5274 ffecom_gfrt_kindtype (gfrt),
5275 FALSE,
5276 NULL_TREE,
5277 arg1_tree,
c7e4ee3a
CB
5278 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5279 ffebld_nonter_hook (expr));
5ff904cd
JL
5280 if (arg3_tree != NULL_TREE) {
5281 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5282 convert (TREE_TYPE (arg3_tree),
5283 expr_tree));
5284 }
5285 }
5286 return expr_tree;
5287
5288 case FFEINTRIN_impKILL_subr:
5289 {
5290 tree arg1_tree;
5291 tree arg2_tree;
5292 tree arg3_tree;
5293
5ff904cd
JL
5294 arg1_tree = convert (ffecom_f2c_integer_type_node,
5295 ffecom_expr (arg1));
5296 arg1_tree = ffecom_1 (ADDR_EXPR,
5297 build_pointer_type (TREE_TYPE (arg1_tree)),
5298 arg1_tree);
5299
5300 arg2_tree = convert (ffecom_f2c_integer_type_node,
5301 ffecom_expr (arg2));
5302 arg2_tree = ffecom_1 (ADDR_EXPR,
5303 build_pointer_type (TREE_TYPE (arg2_tree)),
5304 arg2_tree);
5305
5306 if (arg3 == NULL)
5307 arg3_tree = NULL_TREE;
5308 else
c7e4ee3a 5309 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
5310
5311 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5312 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5313 TREE_CHAIN (arg1_tree) = arg2_tree;
5314 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5315 ffecom_gfrt_kindtype (gfrt),
5316 FALSE,
5317 NULL_TREE,
5318 arg1_tree,
c7e4ee3a
CB
5319 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5320 ffebld_nonter_hook (expr));
5ff904cd
JL
5321 if (arg3_tree != NULL_TREE) {
5322 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5323 convert (TREE_TYPE (arg3_tree),
5324 expr_tree));
5325 }
5326 }
5327 return expr_tree;
5328
5329 case FFEINTRIN_impCTIME_subr:
5330 case FFEINTRIN_impTTYNAM_subr:
5331 {
5332 tree arg1_len = integer_zero_node;
5333 tree arg1_tree;
5334 tree arg2_tree;
5335
2b0bdd9a 5336 arg1_tree = ffecom_arg_ptr_to_expr (arg2, &arg1_len);
5ff904cd 5337
c56f65d6 5338 arg2_tree = convert (((codegen_imp == FFEINTRIN_impCTIME_subr) ?
5ff904cd
JL
5339 ffecom_f2c_longint_type_node :
5340 ffecom_f2c_integer_type_node),
2b0bdd9a 5341 ffecom_expr (arg1));
5ff904cd
JL
5342 arg2_tree = ffecom_1 (ADDR_EXPR,
5343 build_pointer_type (TREE_TYPE (arg2_tree)),
5344 arg2_tree);
5345
5ff904cd
JL
5346 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5347 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5348 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5349 TREE_CHAIN (arg1_len) = arg2_tree;
5350 TREE_CHAIN (arg1_tree) = arg1_len;
5351
5352 expr_tree
5353 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5354 ffecom_gfrt_kindtype (gfrt),
5355 FALSE,
5356 NULL_TREE,
5357 arg1_tree,
c7e4ee3a
CB
5358 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5359 ffebld_nonter_hook (expr));
2b0bdd9a 5360 TREE_SIDE_EFFECTS (expr_tree) = 1;
5ff904cd
JL
5361 }
5362 return expr_tree;
5363
5364 case FFEINTRIN_impIRAND:
5365 case FFEINTRIN_impRAND:
5366 /* Arg defaults to 0 (normal random case) */
5367 {
5368 tree arg1_tree;
5369
5370 if (arg1 == NULL)
5371 arg1_tree = ffecom_integer_zero_node;
5372 else
5373 arg1_tree = ffecom_expr (arg1);
5374 arg1_tree = convert (ffecom_f2c_integer_type_node,
5375 arg1_tree);
5376 arg1_tree = ffecom_1 (ADDR_EXPR,
5377 build_pointer_type (TREE_TYPE (arg1_tree)),
5378 arg1_tree);
5379 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5380
5381 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5382 ffecom_gfrt_kindtype (gfrt),
5383 FALSE,
5384 ((codegen_imp == FFEINTRIN_impIRAND) ?
5385 ffecom_f2c_integer_type_node :
de7f278a 5386 ffecom_f2c_real_type_node),
5ff904cd
JL
5387 arg1_tree,
5388 dest_tree, dest, dest_used,
c7e4ee3a
CB
5389 NULL_TREE, TRUE,
5390 ffebld_nonter_hook (expr));
5ff904cd
JL
5391 }
5392 return expr_tree;
5393
5394 case FFEINTRIN_impFTELL_subr:
5395 case FFEINTRIN_impUMASK_subr:
5396 {
5397 tree arg1_tree;
5398 tree arg2_tree;
5399
5ff904cd
JL
5400 arg1_tree = convert (ffecom_f2c_integer_type_node,
5401 ffecom_expr (arg1));
5402 arg1_tree = ffecom_1 (ADDR_EXPR,
5403 build_pointer_type (TREE_TYPE (arg1_tree)),
5404 arg1_tree);
5405
5406 if (arg2 == NULL)
5407 arg2_tree = NULL_TREE;
5408 else
c7e4ee3a 5409 arg2_tree = ffecom_expr_w (NULL_TREE, arg2);
5ff904cd
JL
5410
5411 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5412 ffecom_gfrt_kindtype (gfrt),
5413 FALSE,
5414 NULL_TREE,
5415 build_tree_list (NULL_TREE, arg1_tree),
5416 NULL_TREE, NULL, NULL, NULL_TREE,
c7e4ee3a
CB
5417 TRUE,
5418 ffebld_nonter_hook (expr));
5ff904cd
JL
5419 if (arg2_tree != NULL_TREE) {
5420 expr_tree = ffecom_modify (NULL_TREE, arg2_tree,
5421 convert (TREE_TYPE (arg2_tree),
5422 expr_tree));
5423 }
5424 }
5425 return expr_tree;
5426
5427 case FFEINTRIN_impCPU_TIME:
5428 case FFEINTRIN_impSECOND_subr:
5429 {
5430 tree arg1_tree;
5431
c7e4ee3a 5432 arg1_tree = ffecom_expr_w (NULL_TREE, arg1);
5ff904cd
JL
5433
5434 expr_tree
5435 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5436 ffecom_gfrt_kindtype (gfrt),
5437 FALSE,
5438 NULL_TREE,
5439 NULL_TREE,
c7e4ee3a
CB
5440 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5441 ffebld_nonter_hook (expr));
5ff904cd
JL
5442
5443 expr_tree
5444 = ffecom_modify (NULL_TREE, arg1_tree,
5445 convert (TREE_TYPE (arg1_tree),
5446 expr_tree));
5447 }
5448 return expr_tree;
5449
5450 case FFEINTRIN_impDTIME_subr:
5451 case FFEINTRIN_impETIME_subr:
5452 {
5453 tree arg1_tree;
2b0bdd9a 5454 tree result_tree;
5ff904cd 5455
2b0bdd9a 5456 result_tree = ffecom_expr_w (NULL_TREE, arg2);
5ff904cd 5457
2b0bdd9a 5458 arg1_tree = ffecom_ptr_to_expr (arg1);
5ff904cd 5459
5ff904cd
JL
5460 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5461 ffecom_gfrt_kindtype (gfrt),
5462 FALSE,
5463 NULL_TREE,
2b0bdd9a 5464 build_tree_list (NULL_TREE, arg1_tree),
5ff904cd 5465 NULL_TREE, NULL, NULL, NULL_TREE,
c7e4ee3a
CB
5466 TRUE,
5467 ffebld_nonter_hook (expr));
2b0bdd9a
CB
5468 expr_tree = ffecom_modify (NULL_TREE, result_tree,
5469 convert (TREE_TYPE (result_tree),
5ff904cd
JL
5470 expr_tree));
5471 }
5472 return expr_tree;
5473
c7e4ee3a 5474 /* Straightforward calls of libf2c routines: */
5ff904cd
JL
5475 case FFEINTRIN_impABORT:
5476 case FFEINTRIN_impACCESS:
5477 case FFEINTRIN_impBESJ0:
5478 case FFEINTRIN_impBESJ1:
5479 case FFEINTRIN_impBESJN:
5480 case FFEINTRIN_impBESY0:
5481 case FFEINTRIN_impBESY1:
5482 case FFEINTRIN_impBESYN:
5483 case FFEINTRIN_impCHDIR_func:
5484 case FFEINTRIN_impCHMOD_func:
5485 case FFEINTRIN_impDATE:
9e8e701d 5486 case FFEINTRIN_impDATE_AND_TIME:
5ff904cd
JL
5487 case FFEINTRIN_impDBESJ0:
5488 case FFEINTRIN_impDBESJ1:
5489 case FFEINTRIN_impDBESJN:
5490 case FFEINTRIN_impDBESY0:
5491 case FFEINTRIN_impDBESY1:
5492 case FFEINTRIN_impDBESYN:
5493 case FFEINTRIN_impDTIME_func:
5494 case FFEINTRIN_impETIME_func:
5495 case FFEINTRIN_impFGETC_func:
5496 case FFEINTRIN_impFGET_func:
5497 case FFEINTRIN_impFNUM:
5498 case FFEINTRIN_impFPUTC_func:
5499 case FFEINTRIN_impFPUT_func:
5500 case FFEINTRIN_impFSEEK:
5501 case FFEINTRIN_impFSTAT_func:
5502 case FFEINTRIN_impFTELL_func:
5503 case FFEINTRIN_impGERROR:
5504 case FFEINTRIN_impGETARG:
5505 case FFEINTRIN_impGETCWD_func:
5506 case FFEINTRIN_impGETENV:
5507 case FFEINTRIN_impGETGID:
5508 case FFEINTRIN_impGETLOG:
5509 case FFEINTRIN_impGETPID:
5510 case FFEINTRIN_impGETUID:
5511 case FFEINTRIN_impGMTIME:
5512 case FFEINTRIN_impHOSTNM_func:
5513 case FFEINTRIN_impIDATE_unix:
5514 case FFEINTRIN_impIDATE_vxt:
5515 case FFEINTRIN_impIERRNO:
5516 case FFEINTRIN_impISATTY:
5517 case FFEINTRIN_impITIME:
5518 case FFEINTRIN_impKILL_func:
5519 case FFEINTRIN_impLINK_func:
5520 case FFEINTRIN_impLNBLNK:
5521 case FFEINTRIN_impLSTAT_func:
5522 case FFEINTRIN_impLTIME:
5523 case FFEINTRIN_impMCLOCK8:
5524 case FFEINTRIN_impMCLOCK:
5525 case FFEINTRIN_impPERROR:
5526 case FFEINTRIN_impRENAME_func:
5527 case FFEINTRIN_impSECNDS:
5528 case FFEINTRIN_impSECOND_func:
5529 case FFEINTRIN_impSLEEP:
5530 case FFEINTRIN_impSRAND:
5531 case FFEINTRIN_impSTAT_func:
5532 case FFEINTRIN_impSYMLNK_func:
5533 case FFEINTRIN_impSYSTEM_CLOCK:
5534 case FFEINTRIN_impSYSTEM_func:
5535 case FFEINTRIN_impTIME8:
5536 case FFEINTRIN_impTIME_unix:
5537 case FFEINTRIN_impTIME_vxt:
5538 case FFEINTRIN_impUMASK_func:
5539 case FFEINTRIN_impUNLINK_func:
5540 break;
5541
5542 case FFEINTRIN_impCTIME_func: /* CHARACTER functions not handled here. */
5543 case FFEINTRIN_impFDATE_func: /* CHARACTER functions not handled here. */
5544 case FFEINTRIN_impTTYNAM_func: /* CHARACTER functions not handled here. */
5545 case FFEINTRIN_impNONE:
5546 case FFEINTRIN_imp: /* Hush up gcc warning. */
5547 fprintf (stderr, "No %s implementation.\n",
5548 ffeintrin_name_implementation (ffebld_symter_implementation (ffebld_left (expr))));
5549 assert ("unimplemented intrinsic" == NULL);
5550 return error_mark_node;
5551 }
5552
5553 assert (gfrt != FFECOM_gfrt); /* Must have an implementation! */
5554
5ff904cd
JL
5555 expr_tree = ffecom_arglist_expr_ (ffecom_gfrt_args_ (gfrt),
5556 ffebld_right (expr));
5ff904cd
JL
5557
5558 return ffecom_call_ (ffecom_gfrt_tree_ (gfrt), ffecom_gfrt_kindtype (gfrt),
5559 (ffe_is_f2c_library () && ffecom_gfrt_complex_[gfrt]),
5560 tree_type,
5561 expr_tree, dest_tree, dest, dest_used,
c7e4ee3a
CB
5562 NULL_TREE, TRUE,
5563 ffebld_nonter_hook (expr));
5ff904cd 5564
c7e4ee3a
CB
5565 /* See bottom of this file for f2c transforms used to determine
5566 many of the above implementations. The info seems to confuse
5567 Emacs's C mode indentation, which is why it's been moved to
5568 the bottom of this source file. */
5569}
5ff904cd 5570
c7e4ee3a
CB
5571#endif
5572/* For power (exponentiation) where right-hand operand is type INTEGER,
5573 generate in-line code to do it the fast way (which, if the operand
5574 is a constant, might just mean a series of multiplies). */
5ff904cd 5575
c7e4ee3a
CB
5576#if FFECOM_targetCURRENT == FFECOM_targetGCC
5577static tree
5578ffecom_expr_power_integer_ (ffebld expr)
5579{
5580 tree l = ffecom_expr (ffebld_left (expr));
5581 tree r = ffecom_expr (ffebld_right (expr));
5582 tree ltype = TREE_TYPE (l);
5583 tree rtype = TREE_TYPE (r);
5584 tree result = NULL_TREE;
5ff904cd 5585
c7e4ee3a
CB
5586 if (l == error_mark_node
5587 || r == error_mark_node)
5588 return error_mark_node;
5ff904cd 5589
c7e4ee3a
CB
5590 if (TREE_CODE (r) == INTEGER_CST)
5591 {
5592 int sgn = tree_int_cst_sgn (r);
5ff904cd 5593
c7e4ee3a
CB
5594 if (sgn == 0)
5595 return convert (ltype, integer_one_node);
5ff904cd 5596
c7e4ee3a
CB
5597 if ((TREE_CODE (ltype) == INTEGER_TYPE)
5598 && (sgn < 0))
5599 {
5600 /* Reciprocal of integer is either 0, -1, or 1, so after
5601 calculating that (which we leave to the back end to do
5602 or not do optimally), don't bother with any multiplying. */
5ff904cd 5603
c7e4ee3a
CB
5604 result = ffecom_tree_divide_ (ltype,
5605 convert (ltype, integer_one_node),
5606 l,
5607 NULL_TREE, NULL, NULL, NULL_TREE);
5608 r = ffecom_1 (NEGATE_EXPR,
5609 rtype,
5610 r);
5611 if ((TREE_INT_CST_LOW (r) & 1) == 0)
5612 result = ffecom_1 (ABS_EXPR, rtype,
5613 result);
5614 }
5ff904cd 5615
c7e4ee3a
CB
5616 /* Generate appropriate series of multiplies, preceded
5617 by divide if the exponent is negative. */
5ff904cd 5618
c7e4ee3a 5619 l = save_expr (l);
5ff904cd 5620
c7e4ee3a
CB
5621 if (sgn < 0)
5622 {
5623 l = ffecom_tree_divide_ (ltype,
5624 convert (ltype, integer_one_node),
5625 l,
5626 NULL_TREE, NULL, NULL,
5627 ffebld_nonter_hook (expr));
5628 r = ffecom_1 (NEGATE_EXPR, rtype, r);
5629 assert (TREE_CODE (r) == INTEGER_CST);
5ff904cd 5630
c7e4ee3a
CB
5631 if (tree_int_cst_sgn (r) < 0)
5632 { /* The "most negative" number. */
5633 r = ffecom_1 (NEGATE_EXPR, rtype,
5634 ffecom_2 (RSHIFT_EXPR, rtype,
5635 r,
5636 integer_one_node));
5637 l = save_expr (l);
5638 l = ffecom_2 (MULT_EXPR, ltype,
5639 l,
5640 l);
5641 }
5642 }
5ff904cd 5643
c7e4ee3a
CB
5644 for (;;)
5645 {
5646 if (TREE_INT_CST_LOW (r) & 1)
5647 {
5648 if (result == NULL_TREE)
5649 result = l;
5650 else
5651 result = ffecom_2 (MULT_EXPR, ltype,
5652 result,
5653 l);
5654 }
5ff904cd 5655
c7e4ee3a
CB
5656 r = ffecom_2 (RSHIFT_EXPR, rtype,
5657 r,
5658 integer_one_node);
5659 if (integer_zerop (r))
5660 break;
5661 assert (TREE_CODE (r) == INTEGER_CST);
5ff904cd 5662
c7e4ee3a
CB
5663 l = save_expr (l);
5664 l = ffecom_2 (MULT_EXPR, ltype,
5665 l,
5666 l);
5667 }
5668 return result;
5669 }
5ff904cd 5670
c7e4ee3a
CB
5671 /* Though rhs isn't a constant, in-line code cannot be expanded
5672 while transforming dummies
5673 because the back end cannot be easily convinced to generate
5674 stores (MODIFY_EXPR), handle temporaries, and so on before
5675 all the appropriate rtx's have been generated for things like
5676 dummy args referenced in rhs -- which doesn't happen until
5677 store_parm_decls() is called (expand_function_start, I believe,
5678 does the actual rtx-stuffing of PARM_DECLs).
5ff904cd 5679
c7e4ee3a
CB
5680 So, in this case, let the caller generate the call to the
5681 run-time-library function to evaluate the power for us. */
5ff904cd 5682
c7e4ee3a
CB
5683 if (ffecom_transform_only_dummies_)
5684 return NULL_TREE;
5ff904cd 5685
c7e4ee3a
CB
5686 /* Right-hand operand not a constant, expand in-line code to figure
5687 out how to do the multiplies, &c.
5ff904cd 5688
c7e4ee3a
CB
5689 The returned expression is expressed this way in GNU C, where l and
5690 r are the "inputs":
5ff904cd 5691
c7e4ee3a
CB
5692 ({ typeof (r) rtmp = r;
5693 typeof (l) ltmp = l;
5694 typeof (l) result;
5ff904cd 5695
c7e4ee3a
CB
5696 if (rtmp == 0)
5697 result = 1;
5698 else
5699 {
5700 if ((basetypeof (l) == basetypeof (int))
5701 && (rtmp < 0))
5702 {
5703 result = ((typeof (l)) 1) / ltmp;
5704 if ((ltmp < 0) && (((-rtmp) & 1) == 0))
5705 result = -result;
5706 }
5707 else
5708 {
5709 result = 1;
5710 if ((basetypeof (l) != basetypeof (int))
5711 && (rtmp < 0))
5712 {
5713 ltmp = ((typeof (l)) 1) / ltmp;
5714 rtmp = -rtmp;
5715 if (rtmp < 0)
5716 {
5717 rtmp = -(rtmp >> 1);
5718 ltmp *= ltmp;
5719 }
5720 }
5721 for (;;)
5722 {
5723 if (rtmp & 1)
5724 result *= ltmp;
5725 if ((rtmp >>= 1) == 0)
5726 break;
5727 ltmp *= ltmp;
5728 }
5729 }
5730 }
5731 result;
5732 })
5ff904cd 5733
c7e4ee3a
CB
5734 Note that some of the above is compile-time collapsable, such as
5735 the first part of the if statements that checks the base type of
5736 l against int. The if statements are phrased that way to suggest
5737 an easy way to generate the if/else constructs here, knowing that
5738 the back end should (and probably does) eliminate the resulting
5739 dead code (either the int case or the non-int case), something
5740 it couldn't do without the redundant phrasing, requiring explicit
5741 dead-code elimination here, which would be kind of difficult to
5742 read. */
5ff904cd 5743
c7e4ee3a
CB
5744 {
5745 tree rtmp;
5746 tree ltmp;
5747 tree divide;
5748 tree basetypeof_l_is_int;
5749 tree se;
5750 tree t;
5ff904cd 5751
c7e4ee3a
CB
5752 basetypeof_l_is_int
5753 = build_int_2 ((TREE_CODE (ltype) == INTEGER_TYPE), 0);
5ff904cd 5754
c7e4ee3a 5755 se = expand_start_stmt_expr ();
5ff904cd 5756
c7e4ee3a
CB
5757 ffecom_start_compstmt ();
5758
5759#ifndef HAHA
5760 rtmp = ffecom_make_tempvar ("power_r", rtype,
5761 FFETARGET_charactersizeNONE, -1);
5762 ltmp = ffecom_make_tempvar ("power_l", ltype,
5763 FFETARGET_charactersizeNONE, -1);
5764 result = ffecom_make_tempvar ("power_res", ltype,
5765 FFETARGET_charactersizeNONE, -1);
5766 if (TREE_CODE (ltype) == COMPLEX_TYPE
5767 || TREE_CODE (ltype) == RECORD_TYPE)
5768 divide = ffecom_make_tempvar ("power_div", ltype,
5769 FFETARGET_charactersizeNONE, -1);
5770 else
5771 divide = NULL_TREE;
5772#else /* HAHA */
5773 {
5774 tree hook;
5775
5776 hook = ffebld_nonter_hook (expr);
5777 assert (hook);
5778 assert (TREE_CODE (hook) == TREE_VEC);
5779 assert (TREE_VEC_LENGTH (hook) == 4);
5780 rtmp = TREE_VEC_ELT (hook, 0);
5781 ltmp = TREE_VEC_ELT (hook, 1);
5782 result = TREE_VEC_ELT (hook, 2);
5783 divide = TREE_VEC_ELT (hook, 3);
5784 if (TREE_CODE (ltype) == COMPLEX_TYPE
5785 || TREE_CODE (ltype) == RECORD_TYPE)
5786 assert (divide);
5787 else
5788 assert (! divide);
5789 }
5790#endif /* HAHA */
5ff904cd 5791
c7e4ee3a
CB
5792 expand_expr_stmt (ffecom_modify (void_type_node,
5793 rtmp,
5794 r));
5795 expand_expr_stmt (ffecom_modify (void_type_node,
5796 ltmp,
5797 l));
5798 expand_start_cond (ffecom_truth_value
5799 (ffecom_2 (EQ_EXPR, integer_type_node,
5800 rtmp,
5801 convert (rtype, integer_zero_node))),
5802 0);
5803 expand_expr_stmt (ffecom_modify (void_type_node,
5804 result,
5805 convert (ltype, integer_one_node)));
5806 expand_start_else ();
5807 if (! integer_zerop (basetypeof_l_is_int))
5808 {
5809 expand_start_cond (ffecom_2 (LT_EXPR, integer_type_node,
5810 rtmp,
5811 convert (rtype,
5812 integer_zero_node)),
5813 0);
5814 expand_expr_stmt (ffecom_modify (void_type_node,
5815 result,
5816 ffecom_tree_divide_
5817 (ltype,
5818 convert (ltype, integer_one_node),
5819 ltmp,
5820 NULL_TREE, NULL, NULL,
5821 divide)));
5822 expand_start_cond (ffecom_truth_value
5823 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
5824 ffecom_2 (LT_EXPR, integer_type_node,
5825 ltmp,
5826 convert (ltype,
5827 integer_zero_node)),
5828 ffecom_2 (EQ_EXPR, integer_type_node,
5829 ffecom_2 (BIT_AND_EXPR,
5830 rtype,
5831 ffecom_1 (NEGATE_EXPR,
5832 rtype,
5833 rtmp),
5834 convert (rtype,
5835 integer_one_node)),
5836 convert (rtype,
5837 integer_zero_node)))),
5838 0);
5839 expand_expr_stmt (ffecom_modify (void_type_node,
5840 result,
5841 ffecom_1 (NEGATE_EXPR,
5842 ltype,
5843 result)));
5844 expand_end_cond ();
5845 expand_start_else ();
5846 }
5847 expand_expr_stmt (ffecom_modify (void_type_node,
5848 result,
5849 convert (ltype, integer_one_node)));
5850 expand_start_cond (ffecom_truth_value
5851 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
5852 ffecom_truth_value_invert
5853 (basetypeof_l_is_int),
5854 ffecom_2 (LT_EXPR, integer_type_node,
5855 rtmp,
5856 convert (rtype,
5857 integer_zero_node)))),
5858 0);
5859 expand_expr_stmt (ffecom_modify (void_type_node,
5860 ltmp,
5861 ffecom_tree_divide_
5862 (ltype,
5863 convert (ltype, integer_one_node),
5864 ltmp,
5865 NULL_TREE, NULL, NULL,
5866 divide)));
5867 expand_expr_stmt (ffecom_modify (void_type_node,
5868 rtmp,
5869 ffecom_1 (NEGATE_EXPR, rtype,
5870 rtmp)));
5871 expand_start_cond (ffecom_truth_value
5872 (ffecom_2 (LT_EXPR, integer_type_node,
5873 rtmp,
5874 convert (rtype, integer_zero_node))),
5875 0);
5876 expand_expr_stmt (ffecom_modify (void_type_node,
5877 rtmp,
5878 ffecom_1 (NEGATE_EXPR, rtype,
5879 ffecom_2 (RSHIFT_EXPR,
5880 rtype,
5881 rtmp,
5882 integer_one_node))));
5883 expand_expr_stmt (ffecom_modify (void_type_node,
5884 ltmp,
5885 ffecom_2 (MULT_EXPR, ltype,
5886 ltmp,
5887 ltmp)));
5888 expand_end_cond ();
5889 expand_end_cond ();
5890 expand_start_loop (1);
5891 expand_start_cond (ffecom_truth_value
5892 (ffecom_2 (BIT_AND_EXPR, rtype,
5893 rtmp,
5894 convert (rtype, integer_one_node))),
5895 0);
5896 expand_expr_stmt (ffecom_modify (void_type_node,
5897 result,
5898 ffecom_2 (MULT_EXPR, ltype,
5899 result,
5900 ltmp)));
5901 expand_end_cond ();
5902 expand_exit_loop_if_false (NULL,
5903 ffecom_truth_value
5904 (ffecom_modify (rtype,
5905 rtmp,
5906 ffecom_2 (RSHIFT_EXPR,
5907 rtype,
5908 rtmp,
5909 integer_one_node))));
5910 expand_expr_stmt (ffecom_modify (void_type_node,
5911 ltmp,
5912 ffecom_2 (MULT_EXPR, ltype,
5913 ltmp,
5914 ltmp)));
5915 expand_end_loop ();
5916 expand_end_cond ();
5917 if (!integer_zerop (basetypeof_l_is_int))
5918 expand_end_cond ();
5919 expand_expr_stmt (result);
5ff904cd 5920
c7e4ee3a 5921 t = ffecom_end_compstmt ();
5ff904cd 5922
c7e4ee3a 5923 result = expand_end_stmt_expr (se);
5ff904cd 5924
c7e4ee3a 5925 /* This code comes from c-parse.in, after its expand_end_stmt_expr. */
5ff904cd 5926
c7e4ee3a
CB
5927 if (TREE_CODE (t) == BLOCK)
5928 {
5929 /* Make a BIND_EXPR for the BLOCK already made. */
5930 result = build (BIND_EXPR, TREE_TYPE (result),
5931 NULL_TREE, result, t);
5932 /* Remove the block from the tree at this point.
5933 It gets put back at the proper place
5934 when the BIND_EXPR is expanded. */
5935 delete_block (t);
5936 }
5937 else
5938 result = t;
5939 }
5ff904cd 5940
c7e4ee3a
CB
5941 return result;
5942}
5ff904cd 5943
c7e4ee3a
CB
5944#endif
5945/* ffecom_expr_transform_ -- Transform symbols in expr
5ff904cd 5946
c7e4ee3a
CB
5947 ffebld expr; // FFE expression.
5948 ffecom_expr_transform_ (expr);
5ff904cd 5949
c7e4ee3a 5950 Recursive descent on expr while transforming any untransformed SYMTERs. */
5ff904cd 5951
c7e4ee3a
CB
5952#if FFECOM_targetCURRENT == FFECOM_targetGCC
5953static void
5954ffecom_expr_transform_ (ffebld expr)
5955{
5956 tree t;
5957 ffesymbol s;
5ff904cd 5958
c7e4ee3a 5959tail_recurse: /* :::::::::::::::::::: */
5ff904cd 5960
c7e4ee3a
CB
5961 if (expr == NULL)
5962 return;
5ff904cd 5963
c7e4ee3a
CB
5964 switch (ffebld_op (expr))
5965 {
5966 case FFEBLD_opSYMTER:
5967 s = ffebld_symter (expr);
5968 t = ffesymbol_hook (s).decl_tree;
5969 if ((t == NULL_TREE)
5970 && ((ffesymbol_kind (s) != FFEINFO_kindNONE)
5971 || ((ffesymbol_where (s) != FFEINFO_whereNONE)
5972 && (ffesymbol_where (s) != FFEINFO_whereINTRINSIC))))
5973 {
5974 s = ffecom_sym_transform_ (s);
5975 t = ffesymbol_hook (s).decl_tree; /* Sfunc expr non-dummy,
5976 DIMENSION expr? */
5977 }
5978 break; /* Ok if (t == NULL) here. */
5ff904cd 5979
c7e4ee3a
CB
5980 case FFEBLD_opITEM:
5981 ffecom_expr_transform_ (ffebld_head (expr));
5982 expr = ffebld_trail (expr);
5983 goto tail_recurse; /* :::::::::::::::::::: */
5ff904cd 5984
c7e4ee3a
CB
5985 default:
5986 break;
5987 }
5ff904cd 5988
c7e4ee3a
CB
5989 switch (ffebld_arity (expr))
5990 {
5991 case 2:
5992 ffecom_expr_transform_ (ffebld_left (expr));
5993 expr = ffebld_right (expr);
5994 goto tail_recurse; /* :::::::::::::::::::: */
5ff904cd 5995
c7e4ee3a
CB
5996 case 1:
5997 expr = ffebld_left (expr);
5998 goto tail_recurse; /* :::::::::::::::::::: */
5ff904cd 5999
c7e4ee3a
CB
6000 default:
6001 break;
6002 }
5ff904cd 6003
c7e4ee3a
CB
6004 return;
6005}
5ff904cd 6006
c7e4ee3a
CB
6007#endif
6008/* Make a type based on info in live f2c.h file. */
5ff904cd 6009
c7e4ee3a
CB
6010#if FFECOM_targetCURRENT == FFECOM_targetGCC
6011static void
6012ffecom_f2c_make_type_ (tree *type, int tcode, const char *name)
6013{
6014 switch (tcode)
6015 {
6016 case FFECOM_f2ccodeCHAR:
6017 *type = make_signed_type (CHAR_TYPE_SIZE);
6018 break;
5ff904cd 6019
c7e4ee3a
CB
6020 case FFECOM_f2ccodeSHORT:
6021 *type = make_signed_type (SHORT_TYPE_SIZE);
6022 break;
5ff904cd 6023
c7e4ee3a
CB
6024 case FFECOM_f2ccodeINT:
6025 *type = make_signed_type (INT_TYPE_SIZE);
6026 break;
5ff904cd 6027
c7e4ee3a
CB
6028 case FFECOM_f2ccodeLONG:
6029 *type = make_signed_type (LONG_TYPE_SIZE);
6030 break;
5ff904cd 6031
c7e4ee3a
CB
6032 case FFECOM_f2ccodeLONGLONG:
6033 *type = make_signed_type (LONG_LONG_TYPE_SIZE);
6034 break;
5ff904cd 6035
c7e4ee3a
CB
6036 case FFECOM_f2ccodeCHARPTR:
6037 *type = build_pointer_type (DEFAULT_SIGNED_CHAR
6038 ? signed_char_type_node
6039 : unsigned_char_type_node);
6040 break;
5ff904cd 6041
c7e4ee3a
CB
6042 case FFECOM_f2ccodeFLOAT:
6043 *type = make_node (REAL_TYPE);
6044 TYPE_PRECISION (*type) = FLOAT_TYPE_SIZE;
6045 layout_type (*type);
6046 break;
6047
6048 case FFECOM_f2ccodeDOUBLE:
6049 *type = make_node (REAL_TYPE);
6050 TYPE_PRECISION (*type) = DOUBLE_TYPE_SIZE;
6051 layout_type (*type);
6052 break;
6053
6054 case FFECOM_f2ccodeLONGDOUBLE:
6055 *type = make_node (REAL_TYPE);
6056 TYPE_PRECISION (*type) = LONG_DOUBLE_TYPE_SIZE;
6057 layout_type (*type);
6058 break;
5ff904cd 6059
c7e4ee3a
CB
6060 case FFECOM_f2ccodeTWOREALS:
6061 *type = ffecom_make_complex_type_ (ffecom_f2c_real_type_node);
6062 break;
5ff904cd 6063
c7e4ee3a
CB
6064 case FFECOM_f2ccodeTWODOUBLEREALS:
6065 *type = ffecom_make_complex_type_ (ffecom_f2c_doublereal_type_node);
6066 break;
5ff904cd 6067
c7e4ee3a
CB
6068 default:
6069 assert ("unexpected FFECOM_f2ccodeXYZZY!" == NULL);
6070 *type = error_mark_node;
6071 return;
6072 }
5ff904cd 6073
c7e4ee3a
CB
6074 pushdecl (build_decl (TYPE_DECL,
6075 ffecom_get_invented_identifier ("__g77_f2c_%s",
6076 name, -1),
6077 *type));
6078}
5ff904cd 6079
c7e4ee3a
CB
6080#endif
6081#if FFECOM_targetCURRENT == FFECOM_targetGCC
6082/* Set the f2c list-directed-I/O code for whatever (integral) type has the
6083 given size. */
5ff904cd 6084
c7e4ee3a
CB
6085static void
6086ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size,
6087 int code)
6088{
6089 int j;
6090 tree t;
5ff904cd 6091
c7e4ee3a
CB
6092 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
6093 if (((t = ffecom_tree_type[bt][j]) != NULL_TREE)
6094 && (TREE_INT_CST_LOW (TYPE_SIZE (t)) == size))
6095 {
6096 assert (code != -1);
6097 ffecom_f2c_typecode_[bt][j] = code;
6098 code = -1;
6099 }
6100}
5ff904cd 6101
c7e4ee3a
CB
6102#endif
6103/* Finish up globals after doing all program units in file
5ff904cd 6104
c7e4ee3a 6105 Need to handle only uninitialized COMMON areas. */
5ff904cd 6106
c7e4ee3a
CB
6107#if FFECOM_targetCURRENT == FFECOM_targetGCC
6108static ffeglobal
6109ffecom_finish_global_ (ffeglobal global)
6110{
6111 tree cbtype;
6112 tree cbt;
6113 tree size;
5ff904cd 6114
c7e4ee3a
CB
6115 if (ffeglobal_type (global) != FFEGLOBAL_typeCOMMON)
6116 return global;
5ff904cd 6117
c7e4ee3a
CB
6118 if (ffeglobal_common_init (global))
6119 return global;
5ff904cd 6120
c7e4ee3a
CB
6121 cbt = ffeglobal_hook (global);
6122 if ((cbt == NULL_TREE)
6123 || !ffeglobal_common_have_size (global))
6124 return global; /* No need to make common, never ref'd. */
5ff904cd 6125
c7e4ee3a 6126 suspend_momentary ();
5ff904cd 6127
c7e4ee3a 6128 DECL_EXTERNAL (cbt) = 0;
5ff904cd 6129
c7e4ee3a 6130 /* Give the array a size now. */
5ff904cd 6131
c7e4ee3a
CB
6132 size = build_int_2 ((ffeglobal_common_size (global)
6133 + ffeglobal_common_pad (global)) - 1,
6134 0);
5ff904cd 6135
c7e4ee3a
CB
6136 cbtype = TREE_TYPE (cbt);
6137 TYPE_DOMAIN (cbtype) = build_range_type (integer_type_node,
6138 integer_zero_node,
6139 size);
6140 if (!TREE_TYPE (size))
6141 TREE_TYPE (size) = TYPE_DOMAIN (cbtype);
6142 layout_type (cbtype);
5ff904cd 6143
c7e4ee3a
CB
6144 cbt = start_decl (cbt, FALSE);
6145 assert (cbt == ffeglobal_hook (global));
5ff904cd 6146
c7e4ee3a 6147 finish_decl (cbt, NULL_TREE, FALSE);
5ff904cd 6148
c7e4ee3a
CB
6149 return global;
6150}
5ff904cd 6151
c7e4ee3a
CB
6152#endif
6153/* Finish up any untransformed symbols. */
5ff904cd 6154
c7e4ee3a
CB
6155#if FFECOM_targetCURRENT == FFECOM_targetGCC
6156static ffesymbol
6157ffecom_finish_symbol_transform_ (ffesymbol s)
5ff904cd 6158{
c7e4ee3a
CB
6159 if ((s == NULL) || (TREE_CODE (current_function_decl) == ERROR_MARK))
6160 return s;
5ff904cd 6161
c7e4ee3a
CB
6162 /* It's easy to know to transform an untransformed symbol, to make sure
6163 we put out debugging info for it. But COMMON variables, unlike
6164 EQUIVALENCE ones, aren't given declarations in addition to the
6165 tree expressions that specify offsets, because COMMON variables
6166 can be referenced in the outer scope where only dummy arguments
6167 (PARM_DECLs) should really be seen. To be safe, just don't do any
6168 VAR_DECLs for COMMON variables when we transform them for real
6169 use, and therefore we do all the VAR_DECL creating here. */
5ff904cd 6170
c7e4ee3a
CB
6171 if (ffesymbol_hook (s).decl_tree == NULL_TREE)
6172 {
6173 if (ffesymbol_kind (s) != FFEINFO_kindNONE
6174 || (ffesymbol_where (s) != FFEINFO_whereNONE
6175 && ffesymbol_where (s) != FFEINFO_whereINTRINSIC
6176 && ffesymbol_where (s) != FFEINFO_whereDUMMY))
6177 /* Not transformed, and not CHARACTER*(*), and not a dummy
6178 argument, which can happen only if the entry point names
6179 it "rides in on" are all invalidated for other reasons. */
6180 s = ffecom_sym_transform_ (s);
6181 }
5ff904cd 6182
c7e4ee3a
CB
6183 if ((ffesymbol_where (s) == FFEINFO_whereCOMMON)
6184 && (ffesymbol_hook (s).decl_tree != error_mark_node))
6185 {
6186#ifdef SOMEONE_GETS_DEBUG_SUPPORT_WORKING
6187 int yes = suspend_momentary ();
5ff904cd 6188
c7e4ee3a
CB
6189 /* This isn't working, at least for dbxout. The .s file looks
6190 okay to me (burley), but in gdb 4.9 at least, the variables
6191 appear to reside somewhere outside of the common area, so
6192 it doesn't make sense to mislead anyone by generating the info
6193 on those variables until this is fixed. NOTE: Same problem
6194 with EQUIVALENCE, sadly...see similar #if later. */
6195 ffecom_member_phase2_ (ffesymbol_storage (ffesymbol_common (s)),
6196 ffesymbol_storage (s));
5ff904cd 6197
c7e4ee3a
CB
6198 resume_momentary (yes);
6199#endif
5ff904cd
JL
6200 }
6201
c7e4ee3a
CB
6202 return s;
6203}
5ff904cd 6204
c7e4ee3a
CB
6205#endif
6206/* Append underscore(s) to name before calling get_identifier. "us"
6207 is nonzero if the name already contains an underscore and thus
6208 needs two underscores appended. */
5ff904cd 6209
c7e4ee3a
CB
6210#if FFECOM_targetCURRENT == FFECOM_targetGCC
6211static tree
6212ffecom_get_appended_identifier_ (char us, const char *name)
6213{
6214 int i;
6215 char *newname;
6216 tree id;
5ff904cd 6217
c7e4ee3a
CB
6218 newname = xmalloc ((i = strlen (name)) + 1
6219 + ffe_is_underscoring ()
6220 + us);
6221 memcpy (newname, name, i);
6222 newname[i] = '_';
6223 newname[i + us] = '_';
6224 newname[i + 1 + us] = '\0';
6225 id = get_identifier (newname);
5ff904cd 6226
c7e4ee3a 6227 free (newname);
5ff904cd 6228
c7e4ee3a
CB
6229 return id;
6230}
5ff904cd 6231
c7e4ee3a
CB
6232#endif
6233/* Decide whether to append underscore to name before calling
6234 get_identifier. */
5ff904cd 6235
c7e4ee3a
CB
6236#if FFECOM_targetCURRENT == FFECOM_targetGCC
6237static tree
6238ffecom_get_external_identifier_ (ffesymbol s)
6239{
6240 char us;
6241 const char *name = ffesymbol_text (s);
5ff904cd 6242
c7e4ee3a 6243 /* If name is a built-in name, just return it as is. */
5ff904cd 6244
c7e4ee3a
CB
6245 if (!ffe_is_underscoring ()
6246 || (strcmp (name, FFETARGET_nameBLANK_COMMON) == 0)
6247#if FFETARGET_isENFORCED_MAIN_NAME
6248 || (strcmp (name, FFETARGET_nameENFORCED_NAME) == 0)
6249#else
6250 || (strcmp (name, FFETARGET_nameUNNAMED_MAIN) == 0)
6251#endif
6252 || (strcmp (name, FFETARGET_nameUNNAMED_BLOCK_DATA) == 0))
6253 return get_identifier (name);
5ff904cd 6254
c7e4ee3a
CB
6255 us = ffe_is_second_underscore ()
6256 ? (strchr (name, '_') != NULL)
6257 : 0;
5ff904cd 6258
c7e4ee3a
CB
6259 return ffecom_get_appended_identifier_ (us, name);
6260}
5ff904cd 6261
c7e4ee3a
CB
6262#endif
6263/* Decide whether to append underscore to internal name before calling
6264 get_identifier.
6265
6266 This is for non-external, top-function-context names only. Transform
6267 identifier so it doesn't conflict with the transformed result
6268 of using a _different_ external name. E.g. if "CALL FOO" is
6269 transformed into "FOO_();", then the variable in "FOO_ = 3"
6270 must be transformed into something that does not conflict, since
6271 these two things should be independent.
5ff904cd 6272
c7e4ee3a
CB
6273 The transformation is as follows. If the name does not contain
6274 an underscore, there is no possible conflict, so just return.
6275 If the name does contain an underscore, then transform it just
6276 like we transform an external identifier. */
5ff904cd 6277
c7e4ee3a
CB
6278#if FFECOM_targetCURRENT == FFECOM_targetGCC
6279static tree
6280ffecom_get_identifier_ (const char *name)
6281{
6282 /* If name does not contain an underscore, just return it as is. */
6283
6284 if (!ffe_is_underscoring ()
6285 || (strchr (name, '_') == NULL))
6286 return get_identifier (name);
6287
6288 return ffecom_get_appended_identifier_ (ffe_is_second_underscore (),
6289 name);
5ff904cd
JL
6290}
6291
6292#endif
c7e4ee3a 6293/* ffecom_gen_sfuncdef_ -- Generate definition of statement function
5ff904cd 6294
c7e4ee3a
CB
6295 tree t;
6296 ffesymbol s; // kindFUNCTION, whereIMMEDIATE.
6297 t = ffecom_gen_sfuncdef_(s,ffesymbol_basictype(s),
6298 ffesymbol_kindtype(s));
5ff904cd 6299
c7e4ee3a
CB
6300 Call after setting up containing function and getting trees for all
6301 other symbols. */
5ff904cd
JL
6302
6303#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
6304static tree
6305ffecom_gen_sfuncdef_ (ffesymbol s, ffeinfoBasictype bt, ffeinfoKindtype kt)
5ff904cd 6306{
c7e4ee3a
CB
6307 ffebld expr = ffesymbol_sfexpr (s);
6308 tree type;
6309 tree func;
6310 tree result;
6311 bool charfunc = (bt == FFEINFO_basictypeCHARACTER);
6312 static bool recurse = FALSE;
6313 int yes;
6314 int old_lineno = lineno;
6315 char *old_input_filename = input_filename;
5ff904cd 6316
c7e4ee3a 6317 ffecom_nested_entry_ = s;
5ff904cd 6318
c7e4ee3a
CB
6319 /* For now, we don't have a handy pointer to where the sfunc is actually
6320 defined, though that should be easy to add to an ffesymbol. (The
6321 token/where info available might well point to the place where the type
6322 of the sfunc is declared, especially if that precedes the place where
6323 the sfunc itself is defined, which is typically the case.) We should
6324 put out a null pointer rather than point somewhere wrong, but I want to
6325 see how it works at this point. */
5ff904cd 6326
c7e4ee3a
CB
6327 input_filename = ffesymbol_where_filename (s);
6328 lineno = ffesymbol_where_filelinenum (s);
5ff904cd 6329
c7e4ee3a
CB
6330 /* Pretransform the expression so any newly discovered things belong to the
6331 outer program unit, not to the statement function. */
5ff904cd 6332
c7e4ee3a 6333 ffecom_expr_transform_ (expr);
5ff904cd 6334
c7e4ee3a
CB
6335 /* Make sure no recursive invocation of this fn (a specific case of failing
6336 to pretransform an sfunc's expression, i.e. where its expression
6337 references another untransformed sfunc) happens. */
6338
6339 assert (!recurse);
6340 recurse = TRUE;
6341
6342 yes = suspend_momentary ();
6343
6344 push_f_function_context ();
6345
6346 if (charfunc)
6347 type = void_type_node;
6348 else
5ff904cd 6349 {
c7e4ee3a
CB
6350 type = ffecom_tree_type[bt][kt];
6351 if (type == NULL_TREE)
6352 type = integer_type_node; /* _sym_exec_transition reports
6353 error. */
6354 }
5ff904cd 6355
c7e4ee3a
CB
6356 start_function (ffecom_get_identifier_ (ffesymbol_text (s)),
6357 build_function_type (type, NULL_TREE),
6358 1, /* nested/inline */
6359 0); /* TREE_PUBLIC */
5ff904cd 6360
c7e4ee3a
CB
6361 /* We don't worry about COMPLEX return values here, because this is
6362 entirely internal to our code, and gcc has the ability to return COMPLEX
6363 directly as a value. */
6364
6365 yes = suspend_momentary ();
6366
6367 if (charfunc)
6368 { /* Prepend arg for where result goes. */
6369 tree type;
6370
6371 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
6372
6373 result = ffecom_get_invented_identifier ("__g77_%s",
6374 "result", -1);
6375
6376 ffecom_char_enhance_arg_ (&type, s); /* Ignore returned length. */
6377
6378 type = build_pointer_type (type);
6379 result = build_decl (PARM_DECL, result, type);
6380
6381 push_parm_decl (result);
5ff904cd 6382 }
c7e4ee3a
CB
6383 else
6384 result = NULL_TREE; /* Not ref'd if !charfunc. */
5ff904cd 6385
c7e4ee3a 6386 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (s), TRUE);
5ff904cd 6387
c7e4ee3a 6388 resume_momentary (yes);
5ff904cd 6389
c7e4ee3a
CB
6390 store_parm_decls (0);
6391
6392 ffecom_start_compstmt ();
6393
6394 if (expr != NULL)
5ff904cd 6395 {
c7e4ee3a
CB
6396 if (charfunc)
6397 {
6398 ffetargetCharacterSize sz = ffesymbol_size (s);
6399 tree result_length;
5ff904cd 6400
c7e4ee3a
CB
6401 result_length = build_int_2 (sz, 0);
6402 TREE_TYPE (result_length) = ffecom_f2c_ftnlen_type_node;
5ff904cd 6403
c7e4ee3a 6404 ffecom_prepare_let_char_ (sz, expr);
5ff904cd 6405
c7e4ee3a 6406 ffecom_prepare_end ();
5ff904cd 6407
c7e4ee3a
CB
6408 ffecom_let_char_ (result, result_length, sz, expr);
6409 expand_null_return ();
6410 }
6411 else
6412 {
6413 ffecom_prepare_expr (expr);
5ff904cd 6414
c7e4ee3a 6415 ffecom_prepare_end ();
5ff904cd 6416
c7e4ee3a
CB
6417 expand_return (ffecom_modify (NULL_TREE,
6418 DECL_RESULT (current_function_decl),
6419 ffecom_expr (expr)));
6420 }
5ff904cd 6421
c7e4ee3a
CB
6422 clear_momentary ();
6423 }
5ff904cd 6424
c7e4ee3a 6425 ffecom_end_compstmt ();
5ff904cd 6426
c7e4ee3a
CB
6427 func = current_function_decl;
6428 finish_function (1);
5ff904cd 6429
c7e4ee3a 6430 pop_f_function_context ();
5ff904cd 6431
c7e4ee3a 6432 resume_momentary (yes);
5ff904cd 6433
c7e4ee3a
CB
6434 recurse = FALSE;
6435
6436 lineno = old_lineno;
6437 input_filename = old_input_filename;
6438
6439 ffecom_nested_entry_ = NULL;
6440
6441 return func;
5ff904cd
JL
6442}
6443
6444#endif
5ff904cd 6445
c7e4ee3a
CB
6446#if FFECOM_targetCURRENT == FFECOM_targetGCC
6447static const char *
6448ffecom_gfrt_args_ (ffecomGfrt ix)
5ff904cd 6449{
c7e4ee3a
CB
6450 return ffecom_gfrt_argstring_[ix];
6451}
5ff904cd 6452
c7e4ee3a
CB
6453#endif
6454#if FFECOM_targetCURRENT == FFECOM_targetGCC
6455static tree
6456ffecom_gfrt_tree_ (ffecomGfrt ix)
6457{
6458 if (ffecom_gfrt_[ix] == NULL_TREE)
6459 ffecom_make_gfrt_ (ix);
6460
6461 return ffecom_1 (ADDR_EXPR,
6462 build_pointer_type (TREE_TYPE (ffecom_gfrt_[ix])),
6463 ffecom_gfrt_[ix]);
5ff904cd
JL
6464}
6465
6466#endif
c7e4ee3a 6467/* Return initialize-to-zero expression for this VAR_DECL. */
5ff904cd
JL
6468
6469#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
6470static tree
6471ffecom_init_zero_ (tree decl)
5ff904cd 6472{
c7e4ee3a
CB
6473 tree init;
6474 int incremental = TREE_STATIC (decl);
6475 tree type = TREE_TYPE (decl);
5ff904cd 6476
c7e4ee3a
CB
6477 if (incremental)
6478 {
6479 int momentary = suspend_momentary ();
6480 push_obstacks_nochange ();
6481 if (TREE_PERMANENT (decl))
6482 end_temporary_allocation ();
6483 make_decl_rtl (decl, NULL, TREE_PUBLIC (decl) ? 1 : 0);
6484 assemble_variable (decl, TREE_PUBLIC (decl) ? 1 : 0, 0, 1);
6485 pop_obstacks ();
6486 resume_momentary (momentary);
6487 }
5ff904cd 6488
c7e4ee3a 6489 push_momentary ();
5ff904cd 6490
c7e4ee3a
CB
6491 if ((TREE_CODE (type) != ARRAY_TYPE)
6492 && (TREE_CODE (type) != RECORD_TYPE)
6493 && (TREE_CODE (type) != UNION_TYPE)
6494 && !incremental)
6495 init = convert (type, integer_zero_node);
6496 else if (!incremental)
6497 {
6498 int momentary = suspend_momentary ();
5ff904cd 6499
c7e4ee3a
CB
6500 init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
6501 TREE_CONSTANT (init) = 1;
6502 TREE_STATIC (init) = 1;
5ff904cd 6503
c7e4ee3a
CB
6504 resume_momentary (momentary);
6505 }
6506 else
6507 {
6508 int momentary = suspend_momentary ();
5ff904cd 6509
c7e4ee3a
CB
6510 assemble_zeros (int_size_in_bytes (type));
6511 init = error_mark_node;
5ff904cd 6512
c7e4ee3a
CB
6513 resume_momentary (momentary);
6514 }
5ff904cd 6515
c7e4ee3a 6516 pop_momentary_nofree ();
5ff904cd 6517
c7e4ee3a 6518 return init;
5ff904cd
JL
6519}
6520
6521#endif
5ff904cd 6522#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
6523static tree
6524ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg,
6525 tree *maybe_tree)
5ff904cd 6526{
c7e4ee3a
CB
6527 tree expr_tree;
6528 tree length_tree;
5ff904cd 6529
c7e4ee3a 6530 switch (ffebld_op (arg))
6829256f 6531 {
c7e4ee3a
CB
6532 case FFEBLD_opCONTER: /* For F90, check 0-length. */
6533 if (ffetarget_length_character1
6534 (ffebld_constant_character1
6535 (ffebld_conter (arg))) == 0)
6536 {
6537 *maybe_tree = integer_zero_node;
6538 return convert (tree_type, integer_zero_node);
6539 }
5ff904cd 6540
c7e4ee3a
CB
6541 *maybe_tree = integer_one_node;
6542 expr_tree = build_int_2 (*ffetarget_text_character1
6543 (ffebld_constant_character1
6544 (ffebld_conter (arg))),
6545 0);
6546 TREE_TYPE (expr_tree) = tree_type;
6547 return expr_tree;
5ff904cd 6548
c7e4ee3a
CB
6549 case FFEBLD_opSYMTER:
6550 case FFEBLD_opARRAYREF:
6551 case FFEBLD_opFUNCREF:
6552 case FFEBLD_opSUBSTR:
6553 ffecom_char_args_ (&expr_tree, &length_tree, arg);
5ff904cd 6554
c7e4ee3a
CB
6555 if ((expr_tree == error_mark_node)
6556 || (length_tree == error_mark_node))
6557 {
6558 *maybe_tree = error_mark_node;
6559 return error_mark_node;
6560 }
5ff904cd 6561
c7e4ee3a
CB
6562 if (integer_zerop (length_tree))
6563 {
6564 *maybe_tree = integer_zero_node;
6565 return convert (tree_type, integer_zero_node);
6566 }
6567
6568 expr_tree
6569 = ffecom_1 (INDIRECT_REF,
6570 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
6571 expr_tree);
6572 expr_tree
6573 = ffecom_2 (ARRAY_REF,
6574 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
6575 expr_tree,
6576 integer_one_node);
6577 expr_tree = convert (tree_type, expr_tree);
6578
6579 if (TREE_CODE (length_tree) == INTEGER_CST)
6580 *maybe_tree = integer_one_node;
6581 else /* Must check length at run time. */
6582 *maybe_tree
6583 = ffecom_truth_value
6584 (ffecom_2 (GT_EXPR, integer_type_node,
6585 length_tree,
6586 ffecom_f2c_ftnlen_zero_node));
6587 return expr_tree;
6588
6589 case FFEBLD_opPAREN:
6590 case FFEBLD_opCONVERT:
6591 if (ffeinfo_size (ffebld_info (arg)) == 0)
6592 {
6593 *maybe_tree = integer_zero_node;
6594 return convert (tree_type, integer_zero_node);
6595 }
6596 return ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
6597 maybe_tree);
6598
6599 case FFEBLD_opCONCATENATE:
6600 {
6601 tree maybe_left;
6602 tree maybe_right;
6603 tree expr_left;
6604 tree expr_right;
6605
6606 expr_left = ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
6607 &maybe_left);
6608 expr_right = ffecom_intrinsic_ichar_ (tree_type, ffebld_right (arg),
6609 &maybe_right);
6610 *maybe_tree = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
6611 maybe_left,
6612 maybe_right);
6613 expr_tree = ffecom_3 (COND_EXPR, tree_type,
6614 maybe_left,
6615 expr_left,
6616 expr_right);
6617 return expr_tree;
6618 }
6619
6620 default:
6621 assert ("bad op in ICHAR" == NULL);
6622 return error_mark_node;
6623 }
5ff904cd
JL
6624}
6625
6626#endif
c7e4ee3a
CB
6627/* ffecom_intrinsic_len_ -- Return length info for char arg (LEN())
6628
6629 tree length_arg;
6630 ffebld expr;
6631 length_arg = ffecom_intrinsic_len_ (expr);
6632
6633 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
6634 subexpressions by constructing the appropriate tree for the
6635 length-of-character-text argument in a calling sequence. */
5ff904cd
JL
6636
6637#if FFECOM_targetCURRENT == FFECOM_targetGCC
6638static tree
c7e4ee3a 6639ffecom_intrinsic_len_ (ffebld expr)
5ff904cd 6640{
c7e4ee3a
CB
6641 ffetargetCharacter1 val;
6642 tree length;
6643
6644 switch (ffebld_op (expr))
6645 {
6646 case FFEBLD_opCONTER:
6647 val = ffebld_constant_character1 (ffebld_conter (expr));
6648 length = build_int_2 (ffetarget_length_character1 (val), 0);
6649 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6650 break;
6651
6652 case FFEBLD_opSYMTER:
6653 {
6654 ffesymbol s = ffebld_symter (expr);
6655 tree item;
6656
6657 item = ffesymbol_hook (s).decl_tree;
6658 if (item == NULL_TREE)
6659 {
6660 s = ffecom_sym_transform_ (s);
6661 item = ffesymbol_hook (s).decl_tree;
6662 }
6663 if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
6664 {
6665 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
6666 length = ffesymbol_hook (s).length_tree;
6667 else
6668 {
6669 length = build_int_2 (ffesymbol_size (s), 0);
6670 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6671 }
6672 }
6673 else if (item == error_mark_node)
6674 length = error_mark_node;
6675 else /* FFEINFO_kindFUNCTION: */
6676 length = NULL_TREE;
6677 }
6678 break;
5ff904cd 6679
c7e4ee3a
CB
6680 case FFEBLD_opARRAYREF:
6681 length = ffecom_intrinsic_len_ (ffebld_left (expr));
6682 break;
5ff904cd 6683
c7e4ee3a
CB
6684 case FFEBLD_opSUBSTR:
6685 {
6686 ffebld start;
6687 ffebld end;
6688 ffebld thing = ffebld_right (expr);
6689 tree start_tree;
6690 tree end_tree;
5ff904cd 6691
c7e4ee3a
CB
6692 assert (ffebld_op (thing) == FFEBLD_opITEM);
6693 start = ffebld_head (thing);
6694 thing = ffebld_trail (thing);
6695 assert (ffebld_trail (thing) == NULL);
6696 end = ffebld_head (thing);
5ff904cd 6697
c7e4ee3a 6698 length = ffecom_intrinsic_len_ (ffebld_left (expr));
5ff904cd 6699
c7e4ee3a
CB
6700 if (length == error_mark_node)
6701 break;
5ff904cd 6702
c7e4ee3a
CB
6703 if (start == NULL)
6704 {
6705 if (end == NULL)
6706 ;
6707 else
6708 {
6709 length = convert (ffecom_f2c_ftnlen_type_node,
6710 ffecom_expr (end));
6711 }
6712 }
6713 else
6714 {
6715 start_tree = convert (ffecom_f2c_ftnlen_type_node,
6716 ffecom_expr (start));
5ff904cd 6717
c7e4ee3a
CB
6718 if (start_tree == error_mark_node)
6719 {
6720 length = error_mark_node;
6721 break;
6722 }
5ff904cd 6723
c7e4ee3a
CB
6724 if (end == NULL)
6725 {
6726 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6727 ffecom_f2c_ftnlen_one_node,
6728 ffecom_2 (MINUS_EXPR,
6729 ffecom_f2c_ftnlen_type_node,
6730 length,
6731 start_tree));
6732 }
6733 else
6734 {
6735 end_tree = convert (ffecom_f2c_ftnlen_type_node,
6736 ffecom_expr (end));
5ff904cd 6737
c7e4ee3a
CB
6738 if (end_tree == error_mark_node)
6739 {
6740 length = error_mark_node;
6741 break;
6742 }
5ff904cd 6743
c7e4ee3a
CB
6744 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6745 ffecom_f2c_ftnlen_one_node,
6746 ffecom_2 (MINUS_EXPR,
6747 ffecom_f2c_ftnlen_type_node,
6748 end_tree, start_tree));
6749 }
6750 }
6751 }
6752 break;
5ff904cd 6753
c7e4ee3a
CB
6754 case FFEBLD_opCONCATENATE:
6755 length
6756 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6757 ffecom_intrinsic_len_ (ffebld_left (expr)),
6758 ffecom_intrinsic_len_ (ffebld_right (expr)));
6759 break;
5ff904cd 6760
c7e4ee3a
CB
6761 case FFEBLD_opFUNCREF:
6762 case FFEBLD_opCONVERT:
6763 length = build_int_2 (ffebld_size (expr), 0);
6764 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6765 break;
5ff904cd 6766
c7e4ee3a
CB
6767 default:
6768 assert ("bad op for single char arg expr" == NULL);
6769 length = ffecom_f2c_ftnlen_zero_node;
6770 break;
6771 }
5ff904cd 6772
c7e4ee3a 6773 assert (length != NULL_TREE);
5ff904cd 6774
c7e4ee3a 6775 return length;
5ff904cd
JL
6776}
6777
6778#endif
c7e4ee3a 6779/* Handle CHARACTER assignments.
5ff904cd 6780
c7e4ee3a
CB
6781 Generates code to do the assignment. Used by ordinary assignment
6782 statement handler ffecom_let_stmt and by statement-function
6783 handler to generate code for a statement function. */
5ff904cd
JL
6784
6785#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
6786static void
6787ffecom_let_char_ (tree dest_tree, tree dest_length,
6788 ffetargetCharacterSize dest_size, ffebld source)
5ff904cd 6789{
c7e4ee3a
CB
6790 ffecomConcatList_ catlist;
6791 tree source_length;
6792 tree source_tree;
6793 tree expr_tree;
5ff904cd 6794
c7e4ee3a
CB
6795 if ((dest_tree == error_mark_node)
6796 || (dest_length == error_mark_node))
6797 return;
5ff904cd 6798
c7e4ee3a
CB
6799 assert (dest_tree != NULL_TREE);
6800 assert (dest_length != NULL_TREE);
5ff904cd 6801
c7e4ee3a
CB
6802 /* Source might be an opCONVERT, which just means it is a different size
6803 than the destination. Since the underlying implementation here handles
6804 that (directly or via the s_copy or s_cat run-time-library functions),
6805 we don't need the "convenience" of an opCONVERT that tells us to
6806 truncate or blank-pad, particularly since the resulting implementation
6807 would probably be slower than otherwise. */
5ff904cd 6808
c7e4ee3a
CB
6809 while (ffebld_op (source) == FFEBLD_opCONVERT)
6810 source = ffebld_left (source);
5ff904cd 6811
c7e4ee3a
CB
6812 catlist = ffecom_concat_list_new_ (source, dest_size);
6813 switch (ffecom_concat_list_count_ (catlist))
6814 {
6815 case 0: /* Shouldn't happen, but in case it does... */
6816 ffecom_concat_list_kill_ (catlist);
6817 source_tree = null_pointer_node;
6818 source_length = ffecom_f2c_ftnlen_zero_node;
6819 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6820 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
6821 TREE_CHAIN (TREE_CHAIN (expr_tree))
6822 = build_tree_list (NULL_TREE, dest_length);
6823 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6824 = build_tree_list (NULL_TREE, source_length);
5ff904cd 6825
c7e4ee3a
CB
6826 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree, NULL_TREE);
6827 TREE_SIDE_EFFECTS (expr_tree) = 1;
5ff904cd 6828
c7e4ee3a 6829 expand_expr_stmt (expr_tree);
5ff904cd 6830
c7e4ee3a 6831 return;
5ff904cd 6832
c7e4ee3a
CB
6833 case 1: /* The (fairly) easy case. */
6834 ffecom_char_args_ (&source_tree, &source_length,
6835 ffecom_concat_list_expr_ (catlist, 0));
6836 ffecom_concat_list_kill_ (catlist);
6837 assert (source_tree != NULL_TREE);
6838 assert (source_length != NULL_TREE);
6839
6840 if ((source_tree == error_mark_node)
6841 || (source_length == error_mark_node))
6842 return;
6843
6844 if (dest_size == 1)
6845 {
6846 dest_tree
6847 = ffecom_1 (INDIRECT_REF,
6848 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6849 (dest_tree))),
6850 dest_tree);
6851 dest_tree
6852 = ffecom_2 (ARRAY_REF,
6853 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6854 (dest_tree))),
6855 dest_tree,
6856 integer_one_node);
6857 source_tree
6858 = ffecom_1 (INDIRECT_REF,
6859 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6860 (source_tree))),
6861 source_tree);
6862 source_tree
6863 = ffecom_2 (ARRAY_REF,
6864 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6865 (source_tree))),
6866 source_tree,
6867 integer_one_node);
5ff904cd 6868
c7e4ee3a 6869 expr_tree = ffecom_modify (void_type_node, dest_tree, source_tree);
5ff904cd 6870
c7e4ee3a 6871 expand_expr_stmt (expr_tree);
5ff904cd 6872
c7e4ee3a
CB
6873 return;
6874 }
5ff904cd 6875
c7e4ee3a
CB
6876 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6877 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
6878 TREE_CHAIN (TREE_CHAIN (expr_tree))
6879 = build_tree_list (NULL_TREE, dest_length);
6880 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6881 = build_tree_list (NULL_TREE, source_length);
5ff904cd 6882
c7e4ee3a
CB
6883 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree, NULL_TREE);
6884 TREE_SIDE_EFFECTS (expr_tree) = 1;
5ff904cd 6885
c7e4ee3a 6886 expand_expr_stmt (expr_tree);
5ff904cd 6887
c7e4ee3a 6888 return;
5ff904cd 6889
c7e4ee3a
CB
6890 default: /* Must actually concatenate things. */
6891 break;
6892 }
5ff904cd 6893
c7e4ee3a 6894 /* Heavy-duty concatenation. */
5ff904cd 6895
c7e4ee3a
CB
6896 {
6897 int count = ffecom_concat_list_count_ (catlist);
6898 int i;
6899 tree lengths;
6900 tree items;
6901 tree length_array;
6902 tree item_array;
6903 tree citem;
6904 tree clength;
5ff904cd 6905
c7e4ee3a
CB
6906#ifdef HOHO
6907 length_array
6908 = lengths
6909 = ffecom_push_tempvar (ffecom_f2c_ftnlen_type_node,
6910 FFETARGET_charactersizeNONE, count, TRUE);
6911 item_array = items = ffecom_push_tempvar (ffecom_f2c_address_type_node,
6912 FFETARGET_charactersizeNONE,
6913 count, TRUE);
6914#else
6915 {
6916 tree hook;
6917
6918 hook = ffebld_nonter_hook (source);
6919 assert (hook);
6920 assert (TREE_CODE (hook) == TREE_VEC);
6921 assert (TREE_VEC_LENGTH (hook) == 2);
6922 length_array = lengths = TREE_VEC_ELT (hook, 0);
6923 item_array = items = TREE_VEC_ELT (hook, 1);
5ff904cd 6924 }
c7e4ee3a 6925#endif
5ff904cd 6926
c7e4ee3a
CB
6927 for (i = 0; i < count; ++i)
6928 {
6929 ffecom_char_args_ (&citem, &clength,
6930 ffecom_concat_list_expr_ (catlist, i));
6931 if ((citem == error_mark_node)
6932 || (clength == error_mark_node))
6933 {
6934 ffecom_concat_list_kill_ (catlist);
6935 return;
6936 }
5ff904cd 6937
c7e4ee3a
CB
6938 items
6939 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
6940 ffecom_modify (void_type_node,
6941 ffecom_2 (ARRAY_REF,
6942 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
6943 item_array,
6944 build_int_2 (i, 0)),
6945 citem),
6946 items);
6947 lengths
6948 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
6949 ffecom_modify (void_type_node,
6950 ffecom_2 (ARRAY_REF,
6951 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
6952 length_array,
6953 build_int_2 (i, 0)),
6954 clength),
6955 lengths);
6956 }
5ff904cd 6957
c7e4ee3a
CB
6958 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6959 TREE_CHAIN (expr_tree)
6960 = build_tree_list (NULL_TREE,
6961 ffecom_1 (ADDR_EXPR,
6962 build_pointer_type (TREE_TYPE (items)),
6963 items));
6964 TREE_CHAIN (TREE_CHAIN (expr_tree))
6965 = build_tree_list (NULL_TREE,
6966 ffecom_1 (ADDR_EXPR,
6967 build_pointer_type (TREE_TYPE (lengths)),
6968 lengths));
6969 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6970 = build_tree_list
6971 (NULL_TREE,
6972 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
6973 convert (ffecom_f2c_ftnlen_type_node,
6974 build_int_2 (count, 0))));
6975 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree))))
6976 = build_tree_list (NULL_TREE, dest_length);
5ff904cd 6977
c7e4ee3a
CB
6978 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCAT, expr_tree, NULL_TREE);
6979 TREE_SIDE_EFFECTS (expr_tree) = 1;
5ff904cd 6980
c7e4ee3a
CB
6981 expand_expr_stmt (expr_tree);
6982 }
5ff904cd 6983
c7e4ee3a
CB
6984 ffecom_concat_list_kill_ (catlist);
6985}
5ff904cd 6986
c7e4ee3a
CB
6987#endif
6988/* ffecom_make_gfrt_ -- Make initial info for run-time routine
5ff904cd 6989
c7e4ee3a
CB
6990 ffecomGfrt ix;
6991 ffecom_make_gfrt_(ix);
5ff904cd 6992
c7e4ee3a
CB
6993 Assumes gfrt_[ix] is NULL_TREE, and replaces it with the FUNCTION_DECL
6994 for the indicated run-time routine (ix). */
5ff904cd 6995
c7e4ee3a
CB
6996#if FFECOM_targetCURRENT == FFECOM_targetGCC
6997static void
6998ffecom_make_gfrt_ (ffecomGfrt ix)
6999{
7000 tree t;
7001 tree ttype;
5ff904cd 7002
c7e4ee3a
CB
7003 push_obstacks_nochange ();
7004 end_temporary_allocation ();
5ff904cd 7005
c7e4ee3a
CB
7006 switch (ffecom_gfrt_type_[ix])
7007 {
7008 case FFECOM_rttypeVOID_:
7009 ttype = void_type_node;
7010 break;
5ff904cd 7011
c7e4ee3a
CB
7012 case FFECOM_rttypeVOIDSTAR_:
7013 ttype = TREE_TYPE (null_pointer_node); /* `void *'. */
7014 break;
5ff904cd 7015
c7e4ee3a
CB
7016 case FFECOM_rttypeFTNINT_:
7017 ttype = ffecom_f2c_ftnint_type_node;
7018 break;
5ff904cd 7019
c7e4ee3a
CB
7020 case FFECOM_rttypeINTEGER_:
7021 ttype = ffecom_f2c_integer_type_node;
7022 break;
5ff904cd 7023
c7e4ee3a
CB
7024 case FFECOM_rttypeLONGINT_:
7025 ttype = ffecom_f2c_longint_type_node;
7026 break;
5ff904cd 7027
c7e4ee3a
CB
7028 case FFECOM_rttypeLOGICAL_:
7029 ttype = ffecom_f2c_logical_type_node;
7030 break;
5ff904cd 7031
c7e4ee3a
CB
7032 case FFECOM_rttypeREAL_F2C_:
7033 ttype = double_type_node;
7034 break;
5ff904cd 7035
c7e4ee3a
CB
7036 case FFECOM_rttypeREAL_GNU_:
7037 ttype = float_type_node;
7038 break;
5ff904cd 7039
c7e4ee3a
CB
7040 case FFECOM_rttypeCOMPLEX_F2C_:
7041 ttype = void_type_node;
7042 break;
5ff904cd 7043
c7e4ee3a
CB
7044 case FFECOM_rttypeCOMPLEX_GNU_:
7045 ttype = ffecom_f2c_complex_type_node;
7046 break;
5ff904cd 7047
c7e4ee3a
CB
7048 case FFECOM_rttypeDOUBLE_:
7049 ttype = double_type_node;
7050 break;
5ff904cd 7051
c7e4ee3a
CB
7052 case FFECOM_rttypeDOUBLEREAL_:
7053 ttype = ffecom_f2c_doublereal_type_node;
7054 break;
5ff904cd 7055
c7e4ee3a
CB
7056 case FFECOM_rttypeDBLCMPLX_F2C_:
7057 ttype = void_type_node;
7058 break;
5ff904cd 7059
c7e4ee3a
CB
7060 case FFECOM_rttypeDBLCMPLX_GNU_:
7061 ttype = ffecom_f2c_doublecomplex_type_node;
7062 break;
5ff904cd 7063
c7e4ee3a
CB
7064 case FFECOM_rttypeCHARACTER_:
7065 ttype = void_type_node;
7066 break;
7067
7068 default:
7069 ttype = NULL;
7070 assert ("bad rttype" == NULL);
7071 break;
5ff904cd 7072 }
5ff904cd 7073
c7e4ee3a
CB
7074 ttype = build_function_type (ttype, NULL_TREE);
7075 t = build_decl (FUNCTION_DECL,
7076 get_identifier (ffecom_gfrt_name_[ix]),
7077 ttype);
7078 DECL_EXTERNAL (t) = 1;
7079 TREE_PUBLIC (t) = 1;
7080 TREE_THIS_VOLATILE (t) = ffecom_gfrt_volatile_[ix] ? 1 : 0;
5ff904cd 7081
c7e4ee3a 7082 t = start_decl (t, TRUE);
5ff904cd 7083
c7e4ee3a 7084 finish_decl (t, NULL_TREE, TRUE);
5ff904cd 7085
c7e4ee3a
CB
7086 resume_temporary_allocation ();
7087 pop_obstacks ();
7088
7089 ffecom_gfrt_[ix] = t;
5ff904cd
JL
7090}
7091
7092#endif
c7e4ee3a
CB
7093/* Phase 1 pass over each member of a COMMON/EQUIVALENCE group. */
7094
5ff904cd 7095#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
7096static void
7097ffecom_member_phase1_ (ffestorag mst UNUSED, ffestorag st)
5ff904cd 7098{
c7e4ee3a 7099 ffesymbol s = ffestorag_symbol (st);
5ff904cd 7100
c7e4ee3a
CB
7101 if (ffesymbol_namelisted (s))
7102 ffecom_member_namelisted_ = TRUE;
7103}
5ff904cd 7104
c7e4ee3a
CB
7105#endif
7106/* Phase 2 pass over each member of a COMMON/EQUIVALENCE group. Declare
7107 the member so debugger will see it. Otherwise nobody should be
7108 referencing the member. */
5ff904cd 7109
c7e4ee3a
CB
7110#if FFECOM_targetCURRENT == FFECOM_targetGCC
7111#ifdef SOMEONE_GETS_DEBUG_SUPPORT_WORKING
7112static void
7113ffecom_member_phase2_ (ffestorag mst, ffestorag st)
7114{
7115 ffesymbol s;
7116 tree t;
7117 tree mt;
7118 tree type;
5ff904cd 7119
c7e4ee3a
CB
7120 if ((mst == NULL)
7121 || ((mt = ffestorag_hook (mst)) == NULL)
7122 || (mt == error_mark_node))
7123 return;
5ff904cd 7124
c7e4ee3a
CB
7125 if ((st == NULL)
7126 || ((s = ffestorag_symbol (st)) == NULL))
7127 return;
5ff904cd 7128
c7e4ee3a
CB
7129 type = ffecom_type_localvar_ (s,
7130 ffesymbol_basictype (s),
7131 ffesymbol_kindtype (s));
7132 if (type == error_mark_node)
7133 return;
5ff904cd 7134
c7e4ee3a
CB
7135 t = build_decl (VAR_DECL,
7136 ffecom_get_identifier_ (ffesymbol_text (s)),
7137 type);
5ff904cd 7138
c7e4ee3a
CB
7139 TREE_STATIC (t) = TREE_STATIC (mt);
7140 DECL_INITIAL (t) = NULL_TREE;
7141 TREE_ASM_WRITTEN (t) = 1;
5ff904cd 7142
c7e4ee3a
CB
7143 DECL_RTL (t)
7144 = gen_rtx (MEM, TYPE_MODE (type),
7145 plus_constant (XEXP (DECL_RTL (mt), 0),
7146 ffestorag_modulo (mst)
7147 + ffestorag_offset (st)
7148 - ffestorag_offset (mst)));
5ff904cd 7149
c7e4ee3a 7150 t = start_decl (t, FALSE);
5ff904cd 7151
c7e4ee3a 7152 finish_decl (t, NULL_TREE, FALSE);
5ff904cd
JL
7153}
7154
7155#endif
c7e4ee3a
CB
7156#endif
7157/* Prepare source expression for assignment into a destination perhaps known
7158 to be of a specific size. */
5ff904cd 7159
c7e4ee3a
CB
7160static void
7161ffecom_prepare_let_char_ (ffetargetCharacterSize dest_size, ffebld source)
5ff904cd 7162{
c7e4ee3a
CB
7163 ffecomConcatList_ catlist;
7164 int count;
7165 int i;
7166 tree ltmp;
7167 tree itmp;
7168 tree tempvar = NULL_TREE;
5ff904cd 7169
c7e4ee3a
CB
7170 while (ffebld_op (source) == FFEBLD_opCONVERT)
7171 source = ffebld_left (source);
5ff904cd 7172
c7e4ee3a
CB
7173 catlist = ffecom_concat_list_new_ (source, dest_size);
7174 count = ffecom_concat_list_count_ (catlist);
5ff904cd 7175
c7e4ee3a
CB
7176 if (count >= 2)
7177 {
7178 ltmp
7179 = ffecom_make_tempvar ("let_char_len", ffecom_f2c_ftnlen_type_node,
7180 FFETARGET_charactersizeNONE, count);
7181 itmp
7182 = ffecom_make_tempvar ("let_char_item", ffecom_f2c_address_type_node,
7183 FFETARGET_charactersizeNONE, count);
7184
7185 tempvar = make_tree_vec (2);
7186 TREE_VEC_ELT (tempvar, 0) = ltmp;
7187 TREE_VEC_ELT (tempvar, 1) = itmp;
7188 }
5ff904cd 7189
c7e4ee3a
CB
7190 for (i = 0; i < count; ++i)
7191 ffecom_prepare_arg_ptr_to_expr (ffecom_concat_list_expr_ (catlist, i));
5ff904cd 7192
c7e4ee3a 7193 ffecom_concat_list_kill_ (catlist);
5ff904cd 7194
c7e4ee3a
CB
7195 if (tempvar)
7196 {
7197 ffebld_nonter_set_hook (source, tempvar);
7198 current_binding_level->prep_state = 1;
7199 }
7200}
5ff904cd 7201
c7e4ee3a 7202/* ffecom_push_dummy_decls_ -- Transform dummy args, push parm decls in order
5ff904cd 7203
c7e4ee3a
CB
7204 Ignores STAR (alternate-return) dummies. All other get exec-transitioned
7205 (which generates their trees) and then their trees get push_parm_decl'd.
5ff904cd 7206
c7e4ee3a
CB
7207 The second arg is TRUE if the dummies are for a statement function, in
7208 which case lengths are not pushed for character arguments (since they are
7209 always known by both the caller and the callee, though the code allows
7210 for someday permitting CHAR*(*) stmtfunc dummies). */
5ff904cd 7211
c7e4ee3a
CB
7212#if FFECOM_targetCURRENT == FFECOM_targetGCC
7213static void
7214ffecom_push_dummy_decls_ (ffebld dummy_list, bool stmtfunc)
7215{
7216 ffebld dummy;
7217 ffebld dumlist;
7218 ffesymbol s;
7219 tree parm;
5ff904cd 7220
c7e4ee3a 7221 ffecom_transform_only_dummies_ = TRUE;
5ff904cd 7222
c7e4ee3a 7223 /* First push the parms corresponding to actual dummy "contents". */
5ff904cd 7224
c7e4ee3a
CB
7225 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
7226 {
7227 dummy = ffebld_head (dumlist);
7228 switch (ffebld_op (dummy))
7229 {
7230 case FFEBLD_opSTAR:
7231 case FFEBLD_opANY:
7232 continue; /* Forget alternate returns. */
5ff904cd 7233
c7e4ee3a
CB
7234 default:
7235 break;
7236 }
7237 assert (ffebld_op (dummy) == FFEBLD_opSYMTER);
7238 s = ffebld_symter (dummy);
7239 parm = ffesymbol_hook (s).decl_tree;
7240 if (parm == NULL_TREE)
7241 {
7242 s = ffecom_sym_transform_ (s);
7243 parm = ffesymbol_hook (s).decl_tree;
7244 assert (parm != NULL_TREE);
7245 }
7246 if (parm != error_mark_node)
7247 push_parm_decl (parm);
5ff904cd
JL
7248 }
7249
c7e4ee3a 7250 /* Then, for CHARACTER dummies, push the parms giving their lengths. */
5ff904cd 7251
c7e4ee3a
CB
7252 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
7253 {
7254 dummy = ffebld_head (dumlist);
7255 switch (ffebld_op (dummy))
7256 {
7257 case FFEBLD_opSTAR:
7258 case FFEBLD_opANY:
7259 continue; /* Forget alternate returns, they mean
7260 NOTHING! */
7261
7262 default:
7263 break;
7264 }
7265 s = ffebld_symter (dummy);
7266 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
7267 continue; /* Only looking for CHARACTER arguments. */
7268 if (stmtfunc && (ffesymbol_size (s) != FFETARGET_charactersizeNONE))
7269 continue; /* Stmtfunc arg with known size needs no
7270 length param. */
7271 if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
7272 continue; /* Only looking for variables and arrays. */
7273 parm = ffesymbol_hook (s).length_tree;
7274 assert (parm != NULL_TREE);
7275 if (parm != error_mark_node)
7276 push_parm_decl (parm);
7277 }
7278
7279 ffecom_transform_only_dummies_ = FALSE;
5ff904cd
JL
7280}
7281
7282#endif
c7e4ee3a 7283/* ffecom_start_progunit_ -- Beginning of program unit
5ff904cd 7284
c7e4ee3a
CB
7285 Does GNU back end stuff necessary to teach it about the start of its
7286 equivalent of a Fortran program unit. */
5ff904cd
JL
7287
7288#if FFECOM_targetCURRENT == FFECOM_targetGCC
7289static void
c7e4ee3a 7290ffecom_start_progunit_ ()
5ff904cd 7291{
c7e4ee3a
CB
7292 ffesymbol fn = ffecom_primary_entry_;
7293 ffebld arglist;
7294 tree id; /* Identifier (name) of function. */
7295 tree type; /* Type of function. */
7296 tree result; /* Result of function. */
7297 ffeinfoBasictype bt;
7298 ffeinfoKindtype kt;
7299 ffeglobal g;
7300 ffeglobalType gt;
7301 ffeglobalType egt = FFEGLOBAL_type;
7302 bool charfunc;
7303 bool cmplxfunc;
7304 bool altentries = (ffecom_num_entrypoints_ != 0);
7305 bool multi
7306 = altentries
7307 && (ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
7308 && (ffecom_master_bt_ == FFEINFO_basictypeNONE);
7309 bool main_program = FALSE;
7310 int old_lineno = lineno;
7311 char *old_input_filename = input_filename;
7312 int yes;
5ff904cd 7313
c7e4ee3a
CB
7314 assert (fn != NULL);
7315 assert (ffesymbol_hook (fn).decl_tree == NULL_TREE);
5ff904cd 7316
c7e4ee3a
CB
7317 input_filename = ffesymbol_where_filename (fn);
7318 lineno = ffesymbol_where_filelinenum (fn);
5ff904cd 7319
c7e4ee3a
CB
7320 /* c-parse.y indeed does call suspend_momentary and not only ignores the
7321 return value, but also never calls resume_momentary, when starting an
7322 outer function (see "fndef:", "setspecs:", and so on). So g77 does the
7323 same thing. It shouldn't be a problem since start_function calls
7324 temporary_allocation, but it might be necessary. If it causes a problem
7325 here, then maybe there's a bug lurking in gcc. NOTE: This identical
7326 comment appears twice in thist file. */
7327
7328 suspend_momentary ();
7329
7330 switch (ffecom_primary_entry_kind_)
7331 {
7332 case FFEINFO_kindPROGRAM:
7333 main_program = TRUE;
7334 gt = FFEGLOBAL_typeMAIN;
7335 bt = FFEINFO_basictypeNONE;
7336 kt = FFEINFO_kindtypeNONE;
7337 type = ffecom_tree_fun_type_void;
7338 charfunc = FALSE;
7339 cmplxfunc = FALSE;
7340 break;
7341
7342 case FFEINFO_kindBLOCKDATA:
7343 gt = FFEGLOBAL_typeBDATA;
7344 bt = FFEINFO_basictypeNONE;
7345 kt = FFEINFO_kindtypeNONE;
7346 type = ffecom_tree_fun_type_void;
7347 charfunc = FALSE;
7348 cmplxfunc = FALSE;
7349 break;
7350
7351 case FFEINFO_kindFUNCTION:
7352 gt = FFEGLOBAL_typeFUNC;
7353 egt = FFEGLOBAL_typeEXT;
7354 bt = ffesymbol_basictype (fn);
7355 kt = ffesymbol_kindtype (fn);
7356 if (bt == FFEINFO_basictypeNONE)
7357 {
7358 ffeimplic_establish_symbol (fn);
7359 if (ffesymbol_funcresult (fn) != NULL)
7360 ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
7361 bt = ffesymbol_basictype (fn);
7362 kt = ffesymbol_kindtype (fn);
7363 }
7364
7365 if (multi)
7366 charfunc = cmplxfunc = FALSE;
7367 else if (bt == FFEINFO_basictypeCHARACTER)
7368 charfunc = TRUE, cmplxfunc = FALSE;
7369 else if ((bt == FFEINFO_basictypeCOMPLEX)
7370 && ffesymbol_is_f2c (fn)
7371 && !altentries)
7372 charfunc = FALSE, cmplxfunc = TRUE;
7373 else
7374 charfunc = cmplxfunc = FALSE;
7375
7376 if (multi || charfunc)
7377 type = ffecom_tree_fun_type_void;
7378 else if (ffesymbol_is_f2c (fn) && !altentries)
7379 type = ffecom_tree_fun_type[bt][kt];
7380 else
7381 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
7382
7383 if ((type == NULL_TREE)
7384 || (TREE_TYPE (type) == NULL_TREE))
7385 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */
7386 break;
7387
7388 case FFEINFO_kindSUBROUTINE:
7389 gt = FFEGLOBAL_typeSUBR;
7390 egt = FFEGLOBAL_typeEXT;
7391 bt = FFEINFO_basictypeNONE;
7392 kt = FFEINFO_kindtypeNONE;
7393 if (ffecom_is_altreturning_)
7394 type = ffecom_tree_subr_type;
7395 else
7396 type = ffecom_tree_fun_type_void;
7397 charfunc = FALSE;
7398 cmplxfunc = FALSE;
7399 break;
5ff904cd 7400
c7e4ee3a
CB
7401 default:
7402 assert ("say what??" == NULL);
7403 /* Fall through. */
7404 case FFEINFO_kindANY:
7405 gt = FFEGLOBAL_typeANY;
7406 bt = FFEINFO_basictypeNONE;
7407 kt = FFEINFO_kindtypeNONE;
7408 type = error_mark_node;
7409 charfunc = FALSE;
7410 cmplxfunc = FALSE;
7411 break;
7412 }
5ff904cd 7413
c7e4ee3a 7414 if (altentries)
5ff904cd 7415 {
c7e4ee3a
CB
7416 id = ffecom_get_invented_identifier ("__g77_masterfun_%s",
7417 ffesymbol_text (fn),
7418 -1);
7419 }
7420#if FFETARGET_isENFORCED_MAIN
7421 else if (main_program)
7422 id = get_identifier (FFETARGET_nameENFORCED_MAIN_NAME);
7423#endif
7424 else
7425 id = ffecom_get_external_identifier_ (fn);
5ff904cd 7426
c7e4ee3a
CB
7427 start_function (id,
7428 type,
7429 0, /* nested/inline */
7430 !altentries); /* TREE_PUBLIC */
5ff904cd 7431
c7e4ee3a 7432 TREE_USED (current_function_decl) = 1; /* Avoid spurious warning if altentries. */
5ff904cd 7433
c7e4ee3a
CB
7434 if (!altentries
7435 && ((g = ffesymbol_global (fn)) != NULL)
7436 && ((ffeglobal_type (g) == gt)
7437 || (ffeglobal_type (g) == egt)))
7438 {
7439 ffeglobal_set_hook (g, current_function_decl);
7440 }
5ff904cd 7441
c7e4ee3a 7442 yes = suspend_momentary ();
5ff904cd 7443
c7e4ee3a
CB
7444 /* Arg handling needs exec-transitioned ffesymbols to work with. But
7445 exec-transitioning needs current_function_decl to be filled in. So we
7446 do these things in two phases. */
5ff904cd 7447
c7e4ee3a
CB
7448 if (altentries)
7449 { /* 1st arg identifies which entrypoint. */
7450 ffecom_which_entrypoint_decl_
7451 = build_decl (PARM_DECL,
7452 ffecom_get_invented_identifier ("__g77_%s",
7453 "which_entrypoint",
7454 -1),
7455 integer_type_node);
7456 push_parm_decl (ffecom_which_entrypoint_decl_);
7457 }
5ff904cd 7458
c7e4ee3a
CB
7459 if (charfunc
7460 || cmplxfunc
7461 || multi)
7462 { /* Arg for result (return value). */
7463 tree type;
7464 tree length;
5ff904cd 7465
c7e4ee3a
CB
7466 if (charfunc)
7467 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
7468 else if (cmplxfunc)
7469 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
7470 else
7471 type = ffecom_multi_type_node_;
5ff904cd 7472
c7e4ee3a
CB
7473 result = ffecom_get_invented_identifier ("__g77_%s",
7474 "result", -1);
5ff904cd 7475
c7e4ee3a 7476 /* Make length arg _and_ enhance type info for CHAR arg itself. */
5ff904cd 7477
c7e4ee3a
CB
7478 if (charfunc)
7479 length = ffecom_char_enhance_arg_ (&type, fn);
7480 else
7481 length = NULL_TREE; /* Not ref'd if !charfunc. */
5ff904cd 7482
c7e4ee3a
CB
7483 type = build_pointer_type (type);
7484 result = build_decl (PARM_DECL, result, type);
5ff904cd 7485
c7e4ee3a
CB
7486 push_parm_decl (result);
7487 if (multi)
7488 ffecom_multi_retval_ = result;
7489 else
7490 ffecom_func_result_ = result;
5ff904cd 7491
c7e4ee3a
CB
7492 if (charfunc)
7493 {
7494 push_parm_decl (length);
7495 ffecom_func_length_ = length;
7496 }
5ff904cd
JL
7497 }
7498
c7e4ee3a
CB
7499 if (ffecom_primary_entry_is_proc_)
7500 {
7501 if (altentries)
7502 arglist = ffecom_master_arglist_;
7503 else
7504 arglist = ffesymbol_dummyargs (fn);
7505 ffecom_push_dummy_decls_ (arglist, FALSE);
7506 }
5ff904cd 7507
c7e4ee3a 7508 resume_momentary (yes);
5ff904cd 7509
c7e4ee3a
CB
7510 if (TREE_CODE (current_function_decl) != ERROR_MARK)
7511 store_parm_decls (main_program ? 1 : 0);
5ff904cd 7512
c7e4ee3a
CB
7513 ffecom_start_compstmt ();
7514 /* Disallow temp vars at this level. */
7515 current_binding_level->prep_state = 2;
5ff904cd 7516
c7e4ee3a
CB
7517 lineno = old_lineno;
7518 input_filename = old_input_filename;
5ff904cd 7519
c7e4ee3a
CB
7520 /* This handles any symbols still untransformed, in case -g specified.
7521 This used to be done in ffecom_finish_progunit, but it turns out to
7522 be necessary to do it here so that statement functions are
7523 expanded before code. But don't bother for BLOCK DATA. */
5ff904cd 7524
c7e4ee3a
CB
7525 if (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
7526 ffesymbol_drive (ffecom_finish_symbol_transform_);
5ff904cd
JL
7527}
7528
7529#endif
c7e4ee3a 7530/* ffecom_sym_transform_ -- Transform FFE sym into backend sym
5ff904cd 7531
c7e4ee3a
CB
7532 ffesymbol s;
7533 ffecom_sym_transform_(s);
7534
7535 The ffesymbol_hook info for s is updated with appropriate backend info
7536 on the symbol. */
7537
7538#if FFECOM_targetCURRENT == FFECOM_targetGCC
7539static ffesymbol
7540ffecom_sym_transform_ (ffesymbol s)
7541{
7542 tree t; /* Transformed thingy. */
7543 tree tlen; /* Length if CHAR*(*). */
7544 bool addr; /* Is t the address of the thingy? */
7545 ffeinfoBasictype bt;
7546 ffeinfoKindtype kt;
7547 ffeglobal g;
7548 int yes;
7549 int old_lineno = lineno;
7550 char *old_input_filename = input_filename;
5ff904cd 7551
c7e4ee3a
CB
7552 /* Must ensure special ASSIGN variables are declared at top of outermost
7553 block, else they'll end up in the innermost block when their first
7554 ASSIGN is seen, which leaves them out of scope when they're the
7555 subject of a GOTO or I/O statement.
5ff904cd 7556
c7e4ee3a
CB
7557 We make this variable even if -fugly-assign. Just let it go unused,
7558 in case it turns out there are cases where we really want to use this
7559 variable anyway (e.g. ASSIGN to INTEGER*2 variable). */
5ff904cd 7560
c7e4ee3a
CB
7561 if (! ffecom_transform_only_dummies_
7562 && ffesymbol_assigned (s)
7563 && ! ffesymbol_hook (s).assign_tree)
7564 s = ffecom_sym_transform_assign_ (s);
5ff904cd 7565
c7e4ee3a 7566 if (ffesymbol_sfdummyparent (s) == NULL)
5ff904cd 7567 {
c7e4ee3a
CB
7568 input_filename = ffesymbol_where_filename (s);
7569 lineno = ffesymbol_where_filelinenum (s);
7570 }
7571 else
7572 {
7573 ffesymbol sf = ffesymbol_sfdummyparent (s);
5ff904cd 7574
c7e4ee3a
CB
7575 input_filename = ffesymbol_where_filename (sf);
7576 lineno = ffesymbol_where_filelinenum (sf);
7577 }
6d433196 7578
c7e4ee3a
CB
7579 bt = ffeinfo_basictype (ffebld_info (s));
7580 kt = ffeinfo_kindtype (ffebld_info (s));
5ff904cd 7581
c7e4ee3a
CB
7582 t = NULL_TREE;
7583 tlen = NULL_TREE;
7584 addr = FALSE;
5ff904cd 7585
c7e4ee3a
CB
7586 switch (ffesymbol_kind (s))
7587 {
7588 case FFEINFO_kindNONE:
7589 switch (ffesymbol_where (s))
7590 {
7591 case FFEINFO_whereDUMMY: /* Subroutine or function. */
7592 assert (ffecom_transform_only_dummies_);
5ff904cd 7593
c7e4ee3a
CB
7594 /* Before 0.4, this could be ENTITY/DUMMY, but see
7595 ffestu_sym_end_transition -- no longer true (in particular, if
7596 it could be an ENTITY, it _will_ be made one, so that
7597 possibility won't come through here). So we never make length
7598 arg for CHARACTER type. */
5ff904cd 7599
c7e4ee3a
CB
7600 t = build_decl (PARM_DECL,
7601 ffecom_get_identifier_ (ffesymbol_text (s)),
7602 ffecom_tree_ptr_to_subr_type);
7603#if BUILT_FOR_270
7604 DECL_ARTIFICIAL (t) = 1;
7605#endif
7606 addr = TRUE;
7607 break;
5ff904cd 7608
c7e4ee3a
CB
7609 case FFEINFO_whereGLOBAL: /* Subroutine or function. */
7610 assert (!ffecom_transform_only_dummies_);
5ff904cd 7611
c7e4ee3a
CB
7612 if (((g = ffesymbol_global (s)) != NULL)
7613 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
7614 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
7615 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
7616 && (ffeglobal_hook (g) != NULL_TREE)
7617 && ffe_is_globals ())
7618 {
7619 t = ffeglobal_hook (g);
7620 break;
7621 }
5ff904cd 7622
c7e4ee3a
CB
7623 push_obstacks_nochange ();
7624 end_temporary_allocation ();
5ff904cd 7625
c7e4ee3a
CB
7626 t = build_decl (FUNCTION_DECL,
7627 ffecom_get_external_identifier_ (s),
7628 ffecom_tree_subr_type); /* Assume subr. */
7629 DECL_EXTERNAL (t) = 1;
7630 TREE_PUBLIC (t) = 1;
5ff904cd 7631
c7e4ee3a
CB
7632 t = start_decl (t, FALSE);
7633 finish_decl (t, NULL_TREE, FALSE);
795232f7 7634
c7e4ee3a
CB
7635 if ((g != NULL)
7636 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
7637 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
7638 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
7639 ffeglobal_set_hook (g, t);
5ff904cd 7640
c7e4ee3a
CB
7641 resume_temporary_allocation ();
7642 pop_obstacks ();
5ff904cd 7643
c7e4ee3a 7644 break;
5ff904cd 7645
c7e4ee3a
CB
7646 default:
7647 assert ("NONE where unexpected" == NULL);
7648 /* Fall through. */
7649 case FFEINFO_whereANY:
7650 break;
7651 }
5ff904cd 7652 break;
5ff904cd 7653
c7e4ee3a
CB
7654 case FFEINFO_kindENTITY:
7655 switch (ffeinfo_where (ffesymbol_info (s)))
7656 {
5ff904cd 7657
c7e4ee3a
CB
7658 case FFEINFO_whereCONSTANT:
7659 /* ~~Debugging info needed? */
7660 assert (!ffecom_transform_only_dummies_);
7661 t = error_mark_node; /* Shouldn't ever see this in expr. */
7662 break;
5ff904cd 7663
c7e4ee3a
CB
7664 case FFEINFO_whereLOCAL:
7665 assert (!ffecom_transform_only_dummies_);
5ff904cd 7666
c7e4ee3a
CB
7667 {
7668 ffestorag st = ffesymbol_storage (s);
7669 tree type;
5ff904cd 7670
c7e4ee3a
CB
7671 if ((st != NULL)
7672 && (ffestorag_size (st) == 0))
7673 {
7674 t = error_mark_node;
7675 break;
7676 }
5ff904cd 7677
c7e4ee3a
CB
7678 yes = suspend_momentary ();
7679 type = ffecom_type_localvar_ (s, bt, kt);
7680 resume_momentary (yes);
5ff904cd 7681
c7e4ee3a
CB
7682 if (type == error_mark_node)
7683 {
7684 t = error_mark_node;
7685 break;
7686 }
5ff904cd 7687
c7e4ee3a
CB
7688 if ((st != NULL)
7689 && (ffestorag_parent (st) != NULL))
7690 { /* Child of EQUIVALENCE parent. */
7691 ffestorag est;
7692 tree et;
7693 int yes;
7694 ffetargetOffset offset;
5ff904cd 7695
c7e4ee3a
CB
7696 est = ffestorag_parent (st);
7697 ffecom_transform_equiv_ (est);
5ff904cd 7698
c7e4ee3a
CB
7699 et = ffestorag_hook (est);
7700 assert (et != NULL_TREE);
5ff904cd 7701
c7e4ee3a
CB
7702 if (! TREE_STATIC (et))
7703 put_var_into_stack (et);
5ff904cd 7704
c7e4ee3a 7705 yes = suspend_momentary ();
5ff904cd 7706
c7e4ee3a
CB
7707 offset = ffestorag_modulo (est)
7708 + ffestorag_offset (ffesymbol_storage (s))
7709 - ffestorag_offset (est);
5ff904cd 7710
c7e4ee3a 7711 ffecom_debug_kludge_ (et, "EQUIVALENCE", s, type, offset);
5ff904cd 7712
c7e4ee3a 7713 /* (t_type *) (((char *) &et) + offset) */
5ff904cd 7714
c7e4ee3a
CB
7715 t = convert (string_type_node, /* (char *) */
7716 ffecom_1 (ADDR_EXPR,
7717 build_pointer_type (TREE_TYPE (et)),
7718 et));
7719 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
7720 t,
7721 build_int_2 (offset, 0));
7722 t = convert (build_pointer_type (type),
7723 t);
d50108c7 7724 TREE_CONSTANT (t) = staticp (et);
5ff904cd 7725
c7e4ee3a 7726 addr = TRUE;
5ff904cd 7727
c7e4ee3a
CB
7728 resume_momentary (yes);
7729 }
7730 else
7731 {
7732 tree initexpr;
7733 bool init = ffesymbol_is_init (s);
5ff904cd 7734
c7e4ee3a 7735 yes = suspend_momentary ();
5ff904cd 7736
c7e4ee3a
CB
7737 t = build_decl (VAR_DECL,
7738 ffecom_get_identifier_ (ffesymbol_text (s)),
7739 type);
5ff904cd 7740
c7e4ee3a
CB
7741 if (init
7742 || ffesymbol_namelisted (s)
7743#ifdef FFECOM_sizeMAXSTACKITEM
7744 || ((st != NULL)
7745 && (ffestorag_size (st) > FFECOM_sizeMAXSTACKITEM))
7746#endif
7747 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
7748 && (ffecom_primary_entry_kind_
7749 != FFEINFO_kindBLOCKDATA)
7750 && (ffesymbol_is_save (s) || ffe_is_saveall ())))
7751 TREE_STATIC (t) = !ffesymbol_attr (s, FFESYMBOL_attrADJUSTABLE);
7752 else
7753 TREE_STATIC (t) = 0; /* No need to make static. */
5ff904cd 7754
c7e4ee3a
CB
7755 if (init || ffe_is_init_local_zero ())
7756 DECL_INITIAL (t) = error_mark_node;
5ff904cd 7757
c7e4ee3a
CB
7758 /* Keep -Wunused from complaining about var if it
7759 is used as sfunc arg or DATA implied-DO. */
7760 if (ffesymbol_attrs (s) & FFESYMBOL_attrsSFARG)
7761 DECL_IN_SYSTEM_HEADER (t) = 1;
5ff904cd 7762
c7e4ee3a 7763 t = start_decl (t, FALSE);
5ff904cd 7764
c7e4ee3a
CB
7765 if (init)
7766 {
7767 if (ffesymbol_init (s) != NULL)
7768 initexpr = ffecom_expr (ffesymbol_init (s));
7769 else
7770 initexpr = ffecom_init_zero_ (t);
7771 }
7772 else if (ffe_is_init_local_zero ())
7773 initexpr = ffecom_init_zero_ (t);
7774 else
7775 initexpr = NULL_TREE; /* Not ref'd if !init. */
5ff904cd 7776
c7e4ee3a 7777 finish_decl (t, initexpr, FALSE);
5ff904cd 7778
c7e4ee3a
CB
7779 if ((st != NULL) && (DECL_SIZE (t) != error_mark_node))
7780 {
7781 tree size_tree;
5ff904cd 7782
c7e4ee3a
CB
7783 size_tree = size_binop (CEIL_DIV_EXPR,
7784 DECL_SIZE (t),
7785 size_int (BITS_PER_UNIT));
7786 assert (TREE_INT_CST_HIGH (size_tree) == 0);
7787 assert (TREE_INT_CST_LOW (size_tree) == ffestorag_size (st));
7788 }
5ff904cd 7789
c7e4ee3a
CB
7790 resume_momentary (yes);
7791 }
7792 }
5ff904cd 7793 break;
5ff904cd 7794
c7e4ee3a
CB
7795 case FFEINFO_whereRESULT:
7796 assert (!ffecom_transform_only_dummies_);
5ff904cd 7797
c7e4ee3a
CB
7798 if (bt == FFEINFO_basictypeCHARACTER)
7799 { /* Result is already in list of dummies, use
7800 it (& length). */
7801 t = ffecom_func_result_;
7802 tlen = ffecom_func_length_;
7803 addr = TRUE;
7804 break;
7805 }
7806 if ((ffecom_num_entrypoints_ == 0)
7807 && (bt == FFEINFO_basictypeCOMPLEX)
7808 && (ffesymbol_is_f2c (ffecom_primary_entry_)))
7809 { /* Result is already in list of dummies, use
7810 it. */
7811 t = ffecom_func_result_;
7812 addr = TRUE;
7813 break;
7814 }
7815 if (ffecom_func_result_ != NULL_TREE)
7816 {
7817 t = ffecom_func_result_;
7818 break;
7819 }
7820 if ((ffecom_num_entrypoints_ != 0)
7821 && (ffecom_master_bt_ == FFEINFO_basictypeNONE))
7822 {
7823 yes = suspend_momentary ();
5ff904cd 7824
c7e4ee3a
CB
7825 assert (ffecom_multi_retval_ != NULL_TREE);
7826 t = ffecom_1 (INDIRECT_REF, ffecom_multi_type_node_,
7827 ffecom_multi_retval_);
7828 t = ffecom_2 (COMPONENT_REF, ffecom_tree_type[bt][kt],
7829 t, ffecom_multi_fields_[bt][kt]);
5ff904cd 7830
c7e4ee3a
CB
7831 resume_momentary (yes);
7832 break;
7833 }
5ff904cd 7834
c7e4ee3a 7835 yes = suspend_momentary ();
5ff904cd 7836
c7e4ee3a
CB
7837 t = build_decl (VAR_DECL,
7838 ffecom_get_identifier_ (ffesymbol_text (s)),
7839 ffecom_tree_type[bt][kt]);
7840 TREE_STATIC (t) = 0; /* Put result on stack. */
7841 t = start_decl (t, FALSE);
7842 finish_decl (t, NULL_TREE, FALSE);
5ff904cd 7843
c7e4ee3a 7844 ffecom_func_result_ = t;
5ff904cd 7845
c7e4ee3a
CB
7846 resume_momentary (yes);
7847 break;
5ff904cd 7848
c7e4ee3a
CB
7849 case FFEINFO_whereDUMMY:
7850 {
7851 tree type;
7852 ffebld dl;
7853 ffebld dim;
7854 tree low;
7855 tree high;
7856 tree old_sizes;
7857 bool adjustable = FALSE; /* Conditionally adjustable? */
5ff904cd 7858
c7e4ee3a
CB
7859 type = ffecom_tree_type[bt][kt];
7860 if (ffesymbol_sfdummyparent (s) != NULL)
7861 {
7862 if (current_function_decl == ffecom_outer_function_decl_)
7863 { /* Exec transition before sfunc
7864 context; get it later. */
7865 break;
7866 }
7867 t = ffecom_get_identifier_ (ffesymbol_text
7868 (ffesymbol_sfdummyparent (s)));
7869 }
7870 else
7871 t = ffecom_get_identifier_ (ffesymbol_text (s));
5ff904cd 7872
c7e4ee3a 7873 assert (ffecom_transform_only_dummies_);
5ff904cd 7874
c7e4ee3a
CB
7875 old_sizes = get_pending_sizes ();
7876 put_pending_sizes (old_sizes);
5ff904cd 7877
c7e4ee3a
CB
7878 if (bt == FFEINFO_basictypeCHARACTER)
7879 tlen = ffecom_char_enhance_arg_ (&type, s);
7880 type = ffecom_check_size_overflow_ (s, type, TRUE);
5ff904cd 7881
c7e4ee3a
CB
7882 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
7883 {
7884 if (type == error_mark_node)
7885 break;
5ff904cd 7886
c7e4ee3a
CB
7887 dim = ffebld_head (dl);
7888 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
7889 if ((ffebld_left (dim) == NULL) || ffecom_doing_entry_)
7890 low = ffecom_integer_one_node;
7891 else
7892 low = ffecom_expr (ffebld_left (dim));
7893 assert (ffebld_right (dim) != NULL);
7894 if ((ffebld_op (ffebld_right (dim)) == FFEBLD_opSTAR)
7895 || ffecom_doing_entry_)
7896 {
7897 /* Used to just do high=low. But for ffecom_tree_
7898 canonize_ref_, it probably is important to correctly
7899 assess the size. E.g. given COMPLEX C(*),CFUNC and
7900 C(2)=CFUNC(C), overlap can happen, while it can't
7901 for, say, C(1)=CFUNC(C(2)). */
7902 /* Even more recently used to set to INT_MAX, but that
7903 broke when some overflow checking went into the back
7904 end. Now we just leave the upper bound unspecified. */
7905 high = NULL;
7906 }
7907 else
7908 high = ffecom_expr (ffebld_right (dim));
5ff904cd 7909
c7e4ee3a
CB
7910 /* Determine whether array is conditionally adjustable,
7911 to decide whether back-end magic is needed.
5ff904cd 7912
c7e4ee3a
CB
7913 Normally the front end uses the back-end function
7914 variable_size to wrap SAVE_EXPR's around expressions
7915 affecting the size/shape of an array so that the
7916 size/shape info doesn't change during execution
7917 of the compiled code even though variables and
7918 functions referenced in those expressions might.
5ff904cd 7919
c7e4ee3a
CB
7920 variable_size also makes sure those saved expressions
7921 get evaluated immediately upon entry to the
7922 compiled procedure -- the front end normally doesn't
7923 have to worry about that.
3cf0cea4 7924
c7e4ee3a
CB
7925 However, there is a problem with this that affects
7926 g77's implementation of entry points, and that is
7927 that it is _not_ true that each invocation of the
7928 compiled procedure is permitted to evaluate
7929 array size/shape info -- because it is possible
7930 that, for some invocations, that info is invalid (in
7931 which case it is "promised" -- i.e. a violation of
7932 the Fortran standard -- that the compiled code
7933 won't reference the array or its size/shape
7934 during that particular invocation).
5ff904cd 7935
c7e4ee3a 7936 To phrase this in C terms, consider this gcc function:
5ff904cd 7937
c7e4ee3a
CB
7938 void foo (int *n, float (*a)[*n])
7939 {
7940 // a is "pointer to array ...", fyi.
7941 }
5ff904cd 7942
c7e4ee3a
CB
7943 Suppose that, for some invocations, it is permitted
7944 for a caller of foo to do this:
5ff904cd 7945
c7e4ee3a 7946 foo (NULL, NULL);
5ff904cd 7947
c7e4ee3a
CB
7948 Now the _written_ code for foo can take such a call
7949 into account by either testing explicitly for whether
7950 (a == NULL) || (n == NULL) -- presumably it is
7951 not permitted to reference *a in various fashions
7952 if (n == NULL) I suppose -- or it can avoid it by
7953 looking at other info (other arguments, static/global
7954 data, etc.).
5ff904cd 7955
c7e4ee3a
CB
7956 However, this won't work in gcc 2.5.8 because it'll
7957 automatically emit the code to save the "*n"
7958 expression, which'll yield a NULL dereference for
7959 the "foo (NULL, NULL)" call, something the code
7960 for foo cannot prevent.
5ff904cd 7961
c7e4ee3a
CB
7962 g77 definitely needs to avoid executing such
7963 code anytime the pointer to the adjustable array
7964 is NULL, because even if its bounds expressions
7965 don't have any references to possible "absent"
7966 variables like "*n" -- say all variable references
7967 are to COMMON variables, i.e. global (though in C,
7968 local static could actually make sense) -- the
7969 expressions could yield other run-time problems
7970 for allowably "dead" values in those variables.
5ff904cd 7971
c7e4ee3a
CB
7972 For example, let's consider a more complicated
7973 version of foo:
5ff904cd 7974
c7e4ee3a
CB
7975 extern int i;
7976 extern int j;
5ff904cd 7977
c7e4ee3a
CB
7978 void foo (float (*a)[i/j])
7979 {
7980 ...
7981 }
5ff904cd 7982
c7e4ee3a
CB
7983 The above is (essentially) quite valid for Fortran
7984 but, again, for a call like "foo (NULL);", it is
7985 permitted for i and j to be undefined when the
7986 call is made. If j happened to be zero, for
7987 example, emitting the code to evaluate "i/j"
7988 could result in a run-time error.
5ff904cd 7989
c7e4ee3a
CB
7990 Offhand, though I don't have my F77 or F90
7991 standards handy, it might even be valid for a
7992 bounds expression to contain a function reference,
7993 in which case I doubt it is permitted for an
7994 implementation to invoke that function in the
7995 Fortran case involved here (invocation of an
7996 alternate ENTRY point that doesn't have the adjustable
7997 array as one of its arguments).
5ff904cd 7998
c7e4ee3a
CB
7999 So, the code that the compiler would normally emit
8000 to preevaluate the size/shape info for an
8001 adjustable array _must not_ be executed at run time
8002 in certain cases. Specifically, for Fortran,
8003 the case is when the pointer to the adjustable
8004 array == NULL. (For gnu-ish C, it might be nice
8005 for the source code itself to specify an expression
8006 that, if TRUE, inhibits execution of the code. Or
8007 reverse the sense for elegance.)
5ff904cd 8008
c7e4ee3a
CB
8009 (Note that g77 could use a different test than NULL,
8010 actually, since it happens to always pass an
8011 integer to the called function that specifies which
8012 entry point is being invoked. Hmm, this might
8013 solve the next problem.)
8014
8015 One way a user could, I suppose, write "foo" so
8016 it works is to insert COND_EXPR's for the
8017 size/shape info so the dangerous stuff isn't
8018 actually done, as in:
8019
8020 void foo (int *n, float (*a)[(a == NULL) ? 0 : *n])
8021 {
8022 ...
8023 }
5ff904cd 8024
c7e4ee3a
CB
8025 The next problem is that the front end needs to
8026 be able to tell the back end about the array's
8027 decl _before_ it tells it about the conditional
8028 expression to inhibit evaluation of size/shape info,
8029 as shown above.
5ff904cd 8030
c7e4ee3a
CB
8031 To solve this, the front end needs to be able
8032 to give the back end the expression to inhibit
8033 generation of the preevaluation code _after_
8034 it makes the decl for the adjustable array.
5ff904cd 8035
c7e4ee3a
CB
8036 Until then, the above example using the COND_EXPR
8037 doesn't pass muster with gcc because the "(a == NULL)"
8038 part has a reference to "a", which is still
8039 undefined at that point.
5ff904cd 8040
c7e4ee3a
CB
8041 g77 will therefore use a different mechanism in the
8042 meantime. */
5ff904cd 8043
c7e4ee3a
CB
8044 if (!adjustable
8045 && ((TREE_CODE (low) != INTEGER_CST)
8046 || (high && TREE_CODE (high) != INTEGER_CST)))
8047 adjustable = TRUE;
5ff904cd 8048
c7e4ee3a
CB
8049#if 0 /* Old approach -- see below. */
8050 if (TREE_CODE (low) != INTEGER_CST)
8051 low = ffecom_3 (COND_EXPR, integer_type_node,
8052 ffecom_adjarray_passed_ (s),
8053 low,
8054 ffecom_integer_zero_node);
5ff904cd 8055
c7e4ee3a
CB
8056 if (high && TREE_CODE (high) != INTEGER_CST)
8057 high = ffecom_3 (COND_EXPR, integer_type_node,
8058 ffecom_adjarray_passed_ (s),
8059 high,
8060 ffecom_integer_zero_node);
8061#endif
5ff904cd 8062
c7e4ee3a
CB
8063 /* ~~~gcc/stor-layout.c (layout_type) should do this,
8064 probably. Fixes 950302-1.f. */
5ff904cd 8065
c7e4ee3a
CB
8066 if (TREE_CODE (low) != INTEGER_CST)
8067 low = variable_size (low);
5ff904cd 8068
c7e4ee3a
CB
8069 /* ~~~Similarly, this fixes dumb0.f. The C front end
8070 does this, which is why dumb0.c would work. */
5ff904cd 8071
c7e4ee3a
CB
8072 if (high && TREE_CODE (high) != INTEGER_CST)
8073 high = variable_size (high);
5ff904cd 8074
c7e4ee3a
CB
8075 type
8076 = build_array_type
8077 (type,
8078 build_range_type (ffecom_integer_type_node,
8079 low, high));
8080 type = ffecom_check_size_overflow_ (s, type, TRUE);
8081 }
5ff904cd 8082
c7e4ee3a
CB
8083 if (type == error_mark_node)
8084 {
8085 t = error_mark_node;
8086 break;
8087 }
5ff904cd 8088
c7e4ee3a
CB
8089 if ((ffesymbol_sfdummyparent (s) == NULL)
8090 || (ffesymbol_basictype (s) == FFEINFO_basictypeCHARACTER))
8091 {
8092 type = build_pointer_type (type);
8093 addr = TRUE;
8094 }
5ff904cd 8095
c7e4ee3a 8096 t = build_decl (PARM_DECL, t, type);
5ff904cd 8097#if BUILT_FOR_270
c7e4ee3a 8098 DECL_ARTIFICIAL (t) = 1;
5ff904cd 8099#endif
5ff904cd 8100
c7e4ee3a
CB
8101 /* If this arg is present in every entry point's list of
8102 dummy args, then we're done. */
5ff904cd 8103
c7e4ee3a
CB
8104 if (ffesymbol_numentries (s)
8105 == (ffecom_num_entrypoints_ + 1))
5ff904cd 8106 break;
5ff904cd 8107
c7e4ee3a 8108#if 1
5ff904cd 8109
c7e4ee3a
CB
8110 /* If variable_size in stor-layout has been called during
8111 the above, then get_pending_sizes should have the
8112 yet-to-be-evaluated saved expressions pending.
8113 Make the whole lot of them get emitted, conditionally
8114 on whether the array decl ("t" above) is not NULL. */
5ff904cd 8115
c7e4ee3a
CB
8116 {
8117 tree sizes = get_pending_sizes ();
8118 tree tem;
5ff904cd 8119
c7e4ee3a
CB
8120 for (tem = sizes;
8121 tem != old_sizes;
8122 tem = TREE_CHAIN (tem))
8123 {
8124 tree temv = TREE_VALUE (tem);
5ff904cd 8125
c7e4ee3a
CB
8126 if (sizes == tem)
8127 sizes = temv;
8128 else
8129 sizes
8130 = ffecom_2 (COMPOUND_EXPR,
8131 TREE_TYPE (sizes),
8132 temv,
8133 sizes);
8134 }
5ff904cd 8135
c7e4ee3a
CB
8136 if (sizes != tem)
8137 {
8138 sizes
8139 = ffecom_3 (COND_EXPR,
8140 TREE_TYPE (sizes),
8141 ffecom_2 (NE_EXPR,
8142 integer_type_node,
8143 t,
8144 null_pointer_node),
8145 sizes,
8146 convert (TREE_TYPE (sizes),
8147 integer_zero_node));
8148 sizes = ffecom_save_tree (sizes);
5ff904cd 8149
c7e4ee3a
CB
8150 sizes
8151 = tree_cons (NULL_TREE, sizes, tem);
8152 }
5ff904cd 8153
c7e4ee3a
CB
8154 if (sizes)
8155 put_pending_sizes (sizes);
8156 }
5ff904cd 8157
c7e4ee3a
CB
8158#else
8159#if 0
8160 if (adjustable
8161 && (ffesymbol_numentries (s)
8162 != ffecom_num_entrypoints_ + 1))
8163 DECL_SOMETHING (t)
8164 = ffecom_2 (NE_EXPR, integer_type_node,
8165 t,
8166 null_pointer_node);
8167#else
8168#if 0
8169 if (adjustable
8170 && (ffesymbol_numentries (s)
8171 != ffecom_num_entrypoints_ + 1))
8172 {
8173 ffebad_start (FFEBAD_MISSING_ADJARRAY_UNSUPPORTED);
8174 ffebad_here (0, ffesymbol_where_line (s),
8175 ffesymbol_where_column (s));
8176 ffebad_string (ffesymbol_text (s));
8177 ffebad_finish ();
8178 }
8179#endif
8180#endif
8181#endif
8182 }
5ff904cd
JL
8183 break;
8184
c7e4ee3a 8185 case FFEINFO_whereCOMMON:
5ff904cd 8186 {
c7e4ee3a
CB
8187 ffesymbol cs;
8188 ffeglobal cg;
8189 tree ct;
5ff904cd
JL
8190 ffestorag st = ffesymbol_storage (s);
8191 tree type;
c7e4ee3a 8192 int yes;
5ff904cd 8193
c7e4ee3a
CB
8194 cs = ffesymbol_common (s); /* The COMMON area itself. */
8195 if (st != NULL) /* Else not laid out. */
5ff904cd 8196 {
c7e4ee3a
CB
8197 ffecom_transform_common_ (cs);
8198 st = ffesymbol_storage (s);
5ff904cd
JL
8199 }
8200
c7e4ee3a 8201 yes = suspend_momentary ();
5ff904cd 8202
c7e4ee3a 8203 type = ffecom_type_localvar_ (s, bt, kt);
5ff904cd 8204
c7e4ee3a
CB
8205 cg = ffesymbol_global (cs); /* The global COMMON info. */
8206 if ((cg == NULL)
8207 || (ffeglobal_type (cg) != FFEGLOBAL_typeCOMMON))
8208 ct = NULL_TREE;
8209 else
8210 ct = ffeglobal_hook (cg); /* The common area's tree. */
5ff904cd 8211
c7e4ee3a
CB
8212 if ((ct == NULL_TREE)
8213 || (st == NULL)
8214 || (type == error_mark_node))
8215 t = error_mark_node;
8216 else
8217 {
8218 ffetargetOffset offset;
8219 ffestorag cst;
5ff904cd 8220
c7e4ee3a
CB
8221 cst = ffestorag_parent (st);
8222 assert (cst == ffesymbol_storage (cs));
5ff904cd 8223
c7e4ee3a
CB
8224 offset = ffestorag_modulo (cst)
8225 + ffestorag_offset (st)
8226 - ffestorag_offset (cst);
5ff904cd 8227
c7e4ee3a 8228 ffecom_debug_kludge_ (ct, "COMMON", s, type, offset);
5ff904cd 8229
c7e4ee3a 8230 /* (t_type *) (((char *) &ct) + offset) */
5ff904cd
JL
8231
8232 t = convert (string_type_node, /* (char *) */
8233 ffecom_1 (ADDR_EXPR,
c7e4ee3a
CB
8234 build_pointer_type (TREE_TYPE (ct)),
8235 ct));
5ff904cd
JL
8236 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
8237 t,
8238 build_int_2 (offset, 0));
8239 t = convert (build_pointer_type (type),
8240 t);
d50108c7 8241 TREE_CONSTANT (t) = 1;
5ff904cd
JL
8242
8243 addr = TRUE;
5ff904cd 8244 }
5ff904cd 8245
c7e4ee3a
CB
8246 resume_momentary (yes);
8247 }
8248 break;
5ff904cd 8249
c7e4ee3a
CB
8250 case FFEINFO_whereIMMEDIATE:
8251 case FFEINFO_whereGLOBAL:
8252 case FFEINFO_whereFLEETING:
8253 case FFEINFO_whereFLEETING_CADDR:
8254 case FFEINFO_whereFLEETING_IADDR:
8255 case FFEINFO_whereINTRINSIC:
8256 case FFEINFO_whereCONSTANT_SUBOBJECT:
8257 default:
8258 assert ("ENTITY where unheard of" == NULL);
8259 /* Fall through. */
8260 case FFEINFO_whereANY:
8261 t = error_mark_node;
8262 break;
8263 }
8264 break;
5ff904cd 8265
c7e4ee3a
CB
8266 case FFEINFO_kindFUNCTION:
8267 switch (ffeinfo_where (ffesymbol_info (s)))
8268 {
8269 case FFEINFO_whereLOCAL: /* Me. */
8270 assert (!ffecom_transform_only_dummies_);
8271 t = current_function_decl;
5ff904cd
JL
8272 break;
8273
c7e4ee3a 8274 case FFEINFO_whereGLOBAL:
5ff904cd
JL
8275 assert (!ffecom_transform_only_dummies_);
8276
c7e4ee3a
CB
8277 if (((g = ffesymbol_global (s)) != NULL)
8278 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8279 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8280 && (ffeglobal_hook (g) != NULL_TREE)
8281 && ffe_is_globals ())
5ff904cd 8282 {
c7e4ee3a 8283 t = ffeglobal_hook (g);
5ff904cd
JL
8284 break;
8285 }
5ff904cd 8286
c7e4ee3a
CB
8287 push_obstacks_nochange ();
8288 end_temporary_allocation ();
5ff904cd 8289
c7e4ee3a
CB
8290 if (ffesymbol_is_f2c (s)
8291 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
8292 t = ffecom_tree_fun_type[bt][kt];
8293 else
8294 t = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
5ff904cd 8295
c7e4ee3a
CB
8296 t = build_decl (FUNCTION_DECL,
8297 ffecom_get_external_identifier_ (s),
8298 t);
8299 DECL_EXTERNAL (t) = 1;
8300 TREE_PUBLIC (t) = 1;
5ff904cd 8301
5ff904cd
JL
8302 t = start_decl (t, FALSE);
8303 finish_decl (t, NULL_TREE, FALSE);
8304
c7e4ee3a
CB
8305 if ((g != NULL)
8306 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8307 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8308 ffeglobal_set_hook (g, t);
8309
8310 resume_temporary_allocation ();
8311 pop_obstacks ();
5ff904cd 8312
5ff904cd
JL
8313 break;
8314
8315 case FFEINFO_whereDUMMY:
c7e4ee3a 8316 assert (ffecom_transform_only_dummies_);
5ff904cd 8317
c7e4ee3a
CB
8318 if (ffesymbol_is_f2c (s)
8319 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
8320 t = ffecom_tree_ptr_to_fun_type[bt][kt];
8321 else
8322 t = build_pointer_type
8323 (build_function_type (ffecom_tree_type[bt][kt], NULL_TREE));
8324
8325 t = build_decl (PARM_DECL,
8326 ffecom_get_identifier_ (ffesymbol_text (s)),
8327 t);
8328#if BUILT_FOR_270
8329 DECL_ARTIFICIAL (t) = 1;
8330#endif
8331 addr = TRUE;
8332 break;
8333
8334 case FFEINFO_whereCONSTANT: /* Statement function. */
8335 assert (!ffecom_transform_only_dummies_);
8336 t = ffecom_gen_sfuncdef_ (s, bt, kt);
8337 break;
8338
8339 case FFEINFO_whereINTRINSIC:
8340 assert (!ffecom_transform_only_dummies_);
8341 break; /* Let actual references generate their
8342 decls. */
8343
8344 default:
8345 assert ("FUNCTION where unheard of" == NULL);
8346 /* Fall through. */
8347 case FFEINFO_whereANY:
8348 t = error_mark_node;
8349 break;
8350 }
8351 break;
8352
8353 case FFEINFO_kindSUBROUTINE:
8354 switch (ffeinfo_where (ffesymbol_info (s)))
8355 {
8356 case FFEINFO_whereLOCAL: /* Me. */
8357 assert (!ffecom_transform_only_dummies_);
8358 t = current_function_decl;
8359 break;
5ff904cd 8360
c7e4ee3a
CB
8361 case FFEINFO_whereGLOBAL:
8362 assert (!ffecom_transform_only_dummies_);
5ff904cd 8363
c7e4ee3a
CB
8364 if (((g = ffesymbol_global (s)) != NULL)
8365 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8366 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8367 && (ffeglobal_hook (g) != NULL_TREE)
8368 && ffe_is_globals ())
8369 {
8370 t = ffeglobal_hook (g);
8371 break;
8372 }
5ff904cd 8373
c7e4ee3a
CB
8374 push_obstacks_nochange ();
8375 end_temporary_allocation ();
5ff904cd 8376
c7e4ee3a
CB
8377 t = build_decl (FUNCTION_DECL,
8378 ffecom_get_external_identifier_ (s),
8379 ffecom_tree_subr_type);
8380 DECL_EXTERNAL (t) = 1;
8381 TREE_PUBLIC (t) = 1;
5ff904cd 8382
c7e4ee3a
CB
8383 t = start_decl (t, FALSE);
8384 finish_decl (t, NULL_TREE, FALSE);
5ff904cd 8385
c7e4ee3a
CB
8386 if ((g != NULL)
8387 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8388 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8389 ffeglobal_set_hook (g, t);
5ff904cd 8390
c7e4ee3a
CB
8391 resume_temporary_allocation ();
8392 pop_obstacks ();
5ff904cd 8393
c7e4ee3a 8394 break;
5ff904cd 8395
c7e4ee3a
CB
8396 case FFEINFO_whereDUMMY:
8397 assert (ffecom_transform_only_dummies_);
5ff904cd 8398
c7e4ee3a
CB
8399 t = build_decl (PARM_DECL,
8400 ffecom_get_identifier_ (ffesymbol_text (s)),
8401 ffecom_tree_ptr_to_subr_type);
8402#if BUILT_FOR_270
8403 DECL_ARTIFICIAL (t) = 1;
8404#endif
8405 addr = TRUE;
8406 break;
5ff904cd 8407
c7e4ee3a
CB
8408 case FFEINFO_whereINTRINSIC:
8409 assert (!ffecom_transform_only_dummies_);
8410 break; /* Let actual references generate their
8411 decls. */
5ff904cd 8412
c7e4ee3a
CB
8413 default:
8414 assert ("SUBROUTINE where unheard of" == NULL);
8415 /* Fall through. */
8416 case FFEINFO_whereANY:
8417 t = error_mark_node;
8418 break;
8419 }
8420 break;
5ff904cd 8421
c7e4ee3a
CB
8422 case FFEINFO_kindPROGRAM:
8423 switch (ffeinfo_where (ffesymbol_info (s)))
8424 {
8425 case FFEINFO_whereLOCAL: /* Me. */
8426 assert (!ffecom_transform_only_dummies_);
8427 t = current_function_decl;
8428 break;
5ff904cd 8429
c7e4ee3a
CB
8430 case FFEINFO_whereCOMMON:
8431 case FFEINFO_whereDUMMY:
8432 case FFEINFO_whereGLOBAL:
8433 case FFEINFO_whereRESULT:
8434 case FFEINFO_whereFLEETING:
8435 case FFEINFO_whereFLEETING_CADDR:
8436 case FFEINFO_whereFLEETING_IADDR:
8437 case FFEINFO_whereIMMEDIATE:
8438 case FFEINFO_whereINTRINSIC:
8439 case FFEINFO_whereCONSTANT:
8440 case FFEINFO_whereCONSTANT_SUBOBJECT:
8441 default:
8442 assert ("PROGRAM where unheard of" == NULL);
8443 /* Fall through. */
8444 case FFEINFO_whereANY:
8445 t = error_mark_node;
8446 break;
8447 }
8448 break;
5ff904cd 8449
c7e4ee3a
CB
8450 case FFEINFO_kindBLOCKDATA:
8451 switch (ffeinfo_where (ffesymbol_info (s)))
8452 {
8453 case FFEINFO_whereLOCAL: /* Me. */
8454 assert (!ffecom_transform_only_dummies_);
8455 t = current_function_decl;
8456 break;
5ff904cd 8457
c7e4ee3a
CB
8458 case FFEINFO_whereGLOBAL:
8459 assert (!ffecom_transform_only_dummies_);
5ff904cd 8460
c7e4ee3a
CB
8461 push_obstacks_nochange ();
8462 end_temporary_allocation ();
5ff904cd 8463
c7e4ee3a
CB
8464 t = build_decl (FUNCTION_DECL,
8465 ffecom_get_external_identifier_ (s),
8466 ffecom_tree_blockdata_type);
8467 DECL_EXTERNAL (t) = 1;
8468 TREE_PUBLIC (t) = 1;
5ff904cd 8469
c7e4ee3a
CB
8470 t = start_decl (t, FALSE);
8471 finish_decl (t, NULL_TREE, FALSE);
5ff904cd 8472
c7e4ee3a
CB
8473 resume_temporary_allocation ();
8474 pop_obstacks ();
5ff904cd 8475
c7e4ee3a 8476 break;
5ff904cd 8477
c7e4ee3a
CB
8478 case FFEINFO_whereCOMMON:
8479 case FFEINFO_whereDUMMY:
8480 case FFEINFO_whereRESULT:
8481 case FFEINFO_whereFLEETING:
8482 case FFEINFO_whereFLEETING_CADDR:
8483 case FFEINFO_whereFLEETING_IADDR:
8484 case FFEINFO_whereIMMEDIATE:
8485 case FFEINFO_whereINTRINSIC:
8486 case FFEINFO_whereCONSTANT:
8487 case FFEINFO_whereCONSTANT_SUBOBJECT:
8488 default:
8489 assert ("BLOCKDATA where unheard of" == NULL);
8490 /* Fall through. */
8491 case FFEINFO_whereANY:
8492 t = error_mark_node;
8493 break;
8494 }
8495 break;
5ff904cd 8496
c7e4ee3a
CB
8497 case FFEINFO_kindCOMMON:
8498 switch (ffeinfo_where (ffesymbol_info (s)))
8499 {
8500 case FFEINFO_whereLOCAL:
8501 assert (!ffecom_transform_only_dummies_);
8502 ffecom_transform_common_ (s);
8503 break;
8504
8505 case FFEINFO_whereNONE:
8506 case FFEINFO_whereCOMMON:
8507 case FFEINFO_whereDUMMY:
8508 case FFEINFO_whereGLOBAL:
8509 case FFEINFO_whereRESULT:
8510 case FFEINFO_whereFLEETING:
8511 case FFEINFO_whereFLEETING_CADDR:
8512 case FFEINFO_whereFLEETING_IADDR:
8513 case FFEINFO_whereIMMEDIATE:
8514 case FFEINFO_whereINTRINSIC:
8515 case FFEINFO_whereCONSTANT:
8516 case FFEINFO_whereCONSTANT_SUBOBJECT:
8517 default:
8518 assert ("COMMON where unheard of" == NULL);
8519 /* Fall through. */
8520 case FFEINFO_whereANY:
8521 t = error_mark_node;
8522 break;
8523 }
8524 break;
5ff904cd 8525
c7e4ee3a
CB
8526 case FFEINFO_kindCONSTRUCT:
8527 switch (ffeinfo_where (ffesymbol_info (s)))
8528 {
8529 case FFEINFO_whereLOCAL:
8530 assert (!ffecom_transform_only_dummies_);
8531 break;
5ff904cd 8532
c7e4ee3a
CB
8533 case FFEINFO_whereNONE:
8534 case FFEINFO_whereCOMMON:
8535 case FFEINFO_whereDUMMY:
8536 case FFEINFO_whereGLOBAL:
8537 case FFEINFO_whereRESULT:
8538 case FFEINFO_whereFLEETING:
8539 case FFEINFO_whereFLEETING_CADDR:
8540 case FFEINFO_whereFLEETING_IADDR:
8541 case FFEINFO_whereIMMEDIATE:
8542 case FFEINFO_whereINTRINSIC:
8543 case FFEINFO_whereCONSTANT:
8544 case FFEINFO_whereCONSTANT_SUBOBJECT:
8545 default:
8546 assert ("CONSTRUCT where unheard of" == NULL);
8547 /* Fall through. */
8548 case FFEINFO_whereANY:
8549 t = error_mark_node;
8550 break;
8551 }
8552 break;
5ff904cd 8553
c7e4ee3a
CB
8554 case FFEINFO_kindNAMELIST:
8555 switch (ffeinfo_where (ffesymbol_info (s)))
8556 {
8557 case FFEINFO_whereLOCAL:
8558 assert (!ffecom_transform_only_dummies_);
8559 t = ffecom_transform_namelist_ (s);
8560 break;
5ff904cd 8561
c7e4ee3a
CB
8562 case FFEINFO_whereNONE:
8563 case FFEINFO_whereCOMMON:
8564 case FFEINFO_whereDUMMY:
8565 case FFEINFO_whereGLOBAL:
8566 case FFEINFO_whereRESULT:
8567 case FFEINFO_whereFLEETING:
8568 case FFEINFO_whereFLEETING_CADDR:
8569 case FFEINFO_whereFLEETING_IADDR:
8570 case FFEINFO_whereIMMEDIATE:
8571 case FFEINFO_whereINTRINSIC:
8572 case FFEINFO_whereCONSTANT:
8573 case FFEINFO_whereCONSTANT_SUBOBJECT:
8574 default:
8575 assert ("NAMELIST where unheard of" == NULL);
8576 /* Fall through. */
8577 case FFEINFO_whereANY:
8578 t = error_mark_node;
8579 break;
8580 }
8581 break;
5ff904cd 8582
c7e4ee3a
CB
8583 default:
8584 assert ("kind unheard of" == NULL);
8585 /* Fall through. */
8586 case FFEINFO_kindANY:
8587 t = error_mark_node;
8588 break;
8589 }
5ff904cd 8590
c7e4ee3a
CB
8591 ffesymbol_hook (s).decl_tree = t;
8592 ffesymbol_hook (s).length_tree = tlen;
8593 ffesymbol_hook (s).addr = addr;
5ff904cd 8594
c7e4ee3a
CB
8595 lineno = old_lineno;
8596 input_filename = old_input_filename;
5ff904cd 8597
c7e4ee3a
CB
8598 return s;
8599}
5ff904cd 8600
5ff904cd 8601#endif
c7e4ee3a 8602/* Transform into ASSIGNable symbol.
5ff904cd 8603
c7e4ee3a
CB
8604 Symbol has already been transformed, but for whatever reason, the
8605 resulting decl_tree has been deemed not usable for an ASSIGN target.
8606 (E.g. it isn't wide enough to hold a pointer.) So, here we invent
8607 another local symbol of type void * and stuff that in the assign_tree
8608 argument. The F77/F90 standards allow this implementation. */
5ff904cd 8609
c7e4ee3a
CB
8610#if FFECOM_targetCURRENT == FFECOM_targetGCC
8611static ffesymbol
8612ffecom_sym_transform_assign_ (ffesymbol s)
8613{
8614 tree t; /* Transformed thingy. */
8615 int yes;
8616 int old_lineno = lineno;
8617 char *old_input_filename = input_filename;
5ff904cd 8618
c7e4ee3a
CB
8619 if (ffesymbol_sfdummyparent (s) == NULL)
8620 {
8621 input_filename = ffesymbol_where_filename (s);
8622 lineno = ffesymbol_where_filelinenum (s);
8623 }
8624 else
8625 {
8626 ffesymbol sf = ffesymbol_sfdummyparent (s);
5ff904cd 8627
c7e4ee3a
CB
8628 input_filename = ffesymbol_where_filename (sf);
8629 lineno = ffesymbol_where_filelinenum (sf);
8630 }
5ff904cd 8631
c7e4ee3a 8632 assert (!ffecom_transform_only_dummies_);
5ff904cd 8633
c7e4ee3a 8634 yes = suspend_momentary ();
5ff904cd 8635
c7e4ee3a
CB
8636 t = build_decl (VAR_DECL,
8637 ffecom_get_invented_identifier ("__g77_ASSIGN_%s",
8638 ffesymbol_text (s),
8639 -1),
8640 TREE_TYPE (null_pointer_node));
5ff904cd 8641
c7e4ee3a
CB
8642 switch (ffesymbol_where (s))
8643 {
8644 case FFEINFO_whereLOCAL:
8645 /* Unlike for regular vars, SAVE status is easy to determine for
8646 ASSIGNed vars, since there's no initialization, there's no
8647 effective storage association (so "SAVE J" does not apply to
8648 K even given "EQUIVALENCE (J,K)"), there's no size issue
8649 to worry about, etc. */
8650 if ((ffesymbol_is_save (s) || ffe_is_saveall ())
8651 && (ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
8652 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA))
8653 TREE_STATIC (t) = 1; /* SAVEd in proc, make static. */
8654 else
8655 TREE_STATIC (t) = 0; /* No need to make static. */
8656 break;
5ff904cd 8657
c7e4ee3a
CB
8658 case FFEINFO_whereCOMMON:
8659 TREE_STATIC (t) = 1; /* Assume COMMONs always SAVEd. */
8660 break;
5ff904cd 8661
c7e4ee3a
CB
8662 case FFEINFO_whereDUMMY:
8663 /* Note that twinning a DUMMY means the caller won't see
8664 the ASSIGNed value. But both F77 and F90 allow implementations
8665 to do this, i.e. disallow Fortran code that would try and
8666 take advantage of actually putting a label into a variable
8667 via a dummy argument (or any other storage association, for
8668 that matter). */
8669 TREE_STATIC (t) = 0;
8670 break;
5ff904cd 8671
c7e4ee3a
CB
8672 default:
8673 TREE_STATIC (t) = 0;
8674 break;
8675 }
5ff904cd 8676
c7e4ee3a
CB
8677 t = start_decl (t, FALSE);
8678 finish_decl (t, NULL_TREE, FALSE);
5ff904cd 8679
c7e4ee3a 8680 resume_momentary (yes);
5ff904cd 8681
c7e4ee3a 8682 ffesymbol_hook (s).assign_tree = t;
5ff904cd 8683
c7e4ee3a
CB
8684 lineno = old_lineno;
8685 input_filename = old_input_filename;
5ff904cd 8686
c7e4ee3a
CB
8687 return s;
8688}
5ff904cd 8689
c7e4ee3a
CB
8690#endif
8691/* Implement COMMON area in back end.
5ff904cd 8692
c7e4ee3a
CB
8693 Because COMMON-based variables can be referenced in the dimension
8694 expressions of dummy (adjustable) arrays, and because dummies
8695 (in the gcc back end) need to be put in the outer binding level
8696 of a function (which has two binding levels, the outer holding
8697 the dummies and the inner holding the other vars), special care
8698 must be taken to handle COMMON areas.
5ff904cd 8699
c7e4ee3a
CB
8700 The current strategy is basically to always tell the back end about
8701 the COMMON area as a top-level external reference to just a block
8702 of storage of the master type of that area (e.g. integer, real,
8703 character, whatever -- not a structure). As a distinct action,
8704 if initial values are provided, tell the back end about the area
8705 as a top-level non-external (initialized) area and remember not to
8706 allow further initialization or expansion of the area. Meanwhile,
8707 if no initialization happens at all, tell the back end about
8708 the largest size we've seen declared so the space does get reserved.
8709 (This function doesn't handle all that stuff, but it does some
8710 of the important things.)
5ff904cd 8711
c7e4ee3a
CB
8712 Meanwhile, for COMMON variables themselves, just keep creating
8713 references like *((float *) (&common_area + offset)) each time
8714 we reference the variable. In other words, don't make a VAR_DECL
8715 or any kind of component reference (like we used to do before 0.4),
8716 though we might do that as well just for debugging purposes (and
8717 stuff the rtl with the appropriate offset expression). */
5ff904cd 8718
c7e4ee3a
CB
8719#if FFECOM_targetCURRENT == FFECOM_targetGCC
8720static void
8721ffecom_transform_common_ (ffesymbol s)
8722{
8723 ffestorag st = ffesymbol_storage (s);
8724 ffeglobal g = ffesymbol_global (s);
8725 tree cbt;
8726 tree cbtype;
8727 tree init;
8728 tree high;
8729 bool is_init = ffestorag_is_init (st);
5ff904cd 8730
c7e4ee3a 8731 assert (st != NULL);
5ff904cd 8732
c7e4ee3a
CB
8733 if ((g == NULL)
8734 || (ffeglobal_type (g) != FFEGLOBAL_typeCOMMON))
8735 return;
5ff904cd 8736
c7e4ee3a 8737 /* First update the size of the area in global terms. */
5ff904cd 8738
c7e4ee3a 8739 ffeglobal_size_common (s, ffestorag_size (st));
5ff904cd 8740
c7e4ee3a
CB
8741 if (!ffeglobal_common_init (g))
8742 is_init = FALSE; /* No explicit init, don't let erroneous joins init. */
5ff904cd 8743
c7e4ee3a 8744 cbt = ffeglobal_hook (g);
5ff904cd 8745
c7e4ee3a
CB
8746 /* If we already have declared this common block for a previous program
8747 unit, and either we already initialized it or we don't have new
8748 initialization for it, just return what we have without changing it. */
5ff904cd 8749
c7e4ee3a
CB
8750 if ((cbt != NULL_TREE)
8751 && (!is_init
8752 || !DECL_EXTERNAL (cbt)))
8753 return;
5ff904cd 8754
c7e4ee3a 8755 /* Process inits. */
5ff904cd 8756
c7e4ee3a
CB
8757 if (is_init)
8758 {
8759 if (ffestorag_init (st) != NULL)
5ff904cd 8760 {
c7e4ee3a 8761 ffebld sexp;
5ff904cd 8762
c7e4ee3a
CB
8763 /* Set the padding for the expression, so ffecom_expr
8764 knows to insert that many zeros. */
8765 switch (ffebld_op (sexp = ffestorag_init (st)))
5ff904cd 8766 {
c7e4ee3a
CB
8767 case FFEBLD_opCONTER:
8768 ffebld_conter_set_pad (sexp, ffestorag_modulo (st));
5ff904cd 8769 break;
5ff904cd 8770
c7e4ee3a
CB
8771 case FFEBLD_opARRTER:
8772 ffebld_arrter_set_pad (sexp, ffestorag_modulo (st));
8773 break;
5ff904cd 8774
c7e4ee3a
CB
8775 case FFEBLD_opACCTER:
8776 ffebld_accter_set_pad (sexp, ffestorag_modulo (st));
8777 break;
5ff904cd 8778
c7e4ee3a
CB
8779 default:
8780 assert ("bad op for cmn init (pad)" == NULL);
8781 break;
8782 }
5ff904cd 8783
c7e4ee3a
CB
8784 init = ffecom_expr (sexp);
8785 if (init == error_mark_node)
8786 { /* Hopefully the back end complained! */
8787 init = NULL_TREE;
8788 if (cbt != NULL_TREE)
8789 return;
8790 }
8791 }
8792 else
8793 init = error_mark_node;
8794 }
8795 else
8796 init = NULL_TREE;
5ff904cd 8797
c7e4ee3a
CB
8798 push_obstacks_nochange ();
8799 end_temporary_allocation ();
5ff904cd 8800
c7e4ee3a 8801 /* cbtype must be permanently allocated! */
5ff904cd 8802
c7e4ee3a
CB
8803 /* Allocate the MAX of the areas so far, seen filewide. */
8804 high = build_int_2 ((ffeglobal_common_size (g)
8805 + ffeglobal_common_pad (g)) - 1, 0);
8806 TREE_TYPE (high) = ffecom_integer_type_node;
5ff904cd 8807
c7e4ee3a
CB
8808 if (init)
8809 cbtype = build_array_type (char_type_node,
8810 build_range_type (integer_type_node,
8811 integer_zero_node,
8812 high));
8813 else
8814 cbtype = build_array_type (char_type_node, NULL_TREE);
5ff904cd 8815
c7e4ee3a
CB
8816 if (cbt == NULL_TREE)
8817 {
8818 cbt
8819 = build_decl (VAR_DECL,
8820 ffecom_get_external_identifier_ (s),
8821 cbtype);
8822 TREE_STATIC (cbt) = 1;
8823 TREE_PUBLIC (cbt) = 1;
8824 }
8825 else
8826 {
8827 assert (is_init);
8828 TREE_TYPE (cbt) = cbtype;
8829 }
8830 DECL_EXTERNAL (cbt) = init ? 0 : 1;
8831 DECL_INITIAL (cbt) = init ? error_mark_node : NULL_TREE;
5ff904cd 8832
c7e4ee3a
CB
8833 cbt = start_decl (cbt, TRUE);
8834 if (ffeglobal_hook (g) != NULL)
8835 assert (cbt == ffeglobal_hook (g));
5ff904cd 8836
c7e4ee3a 8837 assert (!init || !DECL_EXTERNAL (cbt));
5ff904cd 8838
c7e4ee3a
CB
8839 /* Make sure that any type can live in COMMON and be referenced
8840 without getting a bus error. We could pick the most restrictive
8841 alignment of all entities actually placed in the COMMON, but
8842 this seems easy enough. */
5ff904cd 8843
c7e4ee3a 8844 DECL_ALIGN (cbt) = BIGGEST_ALIGNMENT;
5ff904cd 8845
c7e4ee3a
CB
8846 if (is_init && (ffestorag_init (st) == NULL))
8847 init = ffecom_init_zero_ (cbt);
5ff904cd 8848
c7e4ee3a 8849 finish_decl (cbt, init, TRUE);
5ff904cd 8850
c7e4ee3a
CB
8851 if (is_init)
8852 ffestorag_set_init (st, ffebld_new_any ());
5ff904cd 8853
c7e4ee3a
CB
8854 if (init)
8855 {
8856 tree size_tree;
5ff904cd 8857
c7e4ee3a
CB
8858 assert (DECL_SIZE (cbt) != NULL_TREE);
8859 assert (TREE_CODE (DECL_SIZE (cbt)) == INTEGER_CST);
8860 size_tree = size_binop (CEIL_DIV_EXPR,
8861 DECL_SIZE (cbt),
8862 size_int (BITS_PER_UNIT));
8863 assert (TREE_INT_CST_HIGH (size_tree) == 0);
8864 assert (TREE_INT_CST_LOW (size_tree)
8865 == ffeglobal_common_size (g) + ffeglobal_common_pad (g));
8866 }
5ff904cd 8867
c7e4ee3a 8868 ffeglobal_set_hook (g, cbt);
5ff904cd 8869
c7e4ee3a 8870 ffestorag_set_hook (st, cbt);
5ff904cd 8871
c7e4ee3a
CB
8872 resume_temporary_allocation ();
8873 pop_obstacks ();
8874}
5ff904cd 8875
c7e4ee3a
CB
8876#endif
8877/* Make master area for local EQUIVALENCE. */
5ff904cd 8878
c7e4ee3a
CB
8879#if FFECOM_targetCURRENT == FFECOM_targetGCC
8880static void
8881ffecom_transform_equiv_ (ffestorag eqst)
8882{
8883 tree eqt;
8884 tree eqtype;
8885 tree init;
8886 tree high;
8887 bool is_init = ffestorag_is_init (eqst);
8888 int yes;
5ff904cd 8889
c7e4ee3a 8890 assert (eqst != NULL);
5ff904cd 8891
c7e4ee3a 8892 eqt = ffestorag_hook (eqst);
5ff904cd 8893
c7e4ee3a
CB
8894 if (eqt != NULL_TREE)
8895 return;
5ff904cd 8896
c7e4ee3a
CB
8897 /* Process inits. */
8898
8899 if (is_init)
8900 {
8901 if (ffestorag_init (eqst) != NULL)
5ff904cd 8902 {
c7e4ee3a 8903 ffebld sexp;
5ff904cd 8904
c7e4ee3a
CB
8905 /* Set the padding for the expression, so ffecom_expr
8906 knows to insert that many zeros. */
8907 switch (ffebld_op (sexp = ffestorag_init (eqst)))
8908 {
8909 case FFEBLD_opCONTER:
8910 ffebld_conter_set_pad (sexp, ffestorag_modulo (eqst));
8911 break;
5ff904cd 8912
c7e4ee3a
CB
8913 case FFEBLD_opARRTER:
8914 ffebld_arrter_set_pad (sexp, ffestorag_modulo (eqst));
8915 break;
5ff904cd 8916
c7e4ee3a
CB
8917 case FFEBLD_opACCTER:
8918 ffebld_accter_set_pad (sexp, ffestorag_modulo (eqst));
8919 break;
5ff904cd 8920
c7e4ee3a
CB
8921 default:
8922 assert ("bad op for eqv init (pad)" == NULL);
8923 break;
8924 }
5ff904cd 8925
c7e4ee3a
CB
8926 init = ffecom_expr (sexp);
8927 if (init == error_mark_node)
8928 init = NULL_TREE; /* Hopefully the back end complained! */
8929 }
8930 else
8931 init = error_mark_node;
8932 }
8933 else if (ffe_is_init_local_zero ())
8934 init = error_mark_node;
8935 else
8936 init = NULL_TREE;
5ff904cd 8937
c7e4ee3a
CB
8938 ffecom_member_namelisted_ = FALSE;
8939 ffestorag_drive (ffestorag_list_equivs (eqst),
8940 &ffecom_member_phase1_,
8941 eqst);
5ff904cd 8942
c7e4ee3a 8943 yes = suspend_momentary ();
5ff904cd 8944
c7e4ee3a
CB
8945 high = build_int_2 ((ffestorag_size (eqst)
8946 + ffestorag_modulo (eqst)) - 1, 0);
8947 TREE_TYPE (high) = ffecom_integer_type_node;
5ff904cd 8948
c7e4ee3a
CB
8949 eqtype = build_array_type (char_type_node,
8950 build_range_type (ffecom_integer_type_node,
8951 ffecom_integer_zero_node,
8952 high));
8953
8954 eqt = build_decl (VAR_DECL,
8955 ffecom_get_invented_identifier ("__g77_equiv_%s",
8956 ffesymbol_text
8957 (ffestorag_symbol
8958 (eqst)),
8959 -1),
8960 eqtype);
8961 DECL_EXTERNAL (eqt) = 0;
8962 if (is_init
8963 || ffecom_member_namelisted_
8964#ifdef FFECOM_sizeMAXSTACKITEM
8965 || (ffestorag_size (eqst) > FFECOM_sizeMAXSTACKITEM)
8966#endif
8967 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
8968 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
8969 && (ffestorag_is_save (eqst) || ffe_is_saveall ())))
8970 TREE_STATIC (eqt) = 1;
8971 else
8972 TREE_STATIC (eqt) = 0;
8973 TREE_PUBLIC (eqt) = 0;
8974 DECL_CONTEXT (eqt) = current_function_decl;
8975 if (init)
8976 DECL_INITIAL (eqt) = error_mark_node;
8977 else
8978 DECL_INITIAL (eqt) = NULL_TREE;
5ff904cd 8979
c7e4ee3a 8980 eqt = start_decl (eqt, FALSE);
5ff904cd 8981
c7e4ee3a
CB
8982 /* Make sure that any type can live in EQUIVALENCE and be referenced
8983 without getting a bus error. We could pick the most restrictive
8984 alignment of all entities actually placed in the EQUIVALENCE, but
8985 this seems easy enough. */
5ff904cd 8986
c7e4ee3a 8987 DECL_ALIGN (eqt) = BIGGEST_ALIGNMENT;
5ff904cd 8988
c7e4ee3a
CB
8989 if ((!is_init && ffe_is_init_local_zero ())
8990 || (is_init && (ffestorag_init (eqst) == NULL)))
8991 init = ffecom_init_zero_ (eqt);
5ff904cd 8992
c7e4ee3a 8993 finish_decl (eqt, init, FALSE);
5ff904cd 8994
c7e4ee3a
CB
8995 if (is_init)
8996 ffestorag_set_init (eqst, ffebld_new_any ());
5ff904cd 8997
c7e4ee3a
CB
8998 {
8999 tree size_tree;
5ff904cd 9000
c7e4ee3a
CB
9001 size_tree = size_binop (CEIL_DIV_EXPR,
9002 DECL_SIZE (eqt),
9003 size_int (BITS_PER_UNIT));
9004 assert (TREE_INT_CST_HIGH (size_tree) == 0);
9005 assert (TREE_INT_CST_LOW (size_tree)
9006 == ffestorag_size (eqst) + ffestorag_modulo (eqst));
9007 }
5ff904cd 9008
c7e4ee3a 9009 ffestorag_set_hook (eqst, eqt);
5ff904cd 9010
c7e4ee3a
CB
9011#ifdef SOMEONE_GETS_DEBUG_SUPPORT_WORKING
9012 ffestorag_drive (ffestorag_list_equivs (eqst),
9013 &ffecom_member_phase2_,
9014 eqst);
9015#endif
9016
9017 resume_momentary (yes);
5ff904cd
JL
9018}
9019
9020#endif
c7e4ee3a 9021/* Implement NAMELIST in back end. See f2c/format.c for more info. */
5ff904cd
JL
9022
9023#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
9024static tree
9025ffecom_transform_namelist_ (ffesymbol s)
5ff904cd 9026{
c7e4ee3a
CB
9027 tree nmlt;
9028 tree nmltype = ffecom_type_namelist_ ();
9029 tree nmlinits;
9030 tree nameinit;
9031 tree varsinit;
9032 tree nvarsinit;
9033 tree field;
9034 tree high;
5ff904cd 9035 int yes;
c7e4ee3a
CB
9036 int i;
9037 static int mynumber = 0;
5ff904cd 9038
c7e4ee3a 9039 yes = suspend_momentary ();
5ff904cd 9040
c7e4ee3a
CB
9041 nmlt = build_decl (VAR_DECL,
9042 ffecom_get_invented_identifier ("__g77_namelist_%d",
9043 NULL, mynumber++),
9044 nmltype);
9045 TREE_STATIC (nmlt) = 1;
9046 DECL_INITIAL (nmlt) = error_mark_node;
5ff904cd 9047
c7e4ee3a 9048 nmlt = start_decl (nmlt, FALSE);
5ff904cd 9049
c7e4ee3a 9050 /* Process inits. */
5ff904cd 9051
c7e4ee3a 9052 i = strlen (ffesymbol_text (s));
5ff904cd 9053
c7e4ee3a
CB
9054 high = build_int_2 (i, 0);
9055 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
9056
9057 nameinit = ffecom_build_f2c_string_ (i + 1,
9058 ffesymbol_text (s));
9059 TREE_TYPE (nameinit)
9060 = build_type_variant
9061 (build_array_type
9062 (char_type_node,
9063 build_range_type (ffecom_f2c_ftnlen_type_node,
9064 ffecom_f2c_ftnlen_one_node,
9065 high)),
9066 1, 0);
9067 TREE_CONSTANT (nameinit) = 1;
9068 TREE_STATIC (nameinit) = 1;
9069 nameinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (nameinit)),
9070 nameinit);
9071
9072 varsinit = ffecom_vardesc_array_ (s);
9073 varsinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (varsinit)),
9074 varsinit);
9075 TREE_CONSTANT (varsinit) = 1;
9076 TREE_STATIC (varsinit) = 1;
9077
9078 {
9079 ffebld b;
9080
9081 for (i = 0, b = ffesymbol_namelist (s); b != NULL; b = ffebld_trail (b))
9082 ++i;
9083 }
9084 nvarsinit = build_int_2 (i, 0);
9085 TREE_TYPE (nvarsinit) = integer_type_node;
9086 TREE_CONSTANT (nvarsinit) = 1;
9087 TREE_STATIC (nvarsinit) = 1;
9088
9089 nmlinits = build_tree_list ((field = TYPE_FIELDS (nmltype)), nameinit);
9090 TREE_CHAIN (nmlinits) = build_tree_list ((field = TREE_CHAIN (field)),
9091 varsinit);
9092 TREE_CHAIN (TREE_CHAIN (nmlinits))
9093 = build_tree_list ((field = TREE_CHAIN (field)), nvarsinit);
9094
9095 nmlinits = build (CONSTRUCTOR, nmltype, NULL_TREE, nmlinits);
9096 TREE_CONSTANT (nmlinits) = 1;
9097 TREE_STATIC (nmlinits) = 1;
9098
9099 finish_decl (nmlt, nmlinits, FALSE);
9100
9101 nmlt = ffecom_1 (ADDR_EXPR, build_pointer_type (nmltype), nmlt);
9102
9103 resume_momentary (yes);
9104
9105 return nmlt;
9106}
9107
9108#endif
9109
9110/* A subroutine of ffecom_tree_canonize_ref_. The incoming tree is
9111 analyzed on the assumption it is calculating a pointer to be
9112 indirected through. It must return the proper decl and offset,
9113 taking into account different units of measurements for offsets. */
9114
9115#if FFECOM_targetCURRENT == FFECOM_targetGCC
9116static void
9117ffecom_tree_canonize_ptr_ (tree *decl, tree *offset,
9118 tree t)
9119{
9120 switch (TREE_CODE (t))
9121 {
9122 case NOP_EXPR:
9123 case CONVERT_EXPR:
9124 case NON_LVALUE_EXPR:
9125 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
5ff904cd
JL
9126 break;
9127
c7e4ee3a
CB
9128 case PLUS_EXPR:
9129 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
9130 if ((*decl == NULL_TREE)
9131 || (*decl == error_mark_node))
9132 break;
9133
9134 if (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST)
9135 {
9136 /* An offset into COMMON. */
9137 *offset = size_binop (PLUS_EXPR,
9138 *offset,
9139 TREE_OPERAND (t, 1));
9140 /* Convert offset (presumably in bytes) into canonical units
9141 (presumably bits). */
9142 *offset = size_binop (MULT_EXPR,
9143 TYPE_SIZE (TREE_TYPE (TREE_TYPE (t))),
9144 *offset);
9145 break;
9146 }
9147 /* Not a COMMON reference, so an unrecognized pattern. */
9148 *decl = error_mark_node;
5ff904cd
JL
9149 break;
9150
c7e4ee3a
CB
9151 case PARM_DECL:
9152 *decl = t;
9153 *offset = bitsize_int (0L, 0L);
5ff904cd
JL
9154 break;
9155
c7e4ee3a
CB
9156 case ADDR_EXPR:
9157 if (TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL)
9158 {
9159 /* A reference to COMMON. */
9160 *decl = TREE_OPERAND (t, 0);
9161 *offset = bitsize_int (0L, 0L);
9162 break;
9163 }
9164 /* Fall through. */
5ff904cd 9165 default:
c7e4ee3a
CB
9166 /* Not a COMMON reference, so an unrecognized pattern. */
9167 *decl = error_mark_node;
5ff904cd
JL
9168 break;
9169 }
c7e4ee3a
CB
9170}
9171#endif
5ff904cd 9172
c7e4ee3a
CB
9173/* Given a tree that is possibly intended for use as an lvalue, return
9174 information representing a canonical view of that tree as a decl, an
9175 offset into that decl, and a size for the lvalue.
5ff904cd 9176
c7e4ee3a
CB
9177 If there's no applicable decl, NULL_TREE is returned for the decl,
9178 and the other fields are left undefined.
5ff904cd 9179
c7e4ee3a
CB
9180 If the tree doesn't fit the recognizable forms, an ERROR_MARK node
9181 is returned for the decl, and the other fields are left undefined.
5ff904cd 9182
c7e4ee3a
CB
9183 Otherwise, the decl returned currently is either a VAR_DECL or a
9184 PARM_DECL.
5ff904cd 9185
c7e4ee3a
CB
9186 The offset returned is always valid, but of course not necessarily
9187 a constant, and not necessarily converted into the appropriate
9188 type, leaving that up to the caller (so as to avoid that overhead
9189 if the decls being looked at are different anyway).
5ff904cd 9190
c7e4ee3a
CB
9191 If the size cannot be determined (e.g. an adjustable array),
9192 an ERROR_MARK node is returned for the size. Otherwise, the
9193 size returned is valid, not necessarily a constant, and not
9194 necessarily converted into the appropriate type as with the
9195 offset.
5ff904cd 9196
c7e4ee3a
CB
9197 Note that the offset and size expressions are expressed in the
9198 base storage units (usually bits) rather than in the units of
9199 the type of the decl, because two decls with different types
9200 might overlap but with apparently non-overlapping array offsets,
9201 whereas converting the array offsets to consistant offsets will
9202 reveal the overlap. */
5ff904cd
JL
9203
9204#if FFECOM_targetCURRENT == FFECOM_targetGCC
9205static void
c7e4ee3a
CB
9206ffecom_tree_canonize_ref_ (tree *decl, tree *offset,
9207 tree *size, tree t)
5ff904cd 9208{
c7e4ee3a
CB
9209 /* The default path is to report a nonexistant decl. */
9210 *decl = NULL_TREE;
5ff904cd 9211
c7e4ee3a 9212 if (t == NULL_TREE)
5ff904cd
JL
9213 return;
9214
c7e4ee3a
CB
9215 switch (TREE_CODE (t))
9216 {
9217 case ERROR_MARK:
9218 case IDENTIFIER_NODE:
9219 case INTEGER_CST:
9220 case REAL_CST:
9221 case COMPLEX_CST:
9222 case STRING_CST:
9223 case CONST_DECL:
9224 case PLUS_EXPR:
9225 case MINUS_EXPR:
9226 case MULT_EXPR:
9227 case TRUNC_DIV_EXPR:
9228 case CEIL_DIV_EXPR:
9229 case FLOOR_DIV_EXPR:
9230 case ROUND_DIV_EXPR:
9231 case TRUNC_MOD_EXPR:
9232 case CEIL_MOD_EXPR:
9233 case FLOOR_MOD_EXPR:
9234 case ROUND_MOD_EXPR:
9235 case RDIV_EXPR:
9236 case EXACT_DIV_EXPR:
9237 case FIX_TRUNC_EXPR:
9238 case FIX_CEIL_EXPR:
9239 case FIX_FLOOR_EXPR:
9240 case FIX_ROUND_EXPR:
9241 case FLOAT_EXPR:
9242 case EXPON_EXPR:
9243 case NEGATE_EXPR:
9244 case MIN_EXPR:
9245 case MAX_EXPR:
9246 case ABS_EXPR:
9247 case FFS_EXPR:
9248 case LSHIFT_EXPR:
9249 case RSHIFT_EXPR:
9250 case LROTATE_EXPR:
9251 case RROTATE_EXPR:
9252 case BIT_IOR_EXPR:
9253 case BIT_XOR_EXPR:
9254 case BIT_AND_EXPR:
9255 case BIT_ANDTC_EXPR:
9256 case BIT_NOT_EXPR:
9257 case TRUTH_ANDIF_EXPR:
9258 case TRUTH_ORIF_EXPR:
9259 case TRUTH_AND_EXPR:
9260 case TRUTH_OR_EXPR:
9261 case TRUTH_XOR_EXPR:
9262 case TRUTH_NOT_EXPR:
9263 case LT_EXPR:
9264 case LE_EXPR:
9265 case GT_EXPR:
9266 case GE_EXPR:
9267 case EQ_EXPR:
9268 case NE_EXPR:
9269 case COMPLEX_EXPR:
9270 case CONJ_EXPR:
9271 case REALPART_EXPR:
9272 case IMAGPART_EXPR:
9273 case LABEL_EXPR:
9274 case COMPONENT_REF:
9275 case COMPOUND_EXPR:
9276 case ADDR_EXPR:
9277 return;
5ff904cd 9278
c7e4ee3a
CB
9279 case VAR_DECL:
9280 case PARM_DECL:
9281 *decl = t;
9282 *offset = bitsize_int (0L, 0L);
9283 *size = TYPE_SIZE (TREE_TYPE (t));
9284 return;
5ff904cd 9285
c7e4ee3a
CB
9286 case ARRAY_REF:
9287 {
9288 tree array = TREE_OPERAND (t, 0);
9289 tree element = TREE_OPERAND (t, 1);
9290 tree init_offset;
9291
9292 if ((array == NULL_TREE)
9293 || (element == NULL_TREE))
9294 {
9295 *decl = error_mark_node;
9296 return;
9297 }
9298
9299 ffecom_tree_canonize_ref_ (decl, &init_offset, size,
9300 array);
9301 if ((*decl == NULL_TREE)
9302 || (*decl == error_mark_node))
9303 return;
9304
9305 *offset = size_binop (MULT_EXPR,
9306 TYPE_SIZE (TREE_TYPE (TREE_TYPE (array))),
9307 size_binop (MINUS_EXPR,
9308 element,
9309 TYPE_MIN_VALUE
9310 (TYPE_DOMAIN
9311 (TREE_TYPE (array)))));
9312
9313 *offset = size_binop (PLUS_EXPR,
9314 init_offset,
9315 *offset);
9316
9317 *size = TYPE_SIZE (TREE_TYPE (t));
9318 return;
9319 }
9320
9321 case INDIRECT_REF:
9322
9323 /* Most of this code is to handle references to COMMON. And so
9324 far that is useful only for calling library functions, since
9325 external (user) functions might reference common areas. But
9326 even calling an external function, it's worthwhile to decode
9327 COMMON references because if not storing into COMMON, we don't
9328 want COMMON-based arguments to gratuitously force use of a
9329 temporary. */
9330
9331 *size = TYPE_SIZE (TREE_TYPE (t));
5ff904cd 9332
c7e4ee3a
CB
9333 ffecom_tree_canonize_ptr_ (decl, offset,
9334 TREE_OPERAND (t, 0));
5ff904cd 9335
c7e4ee3a 9336 return;
5ff904cd 9337
c7e4ee3a
CB
9338 case CONVERT_EXPR:
9339 case NOP_EXPR:
9340 case MODIFY_EXPR:
9341 case NON_LVALUE_EXPR:
9342 case RESULT_DECL:
9343 case FIELD_DECL:
9344 case COND_EXPR: /* More cases than we can handle. */
9345 case SAVE_EXPR:
9346 case REFERENCE_EXPR:
9347 case PREDECREMENT_EXPR:
9348 case PREINCREMENT_EXPR:
9349 case POSTDECREMENT_EXPR:
9350 case POSTINCREMENT_EXPR:
9351 case CALL_EXPR:
9352 default:
9353 *decl = error_mark_node;
9354 return;
9355 }
9356}
9357#endif
5ff904cd 9358
c7e4ee3a 9359/* Do divide operation appropriate to type of operands. */
5ff904cd 9360
c7e4ee3a
CB
9361#if FFECOM_targetCURRENT == FFECOM_targetGCC
9362static tree
9363ffecom_tree_divide_ (tree tree_type, tree left, tree right,
9364 tree dest_tree, ffebld dest, bool *dest_used,
9365 tree hook)
9366{
9367 if ((left == error_mark_node)
9368 || (right == error_mark_node))
9369 return error_mark_node;
a6fa6420 9370
c7e4ee3a
CB
9371 switch (TREE_CODE (tree_type))
9372 {
9373 case INTEGER_TYPE:
9374 return ffecom_2 (TRUNC_DIV_EXPR, tree_type,
9375 left,
9376 right);
a6fa6420 9377
c7e4ee3a 9378 case COMPLEX_TYPE:
c64f913e
CB
9379 if (! optimize_size)
9380 return ffecom_2 (RDIV_EXPR, tree_type,
9381 left,
9382 right);
c7e4ee3a
CB
9383 {
9384 ffecomGfrt ix;
a6fa6420 9385
c7e4ee3a
CB
9386 if (TREE_TYPE (tree_type)
9387 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9388 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */
9389 else
9390 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */
a6fa6420 9391
c7e4ee3a
CB
9392 left = ffecom_1 (ADDR_EXPR,
9393 build_pointer_type (TREE_TYPE (left)),
9394 left);
9395 left = build_tree_list (NULL_TREE, left);
9396 right = ffecom_1 (ADDR_EXPR,
9397 build_pointer_type (TREE_TYPE (right)),
9398 right);
9399 right = build_tree_list (NULL_TREE, right);
9400 TREE_CHAIN (left) = right;
a6fa6420 9401
c7e4ee3a
CB
9402 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9403 ffecom_gfrt_kindtype (ix),
9404 ffe_is_f2c_library (),
9405 tree_type,
9406 left,
9407 dest_tree, dest, dest_used,
9408 NULL_TREE, TRUE, hook);
9409 }
9410 break;
5ff904cd 9411
c7e4ee3a
CB
9412 case RECORD_TYPE:
9413 {
9414 ffecomGfrt ix;
5ff904cd 9415
c7e4ee3a
CB
9416 if (TREE_TYPE (TYPE_FIELDS (tree_type))
9417 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9418 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */
9419 else
9420 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */
5ff904cd 9421
c7e4ee3a
CB
9422 left = ffecom_1 (ADDR_EXPR,
9423 build_pointer_type (TREE_TYPE (left)),
9424 left);
9425 left = build_tree_list (NULL_TREE, left);
9426 right = ffecom_1 (ADDR_EXPR,
9427 build_pointer_type (TREE_TYPE (right)),
9428 right);
9429 right = build_tree_list (NULL_TREE, right);
9430 TREE_CHAIN (left) = right;
a6fa6420 9431
c7e4ee3a
CB
9432 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9433 ffecom_gfrt_kindtype (ix),
9434 ffe_is_f2c_library (),
9435 tree_type,
9436 left,
9437 dest_tree, dest, dest_used,
9438 NULL_TREE, TRUE, hook);
9439 }
9440 break;
5ff904cd 9441
c7e4ee3a
CB
9442 default:
9443 return ffecom_2 (RDIV_EXPR, tree_type,
9444 left,
9445 right);
5ff904cd 9446 }
c7e4ee3a 9447}
5ff904cd 9448
c7e4ee3a
CB
9449#endif
9450/* Build type info for non-dummy variable. */
5ff904cd 9451
c7e4ee3a
CB
9452#if FFECOM_targetCURRENT == FFECOM_targetGCC
9453static tree
9454ffecom_type_localvar_ (ffesymbol s, ffeinfoBasictype bt,
9455 ffeinfoKindtype kt)
9456{
9457 tree type;
9458 ffebld dl;
9459 ffebld dim;
9460 tree lowt;
9461 tree hight;
5ff904cd 9462
c7e4ee3a
CB
9463 type = ffecom_tree_type[bt][kt];
9464 if (bt == FFEINFO_basictypeCHARACTER)
9465 {
9466 hight = build_int_2 (ffesymbol_size (s), 0);
9467 TREE_TYPE (hight) = ffecom_f2c_ftnlen_type_node;
5ff904cd 9468
c7e4ee3a
CB
9469 type
9470 = build_array_type
9471 (type,
9472 build_range_type (ffecom_f2c_ftnlen_type_node,
9473 ffecom_f2c_ftnlen_one_node,
9474 hight));
9475 type = ffecom_check_size_overflow_ (s, type, FALSE);
9476 }
5ff904cd 9477
c7e4ee3a
CB
9478 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
9479 {
9480 if (type == error_mark_node)
9481 break;
5ff904cd 9482
c7e4ee3a
CB
9483 dim = ffebld_head (dl);
9484 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
5ff904cd 9485
c7e4ee3a
CB
9486 if (ffebld_left (dim) == NULL)
9487 lowt = integer_one_node;
9488 else
9489 lowt = ffecom_expr (ffebld_left (dim));
5ff904cd 9490
c7e4ee3a
CB
9491 if (TREE_CODE (lowt) != INTEGER_CST)
9492 lowt = variable_size (lowt);
5ff904cd 9493
c7e4ee3a
CB
9494 assert (ffebld_right (dim) != NULL);
9495 hight = ffecom_expr (ffebld_right (dim));
5ff904cd 9496
c7e4ee3a
CB
9497 if (TREE_CODE (hight) != INTEGER_CST)
9498 hight = variable_size (hight);
5ff904cd 9499
c7e4ee3a
CB
9500 type = build_array_type (type,
9501 build_range_type (ffecom_integer_type_node,
9502 lowt, hight));
9503 type = ffecom_check_size_overflow_ (s, type, FALSE);
9504 }
5ff904cd 9505
c7e4ee3a 9506 return type;
5ff904cd
JL
9507}
9508
9509#endif
c7e4ee3a 9510/* Build Namelist type. */
5ff904cd 9511
c7e4ee3a
CB
9512#if FFECOM_targetCURRENT == FFECOM_targetGCC
9513static tree
9514ffecom_type_namelist_ ()
9515{
9516 static tree type = NULL_TREE;
5ff904cd 9517
c7e4ee3a
CB
9518 if (type == NULL_TREE)
9519 {
9520 static tree namefield, varsfield, nvarsfield;
9521 tree vardesctype;
5ff904cd 9522
c7e4ee3a 9523 vardesctype = ffecom_type_vardesc_ ();
5ff904cd 9524
c7e4ee3a
CB
9525 push_obstacks_nochange ();
9526 end_temporary_allocation ();
a6fa6420 9527
c7e4ee3a 9528 type = make_node (RECORD_TYPE);
a6fa6420 9529
c7e4ee3a 9530 vardesctype = build_pointer_type (build_pointer_type (vardesctype));
a6fa6420 9531
c7e4ee3a
CB
9532 namefield = ffecom_decl_field (type, NULL_TREE, "name",
9533 string_type_node);
9534 varsfield = ffecom_decl_field (type, namefield, "vars", vardesctype);
9535 nvarsfield = ffecom_decl_field (type, varsfield, "nvars",
9536 integer_type_node);
a6fa6420 9537
c7e4ee3a
CB
9538 TYPE_FIELDS (type) = namefield;
9539 layout_type (type);
a6fa6420 9540
c7e4ee3a
CB
9541 resume_temporary_allocation ();
9542 pop_obstacks ();
5ff904cd 9543 }
5ff904cd 9544
c7e4ee3a
CB
9545 return type;
9546}
5ff904cd 9547
c7e4ee3a 9548#endif
5ff904cd 9549
c7e4ee3a
CB
9550/* Make a copy of a type, assuming caller has switched to the permanent
9551 obstacks and that the type is for an aggregate (array) initializer. */
5ff904cd 9552
c7e4ee3a
CB
9553#if FFECOM_targetCURRENT == FFECOM_targetGCC && 0 /* Not used now. */
9554static tree
9555ffecom_type_permanent_copy_ (tree t)
9556{
9557 tree domain;
9558 tree max;
5ff904cd 9559
c7e4ee3a 9560 assert (TREE_TYPE (t) != NULL_TREE);
5ff904cd 9561
c7e4ee3a 9562 domain = TYPE_DOMAIN (t);
5ff904cd 9563
c7e4ee3a
CB
9564 assert (TREE_CODE (t) == ARRAY_TYPE);
9565 assert (TREE_PERMANENT (TREE_TYPE (t)));
9566 assert (TREE_PERMANENT (TREE_TYPE (domain)));
9567 assert (TREE_PERMANENT (TYPE_MIN_VALUE (domain)));
5ff904cd 9568
c7e4ee3a
CB
9569 max = TYPE_MAX_VALUE (domain);
9570 if (!TREE_PERMANENT (max))
9571 {
9572 assert (TREE_CODE (max) == INTEGER_CST);
5ff904cd 9573
c7e4ee3a
CB
9574 max = build_int_2 (TREE_INT_CST_LOW (max), TREE_INT_CST_HIGH (max));
9575 TREE_TYPE (max) = TREE_TYPE (TYPE_MIN_VALUE (domain));
9576 }
5ff904cd 9577
c7e4ee3a
CB
9578 return build_array_type (TREE_TYPE (t),
9579 build_range_type (TREE_TYPE (domain),
9580 TYPE_MIN_VALUE (domain),
9581 max));
9582}
9583#endif
5ff904cd 9584
c7e4ee3a 9585/* Build Vardesc type. */
5ff904cd 9586
c7e4ee3a
CB
9587#if FFECOM_targetCURRENT == FFECOM_targetGCC
9588static tree
9589ffecom_type_vardesc_ ()
9590{
9591 static tree type = NULL_TREE;
9592 static tree namefield, addrfield, dimsfield, typefield;
5ff904cd 9593
c7e4ee3a
CB
9594 if (type == NULL_TREE)
9595 {
9596 push_obstacks_nochange ();
9597 end_temporary_allocation ();
5ff904cd 9598
c7e4ee3a 9599 type = make_node (RECORD_TYPE);
5ff904cd 9600
c7e4ee3a
CB
9601 namefield = ffecom_decl_field (type, NULL_TREE, "name",
9602 string_type_node);
9603 addrfield = ffecom_decl_field (type, namefield, "addr",
9604 string_type_node);
9605 dimsfield = ffecom_decl_field (type, addrfield, "dims",
9606 ffecom_f2c_ptr_to_ftnlen_type_node);
9607 typefield = ffecom_decl_field (type, dimsfield, "type",
9608 integer_type_node);
5ff904cd 9609
c7e4ee3a
CB
9610 TYPE_FIELDS (type) = namefield;
9611 layout_type (type);
9612
9613 resume_temporary_allocation ();
9614 pop_obstacks ();
9615 }
9616
9617 return type;
5ff904cd
JL
9618}
9619
9620#endif
5ff904cd
JL
9621
9622#if FFECOM_targetCURRENT == FFECOM_targetGCC
9623static tree
c7e4ee3a 9624ffecom_vardesc_ (ffebld expr)
5ff904cd 9625{
c7e4ee3a 9626 ffesymbol s;
5ff904cd 9627
c7e4ee3a
CB
9628 assert (ffebld_op (expr) == FFEBLD_opSYMTER);
9629 s = ffebld_symter (expr);
5ff904cd 9630
c7e4ee3a
CB
9631 if (ffesymbol_hook (s).vardesc_tree == NULL_TREE)
9632 {
9633 int i;
9634 tree vardesctype = ffecom_type_vardesc_ ();
9635 tree var;
9636 tree nameinit;
9637 tree dimsinit;
9638 tree addrinit;
9639 tree typeinit;
9640 tree field;
9641 tree varinits;
9642 int yes;
9643 static int mynumber = 0;
5ff904cd 9644
c7e4ee3a 9645 yes = suspend_momentary ();
5ff904cd 9646
c7e4ee3a
CB
9647 var = build_decl (VAR_DECL,
9648 ffecom_get_invented_identifier ("__g77_vardesc_%d",
9649 NULL, mynumber++),
9650 vardesctype);
9651 TREE_STATIC (var) = 1;
9652 DECL_INITIAL (var) = error_mark_node;
5ff904cd 9653
c7e4ee3a 9654 var = start_decl (var, FALSE);
5ff904cd 9655
c7e4ee3a 9656 /* Process inits. */
5ff904cd 9657
c7e4ee3a
CB
9658 nameinit = ffecom_build_f2c_string_ ((i = strlen (ffesymbol_text (s)))
9659 + 1,
9660 ffesymbol_text (s));
9661 TREE_TYPE (nameinit)
9662 = build_type_variant
9663 (build_array_type
9664 (char_type_node,
9665 build_range_type (integer_type_node,
9666 integer_one_node,
9667 build_int_2 (i, 0))),
9668 1, 0);
9669 TREE_CONSTANT (nameinit) = 1;
9670 TREE_STATIC (nameinit) = 1;
9671 nameinit = ffecom_1 (ADDR_EXPR,
9672 build_pointer_type (TREE_TYPE (nameinit)),
9673 nameinit);
5ff904cd 9674
c7e4ee3a 9675 addrinit = ffecom_arg_ptr_to_expr (expr, &typeinit);
5ff904cd 9676
c7e4ee3a 9677 dimsinit = ffecom_vardesc_dims_ (s);
5ff904cd 9678
c7e4ee3a
CB
9679 if (typeinit == NULL_TREE)
9680 {
9681 ffeinfoBasictype bt = ffesymbol_basictype (s);
9682 ffeinfoKindtype kt = ffesymbol_kindtype (s);
9683 int tc = ffecom_f2c_typecode (bt, kt);
5ff904cd 9684
c7e4ee3a
CB
9685 assert (tc != -1);
9686 typeinit = build_int_2 (tc, (tc < 0) ? -1 : 0);
9687 }
9688 else
9689 typeinit = ffecom_1 (NEGATE_EXPR, TREE_TYPE (typeinit), typeinit);
5ff904cd 9690
c7e4ee3a
CB
9691 varinits = build_tree_list ((field = TYPE_FIELDS (vardesctype)),
9692 nameinit);
9693 TREE_CHAIN (varinits) = build_tree_list ((field = TREE_CHAIN (field)),
9694 addrinit);
9695 TREE_CHAIN (TREE_CHAIN (varinits))
9696 = build_tree_list ((field = TREE_CHAIN (field)), dimsinit);
9697 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (varinits)))
9698 = build_tree_list ((field = TREE_CHAIN (field)), typeinit);
5ff904cd 9699
c7e4ee3a
CB
9700 varinits = build (CONSTRUCTOR, vardesctype, NULL_TREE, varinits);
9701 TREE_CONSTANT (varinits) = 1;
9702 TREE_STATIC (varinits) = 1;
5ff904cd 9703
c7e4ee3a 9704 finish_decl (var, varinits, FALSE);
5ff904cd 9705
c7e4ee3a 9706 var = ffecom_1 (ADDR_EXPR, build_pointer_type (vardesctype), var);
5ff904cd 9707
c7e4ee3a 9708 resume_momentary (yes);
5ff904cd 9709
c7e4ee3a
CB
9710 ffesymbol_hook (s).vardesc_tree = var;
9711 }
5ff904cd 9712
c7e4ee3a
CB
9713 return ffesymbol_hook (s).vardesc_tree;
9714}
5ff904cd 9715
c7e4ee3a 9716#endif
5ff904cd 9717#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
9718static tree
9719ffecom_vardesc_array_ (ffesymbol s)
5ff904cd 9720{
c7e4ee3a
CB
9721 ffebld b;
9722 tree list;
9723 tree item = NULL_TREE;
9724 tree var;
9725 int i;
9726 int yes;
9727 static int mynumber = 0;
5ff904cd 9728
c7e4ee3a
CB
9729 for (i = 0, list = NULL_TREE, b = ffesymbol_namelist (s);
9730 b != NULL;
9731 b = ffebld_trail (b), ++i)
9732 {
9733 tree t;
5ff904cd 9734
c7e4ee3a 9735 t = ffecom_vardesc_ (ffebld_head (b));
5ff904cd 9736
c7e4ee3a
CB
9737 if (list == NULL_TREE)
9738 list = item = build_tree_list (NULL_TREE, t);
9739 else
5ff904cd 9740 {
c7e4ee3a
CB
9741 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
9742 item = TREE_CHAIN (item);
5ff904cd 9743 }
5ff904cd 9744 }
5ff904cd 9745
c7e4ee3a 9746 yes = suspend_momentary ();
5ff904cd 9747
c7e4ee3a
CB
9748 item = build_array_type (build_pointer_type (ffecom_type_vardesc_ ()),
9749 build_range_type (integer_type_node,
9750 integer_one_node,
9751 build_int_2 (i, 0)));
9752 list = build (CONSTRUCTOR, item, NULL_TREE, list);
9753 TREE_CONSTANT (list) = 1;
9754 TREE_STATIC (list) = 1;
5ff904cd 9755
c7e4ee3a
CB
9756 var = ffecom_get_invented_identifier ("__g77_vardesc_array_%d", NULL,
9757 mynumber++);
9758 var = build_decl (VAR_DECL, var, item);
9759 TREE_STATIC (var) = 1;
9760 DECL_INITIAL (var) = error_mark_node;
9761 var = start_decl (var, FALSE);
9762 finish_decl (var, list, FALSE);
5ff904cd 9763
c7e4ee3a 9764 resume_momentary (yes);
5ff904cd 9765
c7e4ee3a
CB
9766 return var;
9767}
5ff904cd 9768
c7e4ee3a
CB
9769#endif
9770#if FFECOM_targetCURRENT == FFECOM_targetGCC
9771static tree
9772ffecom_vardesc_dims_ (ffesymbol s)
9773{
9774 if (ffesymbol_dims (s) == NULL)
9775 return convert (ffecom_f2c_ptr_to_ftnlen_type_node,
9776 integer_zero_node);
5ff904cd 9777
c7e4ee3a
CB
9778 {
9779 ffebld b;
9780 ffebld e;
9781 tree list;
9782 tree backlist;
9783 tree item = NULL_TREE;
9784 tree var;
9785 int yes;
9786 tree numdim;
9787 tree numelem;
9788 tree baseoff = NULL_TREE;
9789 static int mynumber = 0;
9790
9791 numdim = build_int_2 ((int) ffesymbol_rank (s), 0);
9792 TREE_TYPE (numdim) = ffecom_f2c_ftnlen_type_node;
9793
9794 numelem = ffecom_expr (ffesymbol_arraysize (s));
9795 TREE_TYPE (numelem) = ffecom_f2c_ftnlen_type_node;
9796
9797 list = NULL_TREE;
9798 backlist = NULL_TREE;
9799 for (b = ffesymbol_dims (s), e = ffesymbol_extents (s);
9800 b != NULL;
9801 b = ffebld_trail (b), e = ffebld_trail (e))
5ff904cd 9802 {
c7e4ee3a
CB
9803 tree t;
9804 tree low;
9805 tree back;
5ff904cd 9806
c7e4ee3a
CB
9807 if (ffebld_trail (b) == NULL)
9808 t = NULL_TREE;
9809 else
5ff904cd 9810 {
c7e4ee3a
CB
9811 t = convert (ffecom_f2c_ftnlen_type_node,
9812 ffecom_expr (ffebld_head (e)));
5ff904cd 9813
c7e4ee3a
CB
9814 if (list == NULL_TREE)
9815 list = item = build_tree_list (NULL_TREE, t);
9816 else
9817 {
9818 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
9819 item = TREE_CHAIN (item);
9820 }
9821 }
5ff904cd 9822
c7e4ee3a
CB
9823 if (ffebld_left (ffebld_head (b)) == NULL)
9824 low = ffecom_integer_one_node;
9825 else
9826 low = ffecom_expr (ffebld_left (ffebld_head (b)));
9827 low = convert (ffecom_f2c_ftnlen_type_node, low);
5ff904cd 9828
c7e4ee3a
CB
9829 back = build_tree_list (low, t);
9830 TREE_CHAIN (back) = backlist;
9831 backlist = back;
9832 }
5ff904cd 9833
c7e4ee3a
CB
9834 for (item = backlist; item != NULL_TREE; item = TREE_CHAIN (item))
9835 {
9836 if (TREE_VALUE (item) == NULL_TREE)
9837 baseoff = TREE_PURPOSE (item);
9838 else
9839 baseoff = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
9840 TREE_PURPOSE (item),
9841 ffecom_2 (MULT_EXPR,
9842 ffecom_f2c_ftnlen_type_node,
9843 TREE_VALUE (item),
9844 baseoff));
5ff904cd
JL
9845 }
9846
c7e4ee3a 9847 /* backlist now dead, along with all TREE_PURPOSEs on it. */
5ff904cd 9848
c7e4ee3a
CB
9849 baseoff = build_tree_list (NULL_TREE, baseoff);
9850 TREE_CHAIN (baseoff) = list;
5ff904cd 9851
c7e4ee3a
CB
9852 numelem = build_tree_list (NULL_TREE, numelem);
9853 TREE_CHAIN (numelem) = baseoff;
5ff904cd 9854
c7e4ee3a
CB
9855 numdim = build_tree_list (NULL_TREE, numdim);
9856 TREE_CHAIN (numdim) = numelem;
5ff904cd 9857
c7e4ee3a 9858 yes = suspend_momentary ();
5ff904cd 9859
c7e4ee3a
CB
9860 item = build_array_type (ffecom_f2c_ftnlen_type_node,
9861 build_range_type (integer_type_node,
9862 integer_zero_node,
9863 build_int_2
9864 ((int) ffesymbol_rank (s)
9865 + 2, 0)));
9866 list = build (CONSTRUCTOR, item, NULL_TREE, numdim);
9867 TREE_CONSTANT (list) = 1;
9868 TREE_STATIC (list) = 1;
9869
9870 var = ffecom_get_invented_identifier ("__g77_dims_%d", NULL,
9871 mynumber++);
9872 var = build_decl (VAR_DECL, var, item);
9873 TREE_STATIC (var) = 1;
9874 DECL_INITIAL (var) = error_mark_node;
9875 var = start_decl (var, FALSE);
9876 finish_decl (var, list, FALSE);
9877
9878 var = ffecom_1 (ADDR_EXPR, build_pointer_type (item), var);
9879
9880 resume_momentary (yes);
9881
9882 return var;
9883 }
5ff904cd 9884}
c7e4ee3a 9885
5ff904cd 9886#endif
c7e4ee3a
CB
9887/* Essentially does a "fold (build1 (code, type, node))" while checking
9888 for certain housekeeping things.
5ff904cd 9889
c7e4ee3a
CB
9890 NOTE: for building an ADDR_EXPR around a FUNCTION_DECL, use
9891 ffecom_1_fn instead. */
5ff904cd
JL
9892
9893#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
9894tree
9895ffecom_1 (enum tree_code code, tree type, tree node)
5ff904cd 9896{
c7e4ee3a
CB
9897 tree item;
9898
9899 if ((node == error_mark_node)
9900 || (type == error_mark_node))
5ff904cd
JL
9901 return error_mark_node;
9902
c7e4ee3a 9903 if (code == ADDR_EXPR)
5ff904cd 9904 {
c7e4ee3a
CB
9905 if (!mark_addressable (node))
9906 assert ("can't mark_addressable this node!" == NULL);
9907 }
5ff904cd 9908
c7e4ee3a
CB
9909 switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
9910 {
9911 tree realtype;
5ff904cd 9912
c7e4ee3a
CB
9913 case REALPART_EXPR:
9914 item = build (COMPONENT_REF, type, node, TYPE_FIELDS (TREE_TYPE (node)));
5ff904cd
JL
9915 break;
9916
c7e4ee3a
CB
9917 case IMAGPART_EXPR:
9918 item = build (COMPONENT_REF, type, node, TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (node))));
9919 break;
5ff904cd 9920
5ff904cd 9921
c7e4ee3a
CB
9922 case NEGATE_EXPR:
9923 if (TREE_CODE (type) != RECORD_TYPE)
9924 {
9925 item = build1 (code, type, node);
9926 break;
9927 }
9928 node = ffecom_stabilize_aggregate_ (node);
9929 realtype = TREE_TYPE (TYPE_FIELDS (type));
9930 item =
9931 ffecom_2 (COMPLEX_EXPR, type,
9932 ffecom_1 (NEGATE_EXPR, realtype,
9933 ffecom_1 (REALPART_EXPR, realtype,
9934 node)),
9935 ffecom_1 (NEGATE_EXPR, realtype,
9936 ffecom_1 (IMAGPART_EXPR, realtype,
9937 node)));
5ff904cd
JL
9938 break;
9939
9940 default:
c7e4ee3a
CB
9941 item = build1 (code, type, node);
9942 break;
5ff904cd 9943 }
5ff904cd 9944
c7e4ee3a
CB
9945 if (TREE_SIDE_EFFECTS (node))
9946 TREE_SIDE_EFFECTS (item) = 1;
9947 if ((code == ADDR_EXPR) && staticp (node))
9948 TREE_CONSTANT (item) = 1;
9949 return fold (item);
9950}
5ff904cd 9951#endif
5ff904cd 9952
c7e4ee3a
CB
9953/* Like ffecom_1 (ADDR_EXPR, TREE_TYPE (node), node), except
9954 handles TREE_CODE (node) == FUNCTION_DECL. In particular,
9955 does not set TREE_ADDRESSABLE (because calling an inline
9956 function does not mean the function needs to be separately
9957 compiled). */
5ff904cd
JL
9958
9959#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
9960tree
9961ffecom_1_fn (tree node)
5ff904cd 9962{
c7e4ee3a 9963 tree item;
5ff904cd 9964 tree type;
5ff904cd 9965
c7e4ee3a
CB
9966 if (node == error_mark_node)
9967 return error_mark_node;
5ff904cd 9968
c7e4ee3a
CB
9969 type = build_type_variant (TREE_TYPE (node),
9970 TREE_READONLY (node),
9971 TREE_THIS_VOLATILE (node));
9972 item = build1 (ADDR_EXPR,
9973 build_pointer_type (type), node);
9974 if (TREE_SIDE_EFFECTS (node))
9975 TREE_SIDE_EFFECTS (item) = 1;
9976 if (staticp (node))
9977 TREE_CONSTANT (item) = 1;
9978 return fold (item);
5ff904cd 9979}
5ff904cd 9980#endif
c7e4ee3a
CB
9981
9982/* Essentially does a "fold (build (code, type, node1, node2))" while
9983 checking for certain housekeeping things. */
5ff904cd
JL
9984
9985#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
9986tree
9987ffecom_2 (enum tree_code code, tree type, tree node1,
9988 tree node2)
5ff904cd 9989{
c7e4ee3a 9990 tree item;
5ff904cd 9991
c7e4ee3a
CB
9992 if ((node1 == error_mark_node)
9993 || (node2 == error_mark_node)
9994 || (type == error_mark_node))
9995 return error_mark_node;
9996
9997 switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
5ff904cd 9998 {
c7e4ee3a 9999 tree a, b, c, d, realtype;
5ff904cd 10000
c7e4ee3a
CB
10001 case CONJ_EXPR:
10002 assert ("no CONJ_EXPR support yet" == NULL);
10003 return error_mark_node;
5ff904cd 10004
c7e4ee3a
CB
10005 case COMPLEX_EXPR:
10006 item = build_tree_list (TYPE_FIELDS (type), node1);
10007 TREE_CHAIN (item) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), node2);
10008 item = build (CONSTRUCTOR, type, NULL_TREE, item);
10009 break;
5ff904cd 10010
c7e4ee3a
CB
10011 case PLUS_EXPR:
10012 if (TREE_CODE (type) != RECORD_TYPE)
10013 {
10014 item = build (code, type, node1, node2);
10015 break;
10016 }
10017 node1 = ffecom_stabilize_aggregate_ (node1);
10018 node2 = ffecom_stabilize_aggregate_ (node2);
10019 realtype = TREE_TYPE (TYPE_FIELDS (type));
10020 item =
10021 ffecom_2 (COMPLEX_EXPR, type,
10022 ffecom_2 (PLUS_EXPR, realtype,
10023 ffecom_1 (REALPART_EXPR, realtype,
10024 node1),
10025 ffecom_1 (REALPART_EXPR, realtype,
10026 node2)),
10027 ffecom_2 (PLUS_EXPR, realtype,
10028 ffecom_1 (IMAGPART_EXPR, realtype,
10029 node1),
10030 ffecom_1 (IMAGPART_EXPR, realtype,
10031 node2)));
10032 break;
5ff904cd 10033
c7e4ee3a
CB
10034 case MINUS_EXPR:
10035 if (TREE_CODE (type) != RECORD_TYPE)
10036 {
10037 item = build (code, type, node1, node2);
10038 break;
10039 }
10040 node1 = ffecom_stabilize_aggregate_ (node1);
10041 node2 = ffecom_stabilize_aggregate_ (node2);
10042 realtype = TREE_TYPE (TYPE_FIELDS (type));
10043 item =
10044 ffecom_2 (COMPLEX_EXPR, type,
10045 ffecom_2 (MINUS_EXPR, realtype,
10046 ffecom_1 (REALPART_EXPR, realtype,
10047 node1),
10048 ffecom_1 (REALPART_EXPR, realtype,
10049 node2)),
10050 ffecom_2 (MINUS_EXPR, realtype,
10051 ffecom_1 (IMAGPART_EXPR, realtype,
10052 node1),
10053 ffecom_1 (IMAGPART_EXPR, realtype,
10054 node2)));
10055 break;
5ff904cd 10056
c7e4ee3a
CB
10057 case MULT_EXPR:
10058 if (TREE_CODE (type) != RECORD_TYPE)
10059 {
10060 item = build (code, type, node1, node2);
10061 break;
10062 }
10063 node1 = ffecom_stabilize_aggregate_ (node1);
10064 node2 = ffecom_stabilize_aggregate_ (node2);
10065 realtype = TREE_TYPE (TYPE_FIELDS (type));
10066 a = save_expr (ffecom_1 (REALPART_EXPR, realtype,
10067 node1));
10068 b = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
10069 node1));
10070 c = save_expr (ffecom_1 (REALPART_EXPR, realtype,
10071 node2));
10072 d = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
10073 node2));
10074 item =
10075 ffecom_2 (COMPLEX_EXPR, type,
10076 ffecom_2 (MINUS_EXPR, realtype,
10077 ffecom_2 (MULT_EXPR, realtype,
10078 a,
10079 c),
10080 ffecom_2 (MULT_EXPR, realtype,
10081 b,
10082 d)),
10083 ffecom_2 (PLUS_EXPR, realtype,
10084 ffecom_2 (MULT_EXPR, realtype,
10085 a,
10086 d),
10087 ffecom_2 (MULT_EXPR, realtype,
10088 c,
10089 b)));
10090 break;
5ff904cd 10091
c7e4ee3a
CB
10092 case EQ_EXPR:
10093 if ((TREE_CODE (node1) != RECORD_TYPE)
10094 && (TREE_CODE (node2) != RECORD_TYPE))
10095 {
10096 item = build (code, type, node1, node2);
10097 break;
10098 }
10099 assert (TREE_CODE (node1) == RECORD_TYPE);
10100 assert (TREE_CODE (node2) == RECORD_TYPE);
10101 node1 = ffecom_stabilize_aggregate_ (node1);
10102 node2 = ffecom_stabilize_aggregate_ (node2);
10103 realtype = TREE_TYPE (TYPE_FIELDS (type));
10104 item =
10105 ffecom_2 (TRUTH_ANDIF_EXPR, type,
10106 ffecom_2 (code, type,
10107 ffecom_1 (REALPART_EXPR, realtype,
10108 node1),
10109 ffecom_1 (REALPART_EXPR, realtype,
10110 node2)),
10111 ffecom_2 (code, type,
10112 ffecom_1 (IMAGPART_EXPR, realtype,
10113 node1),
10114 ffecom_1 (IMAGPART_EXPR, realtype,
10115 node2)));
10116 break;
10117
10118 case NE_EXPR:
10119 if ((TREE_CODE (node1) != RECORD_TYPE)
10120 && (TREE_CODE (node2) != RECORD_TYPE))
10121 {
10122 item = build (code, type, node1, node2);
10123 break;
10124 }
10125 assert (TREE_CODE (node1) == RECORD_TYPE);
10126 assert (TREE_CODE (node2) == RECORD_TYPE);
10127 node1 = ffecom_stabilize_aggregate_ (node1);
10128 node2 = ffecom_stabilize_aggregate_ (node2);
10129 realtype = TREE_TYPE (TYPE_FIELDS (type));
10130 item =
10131 ffecom_2 (TRUTH_ORIF_EXPR, type,
10132 ffecom_2 (code, type,
10133 ffecom_1 (REALPART_EXPR, realtype,
10134 node1),
10135 ffecom_1 (REALPART_EXPR, realtype,
10136 node2)),
10137 ffecom_2 (code, type,
10138 ffecom_1 (IMAGPART_EXPR, realtype,
10139 node1),
10140 ffecom_1 (IMAGPART_EXPR, realtype,
10141 node2)));
10142 break;
5ff904cd 10143
c7e4ee3a
CB
10144 default:
10145 item = build (code, type, node1, node2);
10146 break;
5ff904cd
JL
10147 }
10148
c7e4ee3a
CB
10149 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2))
10150 TREE_SIDE_EFFECTS (item) = 1;
10151 return fold (item);
5ff904cd
JL
10152}
10153
10154#endif
c7e4ee3a 10155/* ffecom_2pass_advise_entrypoint -- Advise that there's this entrypoint
5ff904cd 10156
c7e4ee3a
CB
10157 ffesymbol s; // the ENTRY point itself
10158 if (ffecom_2pass_advise_entrypoint(s))
10159 // the ENTRY point has been accepted
5ff904cd 10160
c7e4ee3a
CB
10161 Does whatever compiler needs to do when it learns about the entrypoint,
10162 like determine the return type of the master function, count the
10163 number of entrypoints, etc. Returns FALSE if the return type is
10164 not compatible with the return type(s) of other entrypoint(s).
5ff904cd 10165
c7e4ee3a
CB
10166 NOTE: for every call to this fn that returns TRUE, _do_entrypoint must
10167 later (after _finish_progunit) be called with the same entrypoint(s)
10168 as passed to this fn for which TRUE was returned.
5ff904cd 10169
c7e4ee3a
CB
10170 03-Jan-92 JCB 2.0
10171 Return FALSE if the return type conflicts with previous entrypoints. */
5ff904cd
JL
10172
10173#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
10174bool
10175ffecom_2pass_advise_entrypoint (ffesymbol entry)
5ff904cd 10176{
c7e4ee3a
CB
10177 ffebld list; /* opITEM. */
10178 ffebld mlist; /* opITEM. */
10179 ffebld plist; /* opITEM. */
10180 ffebld arg; /* ffebld_head(opITEM). */
10181 ffebld item; /* opITEM. */
10182 ffesymbol s; /* ffebld_symter(arg). */
10183 ffeinfoBasictype bt = ffesymbol_basictype (entry);
10184 ffeinfoKindtype kt = ffesymbol_kindtype (entry);
10185 ffetargetCharacterSize size = ffesymbol_size (entry);
10186 bool ok;
5ff904cd 10187
c7e4ee3a
CB
10188 if (ffecom_num_entrypoints_ == 0)
10189 { /* First entrypoint, make list of main
10190 arglist's dummies. */
10191 assert (ffecom_primary_entry_ != NULL);
5ff904cd 10192
c7e4ee3a
CB
10193 ffecom_master_bt_ = ffesymbol_basictype (ffecom_primary_entry_);
10194 ffecom_master_kt_ = ffesymbol_kindtype (ffecom_primary_entry_);
10195 ffecom_master_size_ = ffesymbol_size (ffecom_primary_entry_);
5ff904cd 10196
c7e4ee3a
CB
10197 for (plist = NULL, list = ffesymbol_dummyargs (ffecom_primary_entry_);
10198 list != NULL;
10199 list = ffebld_trail (list))
10200 {
10201 arg = ffebld_head (list);
10202 if (ffebld_op (arg) != FFEBLD_opSYMTER)
10203 continue; /* Alternate return or some such thing. */
10204 item = ffebld_new_item (arg, NULL);
10205 if (plist == NULL)
10206 ffecom_master_arglist_ = item;
10207 else
10208 ffebld_set_trail (plist, item);
10209 plist = item;
10210 }
5ff904cd
JL
10211 }
10212
c7e4ee3a
CB
10213 /* If necessary, scan entry arglist for alternate returns. Do this scan
10214 apparently redundantly (it's done below to UNIONize the arglists) so
10215 that we don't complain about RETURN 1 if an offending ENTRY is the only
10216 one with an alternate return. */
5ff904cd 10217
c7e4ee3a 10218 if (!ffecom_is_altreturning_)
5ff904cd 10219 {
c7e4ee3a
CB
10220 for (list = ffesymbol_dummyargs (entry);
10221 list != NULL;
10222 list = ffebld_trail (list))
10223 {
10224 arg = ffebld_head (list);
10225 if (ffebld_op (arg) == FFEBLD_opSTAR)
10226 {
10227 ffecom_is_altreturning_ = TRUE;
10228 break;
10229 }
10230 }
10231 }
5ff904cd 10232
c7e4ee3a 10233 /* Now check type compatibility. */
5ff904cd 10234
c7e4ee3a
CB
10235 switch (ffecom_master_bt_)
10236 {
10237 case FFEINFO_basictypeNONE:
10238 ok = (bt != FFEINFO_basictypeCHARACTER);
10239 break;
5ff904cd 10240
c7e4ee3a
CB
10241 case FFEINFO_basictypeCHARACTER:
10242 ok
10243 = (bt == FFEINFO_basictypeCHARACTER)
10244 && (kt == ffecom_master_kt_)
10245 && (size == ffecom_master_size_);
10246 break;
5ff904cd 10247
c7e4ee3a
CB
10248 case FFEINFO_basictypeANY:
10249 return FALSE; /* Just don't bother. */
5ff904cd 10250
c7e4ee3a
CB
10251 default:
10252 if (bt == FFEINFO_basictypeCHARACTER)
5ff904cd 10253 {
c7e4ee3a
CB
10254 ok = FALSE;
10255 break;
5ff904cd 10256 }
c7e4ee3a
CB
10257 ok = TRUE;
10258 if ((bt != ffecom_master_bt_) || (kt != ffecom_master_kt_))
10259 {
10260 ffecom_master_bt_ = FFEINFO_basictypeNONE;
10261 ffecom_master_kt_ = FFEINFO_kindtypeNONE;
10262 }
10263 break;
10264 }
5ff904cd 10265
c7e4ee3a
CB
10266 if (!ok)
10267 {
10268 ffebad_start (FFEBAD_ENTRY_CONFLICTS);
10269 ffest_ffebad_here_current_stmt (0);
10270 ffebad_finish ();
10271 return FALSE; /* Can't handle entrypoint. */
10272 }
5ff904cd 10273
c7e4ee3a 10274 /* Entrypoint type compatible with previous types. */
5ff904cd 10275
c7e4ee3a 10276 ++ffecom_num_entrypoints_;
5ff904cd 10277
c7e4ee3a
CB
10278 /* Master-arg-list = UNION(Master-arg-list,entry-arg-list). */
10279
10280 for (list = ffesymbol_dummyargs (entry);
10281 list != NULL;
10282 list = ffebld_trail (list))
10283 {
10284 arg = ffebld_head (list);
10285 if (ffebld_op (arg) != FFEBLD_opSYMTER)
10286 continue; /* Alternate return or some such thing. */
10287 s = ffebld_symter (arg);
10288 for (plist = NULL, mlist = ffecom_master_arglist_;
10289 mlist != NULL;
10290 plist = mlist, mlist = ffebld_trail (mlist))
10291 { /* plist points to previous item for easy
10292 appending of arg. */
10293 if (ffebld_symter (ffebld_head (mlist)) == s)
10294 break; /* Already have this arg in the master list. */
10295 }
10296 if (mlist != NULL)
10297 continue; /* Already have this arg in the master list. */
5ff904cd 10298
c7e4ee3a 10299 /* Append this arg to the master list. */
5ff904cd 10300
c7e4ee3a
CB
10301 item = ffebld_new_item (arg, NULL);
10302 if (plist == NULL)
10303 ffecom_master_arglist_ = item;
10304 else
10305 ffebld_set_trail (plist, item);
5ff904cd
JL
10306 }
10307
c7e4ee3a 10308 return TRUE;
5ff904cd
JL
10309}
10310
10311#endif
c7e4ee3a
CB
10312/* ffecom_2pass_do_entrypoint -- Do compilation of entrypoint
10313
10314 ffesymbol s; // the ENTRY point itself
10315 ffecom_2pass_do_entrypoint(s);
10316
10317 Does whatever compiler needs to do to make the entrypoint actually
10318 happen. Must be called for each entrypoint after
10319 ffecom_finish_progunit is called. */
10320
5ff904cd 10321#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
10322void
10323ffecom_2pass_do_entrypoint (ffesymbol entry)
5ff904cd 10324{
c7e4ee3a
CB
10325 static int mfn_num = 0;
10326 static int ent_num;
5ff904cd 10327
c7e4ee3a
CB
10328 if (mfn_num != ffecom_num_fns_)
10329 { /* First entrypoint for this program unit. */
10330 ent_num = 1;
10331 mfn_num = ffecom_num_fns_;
10332 ffecom_do_entry_ (ffecom_primary_entry_, 0);
10333 }
10334 else
10335 ++ent_num;
5ff904cd 10336
c7e4ee3a 10337 --ffecom_num_entrypoints_;
5ff904cd 10338
c7e4ee3a
CB
10339 ffecom_do_entry_ (entry, ent_num);
10340}
5ff904cd 10341
c7e4ee3a 10342#endif
5ff904cd 10343
c7e4ee3a
CB
10344/* Essentially does a "fold (build (code, type, node1, node2))" while
10345 checking for certain housekeeping things. Always sets
10346 TREE_SIDE_EFFECTS. */
5ff904cd 10347
c7e4ee3a
CB
10348#if FFECOM_targetCURRENT == FFECOM_targetGCC
10349tree
10350ffecom_2s (enum tree_code code, tree type, tree node1,
10351 tree node2)
10352{
10353 tree item;
5ff904cd 10354
c7e4ee3a
CB
10355 if ((node1 == error_mark_node)
10356 || (node2 == error_mark_node)
10357 || (type == error_mark_node))
10358 return error_mark_node;
5ff904cd 10359
c7e4ee3a
CB
10360 item = build (code, type, node1, node2);
10361 TREE_SIDE_EFFECTS (item) = 1;
10362 return fold (item);
5ff904cd
JL
10363}
10364
10365#endif
c7e4ee3a
CB
10366/* Essentially does a "fold (build (code, type, node1, node2, node3))" while
10367 checking for certain housekeeping things. */
10368
5ff904cd 10369#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
10370tree
10371ffecom_3 (enum tree_code code, tree type, tree node1,
10372 tree node2, tree node3)
5ff904cd 10373{
c7e4ee3a 10374 tree item;
5ff904cd 10375
c7e4ee3a
CB
10376 if ((node1 == error_mark_node)
10377 || (node2 == error_mark_node)
10378 || (node3 == error_mark_node)
10379 || (type == error_mark_node))
10380 return error_mark_node;
5ff904cd 10381
c7e4ee3a
CB
10382 item = build (code, type, node1, node2, node3);
10383 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2)
10384 || (node3 != NULL_TREE && TREE_SIDE_EFFECTS (node3)))
10385 TREE_SIDE_EFFECTS (item) = 1;
10386 return fold (item);
10387}
5ff904cd 10388
c7e4ee3a
CB
10389#endif
10390/* Essentially does a "fold (build (code, type, node1, node2, node3))" while
10391 checking for certain housekeeping things. Always sets
10392 TREE_SIDE_EFFECTS. */
5ff904cd 10393
c7e4ee3a
CB
10394#if FFECOM_targetCURRENT == FFECOM_targetGCC
10395tree
10396ffecom_3s (enum tree_code code, tree type, tree node1,
10397 tree node2, tree node3)
10398{
10399 tree item;
5ff904cd 10400
c7e4ee3a
CB
10401 if ((node1 == error_mark_node)
10402 || (node2 == error_mark_node)
10403 || (node3 == error_mark_node)
10404 || (type == error_mark_node))
10405 return error_mark_node;
5ff904cd 10406
c7e4ee3a
CB
10407 item = build (code, type, node1, node2, node3);
10408 TREE_SIDE_EFFECTS (item) = 1;
10409 return fold (item);
10410}
5ff904cd 10411
c7e4ee3a 10412#endif
5ff904cd 10413
c7e4ee3a 10414/* ffecom_arg_expr -- Transform argument expr into gcc tree
5ff904cd 10415
c7e4ee3a 10416 See use by ffecom_list_expr.
5ff904cd 10417
c7e4ee3a
CB
10418 If expression is NULL, returns an integer zero tree. If it is not
10419 a CHARACTER expression, returns whatever ffecom_expr
10420 returns and sets the length return value to NULL_TREE. Otherwise
10421 generates code to evaluate the character expression, returns the proper
10422 pointer to the result, but does NOT set the length return value to a tree
10423 that specifies the length of the result. (In other words, the length
10424 variable is always set to NULL_TREE, because a length is never passed.)
5ff904cd 10425
c7e4ee3a
CB
10426 21-Dec-91 JCB 1.1
10427 Don't set returned length, since nobody needs it (yet; someday if
10428 we allow CHARACTER*(*) dummies to statement functions, we'll need
10429 it). */
5ff904cd 10430
c7e4ee3a
CB
10431#if FFECOM_targetCURRENT == FFECOM_targetGCC
10432tree
10433ffecom_arg_expr (ffebld expr, tree *length)
10434{
10435 tree ign;
5ff904cd 10436
c7e4ee3a 10437 *length = NULL_TREE;
5ff904cd 10438
c7e4ee3a
CB
10439 if (expr == NULL)
10440 return integer_zero_node;
5ff904cd 10441
c7e4ee3a
CB
10442 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10443 return ffecom_expr (expr);
5ff904cd 10444
c7e4ee3a
CB
10445 return ffecom_arg_ptr_to_expr (expr, &ign);
10446}
10447
10448#endif
10449/* Transform expression into constant argument-pointer-to-expression tree.
10450
10451 If the expression can be transformed into a argument-pointer-to-expression
10452 tree that is constant, that is done, and the tree returned. Else
10453 NULL_TREE is returned.
5ff904cd 10454
c7e4ee3a
CB
10455 That way, a caller can attempt to provide compile-time initialization
10456 of a variable and, if that fails, *then* choose to start a new block
10457 and resort to using temporaries, as appropriate. */
5ff904cd 10458
c7e4ee3a
CB
10459tree
10460ffecom_arg_ptr_to_const_expr (ffebld expr, tree *length)
10461{
10462 if (! expr)
10463 return integer_zero_node;
5ff904cd 10464
c7e4ee3a
CB
10465 if (ffebld_op (expr) == FFEBLD_opANY)
10466 {
10467 if (length)
10468 *length = error_mark_node;
10469 return error_mark_node;
10470 }
10471
10472 if (ffebld_arity (expr) == 0
10473 && (ffebld_op (expr) != FFEBLD_opSYMTER
10474 || ffebld_where (expr) == FFEINFO_whereCOMMON
10475 || ffebld_where (expr) == FFEINFO_whereGLOBAL
10476 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
10477 {
10478 tree t;
10479
10480 t = ffecom_arg_ptr_to_expr (expr, length);
10481 assert (TREE_CONSTANT (t));
10482 assert (! length || TREE_CONSTANT (*length));
10483 return t;
10484 }
10485
10486 if (length
10487 && ffebld_size (expr) != FFETARGET_charactersizeNONE)
10488 *length = build_int_2 (ffebld_size (expr), 0);
10489 else if (length)
10490 *length = NULL_TREE;
10491 return NULL_TREE;
5ff904cd
JL
10492}
10493
c7e4ee3a 10494/* ffecom_arg_ptr_to_expr -- Transform argument expr into gcc tree
5ff904cd 10495
c7e4ee3a
CB
10496 See use by ffecom_list_ptr_to_expr.
10497
10498 If expression is NULL, returns an integer zero tree. If it is not
10499 a CHARACTER expression, returns whatever ffecom_ptr_to_expr
10500 returns and sets the length return value to NULL_TREE. Otherwise
10501 generates code to evaluate the character expression, returns the proper
10502 pointer to the result, AND sets the length return value to a tree that
10503 specifies the length of the result.
10504
10505 If the length argument is NULL, this is a slightly special
10506 case of building a FORMAT expression, that is, an expression that
10507 will be used at run time without regard to length. For the current
10508 implementation, which uses the libf2c library, this means it is nice
10509 to append a null byte to the end of the expression, where feasible,
10510 to make sure any diagnostic about the FORMAT string terminates at
10511 some useful point.
10512
10513 For now, treat %REF(char-expr) as the same as char-expr with a NULL
10514 length argument. This might even be seen as a feature, if a null
10515 byte can always be appended. */
5ff904cd
JL
10516
10517#if FFECOM_targetCURRENT == FFECOM_targetGCC
10518tree
c7e4ee3a 10519ffecom_arg_ptr_to_expr (ffebld expr, tree *length)
5ff904cd
JL
10520{
10521 tree item;
c7e4ee3a
CB
10522 tree ign_length;
10523 ffecomConcatList_ catlist;
5ff904cd 10524
c7e4ee3a
CB
10525 if (length != NULL)
10526 *length = NULL_TREE;
5ff904cd 10527
c7e4ee3a
CB
10528 if (expr == NULL)
10529 return integer_zero_node;
5ff904cd 10530
c7e4ee3a 10531 switch (ffebld_op (expr))
5ff904cd 10532 {
c7e4ee3a
CB
10533 case FFEBLD_opPERCENT_VAL:
10534 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10535 return ffecom_expr (ffebld_left (expr));
10536 {
10537 tree temp_exp;
10538 tree temp_length;
5ff904cd 10539
c7e4ee3a
CB
10540 temp_exp = ffecom_arg_ptr_to_expr (ffebld_left (expr), &temp_length);
10541 if (temp_exp == error_mark_node)
10542 return error_mark_node;
5ff904cd 10543
c7e4ee3a
CB
10544 return ffecom_1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (temp_exp)),
10545 temp_exp);
10546 }
5ff904cd 10547
c7e4ee3a
CB
10548 case FFEBLD_opPERCENT_REF:
10549 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10550 return ffecom_ptr_to_expr (ffebld_left (expr));
10551 if (length != NULL)
10552 {
10553 ign_length = NULL_TREE;
10554 length = &ign_length;
10555 }
10556 expr = ffebld_left (expr);
10557 break;
5ff904cd 10558
c7e4ee3a
CB
10559 case FFEBLD_opPERCENT_DESCR:
10560 switch (ffeinfo_basictype (ffebld_info (expr)))
5ff904cd 10561 {
c7e4ee3a
CB
10562#ifdef PASS_HOLLERITH_BY_DESCRIPTOR
10563 case FFEINFO_basictypeHOLLERITH:
10564#endif
10565 case FFEINFO_basictypeCHARACTER:
10566 break; /* Passed by descriptor anyway. */
10567
10568 default:
10569 item = ffecom_ptr_to_expr (expr);
10570 if (item != error_mark_node)
10571 *length = TYPE_SIZE (TREE_TYPE (TREE_TYPE (item)));
5ff904cd
JL
10572 break;
10573 }
5ff904cd
JL
10574 break;
10575
10576 default:
5ff904cd
JL
10577 break;
10578 }
10579
c7e4ee3a
CB
10580#ifdef PASS_HOLLERITH_BY_DESCRIPTOR
10581 if ((ffeinfo_basictype (ffebld_info (expr)) == FFEINFO_basictypeHOLLERITH)
10582 && (length != NULL))
10583 { /* Pass Hollerith by descriptor. */
10584 ffetargetHollerith h;
10585
10586 assert (ffebld_op (expr) == FFEBLD_opCONTER);
10587 h = ffebld_cu_val_hollerith (ffebld_constant_union
10588 (ffebld_conter (expr)));
10589 *length
10590 = build_int_2 (h.length, 0);
10591 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
10592 }
10593#endif
10594
10595 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10596 return ffecom_ptr_to_expr (expr);
10597
10598 assert (ffeinfo_kindtype (ffebld_info (expr))
10599 == FFEINFO_kindtypeCHARACTER1);
10600
47d98fa2
CB
10601 while (ffebld_op (expr) == FFEBLD_opPAREN)
10602 expr = ffebld_left (expr);
10603
c7e4ee3a
CB
10604 catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
10605 switch (ffecom_concat_list_count_ (catlist))
10606 {
10607 case 0: /* Shouldn't happen, but in case it does... */
10608 if (length != NULL)
10609 {
10610 *length = ffecom_f2c_ftnlen_zero_node;
10611 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
10612 }
10613 ffecom_concat_list_kill_ (catlist);
10614 return null_pointer_node;
10615
10616 case 1: /* The (fairly) easy case. */
10617 if (length == NULL)
10618 ffecom_char_args_with_null_ (&item, &ign_length,
10619 ffecom_concat_list_expr_ (catlist, 0));
10620 else
10621 ffecom_char_args_ (&item, length,
10622 ffecom_concat_list_expr_ (catlist, 0));
10623 ffecom_concat_list_kill_ (catlist);
10624 assert (item != NULL_TREE);
10625 return item;
10626
10627 default: /* Must actually concatenate things. */
10628 break;
10629 }
10630
10631 {
10632 int count = ffecom_concat_list_count_ (catlist);
10633 int i;
10634 tree lengths;
10635 tree items;
10636 tree length_array;
10637 tree item_array;
10638 tree citem;
10639 tree clength;
10640 tree temporary;
10641 tree num;
10642 tree known_length;
10643 ffetargetCharacterSize sz;
10644
10645 sz = ffecom_concat_list_maxlen_ (catlist);
10646 /* ~~Kludge! */
10647 assert (sz != FFETARGET_charactersizeNONE);
10648
10649#ifdef HOHO
10650 length_array
10651 = lengths
10652 = ffecom_push_tempvar (ffecom_f2c_ftnlen_type_node,
10653 FFETARGET_charactersizeNONE, count, TRUE);
10654 item_array
10655 = items
10656 = ffecom_push_tempvar (ffecom_f2c_address_type_node,
10657 FFETARGET_charactersizeNONE, count, TRUE);
10658 temporary = ffecom_push_tempvar (char_type_node,
10659 sz, -1, TRUE);
10660#else
10661 {
10662 tree hook;
10663
10664 hook = ffebld_nonter_hook (expr);
10665 assert (hook);
10666 assert (TREE_CODE (hook) == TREE_VEC);
10667 assert (TREE_VEC_LENGTH (hook) == 3);
10668 length_array = lengths = TREE_VEC_ELT (hook, 0);
10669 item_array = items = TREE_VEC_ELT (hook, 1);
10670 temporary = TREE_VEC_ELT (hook, 2);
10671 }
10672#endif
10673
10674 known_length = ffecom_f2c_ftnlen_zero_node;
10675
10676 for (i = 0; i < count; ++i)
10677 {
10678 if ((i == count)
10679 && (length == NULL))
10680 ffecom_char_args_with_null_ (&citem, &clength,
10681 ffecom_concat_list_expr_ (catlist, i));
10682 else
10683 ffecom_char_args_ (&citem, &clength,
10684 ffecom_concat_list_expr_ (catlist, i));
10685 if ((citem == error_mark_node)
10686 || (clength == error_mark_node))
10687 {
10688 ffecom_concat_list_kill_ (catlist);
10689 *length = error_mark_node;
10690 return error_mark_node;
10691 }
10692
10693 items
10694 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
10695 ffecom_modify (void_type_node,
10696 ffecom_2 (ARRAY_REF,
10697 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
10698 item_array,
10699 build_int_2 (i, 0)),
10700 citem),
10701 items);
10702 clength = ffecom_save_tree (clength);
10703 if (length != NULL)
10704 known_length
10705 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
10706 known_length,
10707 clength);
10708 lengths
10709 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
10710 ffecom_modify (void_type_node,
10711 ffecom_2 (ARRAY_REF,
10712 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
10713 length_array,
10714 build_int_2 (i, 0)),
10715 clength),
10716 lengths);
10717 }
10718
10719 temporary = ffecom_1 (ADDR_EXPR,
10720 build_pointer_type (TREE_TYPE (temporary)),
10721 temporary);
10722
10723 item = build_tree_list (NULL_TREE, temporary);
10724 TREE_CHAIN (item)
10725 = build_tree_list (NULL_TREE,
10726 ffecom_1 (ADDR_EXPR,
10727 build_pointer_type (TREE_TYPE (items)),
10728 items));
10729 TREE_CHAIN (TREE_CHAIN (item))
10730 = build_tree_list (NULL_TREE,
10731 ffecom_1 (ADDR_EXPR,
10732 build_pointer_type (TREE_TYPE (lengths)),
10733 lengths));
10734 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
10735 = build_tree_list
10736 (NULL_TREE,
10737 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
10738 convert (ffecom_f2c_ftnlen_type_node,
10739 build_int_2 (count, 0))));
10740 num = build_int_2 (sz, 0);
10741 TREE_TYPE (num) = ffecom_f2c_ftnlen_type_node;
10742 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item))))
10743 = build_tree_list (NULL_TREE, num);
10744
10745 item = ffecom_call_gfrt (FFECOM_gfrtCAT, item, NULL_TREE);
5ff904cd 10746 TREE_SIDE_EFFECTS (item) = 1;
c7e4ee3a
CB
10747 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (temporary),
10748 item,
10749 temporary);
10750
10751 if (length != NULL)
10752 *length = known_length;
10753 }
10754
10755 ffecom_concat_list_kill_ (catlist);
10756 assert (item != NULL_TREE);
10757 return item;
5ff904cd 10758}
c7e4ee3a 10759
5ff904cd 10760#endif
c7e4ee3a 10761/* Generate call to run-time function.
5ff904cd 10762
c7e4ee3a
CB
10763 The first arg is the GNU Fortran Run-Time function index, the second
10764 arg is the list of arguments to pass to it. Returned is the expression
10765 (WITHOUT TREE_SIDE_EFFECTS set!) that makes the call and returns the
10766 result (which may be void). */
5ff904cd
JL
10767
10768#if FFECOM_targetCURRENT == FFECOM_targetGCC
10769tree
c7e4ee3a 10770ffecom_call_gfrt (ffecomGfrt ix, tree args, tree hook)
5ff904cd 10771{
c7e4ee3a
CB
10772 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
10773 ffecom_gfrt_kindtype (ix),
10774 ffe_is_f2c_library () && ffecom_gfrt_complex_[ix],
10775 NULL_TREE, args, NULL_TREE, NULL,
10776 NULL, NULL_TREE, TRUE, hook);
5ff904cd
JL
10777}
10778#endif
10779
c7e4ee3a 10780/* Transform constant-union to tree. */
5ff904cd
JL
10781
10782#if FFECOM_targetCURRENT == FFECOM_targetGCC
10783tree
c7e4ee3a
CB
10784ffecom_constantunion (ffebldConstantUnion *cu, ffeinfoBasictype bt,
10785 ffeinfoKindtype kt, tree tree_type)
5ff904cd
JL
10786{
10787 tree item;
10788
c7e4ee3a 10789 switch (bt)
5ff904cd 10790 {
c7e4ee3a
CB
10791 case FFEINFO_basictypeINTEGER:
10792 {
10793 int val;
5ff904cd 10794
c7e4ee3a
CB
10795 switch (kt)
10796 {
10797#if FFETARGET_okINTEGER1
10798 case FFEINFO_kindtypeINTEGER1:
10799 val = ffebld_cu_val_integer1 (*cu);
10800 break;
10801#endif
5ff904cd 10802
c7e4ee3a
CB
10803#if FFETARGET_okINTEGER2
10804 case FFEINFO_kindtypeINTEGER2:
10805 val = ffebld_cu_val_integer2 (*cu);
10806 break;
10807#endif
5ff904cd 10808
c7e4ee3a
CB
10809#if FFETARGET_okINTEGER3
10810 case FFEINFO_kindtypeINTEGER3:
10811 val = ffebld_cu_val_integer3 (*cu);
10812 break;
10813#endif
5ff904cd 10814
c7e4ee3a
CB
10815#if FFETARGET_okINTEGER4
10816 case FFEINFO_kindtypeINTEGER4:
10817 val = ffebld_cu_val_integer4 (*cu);
10818 break;
10819#endif
5ff904cd 10820
c7e4ee3a
CB
10821 default:
10822 assert ("bad INTEGER constant kind type" == NULL);
10823 /* Fall through. */
10824 case FFEINFO_kindtypeANY:
10825 return error_mark_node;
10826 }
10827 item = build_int_2 (val, (val < 0) ? -1 : 0);
10828 TREE_TYPE (item) = tree_type;
10829 }
5ff904cd 10830 break;
5ff904cd 10831
c7e4ee3a
CB
10832 case FFEINFO_basictypeLOGICAL:
10833 {
10834 int val;
5ff904cd 10835
c7e4ee3a
CB
10836 switch (kt)
10837 {
10838#if FFETARGET_okLOGICAL1
10839 case FFEINFO_kindtypeLOGICAL1:
10840 val = ffebld_cu_val_logical1 (*cu);
10841 break;
5ff904cd 10842#endif
5ff904cd 10843
c7e4ee3a
CB
10844#if FFETARGET_okLOGICAL2
10845 case FFEINFO_kindtypeLOGICAL2:
10846 val = ffebld_cu_val_logical2 (*cu);
10847 break;
10848#endif
5ff904cd 10849
c7e4ee3a
CB
10850#if FFETARGET_okLOGICAL3
10851 case FFEINFO_kindtypeLOGICAL3:
10852 val = ffebld_cu_val_logical3 (*cu);
10853 break;
10854#endif
5ff904cd 10855
c7e4ee3a
CB
10856#if FFETARGET_okLOGICAL4
10857 case FFEINFO_kindtypeLOGICAL4:
10858 val = ffebld_cu_val_logical4 (*cu);
10859 break;
10860#endif
5ff904cd 10861
c7e4ee3a
CB
10862 default:
10863 assert ("bad LOGICAL constant kind type" == NULL);
10864 /* Fall through. */
10865 case FFEINFO_kindtypeANY:
10866 return error_mark_node;
10867 }
10868 item = build_int_2 (val, (val < 0) ? -1 : 0);
10869 TREE_TYPE (item) = tree_type;
10870 }
10871 break;
5ff904cd 10872
c7e4ee3a
CB
10873 case FFEINFO_basictypeREAL:
10874 {
10875 REAL_VALUE_TYPE val;
5ff904cd 10876
c7e4ee3a
CB
10877 switch (kt)
10878 {
10879#if FFETARGET_okREAL1
10880 case FFEINFO_kindtypeREAL1:
10881 val = ffetarget_value_real1 (ffebld_cu_val_real1 (*cu));
10882 break;
10883#endif
5ff904cd 10884
c7e4ee3a
CB
10885#if FFETARGET_okREAL2
10886 case FFEINFO_kindtypeREAL2:
10887 val = ffetarget_value_real2 (ffebld_cu_val_real2 (*cu));
10888 break;
10889#endif
5ff904cd 10890
c7e4ee3a
CB
10891#if FFETARGET_okREAL3
10892 case FFEINFO_kindtypeREAL3:
10893 val = ffetarget_value_real3 (ffebld_cu_val_real3 (*cu));
10894 break;
10895#endif
5ff904cd 10896
c7e4ee3a
CB
10897#if FFETARGET_okREAL4
10898 case FFEINFO_kindtypeREAL4:
10899 val = ffetarget_value_real4 (ffebld_cu_val_real4 (*cu));
10900 break;
10901#endif
5ff904cd 10902
c7e4ee3a
CB
10903 default:
10904 assert ("bad REAL constant kind type" == NULL);
10905 /* Fall through. */
10906 case FFEINFO_kindtypeANY:
10907 return error_mark_node;
10908 }
10909 item = build_real (tree_type, val);
10910 }
5ff904cd
JL
10911 break;
10912
c7e4ee3a
CB
10913 case FFEINFO_basictypeCOMPLEX:
10914 {
10915 REAL_VALUE_TYPE real;
10916 REAL_VALUE_TYPE imag;
10917 tree el_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
5ff904cd 10918
c7e4ee3a
CB
10919 switch (kt)
10920 {
10921#if FFETARGET_okCOMPLEX1
10922 case FFEINFO_kindtypeREAL1:
10923 real = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).real);
10924 imag = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).imaginary);
10925 break;
10926#endif
5ff904cd 10927
c7e4ee3a
CB
10928#if FFETARGET_okCOMPLEX2
10929 case FFEINFO_kindtypeREAL2:
10930 real = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).real);
10931 imag = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).imaginary);
10932 break;
10933#endif
5ff904cd 10934
c7e4ee3a
CB
10935#if FFETARGET_okCOMPLEX3
10936 case FFEINFO_kindtypeREAL3:
10937 real = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).real);
10938 imag = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).imaginary);
10939 break;
10940#endif
5ff904cd 10941
c7e4ee3a
CB
10942#if FFETARGET_okCOMPLEX4
10943 case FFEINFO_kindtypeREAL4:
10944 real = ffetarget_value_real4 (ffebld_cu_val_complex4 (*cu).real);
10945 imag = ffetarget_value_real4 (ffebld_cu_val_complex4 (*cu).imaginary);
10946 break;
10947#endif
5ff904cd 10948
c7e4ee3a
CB
10949 default:
10950 assert ("bad REAL constant kind type" == NULL);
10951 /* Fall through. */
10952 case FFEINFO_kindtypeANY:
10953 return error_mark_node;
10954 }
10955 item = ffecom_build_complex_constant_ (tree_type,
10956 build_real (el_type, real),
10957 build_real (el_type, imag));
10958 }
10959 break;
5ff904cd 10960
c7e4ee3a
CB
10961 case FFEINFO_basictypeCHARACTER:
10962 { /* Happens only in DATA and similar contexts. */
10963 ffetargetCharacter1 val;
5ff904cd 10964
c7e4ee3a
CB
10965 switch (kt)
10966 {
10967#if FFETARGET_okCHARACTER1
10968 case FFEINFO_kindtypeLOGICAL1:
10969 val = ffebld_cu_val_character1 (*cu);
10970 break;
10971#endif
10972
10973 default:
10974 assert ("bad CHARACTER constant kind type" == NULL);
10975 /* Fall through. */
10976 case FFEINFO_kindtypeANY:
10977 return error_mark_node;
10978 }
10979 item = build_string (ffetarget_length_character1 (val),
10980 ffetarget_text_character1 (val));
10981 TREE_TYPE (item)
10982 = build_type_variant (build_array_type (char_type_node,
10983 build_range_type
10984 (integer_type_node,
10985 integer_one_node,
10986 build_int_2
10987 (ffetarget_length_character1
10988 (val), 0))),
10989 1, 0);
10990 }
10991 break;
5ff904cd 10992
c7e4ee3a
CB
10993 case FFEINFO_basictypeHOLLERITH:
10994 {
10995 ffetargetHollerith h;
5ff904cd 10996
c7e4ee3a 10997 h = ffebld_cu_val_hollerith (*cu);
5ff904cd 10998
c7e4ee3a
CB
10999 /* If not at least as wide as default INTEGER, widen it. */
11000 if (h.length >= FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE)
11001 item = build_string (h.length, h.text);
11002 else
11003 {
11004 char str[FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE];
5ff904cd 11005
c7e4ee3a
CB
11006 memcpy (str, h.text, h.length);
11007 memset (&str[h.length], ' ',
11008 FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE
11009 - h.length);
11010 item = build_string (FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE,
11011 str);
11012 }
11013 TREE_TYPE (item)
11014 = build_type_variant (build_array_type (char_type_node,
11015 build_range_type
11016 (integer_type_node,
11017 integer_one_node,
11018 build_int_2
11019 (h.length, 0))),
11020 1, 0);
11021 }
11022 break;
5ff904cd 11023
c7e4ee3a
CB
11024 case FFEINFO_basictypeTYPELESS:
11025 {
11026 ffetargetInteger1 ival;
11027 ffetargetTypeless tless;
11028 ffebad error;
5ff904cd 11029
c7e4ee3a
CB
11030 tless = ffebld_cu_val_typeless (*cu);
11031 error = ffetarget_convert_integer1_typeless (&ival, tless);
11032 assert (error == FFEBAD);
5ff904cd 11033
c7e4ee3a
CB
11034 item = build_int_2 ((int) ival, 0);
11035 }
11036 break;
5ff904cd 11037
c7e4ee3a
CB
11038 default:
11039 assert ("not yet on constant type" == NULL);
11040 /* Fall through. */
11041 case FFEINFO_basictypeANY:
11042 return error_mark_node;
5ff904cd 11043 }
5ff904cd 11044
c7e4ee3a 11045 TREE_CONSTANT (item) = 1;
5ff904cd 11046
c7e4ee3a 11047 return item;
5ff904cd
JL
11048}
11049
11050#endif
11051
c7e4ee3a
CB
11052/* Transform expression into constant tree.
11053
11054 If the expression can be transformed into a tree that is constant,
11055 that is done, and the tree returned. Else NULL_TREE is returned.
11056
11057 That way, a caller can attempt to provide compile-time initialization
11058 of a variable and, if that fails, *then* choose to start a new block
11059 and resort to using temporaries, as appropriate. */
5ff904cd 11060
5ff904cd 11061tree
c7e4ee3a 11062ffecom_const_expr (ffebld expr)
5ff904cd 11063{
c7e4ee3a
CB
11064 if (! expr)
11065 return integer_zero_node;
5ff904cd 11066
c7e4ee3a 11067 if (ffebld_op (expr) == FFEBLD_opANY)
5ff904cd
JL
11068 return error_mark_node;
11069
c7e4ee3a
CB
11070 if (ffebld_arity (expr) == 0
11071 && (ffebld_op (expr) != FFEBLD_opSYMTER
11072#if NEWCOMMON
11073 /* ~~Enable once common/equivalence is handled properly? */
11074 || ffebld_where (expr) == FFEINFO_whereCOMMON
5ff904cd 11075#endif
c7e4ee3a
CB
11076 || ffebld_where (expr) == FFEINFO_whereGLOBAL
11077 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
11078 {
11079 tree t;
5ff904cd 11080
c7e4ee3a
CB
11081 t = ffecom_expr (expr);
11082 assert (TREE_CONSTANT (t));
11083 return t;
11084 }
5ff904cd 11085
c7e4ee3a 11086 return NULL_TREE;
5ff904cd
JL
11087}
11088
c7e4ee3a 11089/* Handy way to make a field in a struct/union. */
5ff904cd
JL
11090
11091#if FFECOM_targetCURRENT == FFECOM_targetGCC
11092tree
c7e4ee3a
CB
11093ffecom_decl_field (tree context, tree prevfield,
11094 const char *name, tree type)
5ff904cd 11095{
c7e4ee3a 11096 tree field;
5ff904cd 11097
c7e4ee3a
CB
11098 field = build_decl (FIELD_DECL, get_identifier (name), type);
11099 DECL_CONTEXT (field) = context;
11100 DECL_FRAME_SIZE (field) = 0;
11101 if (prevfield != NULL_TREE)
11102 TREE_CHAIN (prevfield) = field;
5ff904cd 11103
c7e4ee3a 11104 return field;
5ff904cd
JL
11105}
11106
11107#endif
5ff904cd 11108
c7e4ee3a
CB
11109void
11110ffecom_close_include (FILE *f)
11111{
11112#if FFECOM_GCC_INCLUDE
11113 ffecom_close_include_ (f);
11114#endif
11115}
5ff904cd 11116
c7e4ee3a
CB
11117int
11118ffecom_decode_include_option (char *spec)
11119{
11120#if FFECOM_GCC_INCLUDE
11121 return ffecom_decode_include_option_ (spec);
11122#else
11123 return 1;
11124#endif
11125}
5ff904cd 11126
c7e4ee3a 11127/* End a compound statement (block). */
5ff904cd
JL
11128
11129#if FFECOM_targetCURRENT == FFECOM_targetGCC
11130tree
c7e4ee3a 11131ffecom_end_compstmt (void)
5ff904cd 11132{
c7e4ee3a
CB
11133 return bison_rule_compstmt_ ();
11134}
11135#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
5ff904cd 11136
c7e4ee3a 11137/* ffecom_end_transition -- Perform end transition on all symbols
5ff904cd 11138
c7e4ee3a 11139 ffecom_end_transition();
5ff904cd 11140
c7e4ee3a 11141 Calls ffecom_sym_end_transition for each global and local symbol. */
5ff904cd 11142
c7e4ee3a
CB
11143void
11144ffecom_end_transition ()
11145{
11146#if FFECOM_targetCURRENT == FFECOM_targetGCC
11147 ffebld item;
5ff904cd 11148#endif
5ff904cd 11149
c7e4ee3a
CB
11150 if (ffe_is_ffedebug ())
11151 fprintf (dmpout, "; end_stmt_transition\n");
86fc7a6c 11152
c7e4ee3a
CB
11153#if FFECOM_targetCURRENT == FFECOM_targetGCC
11154 ffecom_list_blockdata_ = NULL;
11155 ffecom_list_common_ = NULL;
11156#endif
86fc7a6c 11157
c7e4ee3a
CB
11158 ffesymbol_drive (ffecom_sym_end_transition);
11159 if (ffe_is_ffedebug ())
11160 {
11161 ffestorag_report ();
11162#if FFECOM_targetCURRENT == FFECOM_targetFFE
11163 ffesymbol_report_all ();
11164#endif
11165 }
5ff904cd
JL
11166
11167#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
11168 ffecom_start_progunit_ ();
11169
11170 for (item = ffecom_list_blockdata_;
11171 item != NULL;
11172 item = ffebld_trail (item))
11173 {
11174 ffebld callee;
11175 ffesymbol s;
11176 tree dt;
11177 tree t;
11178 tree var;
11179 int yes;
11180 static int number = 0;
11181
11182 callee = ffebld_head (item);
11183 s = ffebld_symter (callee);
11184 t = ffesymbol_hook (s).decl_tree;
11185 if (t == NULL_TREE)
11186 {
11187 s = ffecom_sym_transform_ (s);
11188 t = ffesymbol_hook (s).decl_tree;
11189 }
5ff904cd 11190
c7e4ee3a 11191 yes = suspend_momentary ();
5ff904cd 11192
c7e4ee3a 11193 dt = build_pointer_type (TREE_TYPE (t));
5ff904cd 11194
c7e4ee3a
CB
11195 var = build_decl (VAR_DECL,
11196 ffecom_get_invented_identifier ("__g77_forceload_%d",
11197 NULL, number++),
11198 dt);
11199 DECL_EXTERNAL (var) = 0;
11200 TREE_STATIC (var) = 1;
11201 TREE_PUBLIC (var) = 0;
11202 DECL_INITIAL (var) = error_mark_node;
11203 TREE_USED (var) = 1;
5ff904cd 11204
c7e4ee3a 11205 var = start_decl (var, FALSE);
702edf1d 11206
c7e4ee3a 11207 t = ffecom_1 (ADDR_EXPR, dt, t);
5ff904cd 11208
c7e4ee3a 11209 finish_decl (var, t, FALSE);
5ff904cd 11210
c7e4ee3a
CB
11211 resume_momentary (yes);
11212 }
11213
11214 /* This handles any COMMON areas that weren't referenced but have, for
11215 example, important initial data. */
11216
11217 for (item = ffecom_list_common_;
11218 item != NULL;
11219 item = ffebld_trail (item))
11220 ffecom_transform_common_ (ffebld_symter (ffebld_head (item)));
11221
11222 ffecom_list_common_ = NULL;
5ff904cd 11223#endif
c7e4ee3a 11224}
5ff904cd 11225
c7e4ee3a 11226/* ffecom_exec_transition -- Perform exec transition on all symbols
5ff904cd 11227
c7e4ee3a 11228 ffecom_exec_transition();
5ff904cd 11229
c7e4ee3a
CB
11230 Calls ffecom_sym_exec_transition for each global and local symbol.
11231 Make sure error updating not inhibited. */
5ff904cd 11232
c7e4ee3a
CB
11233void
11234ffecom_exec_transition ()
11235{
11236 bool inhibited;
5ff904cd 11237
c7e4ee3a
CB
11238 if (ffe_is_ffedebug ())
11239 fprintf (dmpout, "; exec_stmt_transition\n");
5ff904cd 11240
c7e4ee3a
CB
11241 inhibited = ffebad_inhibit ();
11242 ffebad_set_inhibit (FALSE);
5ff904cd 11243
c7e4ee3a
CB
11244 ffesymbol_drive (ffecom_sym_exec_transition); /* Don't retract! */
11245 ffeequiv_exec_transition (); /* Handle all pending EQUIVALENCEs. */
11246 if (ffe_is_ffedebug ())
5ff904cd 11247 {
c7e4ee3a
CB
11248 ffestorag_report ();
11249#if FFECOM_targetCURRENT == FFECOM_targetFFE
11250 ffesymbol_report_all ();
11251#endif
11252 }
5ff904cd 11253
c7e4ee3a
CB
11254 if (inhibited)
11255 ffebad_set_inhibit (TRUE);
11256}
5ff904cd 11257
c7e4ee3a 11258/* Handle assignment statement.
5ff904cd 11259
c7e4ee3a
CB
11260 Convert dest and source using ffecom_expr, then join them
11261 with an ASSIGN op and pass the whole thing to expand_expr_stmt. */
5ff904cd 11262
c7e4ee3a
CB
11263#if FFECOM_targetCURRENT == FFECOM_targetGCC
11264void
11265ffecom_expand_let_stmt (ffebld dest, ffebld source)
11266{
11267 tree dest_tree;
11268 tree dest_length;
11269 tree source_tree;
11270 tree expr_tree;
5ff904cd 11271
c7e4ee3a
CB
11272 if (ffeinfo_basictype (ffebld_info (dest)) != FFEINFO_basictypeCHARACTER)
11273 {
11274 bool dest_used;
d6cd84e0 11275 tree assign_temp;
5ff904cd 11276
c7e4ee3a
CB
11277 /* This attempts to replicate the test below, but must not be
11278 true when the test below is false. (Always err on the side
11279 of creating unused temporaries, to avoid ICEs.) */
11280 if (ffebld_op (dest) != FFEBLD_opSYMTER
11281 || ((dest_tree = ffesymbol_hook (ffebld_symter (dest)).decl_tree)
11282 && (TREE_CODE (dest_tree) != VAR_DECL
11283 || TREE_ADDRESSABLE (dest_tree))))
11284 {
11285 ffecom_prepare_expr_ (source, dest);
11286 dest_used = TRUE;
11287 }
11288 else
11289 {
11290 ffecom_prepare_expr_ (source, NULL);
11291 dest_used = FALSE;
11292 }
5ff904cd 11293
c7e4ee3a 11294 ffecom_prepare_expr_w (NULL_TREE, dest);
5ff904cd 11295
d6cd84e0
CB
11296 /* For COMPLEX assignment like C1=C2, if partial overlap is possible,
11297 create a temporary through which the assignment is to take place,
11298 since MODIFY_EXPR doesn't handle partial overlap properly. */
11299 if (ffebld_basictype (dest) == FFEINFO_basictypeCOMPLEX
11300 && ffecom_possible_partial_overlap_ (dest, source))
11301 {
11302 assign_temp = ffecom_make_tempvar ("complex_let",
11303 ffecom_tree_type
11304 [ffebld_basictype (dest)]
11305 [ffebld_kindtype (dest)],
11306 FFETARGET_charactersizeNONE,
11307 -1);
11308 }
11309 else
11310 assign_temp = NULL_TREE;
11311
c7e4ee3a 11312 ffecom_prepare_end ();
5ff904cd 11313
c7e4ee3a
CB
11314 dest_tree = ffecom_expr_w (NULL_TREE, dest);
11315 if (dest_tree == error_mark_node)
11316 return;
5ff904cd 11317
c7e4ee3a
CB
11318 if ((TREE_CODE (dest_tree) != VAR_DECL)
11319 || TREE_ADDRESSABLE (dest_tree))
11320 source_tree = ffecom_expr_ (source, dest_tree, dest, &dest_used,
11321 FALSE, FALSE);
11322 else
11323 {
11324 assert (! dest_used);
11325 dest_used = FALSE;
11326 source_tree = ffecom_expr (source);
11327 }
11328 if (source_tree == error_mark_node)
11329 return;
5ff904cd 11330
c7e4ee3a
CB
11331 if (dest_used)
11332 expr_tree = source_tree;
d6cd84e0
CB
11333 else if (assign_temp)
11334 {
11335#ifdef MOVE_EXPR
11336 /* The back end understands a conceptual move (evaluate source;
11337 store into dest), so use that, in case it can determine
11338 that it is going to use, say, two registers as temporaries
11339 anyway. So don't use the temp (and someday avoid generating
11340 it, once this code starts triggering regularly). */
11341 expr_tree = ffecom_2s (MOVE_EXPR, void_type_node,
11342 dest_tree,
11343 source_tree);
11344#else
11345 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11346 assign_temp,
11347 source_tree);
11348 expand_expr_stmt (expr_tree);
11349 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11350 dest_tree,
11351 assign_temp);
11352#endif
11353 }
c7e4ee3a
CB
11354 else
11355 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11356 dest_tree,
11357 source_tree);
5ff904cd 11358
c7e4ee3a
CB
11359 expand_expr_stmt (expr_tree);
11360 return;
11361 }
5ff904cd 11362
c7e4ee3a
CB
11363 ffecom_prepare_let_char_ (ffebld_size_known (dest), source);
11364 ffecom_prepare_expr_w (NULL_TREE, dest);
11365
11366 ffecom_prepare_end ();
11367
11368 ffecom_char_args_ (&dest_tree, &dest_length, dest);
11369 ffecom_let_char_ (dest_tree, dest_length, ffebld_size_known (dest),
11370 source);
5ff904cd
JL
11371}
11372
11373#endif
c7e4ee3a 11374/* ffecom_expr -- Transform expr into gcc tree
5ff904cd 11375
c7e4ee3a
CB
11376 tree t;
11377 ffebld expr; // FFE expression.
11378 tree = ffecom_expr(expr);
5ff904cd 11379
c7e4ee3a
CB
11380 Recursive descent on expr while making corresponding tree nodes and
11381 attaching type info and such. */
5ff904cd
JL
11382
11383#if FFECOM_targetCURRENT == FFECOM_targetGCC
11384tree
c7e4ee3a 11385ffecom_expr (ffebld expr)
5ff904cd 11386{
c7e4ee3a 11387 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, FALSE, FALSE);
5ff904cd 11388}
c7e4ee3a 11389
5ff904cd 11390#endif
c7e4ee3a 11391/* Like ffecom_expr, but return tree usable for assigned GOTO or FORMAT. */
5ff904cd 11392
c7e4ee3a
CB
11393#if FFECOM_targetCURRENT == FFECOM_targetGCC
11394tree
11395ffecom_expr_assign (ffebld expr)
11396{
11397 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE);
11398}
5ff904cd 11399
c7e4ee3a
CB
11400#endif
11401/* Like ffecom_expr_rw, but return tree usable for ASSIGN. */
5ff904cd
JL
11402
11403#if FFECOM_targetCURRENT == FFECOM_targetGCC
11404tree
c7e4ee3a 11405ffecom_expr_assign_w (ffebld expr)
5ff904cd 11406{
c7e4ee3a
CB
11407 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE);
11408}
5ff904cd 11409
5ff904cd 11410#endif
c7e4ee3a
CB
11411/* Transform expr for use as into read/write tree and stabilize the
11412 reference. Not for use on CHARACTER expressions.
5ff904cd 11413
c7e4ee3a
CB
11414 Recursive descent on expr while making corresponding tree nodes and
11415 attaching type info and such. */
5ff904cd 11416
c7e4ee3a
CB
11417#if FFECOM_targetCURRENT == FFECOM_targetGCC
11418tree
11419ffecom_expr_rw (tree type, ffebld expr)
11420{
11421 assert (expr != NULL);
11422 /* Different target types not yet supported. */
11423 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
11424
11425 return stabilize_reference (ffecom_expr (expr));
11426}
5ff904cd 11427
5ff904cd 11428#endif
c7e4ee3a
CB
11429/* Transform expr for use as into write tree and stabilize the
11430 reference. Not for use on CHARACTER expressions.
5ff904cd 11431
c7e4ee3a
CB
11432 Recursive descent on expr while making corresponding tree nodes and
11433 attaching type info and such. */
5ff904cd 11434
c7e4ee3a
CB
11435#if FFECOM_targetCURRENT == FFECOM_targetGCC
11436tree
11437ffecom_expr_w (tree type, ffebld expr)
11438{
11439 assert (expr != NULL);
11440 /* Different target types not yet supported. */
11441 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
11442
11443 return stabilize_reference (ffecom_expr (expr));
11444}
5ff904cd 11445
5ff904cd 11446#endif
c7e4ee3a
CB
11447/* Do global stuff. */
11448
11449#if FFECOM_targetCURRENT == FFECOM_targetGCC
11450void
11451ffecom_finish_compile ()
11452{
11453 assert (ffecom_outer_function_decl_ == NULL_TREE);
11454 assert (current_function_decl == NULL_TREE);
11455
11456 ffeglobal_drive (ffecom_finish_global_);
11457}
5ff904cd 11458
5ff904cd 11459#endif
c7e4ee3a
CB
11460/* Public entry point for front end to access finish_decl. */
11461
11462#if FFECOM_targetCURRENT == FFECOM_targetGCC
11463void
11464ffecom_finish_decl (tree decl, tree init, bool is_top_level)
11465{
11466 assert (!is_top_level);
11467 finish_decl (decl, init, FALSE);
11468}
5ff904cd 11469
5ff904cd 11470#endif
c7e4ee3a
CB
11471/* Finish a program unit. */
11472
11473#if FFECOM_targetCURRENT == FFECOM_targetGCC
11474void
11475ffecom_finish_progunit ()
11476{
11477 ffecom_end_compstmt ();
11478
11479 ffecom_previous_function_decl_ = current_function_decl;
11480 ffecom_which_entrypoint_decl_ = NULL_TREE;
11481
11482 finish_function (0);
11483}
5ff904cd 11484
5ff904cd 11485#endif
c7e4ee3a
CB
11486/* Wrapper for get_identifier. pattern is sprintf-like, assumed to contain
11487 one %s if text is not NULL, assumed to contain one %d if number is
11488 not -1. If both are assumed, the %s is assumed to precede the %d. */
11489
11490#if FFECOM_targetCURRENT == FFECOM_targetGCC
11491tree
11492ffecom_get_invented_identifier (const char *pattern, const char *text,
11493 int number)
11494{
11495 tree decl;
11496 char *nam;
11497 mallocSize lenlen;
11498 char space[66];
11499
11500 lenlen = 0;
11501 if (text)
11502 lenlen += strlen (text);
11503 if (number != -1)
11504 lenlen += 20;
11505 if (text || number != -1)
11506 {
11507 lenlen += strlen (pattern);
11508 if (lenlen > ARRAY_SIZE (space))
11509 nam = malloc_new_ks (malloc_pool_image (), pattern, lenlen);
11510 else
11511 nam = &space[0];
11512 }
11513 else
11514 {
11515 lenlen = 0;
11516 nam = (char *) pattern;
11517 }
11518
11519 if (text == NULL)
11520 {
11521 if (number != -1)
11522 sprintf (&nam[0], pattern, number);
11523 }
11524 else
11525 {
11526 if (number == -1)
11527 sprintf (&nam[0], pattern, text);
11528 else
11529 sprintf (&nam[0], pattern, text, number);
11530 }
11531
11532 decl = get_identifier (nam);
11533
11534 if (lenlen > ARRAY_SIZE (space))
11535 malloc_kill_ks (malloc_pool_image (), nam, lenlen);
11536
11537 IDENTIFIER_INVENTED (decl) = 1;
11538
11539 return decl;
11540}
11541
11542ffeinfoBasictype
11543ffecom_gfrt_basictype (ffecomGfrt gfrt)
11544{
11545 assert (gfrt < FFECOM_gfrt);
11546
11547 switch (ffecom_gfrt_type_[gfrt])
11548 {
11549 case FFECOM_rttypeVOID_:
11550 case FFECOM_rttypeVOIDSTAR_:
11551 return FFEINFO_basictypeNONE;
11552
11553 case FFECOM_rttypeFTNINT_:
11554 return FFEINFO_basictypeINTEGER;
11555
11556 case FFECOM_rttypeINTEGER_:
11557 return FFEINFO_basictypeINTEGER;
11558
11559 case FFECOM_rttypeLONGINT_:
11560 return FFEINFO_basictypeINTEGER;
11561
11562 case FFECOM_rttypeLOGICAL_:
11563 return FFEINFO_basictypeLOGICAL;
11564
11565 case FFECOM_rttypeREAL_F2C_:
11566 case FFECOM_rttypeREAL_GNU_:
11567 return FFEINFO_basictypeREAL;
11568
11569 case FFECOM_rttypeCOMPLEX_F2C_:
11570 case FFECOM_rttypeCOMPLEX_GNU_:
11571 return FFEINFO_basictypeCOMPLEX;
11572
11573 case FFECOM_rttypeDOUBLE_:
11574 case FFECOM_rttypeDOUBLEREAL_:
11575 return FFEINFO_basictypeREAL;
11576
11577 case FFECOM_rttypeDBLCMPLX_F2C_:
11578 case FFECOM_rttypeDBLCMPLX_GNU_:
11579 return FFEINFO_basictypeCOMPLEX;
11580
11581 case FFECOM_rttypeCHARACTER_:
11582 return FFEINFO_basictypeCHARACTER;
11583
11584 default:
11585 return FFEINFO_basictypeANY;
11586 }
11587}
11588
11589ffeinfoKindtype
11590ffecom_gfrt_kindtype (ffecomGfrt gfrt)
11591{
11592 assert (gfrt < FFECOM_gfrt);
11593
11594 switch (ffecom_gfrt_type_[gfrt])
11595 {
11596 case FFECOM_rttypeVOID_:
11597 case FFECOM_rttypeVOIDSTAR_:
11598 return FFEINFO_kindtypeNONE;
5ff904cd 11599
c7e4ee3a
CB
11600 case FFECOM_rttypeFTNINT_:
11601 return FFEINFO_kindtypeINTEGER1;
5ff904cd 11602
c7e4ee3a
CB
11603 case FFECOM_rttypeINTEGER_:
11604 return FFEINFO_kindtypeINTEGER1;
5ff904cd 11605
c7e4ee3a
CB
11606 case FFECOM_rttypeLONGINT_:
11607 return FFEINFO_kindtypeINTEGER4;
5ff904cd 11608
c7e4ee3a
CB
11609 case FFECOM_rttypeLOGICAL_:
11610 return FFEINFO_kindtypeLOGICAL1;
5ff904cd 11611
c7e4ee3a
CB
11612 case FFECOM_rttypeREAL_F2C_:
11613 case FFECOM_rttypeREAL_GNU_:
11614 return FFEINFO_kindtypeREAL1;
5ff904cd 11615
c7e4ee3a
CB
11616 case FFECOM_rttypeCOMPLEX_F2C_:
11617 case FFECOM_rttypeCOMPLEX_GNU_:
11618 return FFEINFO_kindtypeREAL1;
5ff904cd 11619
c7e4ee3a
CB
11620 case FFECOM_rttypeDOUBLE_:
11621 case FFECOM_rttypeDOUBLEREAL_:
11622 return FFEINFO_kindtypeREAL2;
5ff904cd 11623
c7e4ee3a
CB
11624 case FFECOM_rttypeDBLCMPLX_F2C_:
11625 case FFECOM_rttypeDBLCMPLX_GNU_:
11626 return FFEINFO_kindtypeREAL2;
5ff904cd 11627
c7e4ee3a
CB
11628 case FFECOM_rttypeCHARACTER_:
11629 return FFEINFO_kindtypeCHARACTER1;
5ff904cd 11630
c7e4ee3a
CB
11631 default:
11632 return FFEINFO_kindtypeANY;
11633 }
11634}
5ff904cd 11635
c7e4ee3a
CB
11636void
11637ffecom_init_0 ()
11638{
11639 tree endlink;
11640 int i;
11641 int j;
11642 tree t;
11643 tree field;
11644 ffetype type;
11645 ffetype base_type;
5ff904cd 11646
c7e4ee3a
CB
11647 /* This block of code comes from the now-obsolete cktyps.c. It checks
11648 whether the compiler environment is buggy in known ways, some of which
11649 would, if not explicitly checked here, result in subtle bugs in g77. */
5ff904cd 11650
c7e4ee3a
CB
11651 if (ffe_is_do_internal_checks ())
11652 {
11653 static char names[][12]
11654 =
11655 {"bar", "bletch", "foo", "foobar"};
11656 char *name;
11657 unsigned long ul;
11658 double fl;
5ff904cd 11659
c7e4ee3a
CB
11660 name = bsearch ("foo", &names[0], ARRAY_SIZE (names), sizeof (names[0]),
11661 (int (*)()) strcmp);
11662 if (name != (char *) &names[2])
11663 {
11664 assert ("bsearch doesn't work, #define FFEPROJ_BSEARCH 0 in proj.h"
11665 == NULL);
11666 abort ();
11667 }
5ff904cd 11668
c7e4ee3a
CB
11669 ul = strtoul ("123456789", NULL, 10);
11670 if (ul != 123456789L)
11671 {
11672 assert ("strtoul doesn't have enough range, #define FFEPROJ_STRTOUL 0\
11673 in proj.h" == NULL);
11674 abort ();
11675 }
5ff904cd 11676
c7e4ee3a
CB
11677 fl = atof ("56.789");
11678 if ((fl < 56.788) || (fl > 56.79))
11679 {
11680 assert ("atof not type double, fix your #include <stdio.h>"
11681 == NULL);
11682 abort ();
11683 }
11684 }
5ff904cd 11685
c7e4ee3a
CB
11686#if FFECOM_GCC_INCLUDE
11687 ffecom_initialize_char_syntax_ ();
11688#endif
5ff904cd 11689
c7e4ee3a
CB
11690 ffecom_outer_function_decl_ = NULL_TREE;
11691 current_function_decl = NULL_TREE;
11692 named_labels = NULL_TREE;
11693 current_binding_level = NULL_BINDING_LEVEL;
11694 free_binding_level = NULL_BINDING_LEVEL;
11695 /* Make the binding_level structure for global names. */
11696 pushlevel (0);
11697 global_binding_level = current_binding_level;
11698 current_binding_level->prep_state = 2;
5ff904cd 11699
c7e4ee3a 11700 /* Define `int' and `char' first so that dbx will output them first. */
5ff904cd 11701
c7e4ee3a
CB
11702 integer_type_node = make_signed_type (INT_TYPE_SIZE);
11703 pushdecl (build_decl (TYPE_DECL, get_identifier ("int"),
11704 integer_type_node));
5ff904cd 11705
c7e4ee3a
CB
11706 char_type_node = make_unsigned_type (CHAR_TYPE_SIZE);
11707 pushdecl (build_decl (TYPE_DECL, get_identifier ("char"),
11708 char_type_node));
5ff904cd 11709
c7e4ee3a
CB
11710 long_integer_type_node = make_signed_type (LONG_TYPE_SIZE);
11711 pushdecl (build_decl (TYPE_DECL, get_identifier ("long int"),
11712 long_integer_type_node));
5ff904cd 11713
c7e4ee3a
CB
11714 unsigned_type_node = make_unsigned_type (INT_TYPE_SIZE);
11715 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned int"),
11716 unsigned_type_node));
5ff904cd 11717
c7e4ee3a
CB
11718 long_unsigned_type_node = make_unsigned_type (LONG_TYPE_SIZE);
11719 pushdecl (build_decl (TYPE_DECL, get_identifier ("long unsigned int"),
11720 long_unsigned_type_node));
5ff904cd 11721
c7e4ee3a
CB
11722 long_long_integer_type_node = make_signed_type (LONG_LONG_TYPE_SIZE);
11723 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long int"),
11724 long_long_integer_type_node));
5ff904cd 11725
c7e4ee3a
CB
11726 long_long_unsigned_type_node = make_unsigned_type (LONG_LONG_TYPE_SIZE);
11727 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long unsigned int"),
11728 long_long_unsigned_type_node));
5ff904cd 11729
c7e4ee3a
CB
11730 short_integer_type_node = make_signed_type (SHORT_TYPE_SIZE);
11731 pushdecl (build_decl (TYPE_DECL, get_identifier ("short int"),
11732 short_integer_type_node));
5ff904cd 11733
c7e4ee3a
CB
11734 short_unsigned_type_node = make_unsigned_type (SHORT_TYPE_SIZE);
11735 pushdecl (build_decl (TYPE_DECL, get_identifier ("short unsigned int"),
11736 short_unsigned_type_node));
5ff904cd 11737
ff852b44
CB
11738 /* Set the sizetype before we make other types. This *should* be the
11739 first type we create. */
11740
11741 set_sizetype
11742 (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE))));
11743 ffecom_typesize_pointer_
11744 = TREE_INT_CST_LOW (TYPE_SIZE (sizetype)) / BITS_PER_UNIT;
11745
11746 error_mark_node = make_node (ERROR_MARK);
11747 TREE_TYPE (error_mark_node) = error_mark_node;
11748
c7e4ee3a
CB
11749 /* Define both `signed char' and `unsigned char'. */
11750 signed_char_type_node = make_signed_type (CHAR_TYPE_SIZE);
11751 pushdecl (build_decl (TYPE_DECL, get_identifier ("signed char"),
11752 signed_char_type_node));
5ff904cd 11753
c7e4ee3a
CB
11754 unsigned_char_type_node = make_unsigned_type (CHAR_TYPE_SIZE);
11755 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned char"),
11756 unsigned_char_type_node));
5ff904cd 11757
c7e4ee3a
CB
11758 float_type_node = make_node (REAL_TYPE);
11759 TYPE_PRECISION (float_type_node) = FLOAT_TYPE_SIZE;
11760 layout_type (float_type_node);
11761 pushdecl (build_decl (TYPE_DECL, get_identifier ("float"),
11762 float_type_node));
5ff904cd 11763
c7e4ee3a
CB
11764 double_type_node = make_node (REAL_TYPE);
11765 TYPE_PRECISION (double_type_node) = DOUBLE_TYPE_SIZE;
11766 layout_type (double_type_node);
11767 pushdecl (build_decl (TYPE_DECL, get_identifier ("double"),
11768 double_type_node));
5ff904cd 11769
c7e4ee3a
CB
11770 long_double_type_node = make_node (REAL_TYPE);
11771 TYPE_PRECISION (long_double_type_node) = LONG_DOUBLE_TYPE_SIZE;
11772 layout_type (long_double_type_node);
11773 pushdecl (build_decl (TYPE_DECL, get_identifier ("long double"),
11774 long_double_type_node));
5ff904cd 11775
c7e4ee3a
CB
11776 complex_integer_type_node = ffecom_make_complex_type_ (integer_type_node);
11777 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex int"),
11778 complex_integer_type_node));
5ff904cd 11779
c7e4ee3a
CB
11780 complex_float_type_node = ffecom_make_complex_type_ (float_type_node);
11781 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex float"),
11782 complex_float_type_node));
5ff904cd 11783
c7e4ee3a
CB
11784 complex_double_type_node = ffecom_make_complex_type_ (double_type_node);
11785 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex double"),
11786 complex_double_type_node));
5ff904cd 11787
c7e4ee3a
CB
11788 complex_long_double_type_node = ffecom_make_complex_type_ (long_double_type_node);
11789 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex long double"),
11790 complex_long_double_type_node));
5ff904cd 11791
c7e4ee3a
CB
11792 integer_zero_node = build_int_2 (0, 0);
11793 TREE_TYPE (integer_zero_node) = integer_type_node;
11794 integer_one_node = build_int_2 (1, 0);
11795 TREE_TYPE (integer_one_node) = integer_type_node;
5ff904cd 11796
c7e4ee3a
CB
11797 size_zero_node = build_int_2 (0, 0);
11798 TREE_TYPE (size_zero_node) = sizetype;
11799 size_one_node = build_int_2 (1, 0);
11800 TREE_TYPE (size_one_node) = sizetype;
5ff904cd 11801
c7e4ee3a
CB
11802 void_type_node = make_node (VOID_TYPE);
11803 pushdecl (build_decl (TYPE_DECL, get_identifier ("void"),
11804 void_type_node));
11805 layout_type (void_type_node); /* Uses integer_zero_node */
11806 /* We are not going to have real types in C with less than byte alignment,
11807 so we might as well not have any types that claim to have it. */
11808 TYPE_ALIGN (void_type_node) = BITS_PER_UNIT;
5ff904cd 11809
c7e4ee3a
CB
11810 null_pointer_node = build_int_2 (0, 0);
11811 TREE_TYPE (null_pointer_node) = build_pointer_type (void_type_node);
11812 layout_type (TREE_TYPE (null_pointer_node));
5ff904cd 11813
c7e4ee3a 11814 string_type_node = build_pointer_type (char_type_node);
5ff904cd 11815
c7e4ee3a
CB
11816 ffecom_tree_fun_type_void
11817 = build_function_type (void_type_node, NULL_TREE);
5ff904cd 11818
c7e4ee3a
CB
11819 ffecom_tree_ptr_to_fun_type_void
11820 = build_pointer_type (ffecom_tree_fun_type_void);
5ff904cd 11821
c7e4ee3a 11822 endlink = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
5ff904cd 11823
c7e4ee3a
CB
11824 float_ftype_float
11825 = build_function_type (float_type_node,
11826 tree_cons (NULL_TREE, float_type_node, endlink));
5ff904cd 11827
c7e4ee3a
CB
11828 double_ftype_double
11829 = build_function_type (double_type_node,
11830 tree_cons (NULL_TREE, double_type_node, endlink));
5ff904cd 11831
c7e4ee3a
CB
11832 ldouble_ftype_ldouble
11833 = build_function_type (long_double_type_node,
11834 tree_cons (NULL_TREE, long_double_type_node,
11835 endlink));
5ff904cd 11836
c7e4ee3a
CB
11837 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11838 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11839 {
11840 ffecom_tree_type[i][j] = NULL_TREE;
11841 ffecom_tree_fun_type[i][j] = NULL_TREE;
11842 ffecom_tree_ptr_to_fun_type[i][j] = NULL_TREE;
11843 ffecom_f2c_typecode_[i][j] = -1;
11844 }
5ff904cd 11845
c7e4ee3a
CB
11846 /* Set up standard g77 types. Note that INTEGER and LOGICAL are set
11847 to size FLOAT_TYPE_SIZE because they have to be the same size as
11848 REAL, which also is FLOAT_TYPE_SIZE, according to the standard.
11849 Compiler options and other such stuff that change the ways these
11850 types are set should not affect this particular setup. */
5ff904cd 11851
c7e4ee3a
CB
11852 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1]
11853 = t = make_signed_type (FLOAT_TYPE_SIZE);
11854 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer"),
11855 t));
11856 type = ffetype_new ();
11857 base_type = type;
11858 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER1,
11859 type);
11860 ffetype_set_ams (type,
11861 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11862 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11863 ffetype_set_star (base_type,
11864 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11865 type);
11866 ffetype_set_kind (base_type, 1, type);
ff852b44 11867 ffecom_typesize_integer1_ = ffetype_size (type);
c7e4ee3a 11868 assert (ffetype_size (type) == sizeof (ffetargetInteger1));
5ff904cd 11869
c7e4ee3a
CB
11870 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER1]
11871 = t = make_unsigned_type (FLOAT_TYPE_SIZE); /* HOLLERITH means unsigned. */
11872 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned"),
11873 t));
5ff904cd 11874
c7e4ee3a
CB
11875 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER2]
11876 = t = make_signed_type (CHAR_TYPE_SIZE);
11877 pushdecl (build_decl (TYPE_DECL, get_identifier ("byte"),
11878 t));
11879 type = ffetype_new ();
11880 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER2,
11881 type);
11882 ffetype_set_ams (type,
11883 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11884 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11885 ffetype_set_star (base_type,
11886 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11887 type);
11888 ffetype_set_kind (base_type, 3, type);
11889 assert (ffetype_size (type) == sizeof (ffetargetInteger2));
5ff904cd 11890
c7e4ee3a
CB
11891 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER2]
11892 = t = make_unsigned_type (CHAR_TYPE_SIZE);
11893 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned byte"),
11894 t));
11895
11896 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER3]
11897 = t = make_signed_type (CHAR_TYPE_SIZE * 2);
11898 pushdecl (build_decl (TYPE_DECL, get_identifier ("word"),
11899 t));
11900 type = ffetype_new ();
11901 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER3,
11902 type);
11903 ffetype_set_ams (type,
11904 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11905 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11906 ffetype_set_star (base_type,
11907 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11908 type);
11909 ffetype_set_kind (base_type, 6, type);
11910 assert (ffetype_size (type) == sizeof (ffetargetInteger3));
5ff904cd 11911
c7e4ee3a
CB
11912 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER3]
11913 = t = make_unsigned_type (CHAR_TYPE_SIZE * 2);
11914 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned word"),
11915 t));
5ff904cd 11916
c7e4ee3a
CB
11917 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER4]
11918 = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
11919 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer4"),
11920 t));
11921 type = ffetype_new ();
11922 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER4,
11923 type);
11924 ffetype_set_ams (type,
11925 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11926 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11927 ffetype_set_star (base_type,
11928 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11929 type);
11930 ffetype_set_kind (base_type, 2, type);
11931 assert (ffetype_size (type) == sizeof (ffetargetInteger4));
5ff904cd 11932
c7e4ee3a
CB
11933 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER4]
11934 = t = make_unsigned_type (FLOAT_TYPE_SIZE * 2);
11935 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned4"),
11936 t));
5ff904cd 11937
c7e4ee3a
CB
11938#if 0
11939 if (ffe_is_do_internal_checks ()
11940 && LONG_TYPE_SIZE != FLOAT_TYPE_SIZE
11941 && LONG_TYPE_SIZE != CHAR_TYPE_SIZE
11942 && LONG_TYPE_SIZE != SHORT_TYPE_SIZE
11943 && LONG_TYPE_SIZE != LONG_LONG_TYPE_SIZE)
5ff904cd 11944 {
c7e4ee3a
CB
11945 fprintf (stderr, "Sorry, no g77 support for LONG_TYPE_SIZE (%d bits) yet.\n",
11946 LONG_TYPE_SIZE);
5ff904cd 11947 }
c7e4ee3a 11948#endif
5ff904cd 11949
c7e4ee3a
CB
11950 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL1]
11951 = t = make_signed_type (FLOAT_TYPE_SIZE);
11952 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical"),
11953 t));
11954 type = ffetype_new ();
11955 base_type = type;
11956 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL1,
11957 type);
11958 ffetype_set_ams (type,
11959 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11960 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11961 ffetype_set_star (base_type,
11962 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11963 type);
11964 ffetype_set_kind (base_type, 1, type);
11965 assert (ffetype_size (type) == sizeof (ffetargetLogical1));
5ff904cd 11966
c7e4ee3a
CB
11967 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL2]
11968 = t = make_signed_type (CHAR_TYPE_SIZE);
11969 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical2"),
11970 t));
11971 type = ffetype_new ();
11972 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL2,
11973 type);
11974 ffetype_set_ams (type,
11975 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11976 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11977 ffetype_set_star (base_type,
11978 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11979 type);
11980 ffetype_set_kind (base_type, 3, type);
11981 assert (ffetype_size (type) == sizeof (ffetargetLogical2));
5ff904cd 11982
c7e4ee3a
CB
11983 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL3]
11984 = t = make_signed_type (CHAR_TYPE_SIZE * 2);
11985 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical3"),
11986 t));
11987 type = ffetype_new ();
11988 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL3,
11989 type);
11990 ffetype_set_ams (type,
11991 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11992 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11993 ffetype_set_star (base_type,
11994 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11995 type);
11996 ffetype_set_kind (base_type, 6, type);
11997 assert (ffetype_size (type) == sizeof (ffetargetLogical3));
5ff904cd 11998
c7e4ee3a
CB
11999 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL4]
12000 = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
12001 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical4"),
12002 t));
12003 type = ffetype_new ();
12004 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL4,
12005 type);
12006 ffetype_set_ams (type,
12007 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12008 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12009 ffetype_set_star (base_type,
12010 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12011 type);
12012 ffetype_set_kind (base_type, 2, type);
12013 assert (ffetype_size (type) == sizeof (ffetargetLogical4));
5ff904cd 12014
c7e4ee3a
CB
12015 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
12016 = t = make_node (REAL_TYPE);
12017 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE;
12018 pushdecl (build_decl (TYPE_DECL, get_identifier ("real"),
12019 t));
12020 layout_type (t);
12021 type = ffetype_new ();
12022 base_type = type;
12023 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREAL1,
12024 type);
12025 ffetype_set_ams (type,
12026 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12027 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12028 ffetype_set_star (base_type,
12029 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12030 type);
12031 ffetype_set_kind (base_type, 1, type);
12032 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
12033 = FFETARGET_f2cTYREAL;
12034 assert (ffetype_size (type) == sizeof (ffetargetReal1));
5ff904cd 12035
c7e4ee3a
CB
12036 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREALDOUBLE]
12037 = t = make_node (REAL_TYPE);
12038 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE * 2; /* Always twice REAL. */
12039 pushdecl (build_decl (TYPE_DECL, get_identifier ("double precision"),
12040 t));
12041 layout_type (t);
12042 type = ffetype_new ();
12043 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREALDOUBLE,
12044 type);
12045 ffetype_set_ams (type,
12046 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12047 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12048 ffetype_set_star (base_type,
12049 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12050 type);
12051 ffetype_set_kind (base_type, 2, type);
12052 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]
12053 = FFETARGET_f2cTYDREAL;
12054 assert (ffetype_size (type) == sizeof (ffetargetReal2));
5ff904cd 12055
c7e4ee3a
CB
12056 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
12057 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]);
12058 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex"),
12059 t));
12060 type = ffetype_new ();
12061 base_type = type;
12062 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREAL1,
12063 type);
12064 ffetype_set_ams (type,
12065 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12066 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12067 ffetype_set_star (base_type,
12068 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12069 type);
12070 ffetype_set_kind (base_type, 1, type);
12071 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
12072 = FFETARGET_f2cTYCOMPLEX;
12073 assert (ffetype_size (type) == sizeof (ffetargetComplex1));
5ff904cd 12074
c7e4ee3a
CB
12075 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREALDOUBLE]
12076 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]);
12077 pushdecl (build_decl (TYPE_DECL, get_identifier ("double complex"),
12078 t));
12079 type = ffetype_new ();
12080 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREALDOUBLE,
12081 type);
12082 ffetype_set_ams (type,
12083 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12084 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12085 ffetype_set_star (base_type,
12086 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12087 type);
12088 ffetype_set_kind (base_type, 2,
12089 type);
12090 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL2]
12091 = FFETARGET_f2cTYDCOMPLEX;
12092 assert (ffetype_size (type) == sizeof (ffetargetComplex2));
5ff904cd 12093
c7e4ee3a 12094 /* Make function and ptr-to-function types for non-CHARACTER types. */
5ff904cd 12095
c7e4ee3a
CB
12096 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
12097 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
12098 {
12099 if ((t = ffecom_tree_type[i][j]) != NULL_TREE)
12100 {
12101 if (i == FFEINFO_basictypeINTEGER)
12102 {
12103 /* Figure out the smallest INTEGER type that can hold
12104 a pointer on this machine. */
12105 if (GET_MODE_SIZE (TYPE_MODE (t))
12106 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
12107 {
12108 if ((ffecom_pointer_kind_ == FFEINFO_kindtypeNONE)
12109 || (GET_MODE_SIZE (TYPE_MODE (ffecom_tree_type[i][ffecom_pointer_kind_]))
12110 > GET_MODE_SIZE (TYPE_MODE (t))))
12111 ffecom_pointer_kind_ = j;
12112 }
12113 }
12114 else if (i == FFEINFO_basictypeCOMPLEX)
12115 t = void_type_node;
12116 /* For f2c compatibility, REAL functions are really
12117 implemented as DOUBLE PRECISION. */
12118 else if ((i == FFEINFO_basictypeREAL)
12119 && (j == FFEINFO_kindtypeREAL1))
12120 t = ffecom_tree_type
12121 [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2];
5ff904cd 12122
c7e4ee3a
CB
12123 t = ffecom_tree_fun_type[i][j] = build_function_type (t,
12124 NULL_TREE);
12125 ffecom_tree_ptr_to_fun_type[i][j] = build_pointer_type (t);
12126 }
12127 }
5ff904cd 12128
c7e4ee3a 12129 /* Set up pointer types. */
5ff904cd 12130
c7e4ee3a
CB
12131 if (ffecom_pointer_kind_ == FFEINFO_basictypeNONE)
12132 fatal ("no INTEGER type can hold a pointer on this configuration");
12133 else if (0 && ffe_is_do_internal_checks ())
12134 fprintf (stderr, "Pointer type kt=%d\n", ffecom_pointer_kind_);
12135 ffetype_set_kind (ffeinfo_type (FFEINFO_basictypeINTEGER,
12136 FFEINFO_kindtypeINTEGERDEFAULT),
12137 7,
12138 ffeinfo_type (FFEINFO_basictypeINTEGER,
12139 ffecom_pointer_kind_));
5ff904cd 12140
c7e4ee3a
CB
12141 if (ffe_is_ugly_assign ())
12142 ffecom_label_kind_ = ffecom_pointer_kind_; /* Require ASSIGN etc to this. */
12143 else
12144 ffecom_label_kind_ = FFEINFO_kindtypeINTEGERDEFAULT;
12145 if (0 && ffe_is_do_internal_checks ())
12146 fprintf (stderr, "Label type kt=%d\n", ffecom_label_kind_);
5ff904cd 12147
c7e4ee3a
CB
12148 ffecom_integer_type_node
12149 = ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1];
12150 ffecom_integer_zero_node = convert (ffecom_integer_type_node,
12151 integer_zero_node);
12152 ffecom_integer_one_node = convert (ffecom_integer_type_node,
12153 integer_one_node);
5ff904cd 12154
c7e4ee3a
CB
12155 /* Yes, the "FLOAT_TYPE_SIZE" references below are intentional.
12156 Turns out that by TYLONG, runtime/libI77/lio.h really means
12157 "whatever size an ftnint is". For consistency and sanity,
12158 com.h and runtime/f2c.h.in agree that flag, ftnint, and ftlen
12159 all are INTEGER, which we also make out of whatever back-end
12160 integer type is FLOAT_TYPE_SIZE bits wide. This change, from
12161 LONG_TYPE_SIZE, for TYLONG and TYLOGICAL, was necessary to
12162 accommodate machines like the Alpha. Note that this suggests
12163 f2c and libf2c are missing a distinction perhaps needed on
12164 some machines between "int" and "long int". -- burley 0.5.5 950215 */
5ff904cd 12165
c7e4ee3a
CB
12166 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, FLOAT_TYPE_SIZE,
12167 FFETARGET_f2cTYLONG);
12168 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, SHORT_TYPE_SIZE,
12169 FFETARGET_f2cTYSHORT);
12170 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, CHAR_TYPE_SIZE,
12171 FFETARGET_f2cTYINT1);
12172 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, LONG_LONG_TYPE_SIZE,
12173 FFETARGET_f2cTYQUAD);
12174 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, FLOAT_TYPE_SIZE,
12175 FFETARGET_f2cTYLOGICAL);
12176 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, SHORT_TYPE_SIZE,
12177 FFETARGET_f2cTYLOGICAL2);
12178 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, CHAR_TYPE_SIZE,
12179 FFETARGET_f2cTYLOGICAL1);
12180 /* ~~~Not really such a type in libf2c, e.g. I/O support? */
12181 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, LONG_LONG_TYPE_SIZE,
12182 FFETARGET_f2cTYQUAD);
5ff904cd 12183
c7e4ee3a
CB
12184 /* CHARACTER stuff is all special-cased, so it is not handled in the above
12185 loop. CHARACTER items are built as arrays of unsigned char. */
5ff904cd 12186
c7e4ee3a
CB
12187 ffecom_tree_type[FFEINFO_basictypeCHARACTER]
12188 [FFEINFO_kindtypeCHARACTER1] = t = char_type_node;
12189 type = ffetype_new ();
12190 base_type = type;
12191 ffeinfo_set_type (FFEINFO_basictypeCHARACTER,
12192 FFEINFO_kindtypeCHARACTER1,
12193 type);
12194 ffetype_set_ams (type,
12195 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12196 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12197 ffetype_set_kind (base_type, 1, type);
12198 assert (ffetype_size (type)
12199 == sizeof (((ffetargetCharacter1) { 0, NULL }).text[0]));
5ff904cd 12200
c7e4ee3a
CB
12201 ffecom_tree_fun_type[FFEINFO_basictypeCHARACTER]
12202 [FFEINFO_kindtypeCHARACTER1] = ffecom_tree_fun_type_void;
12203 ffecom_tree_ptr_to_fun_type[FFEINFO_basictypeCHARACTER]
12204 [FFEINFO_kindtypeCHARACTER1]
12205 = ffecom_tree_ptr_to_fun_type_void;
12206 ffecom_f2c_typecode_[FFEINFO_basictypeCHARACTER][FFEINFO_kindtypeCHARACTER1]
12207 = FFETARGET_f2cTYCHAR;
5ff904cd 12208
c7e4ee3a
CB
12209 ffecom_f2c_typecode_[FFEINFO_basictypeANY][FFEINFO_kindtypeANY]
12210 = 0;
5ff904cd 12211
c7e4ee3a 12212 /* Make multi-return-value type and fields. */
5ff904cd 12213
c7e4ee3a 12214 ffecom_multi_type_node_ = make_node (UNION_TYPE);
5ff904cd 12215
c7e4ee3a 12216 field = NULL_TREE;
5ff904cd 12217
c7e4ee3a
CB
12218 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
12219 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
12220 {
12221 char name[30];
5ff904cd 12222
c7e4ee3a
CB
12223 if (ffecom_tree_type[i][j] == NULL_TREE)
12224 continue; /* Not supported. */
12225 sprintf (&name[0], "bt_%s_kt_%s",
12226 ffeinfo_basictype_string ((ffeinfoBasictype) i),
12227 ffeinfo_kindtype_string ((ffeinfoKindtype) j));
12228 ffecom_multi_fields_[i][j] = build_decl (FIELD_DECL,
12229 get_identifier (name),
12230 ffecom_tree_type[i][j]);
12231 DECL_CONTEXT (ffecom_multi_fields_[i][j])
12232 = ffecom_multi_type_node_;
12233 DECL_FRAME_SIZE (ffecom_multi_fields_[i][j]) = 0;
12234 TREE_CHAIN (ffecom_multi_fields_[i][j]) = field;
12235 field = ffecom_multi_fields_[i][j];
12236 }
5ff904cd 12237
c7e4ee3a
CB
12238 TYPE_FIELDS (ffecom_multi_type_node_) = field;
12239 layout_type (ffecom_multi_type_node_);
5ff904cd 12240
c7e4ee3a
CB
12241 /* Subroutines usually return integer because they might have alternate
12242 returns. */
5ff904cd 12243
c7e4ee3a
CB
12244 ffecom_tree_subr_type
12245 = build_function_type (integer_type_node, NULL_TREE);
12246 ffecom_tree_ptr_to_subr_type
12247 = build_pointer_type (ffecom_tree_subr_type);
12248 ffecom_tree_blockdata_type
12249 = build_function_type (void_type_node, NULL_TREE);
5ff904cd 12250
c7e4ee3a
CB
12251 builtin_function ("__builtin_sqrtf", float_ftype_float,
12252 BUILT_IN_FSQRT, "sqrtf");
12253 builtin_function ("__builtin_fsqrt", double_ftype_double,
12254 BUILT_IN_FSQRT, "sqrt");
12255 builtin_function ("__builtin_sqrtl", ldouble_ftype_ldouble,
12256 BUILT_IN_FSQRT, "sqrtl");
12257 builtin_function ("__builtin_sinf", float_ftype_float,
12258 BUILT_IN_SIN, "sinf");
12259 builtin_function ("__builtin_sin", double_ftype_double,
12260 BUILT_IN_SIN, "sin");
12261 builtin_function ("__builtin_sinl", ldouble_ftype_ldouble,
12262 BUILT_IN_SIN, "sinl");
12263 builtin_function ("__builtin_cosf", float_ftype_float,
12264 BUILT_IN_COS, "cosf");
12265 builtin_function ("__builtin_cos", double_ftype_double,
12266 BUILT_IN_COS, "cos");
12267 builtin_function ("__builtin_cosl", ldouble_ftype_ldouble,
12268 BUILT_IN_COS, "cosl");
5ff904cd 12269
c7e4ee3a
CB
12270#if BUILT_FOR_270
12271 pedantic_lvalues = FALSE;
5ff904cd 12272#endif
5ff904cd 12273
c7e4ee3a
CB
12274 ffecom_f2c_make_type_ (&ffecom_f2c_integer_type_node,
12275 FFECOM_f2cINTEGER,
12276 "integer");
12277 ffecom_f2c_make_type_ (&ffecom_f2c_address_type_node,
12278 FFECOM_f2cADDRESS,
12279 "address");
12280 ffecom_f2c_make_type_ (&ffecom_f2c_real_type_node,
12281 FFECOM_f2cREAL,
12282 "real");
12283 ffecom_f2c_make_type_ (&ffecom_f2c_doublereal_type_node,
12284 FFECOM_f2cDOUBLEREAL,
12285 "doublereal");
12286 ffecom_f2c_make_type_ (&ffecom_f2c_complex_type_node,
12287 FFECOM_f2cCOMPLEX,
12288 "complex");
12289 ffecom_f2c_make_type_ (&ffecom_f2c_doublecomplex_type_node,
12290 FFECOM_f2cDOUBLECOMPLEX,
12291 "doublecomplex");
12292 ffecom_f2c_make_type_ (&ffecom_f2c_longint_type_node,
12293 FFECOM_f2cLONGINT,
12294 "longint");
12295 ffecom_f2c_make_type_ (&ffecom_f2c_logical_type_node,
12296 FFECOM_f2cLOGICAL,
12297 "logical");
12298 ffecom_f2c_make_type_ (&ffecom_f2c_flag_type_node,
12299 FFECOM_f2cFLAG,
12300 "flag");
12301 ffecom_f2c_make_type_ (&ffecom_f2c_ftnlen_type_node,
12302 FFECOM_f2cFTNLEN,
12303 "ftnlen");
12304 ffecom_f2c_make_type_ (&ffecom_f2c_ftnint_type_node,
12305 FFECOM_f2cFTNINT,
12306 "ftnint");
5ff904cd 12307
c7e4ee3a
CB
12308 ffecom_f2c_ftnlen_zero_node
12309 = convert (ffecom_f2c_ftnlen_type_node, integer_zero_node);
5ff904cd 12310
c7e4ee3a
CB
12311 ffecom_f2c_ftnlen_one_node
12312 = convert (ffecom_f2c_ftnlen_type_node, integer_one_node);
5ff904cd 12313
c7e4ee3a
CB
12314 ffecom_f2c_ftnlen_two_node = build_int_2 (2, 0);
12315 TREE_TYPE (ffecom_f2c_ftnlen_two_node) = ffecom_integer_type_node;
5ff904cd 12316
c7e4ee3a
CB
12317 ffecom_f2c_ptr_to_ftnlen_type_node
12318 = build_pointer_type (ffecom_f2c_ftnlen_type_node);
5ff904cd 12319
c7e4ee3a
CB
12320 ffecom_f2c_ptr_to_ftnint_type_node
12321 = build_pointer_type (ffecom_f2c_ftnint_type_node);
5ff904cd 12322
c7e4ee3a
CB
12323 ffecom_f2c_ptr_to_integer_type_node
12324 = build_pointer_type (ffecom_f2c_integer_type_node);
5ff904cd 12325
c7e4ee3a
CB
12326 ffecom_f2c_ptr_to_real_type_node
12327 = build_pointer_type (ffecom_f2c_real_type_node);
5ff904cd 12328
c7e4ee3a
CB
12329 ffecom_float_zero_ = build_real (float_type_node, dconst0);
12330 ffecom_double_zero_ = build_real (double_type_node, dconst0);
12331 {
12332 REAL_VALUE_TYPE point_5;
5ff904cd 12333
c7e4ee3a
CB
12334#ifdef REAL_ARITHMETIC
12335 REAL_ARITHMETIC (point_5, RDIV_EXPR, dconst1, dconst2);
12336#else
12337 point_5 = .5;
12338#endif
12339 ffecom_float_half_ = build_real (float_type_node, point_5);
12340 ffecom_double_half_ = build_real (double_type_node, point_5);
12341 }
5ff904cd 12342
c7e4ee3a 12343 /* Do "extern int xargc;". */
5ff904cd 12344
c7e4ee3a
CB
12345 ffecom_tree_xargc_ = build_decl (VAR_DECL,
12346 get_identifier ("f__xargc"),
12347 integer_type_node);
12348 DECL_EXTERNAL (ffecom_tree_xargc_) = 1;
12349 TREE_STATIC (ffecom_tree_xargc_) = 1;
12350 TREE_PUBLIC (ffecom_tree_xargc_) = 1;
12351 ffecom_tree_xargc_ = start_decl (ffecom_tree_xargc_, FALSE);
12352 finish_decl (ffecom_tree_xargc_, NULL_TREE, FALSE);
5ff904cd 12353
c7e4ee3a
CB
12354#if 0 /* This is being fixed, and seems to be working now. */
12355 if ((FLOAT_TYPE_SIZE != 32)
12356 || (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))) != 32))
5ff904cd 12357 {
c7e4ee3a
CB
12358 warning ("configuration: REAL, INTEGER, and LOGICAL are %d bits wide,",
12359 (int) FLOAT_TYPE_SIZE);
12360 warning ("and pointers are %d bits wide, but g77 doesn't yet work",
12361 (int) TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))));
12362 warning ("properly unless they all are 32 bits wide.");
12363 warning ("Please keep this in mind before you report bugs. g77 should");
12364 warning ("support non-32-bit machines better as of version 0.6.");
12365 }
12366#endif
5ff904cd 12367
c7e4ee3a
CB
12368#if 0 /* Code in ste.c that would crash has been commented out. */
12369 if (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)
12370 < TYPE_PRECISION (string_type_node))
12371 /* I/O will probably crash. */
12372 warning ("configuration: char * holds %d bits, but ftnlen only %d",
12373 TYPE_PRECISION (string_type_node),
12374 TYPE_PRECISION (ffecom_f2c_ftnlen_type_node));
12375#endif
5ff904cd 12376
c7e4ee3a
CB
12377#if 0 /* ASSIGN-related stuff has been changed to accommodate this. */
12378 if (TYPE_PRECISION (ffecom_integer_type_node)
12379 < TYPE_PRECISION (string_type_node))
12380 /* ASSIGN 10 TO I will crash. */
12381 warning ("configuration: char * holds %d bits, but INTEGER only %d --\n\
12382 ASSIGN statement might fail",
12383 TYPE_PRECISION (string_type_node),
12384 TYPE_PRECISION (ffecom_integer_type_node));
12385#endif
12386}
5ff904cd 12387
c7e4ee3a
CB
12388#endif
12389/* ffecom_init_2 -- Initialize
5ff904cd 12390
c7e4ee3a 12391 ffecom_init_2(); */
5ff904cd 12392
c7e4ee3a
CB
12393#if FFECOM_targetCURRENT == FFECOM_targetGCC
12394void
12395ffecom_init_2 ()
12396{
12397 assert (ffecom_outer_function_decl_ == NULL_TREE);
12398 assert (current_function_decl == NULL_TREE);
12399 assert (ffecom_which_entrypoint_decl_ == NULL_TREE);
5ff904cd 12400
c7e4ee3a
CB
12401 ffecom_master_arglist_ = NULL;
12402 ++ffecom_num_fns_;
12403 ffecom_primary_entry_ = NULL;
12404 ffecom_is_altreturning_ = FALSE;
12405 ffecom_func_result_ = NULL_TREE;
12406 ffecom_multi_retval_ = NULL_TREE;
12407}
5ff904cd 12408
c7e4ee3a
CB
12409#endif
12410/* ffecom_list_expr -- Transform list of exprs into gcc tree
5ff904cd 12411
c7e4ee3a
CB
12412 tree t;
12413 ffebld expr; // FFE opITEM list.
12414 tree = ffecom_list_expr(expr);
5ff904cd 12415
c7e4ee3a 12416 List of actual args is transformed into corresponding gcc backend list. */
5ff904cd 12417
c7e4ee3a
CB
12418#if FFECOM_targetCURRENT == FFECOM_targetGCC
12419tree
12420ffecom_list_expr (ffebld expr)
5ff904cd 12421{
c7e4ee3a
CB
12422 tree list;
12423 tree *plist = &list;
12424 tree trail = NULL_TREE; /* Append char length args here. */
12425 tree *ptrail = &trail;
12426 tree length;
5ff904cd 12427
c7e4ee3a 12428 while (expr != NULL)
5ff904cd 12429 {
c7e4ee3a 12430 tree texpr = ffecom_arg_expr (ffebld_head (expr), &length);
5ff904cd 12431
c7e4ee3a
CB
12432 if (texpr == error_mark_node)
12433 return error_mark_node;
5ff904cd 12434
c7e4ee3a
CB
12435 *plist = build_tree_list (NULL_TREE, texpr);
12436 plist = &TREE_CHAIN (*plist);
12437 expr = ffebld_trail (expr);
12438 if (length != NULL_TREE)
5ff904cd 12439 {
c7e4ee3a
CB
12440 *ptrail = build_tree_list (NULL_TREE, length);
12441 ptrail = &TREE_CHAIN (*ptrail);
5ff904cd
JL
12442 }
12443 }
12444
c7e4ee3a 12445 *plist = trail;
5ff904cd 12446
c7e4ee3a
CB
12447 return list;
12448}
5ff904cd 12449
c7e4ee3a
CB
12450#endif
12451/* ffecom_list_ptr_to_expr -- Transform list of exprs into gcc tree
5ff904cd 12452
c7e4ee3a
CB
12453 tree t;
12454 ffebld expr; // FFE opITEM list.
12455 tree = ffecom_list_ptr_to_expr(expr);
5ff904cd 12456
c7e4ee3a
CB
12457 List of actual args is transformed into corresponding gcc backend list for
12458 use in calling an external procedure (vs. a statement function). */
5ff904cd 12459
c7e4ee3a
CB
12460#if FFECOM_targetCURRENT == FFECOM_targetGCC
12461tree
12462ffecom_list_ptr_to_expr (ffebld expr)
12463{
12464 tree list;
12465 tree *plist = &list;
12466 tree trail = NULL_TREE; /* Append char length args here. */
12467 tree *ptrail = &trail;
12468 tree length;
5ff904cd 12469
c7e4ee3a
CB
12470 while (expr != NULL)
12471 {
12472 tree texpr = ffecom_arg_ptr_to_expr (ffebld_head (expr), &length);
5ff904cd 12473
c7e4ee3a
CB
12474 if (texpr == error_mark_node)
12475 return error_mark_node;
5ff904cd 12476
c7e4ee3a
CB
12477 *plist = build_tree_list (NULL_TREE, texpr);
12478 plist = &TREE_CHAIN (*plist);
12479 expr = ffebld_trail (expr);
12480 if (length != NULL_TREE)
12481 {
12482 *ptrail = build_tree_list (NULL_TREE, length);
12483 ptrail = &TREE_CHAIN (*ptrail);
12484 }
12485 }
5ff904cd 12486
c7e4ee3a 12487 *plist = trail;
5ff904cd 12488
c7e4ee3a
CB
12489 return list;
12490}
5ff904cd 12491
c7e4ee3a
CB
12492#endif
12493/* Obtain gcc's LABEL_DECL tree for label. */
5ff904cd 12494
c7e4ee3a
CB
12495#if FFECOM_targetCURRENT == FFECOM_targetGCC
12496tree
12497ffecom_lookup_label (ffelab label)
12498{
12499 tree glabel;
5ff904cd 12500
c7e4ee3a
CB
12501 if (ffelab_hook (label) == NULL_TREE)
12502 {
12503 char labelname[16];
5ff904cd 12504
c7e4ee3a
CB
12505 switch (ffelab_type (label))
12506 {
12507 case FFELAB_typeLOOPEND:
12508 case FFELAB_typeNOTLOOP:
12509 case FFELAB_typeENDIF:
12510 sprintf (labelname, "%" ffelabValue_f "u", ffelab_value (label));
12511 glabel = build_decl (LABEL_DECL, get_identifier (labelname),
12512 void_type_node);
12513 DECL_CONTEXT (glabel) = current_function_decl;
12514 DECL_MODE (glabel) = VOIDmode;
12515 break;
5ff904cd 12516
c7e4ee3a
CB
12517 case FFELAB_typeFORMAT:
12518 push_obstacks_nochange ();
12519 end_temporary_allocation ();
5ff904cd 12520
c7e4ee3a
CB
12521 glabel = build_decl (VAR_DECL,
12522 ffecom_get_invented_identifier
12523 ("__g77_format_%d", NULL,
12524 (int) ffelab_value (label)),
12525 build_type_variant (build_array_type
12526 (char_type_node,
12527 NULL_TREE),
12528 1, 0));
12529 TREE_CONSTANT (glabel) = 1;
12530 TREE_STATIC (glabel) = 1;
12531 DECL_CONTEXT (glabel) = 0;
12532 DECL_INITIAL (glabel) = NULL;
12533 make_decl_rtl (glabel, NULL, 0);
12534 expand_decl (glabel);
5ff904cd 12535
c7e4ee3a
CB
12536 resume_temporary_allocation ();
12537 pop_obstacks ();
5ff904cd 12538
c7e4ee3a 12539 break;
5ff904cd 12540
c7e4ee3a
CB
12541 case FFELAB_typeANY:
12542 glabel = error_mark_node;
12543 break;
5ff904cd 12544
c7e4ee3a
CB
12545 default:
12546 assert ("bad label type" == NULL);
12547 glabel = NULL;
12548 break;
12549 }
12550 ffelab_set_hook (label, glabel);
12551 }
12552 else
12553 {
12554 glabel = ffelab_hook (label);
12555 }
5ff904cd 12556
c7e4ee3a
CB
12557 return glabel;
12558}
5ff904cd 12559
c7e4ee3a
CB
12560#endif
12561/* Stabilizes the arguments. Don't use this if the lhs and rhs come from
12562 a single source specification (as in the fourth argument of MVBITS).
12563 If the type is NULL_TREE, the type of lhs is used to make the type of
12564 the MODIFY_EXPR. */
5ff904cd 12565
c7e4ee3a
CB
12566#if FFECOM_targetCURRENT == FFECOM_targetGCC
12567tree
12568ffecom_modify (tree newtype, tree lhs,
12569 tree rhs)
12570{
12571 if (lhs == error_mark_node || rhs == error_mark_node)
12572 return error_mark_node;
5ff904cd 12573
c7e4ee3a
CB
12574 if (newtype == NULL_TREE)
12575 newtype = TREE_TYPE (lhs);
5ff904cd 12576
c7e4ee3a
CB
12577 if (TREE_SIDE_EFFECTS (lhs))
12578 lhs = stabilize_reference (lhs);
5ff904cd 12579
c7e4ee3a
CB
12580 return ffecom_2s (MODIFY_EXPR, newtype, lhs, rhs);
12581}
5ff904cd 12582
c7e4ee3a 12583#endif
5ff904cd 12584
c7e4ee3a 12585/* Register source file name. */
5ff904cd 12586
c7e4ee3a
CB
12587void
12588ffecom_file (char *name)
12589{
12590#if FFECOM_GCC_INCLUDE
12591 ffecom_file_ (name);
12592#endif
12593}
5ff904cd 12594
c7e4ee3a 12595/* ffecom_notify_init_storage -- An aggregate storage is now fully init'ed
5ff904cd 12596
c7e4ee3a
CB
12597 ffestorag st;
12598 ffecom_notify_init_storage(st);
5ff904cd 12599
c7e4ee3a
CB
12600 Gets called when all possible units in an aggregate storage area (a LOCAL
12601 with equivalences or a COMMON) have been initialized. The initialization
12602 info either is in ffestorag_init or, if that is NULL,
12603 ffestorag_accretion:
5ff904cd 12604
c7e4ee3a
CB
12605 ffestorag_init may contain an opCONTER or opARRTER. opCONTER may occur
12606 even for an array if the array is one element in length!
5ff904cd 12607
c7e4ee3a
CB
12608 ffestorag_accretion will contain an opACCTER. It is much like an
12609 opARRTER except it has an ffebit object in it instead of just a size.
12610 The back end can use the info in the ffebit object, if it wants, to
12611 reduce the amount of actual initialization, but in any case it should
12612 kill the ffebit object when done. Also, set accretion to NULL but
12613 init to a non-NULL value.
5ff904cd 12614
c7e4ee3a
CB
12615 After performing initialization, DO NOT set init to NULL, because that'll
12616 tell the front end it is ok for more initialization to happen. Instead,
12617 set init to an opANY expression or some such thing that you can use to
12618 tell that you've already initialized the object.
5ff904cd 12619
c7e4ee3a
CB
12620 27-Oct-91 JCB 1.1
12621 Support two-pass FFE. */
5ff904cd 12622
c7e4ee3a
CB
12623void
12624ffecom_notify_init_storage (ffestorag st)
12625{
12626 ffebld init; /* The initialization expression. */
12627#if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12628 ffetargetOffset size; /* The size of the entity. */
12629 ffetargetAlign pad; /* Its initial padding. */
12630#endif
12631
12632 if (ffestorag_init (st) == NULL)
5ff904cd 12633 {
c7e4ee3a
CB
12634 init = ffestorag_accretion (st);
12635 assert (init != NULL);
12636 ffestorag_set_accretion (st, NULL);
12637 ffestorag_set_accretes (st, 0);
12638
12639#if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12640 /* For GNU backend, just turn ACCTER into ARRTER and proceed. */
12641 size = ffebld_accter_size (init);
12642 pad = ffebld_accter_pad (init);
12643 ffebit_kill (ffebld_accter_bits (init));
12644 ffebld_set_op (init, FFEBLD_opARRTER);
12645 ffebld_set_arrter (init, ffebld_accter (init));
12646 ffebld_arrter_set_size (init, size);
12647 ffebld_arrter_set_pad (init, size);
12648#endif
12649
12650#if FFECOM_TWOPASS
12651 ffestorag_set_init (st, init);
12652#endif
5ff904cd 12653 }
c7e4ee3a
CB
12654#if FFECOM_ONEPASS
12655 else
12656 init = ffestorag_init (st);
5ff904cd
JL
12657#endif
12658
c7e4ee3a
CB
12659#if FFECOM_ONEPASS /* Process the inits, wipe 'em out. */
12660 ffestorag_set_init (st, ffebld_new_any ());
5ff904cd 12661
c7e4ee3a
CB
12662 if (ffebld_op (init) == FFEBLD_opANY)
12663 return; /* Oh, we already did this! */
5ff904cd 12664
c7e4ee3a
CB
12665#if FFECOM_targetCURRENT == FFECOM_targetFFE
12666 {
12667 ffesymbol s;
5ff904cd 12668
c7e4ee3a
CB
12669 if (ffestorag_symbol (st) != NULL)
12670 s = ffestorag_symbol (st);
12671 else
12672 s = ffestorag_typesymbol (st);
5ff904cd 12673
c7e4ee3a
CB
12674 fprintf (dmpout, "= initialize_storage \"%s\" ",
12675 (s != NULL) ? ffesymbol_text (s) : "(unnamed)");
12676 ffebld_dump (init);
12677 fputc ('\n', dmpout);
12678 }
12679#endif
5ff904cd 12680
c7e4ee3a
CB
12681#endif /* if FFECOM_ONEPASS */
12682}
5ff904cd 12683
c7e4ee3a 12684/* ffecom_notify_init_symbol -- A symbol is now fully init'ed
5ff904cd 12685
c7e4ee3a
CB
12686 ffesymbol s;
12687 ffecom_notify_init_symbol(s);
5ff904cd 12688
c7e4ee3a
CB
12689 Gets called when all possible units in a symbol (not placed in COMMON
12690 or involved in EQUIVALENCE, unless it as yet has no ffestorag object)
12691 have been initialized. The initialization info either is in
12692 ffesymbol_init or, if that is NULL, ffesymbol_accretion:
5ff904cd 12693
c7e4ee3a
CB
12694 ffesymbol_init may contain an opCONTER or opARRTER. opCONTER may occur
12695 even for an array if the array is one element in length!
5ff904cd 12696
c7e4ee3a
CB
12697 ffesymbol_accretion will contain an opACCTER. It is much like an
12698 opARRTER except it has an ffebit object in it instead of just a size.
12699 The back end can use the info in the ffebit object, if it wants, to
12700 reduce the amount of actual initialization, but in any case it should
12701 kill the ffebit object when done. Also, set accretion to NULL but
12702 init to a non-NULL value.
5ff904cd 12703
c7e4ee3a
CB
12704 After performing initialization, DO NOT set init to NULL, because that'll
12705 tell the front end it is ok for more initialization to happen. Instead,
12706 set init to an opANY expression or some such thing that you can use to
12707 tell that you've already initialized the object.
5ff904cd 12708
c7e4ee3a
CB
12709 27-Oct-91 JCB 1.1
12710 Support two-pass FFE. */
5ff904cd 12711
c7e4ee3a
CB
12712void
12713ffecom_notify_init_symbol (ffesymbol s)
12714{
12715 ffebld init; /* The initialization expression. */
12716#if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12717 ffetargetOffset size; /* The size of the entity. */
12718 ffetargetAlign pad; /* Its initial padding. */
12719#endif
5ff904cd 12720
c7e4ee3a
CB
12721 if (ffesymbol_storage (s) == NULL)
12722 return; /* Do nothing until COMMON/EQUIVALENCE
12723 possibilities checked. */
5ff904cd 12724
c7e4ee3a
CB
12725 if ((ffesymbol_init (s) == NULL)
12726 && ((init = ffesymbol_accretion (s)) != NULL))
12727 {
12728 ffesymbol_set_accretion (s, NULL);
12729 ffesymbol_set_accretes (s, 0);
5ff904cd 12730
c7e4ee3a
CB
12731#if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12732 /* For GNU backend, just turn ACCTER into ARRTER and proceed. */
12733 size = ffebld_accter_size (init);
12734 pad = ffebld_accter_pad (init);
12735 ffebit_kill (ffebld_accter_bits (init));
12736 ffebld_set_op (init, FFEBLD_opARRTER);
12737 ffebld_set_arrter (init, ffebld_accter (init));
12738 ffebld_arrter_set_size (init, size);
12739 ffebld_arrter_set_pad (init, size);
12740#endif
5ff904cd 12741
c7e4ee3a
CB
12742#if FFECOM_TWOPASS
12743 ffesymbol_set_init (s, init);
12744#endif
12745 }
12746#if FFECOM_ONEPASS
12747 else
12748 init = ffesymbol_init (s);
12749#endif
5ff904cd 12750
c7e4ee3a
CB
12751#if FFECOM_ONEPASS
12752 ffesymbol_set_init (s, ffebld_new_any ());
5ff904cd 12753
c7e4ee3a
CB
12754 if (ffebld_op (init) == FFEBLD_opANY)
12755 return; /* Oh, we already did this! */
5ff904cd 12756
c7e4ee3a
CB
12757#if FFECOM_targetCURRENT == FFECOM_targetFFE
12758 fprintf (dmpout, "= initialize_symbol \"%s\" ", ffesymbol_text (s));
12759 ffebld_dump (init);
12760 fputc ('\n', dmpout);
12761#endif
5ff904cd 12762
c7e4ee3a
CB
12763#endif /* if FFECOM_ONEPASS */
12764}
5ff904cd 12765
c7e4ee3a 12766/* ffecom_notify_primary_entry -- Learn which is the primary entry point
5ff904cd 12767
c7e4ee3a
CB
12768 ffesymbol s;
12769 ffecom_notify_primary_entry(s);
5ff904cd 12770
c7e4ee3a
CB
12771 Gets called when implicit or explicit PROGRAM statement seen or when
12772 FUNCTION, SUBROUTINE, or BLOCK DATA statement seen, with the primary
12773 global symbol that serves as the entry point. */
5ff904cd 12774
c7e4ee3a
CB
12775void
12776ffecom_notify_primary_entry (ffesymbol s)
12777{
12778 ffecom_primary_entry_ = s;
12779 ffecom_primary_entry_kind_ = ffesymbol_kind (s);
5ff904cd 12780
c7e4ee3a
CB
12781 if ((ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
12782 || (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE))
12783 ffecom_primary_entry_is_proc_ = TRUE;
12784 else
12785 ffecom_primary_entry_is_proc_ = FALSE;
5ff904cd 12786
c7e4ee3a
CB
12787 if (!ffe_is_silent ())
12788 {
12789 if (ffecom_primary_entry_kind_ == FFEINFO_kindPROGRAM)
12790 fprintf (stderr, "%s:\n", ffesymbol_text (s));
12791 else
12792 fprintf (stderr, " %s:\n", ffesymbol_text (s));
12793 }
5ff904cd 12794
c7e4ee3a
CB
12795#if FFECOM_targetCURRENT == FFECOM_targetGCC
12796 if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
12797 {
12798 ffebld list;
12799 ffebld arg;
5ff904cd 12800
c7e4ee3a
CB
12801 for (list = ffesymbol_dummyargs (s);
12802 list != NULL;
12803 list = ffebld_trail (list))
12804 {
12805 arg = ffebld_head (list);
12806 if (ffebld_op (arg) == FFEBLD_opSTAR)
12807 {
12808 ffecom_is_altreturning_ = TRUE;
12809 break;
12810 }
12811 }
12812 }
12813#endif
12814}
5ff904cd 12815
c7e4ee3a
CB
12816FILE *
12817ffecom_open_include (char *name, ffewhereLine l, ffewhereColumn c)
12818{
12819#if FFECOM_GCC_INCLUDE
12820 return ffecom_open_include_ (name, l, c);
12821#else
12822 return fopen (name, "r");
5ff904cd 12823#endif
c7e4ee3a 12824}
5ff904cd 12825
c7e4ee3a 12826/* ffecom_ptr_to_expr -- Transform expr into gcc tree with & in front
5ff904cd 12827
c7e4ee3a
CB
12828 tree t;
12829 ffebld expr; // FFE expression.
12830 tree = ffecom_ptr_to_expr(expr);
5ff904cd 12831
c7e4ee3a 12832 Like ffecom_expr, but sticks address-of in front of most things. */
5ff904cd 12833
c7e4ee3a
CB
12834#if FFECOM_targetCURRENT == FFECOM_targetGCC
12835tree
12836ffecom_ptr_to_expr (ffebld expr)
12837{
12838 tree item;
12839 ffeinfoBasictype bt;
12840 ffeinfoKindtype kt;
12841 ffesymbol s;
5ff904cd 12842
c7e4ee3a 12843 assert (expr != NULL);
5ff904cd 12844
c7e4ee3a
CB
12845 switch (ffebld_op (expr))
12846 {
12847 case FFEBLD_opSYMTER:
12848 s = ffebld_symter (expr);
12849 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
12850 {
12851 ffecomGfrt ix;
5ff904cd 12852
c7e4ee3a
CB
12853 ix = ffeintrin_gfrt_indirect (ffebld_symter_implementation (expr));
12854 assert (ix != FFECOM_gfrt);
12855 if ((item = ffecom_gfrt_[ix]) == NULL_TREE)
12856 {
12857 ffecom_make_gfrt_ (ix);
12858 item = ffecom_gfrt_[ix];
12859 }
12860 }
12861 else
12862 {
12863 item = ffesymbol_hook (s).decl_tree;
12864 if (item == NULL_TREE)
12865 {
12866 s = ffecom_sym_transform_ (s);
12867 item = ffesymbol_hook (s).decl_tree;
12868 }
12869 }
12870 assert (item != NULL);
12871 if (item == error_mark_node)
12872 return item;
12873 if (!ffesymbol_hook (s).addr)
12874 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12875 item);
12876 return item;
5ff904cd 12877
c7e4ee3a 12878 case FFEBLD_opARRAYREF:
ff852b44 12879 return ffecom_arrayref_ (NULL_TREE, expr, 1);
5ff904cd 12880
c7e4ee3a 12881 case FFEBLD_opCONTER:
5ff904cd 12882
c7e4ee3a
CB
12883 bt = ffeinfo_basictype (ffebld_info (expr));
12884 kt = ffeinfo_kindtype (ffebld_info (expr));
5ff904cd 12885
c7e4ee3a
CB
12886 item = ffecom_constantunion (&ffebld_constant_union
12887 (ffebld_conter (expr)), bt, kt,
12888 ffecom_tree_type[bt][kt]);
12889 if (item == error_mark_node)
12890 return error_mark_node;
12891 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12892 item);
12893 return item;
5ff904cd 12894
c7e4ee3a
CB
12895 case FFEBLD_opANY:
12896 return error_mark_node;
5ff904cd 12897
c7e4ee3a
CB
12898 default:
12899 bt = ffeinfo_basictype (ffebld_info (expr));
12900 kt = ffeinfo_kindtype (ffebld_info (expr));
12901
12902 item = ffecom_expr (expr);
12903 if (item == error_mark_node)
12904 return error_mark_node;
12905
12906 /* The back end currently optimizes a bit too zealously for us, in that
12907 we fail JCB001 if the following block of code is omitted. It checks
12908 to see if the transformed expression is a symbol or array reference,
12909 and encloses it in a SAVE_EXPR if that is the case. */
12910
12911 STRIP_NOPS (item);
12912 if ((TREE_CODE (item) == VAR_DECL)
12913 || (TREE_CODE (item) == PARM_DECL)
12914 || (TREE_CODE (item) == RESULT_DECL)
12915 || (TREE_CODE (item) == INDIRECT_REF)
12916 || (TREE_CODE (item) == ARRAY_REF)
12917 || (TREE_CODE (item) == COMPONENT_REF)
12918#ifdef OFFSET_REF
12919 || (TREE_CODE (item) == OFFSET_REF)
12920#endif
12921 || (TREE_CODE (item) == BUFFER_REF)
12922 || (TREE_CODE (item) == REALPART_EXPR)
12923 || (TREE_CODE (item) == IMAGPART_EXPR))
12924 {
12925 item = ffecom_save_tree (item);
12926 }
12927
12928 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12929 item);
12930 return item;
12931 }
12932
12933 assert ("fall-through error" == NULL);
12934 return error_mark_node;
5ff904cd
JL
12935}
12936
12937#endif
c7e4ee3a 12938/* Obtain a temp var with given data type.
5ff904cd 12939
c7e4ee3a
CB
12940 size is FFETARGET_charactersizeNONE for a non-CHARACTER type
12941 or >= 0 for a CHARACTER type.
5ff904cd 12942
c7e4ee3a 12943 elements is -1 for a scalar or > 0 for an array of type. */
5ff904cd
JL
12944
12945#if FFECOM_targetCURRENT == FFECOM_targetGCC
12946tree
c7e4ee3a
CB
12947ffecom_make_tempvar (const char *commentary, tree type,
12948 ffetargetCharacterSize size, int elements)
5ff904cd 12949{
c7e4ee3a
CB
12950 int yes;
12951 tree t;
12952 static int mynumber;
5ff904cd 12953
c7e4ee3a 12954 assert (current_binding_level->prep_state < 2);
702edf1d 12955
c7e4ee3a
CB
12956 if (type == error_mark_node)
12957 return error_mark_node;
702edf1d 12958
c7e4ee3a 12959 yes = suspend_momentary ();
5ff904cd 12960
c7e4ee3a
CB
12961 if (size != FFETARGET_charactersizeNONE)
12962 type = build_array_type (type,
12963 build_range_type (ffecom_f2c_ftnlen_type_node,
12964 ffecom_f2c_ftnlen_one_node,
12965 build_int_2 (size, 0)));
12966 if (elements != -1)
12967 type = build_array_type (type,
12968 build_range_type (integer_type_node,
12969 integer_zero_node,
12970 build_int_2 (elements - 1,
12971 0)));
12972 t = build_decl (VAR_DECL,
12973 ffecom_get_invented_identifier ("__g77_%s_%d",
12974 commentary,
12975 mynumber++),
12976 type);
5ff904cd 12977
c7e4ee3a
CB
12978 t = start_decl (t, FALSE);
12979 finish_decl (t, NULL_TREE, FALSE);
12980
12981 resume_momentary (yes);
5ff904cd 12982
c7e4ee3a
CB
12983 return t;
12984}
5ff904cd 12985#endif
5ff904cd 12986
c7e4ee3a 12987/* Prepare argument pointer to expression.
5ff904cd 12988
c7e4ee3a
CB
12989 Like ffecom_prepare_expr, except for expressions to be evaluated
12990 via ffecom_arg_ptr_to_expr. */
5ff904cd 12991
c7e4ee3a
CB
12992void
12993ffecom_prepare_arg_ptr_to_expr (ffebld expr)
5ff904cd 12994{
c7e4ee3a
CB
12995 /* ~~For now, it seems to be the same thing. */
12996 ffecom_prepare_expr (expr);
12997 return;
12998}
702edf1d 12999
c7e4ee3a 13000/* End of preparations. */
702edf1d 13001
c7e4ee3a
CB
13002bool
13003ffecom_prepare_end (void)
13004{
13005 int prep_state = current_binding_level->prep_state;
5ff904cd 13006
c7e4ee3a
CB
13007 assert (prep_state < 2);
13008 current_binding_level->prep_state = 2;
5ff904cd 13009
c7e4ee3a 13010 return (prep_state == 1) ? TRUE : FALSE;
5ff904cd
JL
13011}
13012
c7e4ee3a 13013/* Prepare expression.
5ff904cd 13014
c7e4ee3a
CB
13015 This is called before any code is generated for the current block.
13016 It scans the expression, declares any temporaries that might be needed
13017 during evaluation of the expression, and stores those temporaries in
13018 the appropriate "hook" fields of the expression. `dest', if not NULL,
13019 specifies the destination that ffecom_expr_ will see, in case that
13020 helps avoid generating unused temporaries.
13021
13022 ~~Improve to avoid allocating unused temporaries by taking `dest'
13023 into account vis-a-vis aliasing requirements of complex/character
13024 functions. */
13025
13026void
13027ffecom_prepare_expr_ (ffebld expr, ffebld dest UNUSED)
5ff904cd 13028{
c7e4ee3a
CB
13029 ffeinfoBasictype bt;
13030 ffeinfoKindtype kt;
13031 ffetargetCharacterSize sz;
13032 tree tempvar = NULL_TREE;
5ff904cd 13033
c7e4ee3a
CB
13034 assert (current_binding_level->prep_state < 2);
13035
13036 if (! expr)
13037 return;
13038
13039 bt = ffeinfo_basictype (ffebld_info (expr));
13040 kt = ffeinfo_kindtype (ffebld_info (expr));
13041 sz = ffeinfo_size (ffebld_info (expr));
13042
13043 /* Generate whatever temporaries are needed to represent the result
13044 of the expression. */
13045
47d98fa2
CB
13046 if (bt == FFEINFO_basictypeCHARACTER)
13047 {
13048 while (ffebld_op (expr) == FFEBLD_opPAREN)
13049 expr = ffebld_left (expr);
13050 }
13051
c7e4ee3a 13052 switch (ffebld_op (expr))
5ff904cd 13053 {
c7e4ee3a
CB
13054 default:
13055 /* Don't make temps for SYMTER, CONTER, etc. */
13056 if (ffebld_arity (expr) == 0)
13057 break;
5ff904cd 13058
c7e4ee3a 13059 switch (bt)
5ff904cd 13060 {
c7e4ee3a
CB
13061 case FFEINFO_basictypeCOMPLEX:
13062 if (ffebld_op (expr) == FFEBLD_opFUNCREF)
13063 {
13064 ffesymbol s;
5ff904cd 13065
c7e4ee3a
CB
13066 if (ffebld_op (ffebld_left (expr)) != FFEBLD_opSYMTER)
13067 break;
5ff904cd 13068
c7e4ee3a
CB
13069 s = ffebld_symter (ffebld_left (expr));
13070 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT
13071 || ! ffesymbol_is_f2c (s))
13072 break;
13073 }
13074 else if (ffebld_op (expr) == FFEBLD_opPOWER)
13075 {
13076 /* Requires special treatment. There's no POW_CC function
13077 in libg2c, so POW_ZZ is used, which means we always
13078 need a double-complex temp, not a single-complex. */
13079 kt = FFEINFO_kindtypeREAL2;
13080 }
13081 else if (ffebld_op (expr) != FFEBLD_opDIVIDE)
13082 /* The other ops don't need temps for complex operands. */
13083 break;
5ff904cd 13084
c7e4ee3a
CB
13085 /* ~~~Avoid making temps for some intrinsics, such as AIMAG(C),
13086 REAL(C). See 19990325-0.f, routine `check', for cases. */
13087 tempvar = ffecom_make_tempvar ("complex",
13088 ffecom_tree_type
13089 [FFEINFO_basictypeCOMPLEX][kt],
13090 FFETARGET_charactersizeNONE,
13091 -1);
5ff904cd
JL
13092 break;
13093
c7e4ee3a
CB
13094 case FFEINFO_basictypeCHARACTER:
13095 if (ffebld_op (expr) != FFEBLD_opFUNCREF)
13096 break;
13097
13098 if (sz == FFETARGET_charactersizeNONE)
13099 /* ~~Kludge alert! This should someday be fixed. */
13100 sz = 24;
13101
13102 tempvar = ffecom_make_tempvar ("char", char_type_node, sz, -1);
5ff904cd
JL
13103 break;
13104
13105 default:
5ff904cd
JL
13106 break;
13107 }
c7e4ee3a 13108 break;
5ff904cd 13109
c7e4ee3a
CB
13110#ifdef HAHA
13111 case FFEBLD_opPOWER:
13112 {
13113 tree rtype, ltype;
13114 tree rtmp, ltmp, result;
5ff904cd 13115
c7e4ee3a
CB
13116 ltype = ffecom_type_expr (ffebld_left (expr));
13117 rtype = ffecom_type_expr (ffebld_right (expr));
5ff904cd 13118
c7e4ee3a
CB
13119 rtmp = ffecom_make_tempvar (rtype, FFETARGET_charactersizeNONE, -1);
13120 ltmp = ffecom_make_tempvar (ltype, FFETARGET_charactersizeNONE, -1);
13121 result = ffecom_make_tempvar (ltype, FFETARGET_charactersizeNONE, -1);
5ff904cd 13122
c7e4ee3a
CB
13123 tempvar = make_tree_vec (3);
13124 TREE_VEC_ELT (tempvar, 0) = rtmp;
13125 TREE_VEC_ELT (tempvar, 1) = ltmp;
13126 TREE_VEC_ELT (tempvar, 2) = result;
13127 }
13128 break;
13129#endif /* HAHA */
5ff904cd 13130
c7e4ee3a
CB
13131 case FFEBLD_opCONCATENATE:
13132 {
13133 /* This gets special handling, because only one set of temps
13134 is needed for a tree of these -- the tree is treated as
13135 a flattened list of concatenations when generating code. */
5ff904cd 13136
c7e4ee3a
CB
13137 ffecomConcatList_ catlist;
13138 tree ltmp, itmp, result;
13139 int count;
13140 int i;
5ff904cd 13141
c7e4ee3a
CB
13142 catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
13143 count = ffecom_concat_list_count_ (catlist);
5ff904cd 13144
c7e4ee3a
CB
13145 if (count >= 2)
13146 {
13147 ltmp
13148 = ffecom_make_tempvar ("concat_len",
13149 ffecom_f2c_ftnlen_type_node,
13150 FFETARGET_charactersizeNONE, count);
13151 itmp
13152 = ffecom_make_tempvar ("concat_item",
13153 ffecom_f2c_address_type_node,
13154 FFETARGET_charactersizeNONE, count);
13155 result
13156 = ffecom_make_tempvar ("concat_res",
13157 char_type_node,
13158 ffecom_concat_list_maxlen_ (catlist),
13159 -1);
13160
13161 tempvar = make_tree_vec (3);
13162 TREE_VEC_ELT (tempvar, 0) = ltmp;
13163 TREE_VEC_ELT (tempvar, 1) = itmp;
13164 TREE_VEC_ELT (tempvar, 2) = result;
13165 }
5ff904cd 13166
c7e4ee3a
CB
13167 for (i = 0; i < count; ++i)
13168 ffecom_prepare_arg_ptr_to_expr (ffecom_concat_list_expr_ (catlist,
13169 i));
5ff904cd 13170
c7e4ee3a 13171 ffecom_concat_list_kill_ (catlist);
5ff904cd 13172
c7e4ee3a
CB
13173 if (tempvar)
13174 {
13175 ffebld_nonter_set_hook (expr, tempvar);
13176 current_binding_level->prep_state = 1;
13177 }
13178 }
13179 return;
5ff904cd 13180
c7e4ee3a
CB
13181 case FFEBLD_opCONVERT:
13182 if (bt == FFEINFO_basictypeCHARACTER
13183 && ((ffebld_size_known (ffebld_left (expr))
13184 == FFETARGET_charactersizeNONE)
13185 || (ffebld_size_known (ffebld_left (expr)) >= sz)))
13186 tempvar = ffecom_make_tempvar ("convert", char_type_node, sz, -1);
13187 break;
13188 }
5ff904cd 13189
c7e4ee3a
CB
13190 if (tempvar)
13191 {
13192 ffebld_nonter_set_hook (expr, tempvar);
13193 current_binding_level->prep_state = 1;
13194 }
5ff904cd 13195
c7e4ee3a 13196 /* Prepare subexpressions for this expr. */
5ff904cd 13197
c7e4ee3a 13198 switch (ffebld_op (expr))
5ff904cd 13199 {
c7e4ee3a
CB
13200 case FFEBLD_opPERCENT_LOC:
13201 ffecom_prepare_ptr_to_expr (ffebld_left (expr));
13202 break;
5ff904cd 13203
c7e4ee3a
CB
13204 case FFEBLD_opPERCENT_VAL:
13205 case FFEBLD_opPERCENT_REF:
13206 ffecom_prepare_expr (ffebld_left (expr));
13207 break;
5ff904cd 13208
c7e4ee3a
CB
13209 case FFEBLD_opPERCENT_DESCR:
13210 ffecom_prepare_arg_ptr_to_expr (ffebld_left (expr));
13211 break;
5ff904cd 13212
c7e4ee3a
CB
13213 case FFEBLD_opITEM:
13214 {
13215 ffebld item;
5ff904cd 13216
c7e4ee3a
CB
13217 for (item = expr;
13218 item != NULL;
13219 item = ffebld_trail (item))
13220 if (ffebld_head (item) != NULL)
13221 ffecom_prepare_expr (ffebld_head (item));
13222 }
13223 break;
5ff904cd 13224
c7e4ee3a
CB
13225 default:
13226 /* Need to handle character conversion specially. */
13227 switch (ffebld_arity (expr))
13228 {
13229 case 2:
13230 ffecom_prepare_expr (ffebld_left (expr));
13231 ffecom_prepare_expr (ffebld_right (expr));
13232 break;
5ff904cd 13233
c7e4ee3a
CB
13234 case 1:
13235 ffecom_prepare_expr (ffebld_left (expr));
13236 break;
5ff904cd 13237
c7e4ee3a
CB
13238 default:
13239 break;
13240 }
13241 }
5ff904cd 13242
c7e4ee3a 13243 return;
5ff904cd
JL
13244}
13245
c7e4ee3a 13246/* Prepare expression for reading and writing.
5ff904cd 13247
c7e4ee3a
CB
13248 Like ffecom_prepare_expr, except for expressions to be evaluated
13249 via ffecom_expr_rw. */
5ff904cd 13250
c7e4ee3a
CB
13251void
13252ffecom_prepare_expr_rw (tree type, ffebld expr)
13253{
13254 /* This is all we support for now. */
13255 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
5ff904cd 13256
c7e4ee3a
CB
13257 /* ~~For now, it seems to be the same thing. */
13258 ffecom_prepare_expr (expr);
13259 return;
13260}
5ff904cd 13261
c7e4ee3a 13262/* Prepare expression for writing.
5ff904cd 13263
c7e4ee3a
CB
13264 Like ffecom_prepare_expr, except for expressions to be evaluated
13265 via ffecom_expr_w. */
5ff904cd
JL
13266
13267void
c7e4ee3a 13268ffecom_prepare_expr_w (tree type, ffebld expr)
5ff904cd 13269{
c7e4ee3a
CB
13270 /* This is all we support for now. */
13271 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
5ff904cd 13272
c7e4ee3a
CB
13273 /* ~~For now, it seems to be the same thing. */
13274 ffecom_prepare_expr (expr);
13275 return;
13276}
5ff904cd 13277
c7e4ee3a 13278/* Prepare expression for returning.
5ff904cd 13279
c7e4ee3a
CB
13280 Like ffecom_prepare_expr, except for expressions to be evaluated
13281 via ffecom_return_expr. */
5ff904cd 13282
c7e4ee3a
CB
13283void
13284ffecom_prepare_return_expr (ffebld expr)
13285{
13286 assert (current_binding_level->prep_state < 2);
5ff904cd 13287
c7e4ee3a
CB
13288 if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE
13289 && ffecom_is_altreturning_
13290 && expr != NULL)
13291 ffecom_prepare_expr (expr);
13292}
5ff904cd 13293
c7e4ee3a 13294/* Prepare pointer to expression.
5ff904cd 13295
c7e4ee3a
CB
13296 Like ffecom_prepare_expr, except for expressions to be evaluated
13297 via ffecom_ptr_to_expr. */
5ff904cd 13298
c7e4ee3a
CB
13299void
13300ffecom_prepare_ptr_to_expr (ffebld expr)
13301{
13302 /* ~~For now, it seems to be the same thing. */
13303 ffecom_prepare_expr (expr);
13304 return;
5ff904cd
JL
13305}
13306
c7e4ee3a 13307/* Transform expression into constant pointer-to-expression tree.
5ff904cd 13308
c7e4ee3a
CB
13309 If the expression can be transformed into a pointer-to-expression tree
13310 that is constant, that is done, and the tree returned. Else NULL_TREE
13311 is returned.
5ff904cd 13312
c7e4ee3a
CB
13313 That way, a caller can attempt to provide compile-time initialization
13314 of a variable and, if that fails, *then* choose to start a new block
13315 and resort to using temporaries, as appropriate. */
5ff904cd 13316
c7e4ee3a
CB
13317tree
13318ffecom_ptr_to_const_expr (ffebld expr)
5ff904cd 13319{
c7e4ee3a
CB
13320 if (! expr)
13321 return integer_zero_node;
5ff904cd 13322
c7e4ee3a
CB
13323 if (ffebld_op (expr) == FFEBLD_opANY)
13324 return error_mark_node;
5ff904cd 13325
c7e4ee3a
CB
13326 if (ffebld_arity (expr) == 0
13327 && (ffebld_op (expr) != FFEBLD_opSYMTER
13328 || ffebld_where (expr) == FFEINFO_whereCOMMON
13329 || ffebld_where (expr) == FFEINFO_whereGLOBAL
13330 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
5ff904cd 13331 {
c7e4ee3a
CB
13332 tree t;
13333
13334 t = ffecom_ptr_to_expr (expr);
13335 assert (TREE_CONSTANT (t));
13336 return t;
5ff904cd
JL
13337 }
13338
c7e4ee3a
CB
13339 return NULL_TREE;
13340}
13341
13342/* ffecom_return_expr -- Returns return-value expr given alt return expr
13343
13344 tree rtn; // NULL_TREE means use expand_null_return()
13345 ffebld expr; // NULL if no alt return expr to RETURN stmt
13346 rtn = ffecom_return_expr(expr);
13347
13348 Based on the program unit type and other info (like return function
13349 type, return master function type when alternate ENTRY points,
13350 whether subroutine has any alternate RETURN points, etc), returns the
13351 appropriate expression to be returned to the caller, or NULL_TREE
13352 meaning no return value or the caller expects it to be returned somewhere
13353 else (which is handled by other parts of this module). */
13354
5ff904cd 13355#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
13356tree
13357ffecom_return_expr (ffebld expr)
13358{
13359 tree rtn;
13360
13361 switch (ffecom_primary_entry_kind_)
5ff904cd 13362 {
c7e4ee3a
CB
13363 case FFEINFO_kindPROGRAM:
13364 case FFEINFO_kindBLOCKDATA:
13365 rtn = NULL_TREE;
13366 break;
5ff904cd 13367
c7e4ee3a
CB
13368 case FFEINFO_kindSUBROUTINE:
13369 if (!ffecom_is_altreturning_)
13370 rtn = NULL_TREE; /* No alt returns, never an expr. */
13371 else if (expr == NULL)
13372 rtn = integer_zero_node;
13373 else
13374 rtn = ffecom_expr (expr);
13375 break;
13376
13377 case FFEINFO_kindFUNCTION:
13378 if ((ffecom_multi_retval_ != NULL_TREE)
13379 || (ffesymbol_basictype (ffecom_primary_entry_)
13380 == FFEINFO_basictypeCHARACTER)
13381 || ((ffesymbol_basictype (ffecom_primary_entry_)
13382 == FFEINFO_basictypeCOMPLEX)
13383 && (ffecom_num_entrypoints_ == 0)
13384 && ffesymbol_is_f2c (ffecom_primary_entry_)))
13385 { /* Value is returned by direct assignment
13386 into (implicit) dummy. */
13387 rtn = NULL_TREE;
13388 break;
5ff904cd 13389 }
c7e4ee3a
CB
13390 rtn = ffecom_func_result_;
13391#if 0
13392 /* Spurious error if RETURN happens before first reference! So elide
13393 this code. In particular, for debugging registry, rtn should always
13394 be non-null after all, but TREE_USED won't be set until we encounter
13395 a reference in the code. Perfectly okay (but weird) code that,
13396 e.g., has "GOTO 20;10 RETURN;20 RTN=0;GOTO 10", would result in
13397 this diagnostic for no reason. Have people use -O -Wuninitialized
13398 and leave it to the back end to find obviously weird cases. */
5ff904cd 13399
c7e4ee3a
CB
13400 /* Used to "assert(rtn != NULL_TREE);" here, but it's kind of a valid
13401 situation; if the return value has never been referenced, it won't
13402 have a tree under 2pass mode. */
13403 if ((rtn == NULL_TREE)
13404 || !TREE_USED (rtn))
13405 {
13406 ffebad_start (FFEBAD_RETURN_VALUE_UNSET);
13407 ffebad_here (0, ffesymbol_where_line (ffecom_primary_entry_),
13408 ffesymbol_where_column (ffecom_primary_entry_));
13409 ffebad_string (ffesymbol_text (ffesymbol_funcresult
13410 (ffecom_primary_entry_)));
13411 ffebad_finish ();
13412 }
5ff904cd 13413#endif
c7e4ee3a 13414 break;
5ff904cd 13415
c7e4ee3a
CB
13416 default:
13417 assert ("bad unit kind" == NULL);
13418 case FFEINFO_kindANY:
13419 rtn = error_mark_node;
13420 break;
13421 }
5ff904cd 13422
c7e4ee3a
CB
13423 return rtn;
13424}
5ff904cd 13425
c7e4ee3a
CB
13426#endif
13427/* Do save_expr only if tree is not error_mark_node. */
5ff904cd
JL
13428
13429#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
13430tree
13431ffecom_save_tree (tree t)
5ff904cd 13432{
c7e4ee3a 13433 return save_expr (t);
5ff904cd 13434}
5ff904cd 13435#endif
c7e4ee3a
CB
13436
13437/* Start a compound statement (block). */
5ff904cd
JL
13438
13439#if FFECOM_targetCURRENT == FFECOM_targetGCC
13440void
c7e4ee3a 13441ffecom_start_compstmt (void)
5ff904cd 13442{
c7e4ee3a 13443 bison_rule_pushlevel_ ();
5ff904cd 13444}
c7e4ee3a 13445#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
5ff904cd 13446
c7e4ee3a 13447/* Public entry point for front end to access start_decl. */
5ff904cd
JL
13448
13449#if FFECOM_targetCURRENT == FFECOM_targetGCC
13450tree
c7e4ee3a 13451ffecom_start_decl (tree decl, bool is_initialized)
5ff904cd 13452{
c7e4ee3a
CB
13453 DECL_INITIAL (decl) = is_initialized ? error_mark_node : NULL_TREE;
13454 return start_decl (decl, FALSE);
13455}
5ff904cd 13456
c7e4ee3a
CB
13457#endif
13458/* ffecom_sym_commit -- Symbol's state being committed to reality
5ff904cd 13459
c7e4ee3a
CB
13460 ffesymbol s;
13461 ffecom_sym_commit(s);
5ff904cd 13462
c7e4ee3a
CB
13463 Does whatever the backend needs when a symbol is committed after having
13464 been backtrackable for a period of time. */
5ff904cd 13465
c7e4ee3a
CB
13466#if FFECOM_targetCURRENT == FFECOM_targetGCC
13467void
13468ffecom_sym_commit (ffesymbol s UNUSED)
13469{
13470 assert (!ffesymbol_retractable ());
13471}
5ff904cd 13472
c7e4ee3a
CB
13473#endif
13474/* ffecom_sym_end_transition -- Perform end transition on all symbols
5ff904cd 13475
c7e4ee3a 13476 ffecom_sym_end_transition();
5ff904cd 13477
c7e4ee3a
CB
13478 Does backend-specific stuff and also calls ffest_sym_end_transition
13479 to do the necessary FFE stuff.
5ff904cd 13480
c7e4ee3a
CB
13481 Backtracking is never enabled when this fn is called, so don't worry
13482 about it. */
5ff904cd 13483
c7e4ee3a
CB
13484ffesymbol
13485ffecom_sym_end_transition (ffesymbol s)
13486{
13487 ffestorag st;
5ff904cd 13488
c7e4ee3a 13489 assert (!ffesymbol_retractable ());
5ff904cd 13490
c7e4ee3a 13491 s = ffest_sym_end_transition (s);
5ff904cd 13492
c7e4ee3a
CB
13493#if FFECOM_targetCURRENT == FFECOM_targetGCC
13494 if ((ffesymbol_kind (s) == FFEINFO_kindBLOCKDATA)
13495 && (ffesymbol_where (s) == FFEINFO_whereGLOBAL))
13496 {
13497 ffecom_list_blockdata_
13498 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
13499 FFEINTRIN_specNONE,
13500 FFEINTRIN_impNONE),
13501 ffecom_list_blockdata_);
5ff904cd 13502 }
5ff904cd 13503#endif
5ff904cd 13504
c7e4ee3a
CB
13505 /* This is where we finally notice that a symbol has partial initialization
13506 and finalize it. */
5ff904cd 13507
c7e4ee3a
CB
13508 if (ffesymbol_accretion (s) != NULL)
13509 {
13510 assert (ffesymbol_init (s) == NULL);
13511 ffecom_notify_init_symbol (s);
13512 }
13513 else if (((st = ffesymbol_storage (s)) != NULL)
13514 && ((st = ffestorag_parent (st)) != NULL)
13515 && (ffestorag_accretion (st) != NULL))
13516 {
13517 assert (ffestorag_init (st) == NULL);
13518 ffecom_notify_init_storage (st);
13519 }
5ff904cd
JL
13520
13521#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
13522 if ((ffesymbol_kind (s) == FFEINFO_kindCOMMON)
13523 && (ffesymbol_where (s) == FFEINFO_whereLOCAL)
13524 && (ffesymbol_storage (s) != NULL))
13525 {
13526 ffecom_list_common_
13527 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
13528 FFEINTRIN_specNONE,
13529 FFEINTRIN_impNONE),
13530 ffecom_list_common_);
13531 }
13532#endif
5ff904cd 13533
c7e4ee3a
CB
13534 return s;
13535}
5ff904cd 13536
c7e4ee3a 13537/* ffecom_sym_exec_transition -- Perform exec transition on all symbols
5ff904cd 13538
c7e4ee3a 13539 ffecom_sym_exec_transition();
5ff904cd 13540
c7e4ee3a
CB
13541 Does backend-specific stuff and also calls ffest_sym_exec_transition
13542 to do the necessary FFE stuff.
5ff904cd 13543
c7e4ee3a
CB
13544 See the long-winded description in ffecom_sym_learned for info
13545 on handling the situation where backtracking is inhibited. */
5ff904cd 13546
c7e4ee3a
CB
13547ffesymbol
13548ffecom_sym_exec_transition (ffesymbol s)
13549{
13550 s = ffest_sym_exec_transition (s);
5ff904cd 13551
c7e4ee3a
CB
13552 return s;
13553}
5ff904cd 13554
c7e4ee3a 13555/* ffecom_sym_learned -- Initial or more info gained on symbol after exec
5ff904cd 13556
c7e4ee3a
CB
13557 ffesymbol s;
13558 s = ffecom_sym_learned(s);
5ff904cd 13559
c7e4ee3a
CB
13560 Called when a new symbol is seen after the exec transition or when more
13561 info (perhaps) is gained for an UNCERTAIN symbol. The symbol state when
13562 it arrives here is that all its latest info is updated already, so its
13563 state may be UNCERTAIN or UNDERSTOOD, it might already have the hook
13564 field filled in if its gone through here or exec_transition first, and
13565 so on.
5ff904cd 13566
c7e4ee3a
CB
13567 The backend probably wants to check ffesymbol_retractable() to see if
13568 backtracking is in effect. If so, the FFE's changes to the symbol may
13569 be retracted (undone) or committed (ratified), at which time the
13570 appropriate ffecom_sym_retract or _commit function will be called
13571 for that function.
5ff904cd 13572
c7e4ee3a
CB
13573 If the backend has its own backtracking mechanism, great, use it so that
13574 committal is a simple operation. Though it doesn't make much difference,
13575 I suppose: the reason for tentative symbol evolution in the FFE is to
13576 enable error detection in weird incorrect statements early and to disable
13577 incorrect error detection on a correct statement. The backend is not
13578 likely to introduce any information that'll get involved in these
13579 considerations, so it is probably just fine that the implementation
13580 model for this fn and for _exec_transition is to not do anything
13581 (besides the required FFE stuff) if ffesymbol_retractable() returns TRUE
13582 and instead wait until ffecom_sym_commit is called (which it never
13583 will be as long as we're using ambiguity-detecting statement analysis in
13584 the FFE, which we are initially to shake out the code, but don't depend
13585 on this), otherwise go ahead and do whatever is needed.
5ff904cd 13586
c7e4ee3a
CB
13587 In essence, then, when this fn and _exec_transition get called while
13588 backtracking is enabled, a general mechanism would be to flag which (or
13589 both) of these were called (and in what order? neat question as to what
13590 might happen that I'm too lame to think through right now) and then when
13591 _commit is called reproduce the original calling sequence, if any, for
13592 the two fns (at which point backtracking will, of course, be disabled). */
5ff904cd 13593
c7e4ee3a
CB
13594ffesymbol
13595ffecom_sym_learned (ffesymbol s)
13596{
13597 ffestorag_exec_layout (s);
5ff904cd 13598
c7e4ee3a 13599 return s;
5ff904cd
JL
13600}
13601
c7e4ee3a 13602/* ffecom_sym_retract -- Symbol's state being retracted from reality
5ff904cd 13603
c7e4ee3a
CB
13604 ffesymbol s;
13605 ffecom_sym_retract(s);
5ff904cd 13606
c7e4ee3a
CB
13607 Does whatever the backend needs when a symbol is retracted after having
13608 been backtrackable for a period of time. */
5ff904cd
JL
13609
13610#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
13611void
13612ffecom_sym_retract (ffesymbol s UNUSED)
5ff904cd 13613{
c7e4ee3a 13614 assert (!ffesymbol_retractable ());
5ff904cd 13615
c7e4ee3a
CB
13616#if 0 /* GCC doesn't commit any backtrackable sins,
13617 so nothing needed here. */
13618 switch (ffesymbol_hook (s).state)
5ff904cd 13619 {
c7e4ee3a 13620 case 0: /* nothing happened yet. */
5ff904cd
JL
13621 break;
13622
c7e4ee3a 13623 case 1: /* exec transition happened. */
5ff904cd
JL
13624 break;
13625
c7e4ee3a
CB
13626 case 2: /* learned happened. */
13627 break;
5ff904cd 13628
c7e4ee3a
CB
13629 case 3: /* learned then exec. */
13630 break;
13631
13632 case 4: /* exec then learned. */
5ff904cd
JL
13633 break;
13634
13635 default:
c7e4ee3a 13636 assert ("bad hook state" == NULL);
5ff904cd
JL
13637 break;
13638 }
c7e4ee3a
CB
13639#endif
13640}
5ff904cd 13641
c7e4ee3a
CB
13642#endif
13643/* Create temporary gcc label. */
13644
13645#if FFECOM_targetCURRENT == FFECOM_targetGCC
13646tree
13647ffecom_temp_label ()
13648{
13649 tree glabel;
13650 static int mynumber = 0;
13651
13652 glabel = build_decl (LABEL_DECL,
13653 ffecom_get_invented_identifier ("__g77_label_%d",
13654 NULL,
13655 mynumber++),
13656 void_type_node);
13657 DECL_CONTEXT (glabel) = current_function_decl;
13658 DECL_MODE (glabel) = VOIDmode;
13659
13660 return glabel;
5ff904cd
JL
13661}
13662
13663#endif
c7e4ee3a
CB
13664/* Return an expression that is usable as an arg in a conditional context
13665 (IF, DO WHILE, .NOT., and so on).
13666
13667 Use the one provided for the back end as of >2.6.0. */
5ff904cd
JL
13668
13669#if FFECOM_targetCURRENT == FFECOM_targetGCC
a2977d2d 13670tree
c7e4ee3a 13671ffecom_truth_value (tree expr)
5ff904cd 13672{
c7e4ee3a 13673 return truthvalue_conversion (expr);
5ff904cd 13674}
c7e4ee3a 13675
5ff904cd 13676#endif
c7e4ee3a
CB
13677/* Return the inversion of a truth value (the inversion of what
13678 ffecom_truth_value builds).
5ff904cd 13679
c7e4ee3a
CB
13680 Apparently invert_truthvalue, which is properly in the back end, is
13681 enough for now, so just use it. */
5ff904cd
JL
13682
13683#if FFECOM_targetCURRENT == FFECOM_targetGCC
13684tree
c7e4ee3a 13685ffecom_truth_value_invert (tree expr)
5ff904cd 13686{
c7e4ee3a 13687 return invert_truthvalue (ffecom_truth_value (expr));
5ff904cd
JL
13688}
13689
13690#endif
5ff904cd 13691
c7e4ee3a
CB
13692/* Return the tree that is the type of the expression, as would be
13693 returned in TREE_TYPE(ffecom_expr(expr)), without otherwise
13694 transforming the expression, generating temporaries, etc. */
5ff904cd 13695
c7e4ee3a
CB
13696tree
13697ffecom_type_expr (ffebld expr)
13698{
13699 ffeinfoBasictype bt;
13700 ffeinfoKindtype kt;
13701 tree tree_type;
13702
13703 assert (expr != NULL);
13704
13705 bt = ffeinfo_basictype (ffebld_info (expr));
13706 kt = ffeinfo_kindtype (ffebld_info (expr));
13707 tree_type = ffecom_tree_type[bt][kt];
13708
13709 switch (ffebld_op (expr))
13710 {
13711 case FFEBLD_opCONTER:
13712 case FFEBLD_opSYMTER:
13713 case FFEBLD_opARRAYREF:
13714 case FFEBLD_opUPLUS:
13715 case FFEBLD_opPAREN:
13716 case FFEBLD_opUMINUS:
13717 case FFEBLD_opADD:
13718 case FFEBLD_opSUBTRACT:
13719 case FFEBLD_opMULTIPLY:
13720 case FFEBLD_opDIVIDE:
13721 case FFEBLD_opPOWER:
13722 case FFEBLD_opNOT:
13723 case FFEBLD_opFUNCREF:
13724 case FFEBLD_opSUBRREF:
13725 case FFEBLD_opAND:
13726 case FFEBLD_opOR:
13727 case FFEBLD_opXOR:
13728 case FFEBLD_opNEQV:
13729 case FFEBLD_opEQV:
13730 case FFEBLD_opCONVERT:
13731 case FFEBLD_opLT:
13732 case FFEBLD_opLE:
13733 case FFEBLD_opEQ:
13734 case FFEBLD_opNE:
13735 case FFEBLD_opGT:
13736 case FFEBLD_opGE:
13737 case FFEBLD_opPERCENT_LOC:
13738 return tree_type;
13739
13740 case FFEBLD_opACCTER:
13741 case FFEBLD_opARRTER:
13742 case FFEBLD_opITEM:
13743 case FFEBLD_opSTAR:
13744 case FFEBLD_opBOUNDS:
13745 case FFEBLD_opREPEAT:
13746 case FFEBLD_opLABTER:
13747 case FFEBLD_opLABTOK:
13748 case FFEBLD_opIMPDO:
13749 case FFEBLD_opCONCATENATE:
13750 case FFEBLD_opSUBSTR:
13751 default:
13752 assert ("bad op for ffecom_type_expr" == NULL);
13753 /* Fall through. */
13754 case FFEBLD_opANY:
13755 return error_mark_node;
13756 }
13757}
13758
13759/* Return PARM_DECL for arg#1 of master fn containing alternate ENTRY points
13760
13761 If the PARM_DECL already exists, return it, else create it. It's an
13762 integer_type_node argument for the master function that implements a
13763 subroutine or function with more than one entrypoint and is bound at
13764 run time with the entrypoint number (0 for SUBROUTINE/FUNCTION, 1 for
13765 first ENTRY statement, and so on). */
5ff904cd
JL
13766
13767#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
13768tree
13769ffecom_which_entrypoint_decl ()
5ff904cd 13770{
c7e4ee3a
CB
13771 assert (ffecom_which_entrypoint_decl_ != NULL_TREE);
13772
13773 return ffecom_which_entrypoint_decl_;
5ff904cd
JL
13774}
13775
13776#endif
c7e4ee3a
CB
13777\f
13778/* The following sections consists of private and public functions
13779 that have the same names and perform roughly the same functions
13780 as counterparts in the C front end. Changes in the C front end
13781 might affect how things should be done here. Only functions
13782 needed by the back end should be public here; the rest should
13783 be private (static in the C sense). Functions needed by other
13784 g77 front-end modules should be accessed by them via public
13785 ffecom_* names, which should themselves call private versions
13786 in this section so the private versions are easy to recognize
13787 when upgrading to a new gcc and finding interesting changes
13788 in the front end.
5ff904cd 13789
c7e4ee3a
CB
13790 Functions named after rule "foo:" in c-parse.y are named
13791 "bison_rule_foo_" so they are easy to find. */
5ff904cd 13792
c7e4ee3a 13793#if FFECOM_targetCURRENT == FFECOM_targetGCC
5ff904cd 13794
c7e4ee3a
CB
13795static void
13796bison_rule_pushlevel_ ()
13797{
13798 emit_line_note (input_filename, lineno);
13799 pushlevel (0);
13800 clear_last_expr ();
13801 push_momentary ();
13802 expand_start_bindings (0);
13803}
5ff904cd 13804
c7e4ee3a
CB
13805static tree
13806bison_rule_compstmt_ ()
5ff904cd 13807{
c7e4ee3a
CB
13808 tree t;
13809 int keep = kept_level_p ();
5ff904cd 13810
c7e4ee3a
CB
13811 /* Make the temps go away. */
13812 if (! keep)
13813 current_binding_level->names = NULL_TREE;
5ff904cd 13814
c7e4ee3a
CB
13815 emit_line_note (input_filename, lineno);
13816 expand_end_bindings (getdecls (), keep, 0);
13817 t = poplevel (keep, 1, 0);
13818 pop_momentary ();
5ff904cd 13819
c7e4ee3a
CB
13820 return t;
13821}
5ff904cd 13822
c7e4ee3a
CB
13823/* Return a definition for a builtin function named NAME and whose data type
13824 is TYPE. TYPE should be a function type with argument types.
13825 FUNCTION_CODE tells later passes how to compile calls to this function.
13826 See tree.h for its possible values.
5ff904cd 13827
c7e4ee3a
CB
13828 If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME,
13829 the name to be called if we can't opencode the function. */
5ff904cd 13830
c7e4ee3a
CB
13831static tree
13832builtin_function (const char *name, tree type,
13833 enum built_in_function function_code,
13834 const char *library_name)
13835{
13836 tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
13837 DECL_EXTERNAL (decl) = 1;
13838 TREE_PUBLIC (decl) = 1;
13839 if (library_name)
13840 DECL_ASSEMBLER_NAME (decl) = get_identifier (library_name);
13841 make_decl_rtl (decl, NULL_PTR, 1);
13842 pushdecl (decl);
13843 if (function_code != NOT_BUILT_IN)
5ff904cd 13844 {
c7e4ee3a
CB
13845 DECL_BUILT_IN (decl) = 1;
13846 DECL_FUNCTION_CODE (decl) = function_code;
5ff904cd 13847 }
5ff904cd 13848
c7e4ee3a 13849 return decl;
5ff904cd
JL
13850}
13851
c7e4ee3a
CB
13852/* Handle when a new declaration NEWDECL
13853 has the same name as an old one OLDDECL
13854 in the same binding contour.
13855 Prints an error message if appropriate.
5ff904cd 13856
c7e4ee3a
CB
13857 If safely possible, alter OLDDECL to look like NEWDECL, and return 1.
13858 Otherwise, return 0. */
5ff904cd 13859
c7e4ee3a
CB
13860static int
13861duplicate_decls (tree newdecl, tree olddecl)
5ff904cd 13862{
c7e4ee3a
CB
13863 int types_match = 1;
13864 int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
13865 && DECL_INITIAL (newdecl) != 0);
13866 tree oldtype = TREE_TYPE (olddecl);
13867 tree newtype = TREE_TYPE (newdecl);
5ff904cd 13868
c7e4ee3a
CB
13869 if (olddecl == newdecl)
13870 return 1;
5ff904cd 13871
c7e4ee3a
CB
13872 if (TREE_CODE (newtype) == ERROR_MARK
13873 || TREE_CODE (oldtype) == ERROR_MARK)
13874 types_match = 0;
5ff904cd 13875
c7e4ee3a
CB
13876 /* New decl is completely inconsistent with the old one =>
13877 tell caller to replace the old one.
13878 This is always an error except in the case of shadowing a builtin. */
13879 if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
13880 return 0;
5ff904cd 13881
c7e4ee3a
CB
13882 /* For real parm decl following a forward decl,
13883 return 1 so old decl will be reused. */
13884 if (types_match && TREE_CODE (newdecl) == PARM_DECL
13885 && TREE_ASM_WRITTEN (olddecl) && ! TREE_ASM_WRITTEN (newdecl))
13886 return 1;
5ff904cd 13887
c7e4ee3a
CB
13888 /* The new declaration is the same kind of object as the old one.
13889 The declarations may partially match. Print warnings if they don't
13890 match enough. Ultimately, copy most of the information from the new
13891 decl to the old one, and keep using the old one. */
5ff904cd 13892
c7e4ee3a
CB
13893 if (TREE_CODE (olddecl) == FUNCTION_DECL
13894 && DECL_BUILT_IN (olddecl))
13895 {
13896 /* A function declaration for a built-in function. */
13897 if (!TREE_PUBLIC (newdecl))
13898 return 0;
13899 else if (!types_match)
13900 {
13901 /* Accept the return type of the new declaration if same modes. */
13902 tree oldreturntype = TREE_TYPE (TREE_TYPE (olddecl));
13903 tree newreturntype = TREE_TYPE (TREE_TYPE (newdecl));
5ff904cd 13904
c7e4ee3a
CB
13905 /* Make sure we put the new type in the same obstack as the old ones.
13906 If the old types are not both in the same obstack, use the
13907 permanent one. */
13908 if (TYPE_OBSTACK (oldtype) == TYPE_OBSTACK (newtype))
13909 push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype));
13910 else
13911 {
13912 push_obstacks_nochange ();
13913 end_temporary_allocation ();
13914 }
5ff904cd 13915
c7e4ee3a
CB
13916 if (TYPE_MODE (oldreturntype) == TYPE_MODE (newreturntype))
13917 {
13918 /* Function types may be shared, so we can't just modify
13919 the return type of olddecl's function type. */
13920 tree newtype
13921 = build_function_type (newreturntype,
13922 TYPE_ARG_TYPES (TREE_TYPE (olddecl)));
5ff904cd 13923
c7e4ee3a
CB
13924 types_match = 1;
13925 if (types_match)
13926 TREE_TYPE (olddecl) = newtype;
13927 }
5ff904cd 13928
c7e4ee3a
CB
13929 pop_obstacks ();
13930 }
13931 if (!types_match)
13932 return 0;
13933 }
13934 else if (TREE_CODE (olddecl) == FUNCTION_DECL
13935 && DECL_SOURCE_LINE (olddecl) == 0)
5ff904cd 13936 {
c7e4ee3a
CB
13937 /* A function declaration for a predeclared function
13938 that isn't actually built in. */
13939 if (!TREE_PUBLIC (newdecl))
13940 return 0;
13941 else if (!types_match)
13942 {
13943 /* If the types don't match, preserve volatility indication.
13944 Later on, we will discard everything else about the
13945 default declaration. */
13946 TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
13947 }
13948 }
5ff904cd 13949
c7e4ee3a
CB
13950 /* Copy all the DECL_... slots specified in the new decl
13951 except for any that we copy here from the old type.
5ff904cd 13952
c7e4ee3a
CB
13953 Past this point, we don't change OLDTYPE and NEWTYPE
13954 even if we change the types of NEWDECL and OLDDECL. */
5ff904cd 13955
c7e4ee3a
CB
13956 if (types_match)
13957 {
13958 /* Make sure we put the new type in the same obstack as the old ones.
13959 If the old types are not both in the same obstack, use the permanent
13960 one. */
13961 if (TYPE_OBSTACK (oldtype) == TYPE_OBSTACK (newtype))
13962 push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype));
13963 else
13964 {
13965 push_obstacks_nochange ();
13966 end_temporary_allocation ();
13967 }
5ff904cd 13968
c7e4ee3a
CB
13969 /* Merge the data types specified in the two decls. */
13970 if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl))
13971 TREE_TYPE (newdecl)
13972 = TREE_TYPE (olddecl)
13973 = TREE_TYPE (newdecl);
5ff904cd 13974
c7e4ee3a
CB
13975 /* Lay the type out, unless already done. */
13976 if (oldtype != TREE_TYPE (newdecl))
13977 {
13978 if (TREE_TYPE (newdecl) != error_mark_node)
13979 layout_type (TREE_TYPE (newdecl));
13980 if (TREE_CODE (newdecl) != FUNCTION_DECL
13981 && TREE_CODE (newdecl) != TYPE_DECL
13982 && TREE_CODE (newdecl) != CONST_DECL)
13983 layout_decl (newdecl, 0);
13984 }
13985 else
13986 {
13987 /* Since the type is OLDDECL's, make OLDDECL's size go with. */
13988 DECL_SIZE (newdecl) = DECL_SIZE (olddecl);
13989 if (TREE_CODE (olddecl) != FUNCTION_DECL)
13990 if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
13991 DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
13992 }
5ff904cd 13993
c7e4ee3a
CB
13994 /* Keep the old rtl since we can safely use it. */
13995 DECL_RTL (newdecl) = DECL_RTL (olddecl);
5ff904cd 13996
c7e4ee3a
CB
13997 /* Merge the type qualifiers. */
13998 if (DECL_BUILT_IN_NONANSI (olddecl) && TREE_THIS_VOLATILE (olddecl)
13999 && !TREE_THIS_VOLATILE (newdecl))
14000 TREE_THIS_VOLATILE (olddecl) = 0;
14001 if (TREE_READONLY (newdecl))
14002 TREE_READONLY (olddecl) = 1;
14003 if (TREE_THIS_VOLATILE (newdecl))
14004 {
14005 TREE_THIS_VOLATILE (olddecl) = 1;
14006 if (TREE_CODE (newdecl) == VAR_DECL)
14007 make_var_volatile (newdecl);
14008 }
5ff904cd 14009
c7e4ee3a
CB
14010 /* Keep source location of definition rather than declaration.
14011 Likewise, keep decl at outer scope. */
14012 if ((DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0)
14013 || (DECL_CONTEXT (newdecl) != 0 && DECL_CONTEXT (olddecl) == 0))
14014 {
14015 DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl);
14016 DECL_SOURCE_FILE (newdecl) = DECL_SOURCE_FILE (olddecl);
5ff904cd 14017
c7e4ee3a
CB
14018 if (DECL_CONTEXT (olddecl) == 0
14019 && TREE_CODE (newdecl) != FUNCTION_DECL)
14020 DECL_CONTEXT (newdecl) = 0;
14021 }
5ff904cd 14022
c7e4ee3a
CB
14023 /* Merge the unused-warning information. */
14024 if (DECL_IN_SYSTEM_HEADER (olddecl))
14025 DECL_IN_SYSTEM_HEADER (newdecl) = 1;
14026 else if (DECL_IN_SYSTEM_HEADER (newdecl))
14027 DECL_IN_SYSTEM_HEADER (olddecl) = 1;
5ff904cd 14028
c7e4ee3a
CB
14029 /* Merge the initialization information. */
14030 if (DECL_INITIAL (newdecl) == 0)
14031 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
5ff904cd 14032
c7e4ee3a
CB
14033 /* Merge the section attribute.
14034 We want to issue an error if the sections conflict but that must be
14035 done later in decl_attributes since we are called before attributes
14036 are assigned. */
14037 if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
14038 DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
5ff904cd 14039
c7e4ee3a
CB
14040#if BUILT_FOR_270
14041 if (TREE_CODE (newdecl) == FUNCTION_DECL)
14042 {
14043 DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
14044 DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
14045 }
5ff904cd 14046#endif
5ff904cd 14047
c7e4ee3a
CB
14048 pop_obstacks ();
14049 }
14050 /* If cannot merge, then use the new type and qualifiers,
14051 and don't preserve the old rtl. */
14052 else
14053 {
14054 TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
14055 TREE_READONLY (olddecl) = TREE_READONLY (newdecl);
14056 TREE_THIS_VOLATILE (olddecl) = TREE_THIS_VOLATILE (newdecl);
14057 TREE_SIDE_EFFECTS (olddecl) = TREE_SIDE_EFFECTS (newdecl);
14058 }
5ff904cd 14059
c7e4ee3a
CB
14060 /* Merge the storage class information. */
14061 /* For functions, static overrides non-static. */
14062 if (TREE_CODE (newdecl) == FUNCTION_DECL)
14063 {
14064 TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl);
14065 /* This is since we don't automatically
14066 copy the attributes of NEWDECL into OLDDECL. */
14067 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
14068 /* If this clears `static', clear it in the identifier too. */
14069 if (! TREE_PUBLIC (olddecl))
14070 TREE_PUBLIC (DECL_NAME (olddecl)) = 0;
14071 }
14072 if (DECL_EXTERNAL (newdecl))
14073 {
14074 TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
14075 DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
14076 /* An extern decl does not override previous storage class. */
14077 TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
14078 }
14079 else
14080 {
14081 TREE_STATIC (olddecl) = TREE_STATIC (newdecl);
14082 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
14083 }
5ff904cd 14084
c7e4ee3a
CB
14085 /* If either decl says `inline', this fn is inline,
14086 unless its definition was passed already. */
14087 if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == 0)
14088 DECL_INLINE (olddecl) = 1;
14089 DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
5ff904cd 14090
c7e4ee3a
CB
14091 /* Get rid of any built-in function if new arg types don't match it
14092 or if we have a function definition. */
14093 if (TREE_CODE (newdecl) == FUNCTION_DECL
14094 && DECL_BUILT_IN (olddecl)
14095 && (!types_match || new_is_definition))
14096 {
14097 TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
14098 DECL_BUILT_IN (olddecl) = 0;
14099 }
5ff904cd 14100
c7e4ee3a
CB
14101 /* If redeclaring a builtin function, and not a definition,
14102 it stays built in.
14103 Also preserve various other info from the definition. */
14104 if (TREE_CODE (newdecl) == FUNCTION_DECL && !new_is_definition)
14105 {
14106 if (DECL_BUILT_IN (olddecl))
14107 {
14108 DECL_BUILT_IN (newdecl) = 1;
14109 DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
14110 }
14111 else
14112 DECL_FRAME_SIZE (newdecl) = DECL_FRAME_SIZE (olddecl);
5ff904cd 14113
c7e4ee3a
CB
14114 DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
14115 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
14116 DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
14117 DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
14118 }
5ff904cd 14119
c7e4ee3a
CB
14120 /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
14121 But preserve olddecl's DECL_UID. */
14122 {
14123 register unsigned olddecl_uid = DECL_UID (olddecl);
5ff904cd 14124
c7e4ee3a
CB
14125 memcpy ((char *) olddecl + sizeof (struct tree_common),
14126 (char *) newdecl + sizeof (struct tree_common),
14127 sizeof (struct tree_decl) - sizeof (struct tree_common));
14128 DECL_UID (olddecl) = olddecl_uid;
14129 }
5ff904cd 14130
c7e4ee3a 14131 return 1;
5ff904cd
JL
14132}
14133
c7e4ee3a
CB
14134/* Finish processing of a declaration;
14135 install its initial value.
14136 If the length of an array type is not known before,
14137 it must be determined now, from the initial value, or it is an error. */
14138
5ff904cd 14139static void
c7e4ee3a 14140finish_decl (tree decl, tree init, bool is_top_level)
5ff904cd 14141{
c7e4ee3a
CB
14142 register tree type = TREE_TYPE (decl);
14143 int was_incomplete = (DECL_SIZE (decl) == 0);
14144 int temporary = allocation_temporary_p ();
14145 bool at_top_level = (current_binding_level == global_binding_level);
14146 bool top_level = is_top_level || at_top_level;
5ff904cd 14147
c7e4ee3a
CB
14148 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
14149 level anyway. */
14150 assert (!is_top_level || !at_top_level);
5ff904cd 14151
c7e4ee3a
CB
14152 if (TREE_CODE (decl) == PARM_DECL)
14153 assert (init == NULL_TREE);
14154 /* Remember that PARM_DECL doesn't have a DECL_INITIAL field per se -- it
14155 overlaps DECL_ARG_TYPE. */
14156 else if (init == NULL_TREE)
14157 assert (DECL_INITIAL (decl) == NULL_TREE);
14158 else
14159 assert (DECL_INITIAL (decl) == error_mark_node);
5ff904cd 14160
c7e4ee3a 14161 if (init != NULL_TREE)
5ff904cd 14162 {
c7e4ee3a
CB
14163 if (TREE_CODE (decl) != TYPE_DECL)
14164 DECL_INITIAL (decl) = init;
14165 else
14166 {
14167 /* typedef foo = bar; store the type of bar as the type of foo. */
14168 TREE_TYPE (decl) = TREE_TYPE (init);
14169 DECL_INITIAL (decl) = init = 0;
14170 }
5ff904cd
JL
14171 }
14172
c7e4ee3a
CB
14173 /* Pop back to the obstack that is current for this binding level. This is
14174 because MAXINDEX, rtl, etc. to be made below must go in the permanent
14175 obstack. But don't discard the temporary data yet. */
14176 pop_obstacks ();
5ff904cd 14177
c7e4ee3a 14178 /* Deduce size of array from initialization, if not already known */
5ff904cd 14179
c7e4ee3a
CB
14180 if (TREE_CODE (type) == ARRAY_TYPE
14181 && TYPE_DOMAIN (type) == 0
14182 && TREE_CODE (decl) != TYPE_DECL)
14183 {
14184 assert (top_level);
14185 assert (was_incomplete);
5ff904cd 14186
c7e4ee3a
CB
14187 layout_decl (decl, 0);
14188 }
5ff904cd 14189
c7e4ee3a
CB
14190 if (TREE_CODE (decl) == VAR_DECL)
14191 {
14192 if (DECL_SIZE (decl) == NULL_TREE
14193 && TYPE_SIZE (TREE_TYPE (decl)) != NULL_TREE)
14194 layout_decl (decl, 0);
5ff904cd 14195
c7e4ee3a
CB
14196 if (DECL_SIZE (decl) == NULL_TREE
14197 && (TREE_STATIC (decl)
14198 ?
14199 /* A static variable with an incomplete type is an error if it is
14200 initialized. Also if it is not file scope. Otherwise, let it
14201 through, but if it is not `extern' then it may cause an error
14202 message later. */
14203 (DECL_INITIAL (decl) != 0 || DECL_CONTEXT (decl) != 0)
14204 :
14205 /* An automatic variable with an incomplete type is an error. */
14206 !DECL_EXTERNAL (decl)))
14207 {
14208 assert ("storage size not known" == NULL);
14209 abort ();
14210 }
5ff904cd 14211
c7e4ee3a
CB
14212 if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
14213 && (DECL_SIZE (decl) != 0)
14214 && (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST))
14215 {
14216 assert ("storage size not constant" == NULL);
14217 abort ();
14218 }
14219 }
5ff904cd 14220
c7e4ee3a
CB
14221 /* Output the assembler code and/or RTL code for variables and functions,
14222 unless the type is an undefined structure or union. If not, it will get
14223 done when the type is completed. */
5ff904cd 14224
c7e4ee3a 14225 if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
5ff904cd 14226 {
c7e4ee3a
CB
14227 rest_of_decl_compilation (decl, NULL,
14228 DECL_CONTEXT (decl) == 0,
14229 0);
5ff904cd 14230
c7e4ee3a
CB
14231 if (DECL_CONTEXT (decl) != 0)
14232 {
14233 /* Recompute the RTL of a local array now if it used to be an
14234 incomplete type. */
14235 if (was_incomplete
14236 && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
5ff904cd 14237 {
c7e4ee3a
CB
14238 /* If we used it already as memory, it must stay in memory. */
14239 TREE_ADDRESSABLE (decl) = TREE_USED (decl);
14240 /* If it's still incomplete now, no init will save it. */
14241 if (DECL_SIZE (decl) == 0)
14242 DECL_INITIAL (decl) = 0;
14243 expand_decl (decl);
5ff904cd 14244 }
c7e4ee3a
CB
14245 /* Compute and store the initial value. */
14246 if (TREE_CODE (decl) != FUNCTION_DECL)
14247 expand_decl_init (decl);
14248 }
14249 }
14250 else if (TREE_CODE (decl) == TYPE_DECL)
14251 {
14252 rest_of_decl_compilation (decl, NULL_PTR,
14253 DECL_CONTEXT (decl) == 0,
14254 0);
14255 }
5ff904cd 14256
c7e4ee3a
CB
14257 /* This test used to include TREE_PERMANENT, however, we have the same
14258 problem with initializers at the function level. Such initializers get
14259 saved until the end of the function on the momentary_obstack. */
14260 if (!(TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl))
14261 && temporary
14262 /* DECL_INITIAL is not defined in PARM_DECLs, since it shares space with
14263 DECL_ARG_TYPE. */
14264 && TREE_CODE (decl) != PARM_DECL)
14265 {
14266 /* We need to remember that this array HAD an initialization, but
14267 discard the actual temporary nodes, since we can't have a permanent
14268 node keep pointing to them. */
14269 /* We make an exception for inline functions, since it's normal for a
14270 local extern redeclaration of an inline function to have a copy of
14271 the top-level decl's DECL_INLINE. */
14272 if ((DECL_INITIAL (decl) != 0)
14273 && (DECL_INITIAL (decl) != error_mark_node))
14274 {
14275 /* If this is a const variable, then preserve the
14276 initializer instead of discarding it so that we can optimize
14277 references to it. */
14278 /* This test used to include TREE_STATIC, but this won't be set
14279 for function level initializers. */
14280 if (TREE_READONLY (decl))
5ff904cd 14281 {
c7e4ee3a
CB
14282 preserve_initializer ();
14283 /* Hack? Set the permanent bit for something that is
14284 permanent, but not on the permenent obstack, so as to
14285 convince output_constant_def to make its rtl on the
14286 permanent obstack. */
14287 TREE_PERMANENT (DECL_INITIAL (decl)) = 1;
5ff904cd 14288
c7e4ee3a
CB
14289 /* The initializer and DECL must have the same (or equivalent
14290 types), but if the initializer is a STRING_CST, its type
14291 might not be on the right obstack, so copy the type
14292 of DECL. */
14293 TREE_TYPE (DECL_INITIAL (decl)) = type;
5ff904cd 14294 }
c7e4ee3a
CB
14295 else
14296 DECL_INITIAL (decl) = error_mark_node;
5ff904cd 14297 }
5ff904cd 14298 }
c7e4ee3a
CB
14299
14300 /* If requested, warn about definitions of large data objects. */
14301
14302 if (warn_larger_than
14303 && (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
14304 && !DECL_EXTERNAL (decl))
5ff904cd 14305 {
c7e4ee3a
CB
14306 register tree decl_size = DECL_SIZE (decl);
14307
14308 if (decl_size && TREE_CODE (decl_size) == INTEGER_CST)
5ff904cd 14309 {
c7e4ee3a
CB
14310 unsigned units = TREE_INT_CST_LOW (decl_size) / BITS_PER_UNIT;
14311
14312 if (units > larger_than_size)
14313 warning_with_decl (decl, "size of `%s' is %u bytes", units);
5ff904cd
JL
14314 }
14315 }
14316
c7e4ee3a
CB
14317 /* If we have gone back from temporary to permanent allocation, actually
14318 free the temporary space that we no longer need. */
14319 if (temporary && !allocation_temporary_p ())
14320 permanent_allocation (0);
5ff904cd 14321
c7e4ee3a
CB
14322 /* At the end of a declaration, throw away any variable type sizes of types
14323 defined inside that declaration. There is no use computing them in the
14324 following function definition. */
14325 if (current_binding_level == global_binding_level)
14326 get_pending_sizes ();
14327}
5ff904cd 14328
c7e4ee3a
CB
14329/* Finish up a function declaration and compile that function
14330 all the way to assembler language output. The free the storage
14331 for the function definition.
5ff904cd 14332
c7e4ee3a 14333 This is called after parsing the body of the function definition.
5ff904cd 14334
c7e4ee3a
CB
14335 NESTED is nonzero if the function being finished is nested in another. */
14336
14337static void
14338finish_function (int nested)
14339{
14340 register tree fndecl = current_function_decl;
14341
14342 assert (fndecl != NULL_TREE);
14343 if (TREE_CODE (fndecl) != ERROR_MARK)
14344 {
14345 if (nested)
14346 assert (DECL_CONTEXT (fndecl) != NULL_TREE);
5ff904cd 14347 else
c7e4ee3a
CB
14348 assert (DECL_CONTEXT (fndecl) == NULL_TREE);
14349 }
5ff904cd 14350
c7e4ee3a
CB
14351/* TREE_READONLY (fndecl) = 1;
14352 This caused &foo to be of type ptr-to-const-function
14353 which then got a warning when stored in a ptr-to-function variable. */
5ff904cd 14354
c7e4ee3a 14355 poplevel (1, 0, 1);
5ff904cd 14356
c7e4ee3a
CB
14357 if (TREE_CODE (fndecl) != ERROR_MARK)
14358 {
14359 BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
5ff904cd 14360
c7e4ee3a 14361 /* Must mark the RESULT_DECL as being in this function. */
5ff904cd 14362
c7e4ee3a 14363 DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
5ff904cd 14364
c7e4ee3a
CB
14365 /* Obey `register' declarations if `setjmp' is called in this fn. */
14366 /* Generate rtl for function exit. */
14367 expand_function_end (input_filename, lineno, 0);
5ff904cd 14368
c7e4ee3a
CB
14369 /* So we can tell if jump_optimize sets it to 1. */
14370 can_reach_end = 0;
5ff904cd 14371
c7e4ee3a
CB
14372 /* Run the optimizers and output the assembler code for this function. */
14373 rest_of_compilation (fndecl);
14374 }
5ff904cd 14375
c7e4ee3a
CB
14376 /* Free all the tree nodes making up this function. */
14377 /* Switch back to allocating nodes permanently until we start another
14378 function. */
14379 if (!nested)
14380 permanent_allocation (1);
14381
14382 if (TREE_CODE (fndecl) != ERROR_MARK
14383 && !nested
14384 && DECL_SAVED_INSNS (fndecl) == 0)
14385 {
14386 /* Stop pointing to the local nodes about to be freed. */
14387 /* But DECL_INITIAL must remain nonzero so we know this was an actual
14388 function definition. */
14389 /* For a nested function, this is done in pop_f_function_context. */
14390 /* If rest_of_compilation set this to 0, leave it 0. */
14391 if (DECL_INITIAL (fndecl) != 0)
14392 DECL_INITIAL (fndecl) = error_mark_node;
14393 DECL_ARGUMENTS (fndecl) = 0;
5ff904cd 14394 }
c7e4ee3a
CB
14395
14396 if (!nested)
5ff904cd 14397 {
c7e4ee3a
CB
14398 /* Let the error reporting routines know that we're outside a function.
14399 For a nested function, this value is used in pop_c_function_context
14400 and then reset via pop_function_context. */
14401 ffecom_outer_function_decl_ = current_function_decl = NULL;
5ff904cd 14402 }
c7e4ee3a 14403}
5ff904cd 14404
c7e4ee3a
CB
14405/* Plug-in replacement for identifying the name of a decl and, for a
14406 function, what we call it in diagnostics. For now, "program unit"
14407 should suffice, since it's a bit of a hassle to figure out which
14408 of several kinds of things it is. Note that it could conceivably
14409 be a statement function, which probably isn't really a program unit
14410 per se, but if that comes up, it should be easy to check (being a
14411 nested function and all). */
14412
14413static char *
14414lang_printable_name (tree decl, int v)
14415{
14416 /* Just to keep GCC quiet about the unused variable.
14417 In theory, differing values of V should produce different
14418 output. */
14419 switch (v)
5ff904cd 14420 {
c7e4ee3a
CB
14421 default:
14422 if (TREE_CODE (decl) == ERROR_MARK)
14423 return "erroneous code";
14424 return IDENTIFIER_POINTER (DECL_NAME (decl));
5ff904cd 14425 }
c7e4ee3a
CB
14426}
14427
14428/* g77's function to print out name of current function that caused
14429 an error. */
14430
14431#if BUILT_FOR_270
14432void
14433lang_print_error_function (file)
14434 char *file;
14435{
14436 static ffeglobal last_g = NULL;
14437 static ffesymbol last_s = NULL;
14438 ffeglobal g;
14439 ffesymbol s;
14440 const char *kind;
14441
14442 if ((ffecom_primary_entry_ == NULL)
14443 || (ffesymbol_global (ffecom_primary_entry_) == NULL))
5ff904cd 14444 {
c7e4ee3a
CB
14445 g = NULL;
14446 s = NULL;
14447 kind = NULL;
5ff904cd
JL
14448 }
14449 else
14450 {
c7e4ee3a
CB
14451 g = ffesymbol_global (ffecom_primary_entry_);
14452 if (ffecom_nested_entry_ == NULL)
14453 {
14454 s = ffecom_primary_entry_;
14455 switch (ffesymbol_kind (s))
14456 {
14457 case FFEINFO_kindFUNCTION:
14458 kind = "function";
14459 break;
5ff904cd 14460
c7e4ee3a
CB
14461 case FFEINFO_kindSUBROUTINE:
14462 kind = "subroutine";
14463 break;
5ff904cd 14464
c7e4ee3a
CB
14465 case FFEINFO_kindPROGRAM:
14466 kind = "program";
14467 break;
14468
14469 case FFEINFO_kindBLOCKDATA:
14470 kind = "block-data";
14471 break;
14472
14473 default:
14474 kind = ffeinfo_kind_message (ffesymbol_kind (s));
14475 break;
14476 }
14477 }
14478 else
14479 {
14480 s = ffecom_nested_entry_;
14481 kind = "statement function";
14482 }
5ff904cd
JL
14483 }
14484
c7e4ee3a 14485 if ((last_g != g) || (last_s != s))
5ff904cd 14486 {
c7e4ee3a
CB
14487 if (file)
14488 fprintf (stderr, "%s: ", file);
14489
14490 if (s == NULL)
14491 fprintf (stderr, "Outside of any program unit:\n");
14492 else
5ff904cd 14493 {
c7e4ee3a
CB
14494 const char *name = ffesymbol_text (s);
14495
14496 fprintf (stderr, "In %s `%s':\n", kind, name);
5ff904cd 14497 }
5ff904cd 14498
c7e4ee3a
CB
14499 last_g = g;
14500 last_s = s;
5ff904cd 14501 }
c7e4ee3a
CB
14502}
14503#endif
5ff904cd 14504
c7e4ee3a 14505/* Similar to `lookup_name' but look only at current binding level. */
5ff904cd 14506
c7e4ee3a
CB
14507static tree
14508lookup_name_current_level (tree name)
14509{
14510 register tree t;
5ff904cd 14511
c7e4ee3a
CB
14512 if (current_binding_level == global_binding_level)
14513 return IDENTIFIER_GLOBAL_VALUE (name);
14514
14515 if (IDENTIFIER_LOCAL_VALUE (name) == 0)
14516 return 0;
14517
14518 for (t = current_binding_level->names; t; t = TREE_CHAIN (t))
14519 if (DECL_NAME (t) == name)
14520 break;
14521
14522 return t;
5ff904cd
JL
14523}
14524
c7e4ee3a 14525/* Create a new `struct binding_level'. */
5ff904cd 14526
c7e4ee3a
CB
14527static struct binding_level *
14528make_binding_level ()
5ff904cd 14529{
c7e4ee3a
CB
14530 /* NOSTRICT */
14531 return (struct binding_level *) xmalloc (sizeof (struct binding_level));
14532}
5ff904cd 14533
c7e4ee3a
CB
14534/* Save and restore the variables in this file and elsewhere
14535 that keep track of the progress of compilation of the current function.
14536 Used for nested functions. */
5ff904cd 14537
c7e4ee3a
CB
14538struct f_function
14539{
14540 struct f_function *next;
14541 tree named_labels;
14542 tree shadowed_labels;
14543 struct binding_level *binding_level;
14544};
5ff904cd 14545
c7e4ee3a 14546struct f_function *f_function_chain;
5ff904cd 14547
c7e4ee3a 14548/* Restore the variables used during compilation of a C function. */
5ff904cd 14549
c7e4ee3a
CB
14550static void
14551pop_f_function_context ()
14552{
14553 struct f_function *p = f_function_chain;
14554 tree link;
5ff904cd 14555
c7e4ee3a
CB
14556 /* Bring back all the labels that were shadowed. */
14557 for (link = shadowed_labels; link; link = TREE_CHAIN (link))
14558 if (DECL_NAME (TREE_VALUE (link)) != 0)
14559 IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)))
14560 = TREE_VALUE (link);
5ff904cd 14561
c7e4ee3a
CB
14562 if (current_function_decl != error_mark_node
14563 && DECL_SAVED_INSNS (current_function_decl) == 0)
14564 {
14565 /* Stop pointing to the local nodes about to be freed. */
14566 /* But DECL_INITIAL must remain nonzero so we know this was an actual
14567 function definition. */
14568 DECL_INITIAL (current_function_decl) = error_mark_node;
14569 DECL_ARGUMENTS (current_function_decl) = 0;
5ff904cd
JL
14570 }
14571
c7e4ee3a 14572 pop_function_context ();
5ff904cd 14573
c7e4ee3a 14574 f_function_chain = p->next;
5ff904cd 14575
c7e4ee3a
CB
14576 named_labels = p->named_labels;
14577 shadowed_labels = p->shadowed_labels;
14578 current_binding_level = p->binding_level;
5ff904cd 14579
c7e4ee3a
CB
14580 free (p);
14581}
5ff904cd 14582
c7e4ee3a
CB
14583/* Save and reinitialize the variables
14584 used during compilation of a C function. */
5ff904cd 14585
c7e4ee3a
CB
14586static void
14587push_f_function_context ()
14588{
14589 struct f_function *p
14590 = (struct f_function *) xmalloc (sizeof (struct f_function));
5ff904cd 14591
c7e4ee3a
CB
14592 push_function_context ();
14593
14594 p->next = f_function_chain;
14595 f_function_chain = p;
14596
14597 p->named_labels = named_labels;
14598 p->shadowed_labels = shadowed_labels;
14599 p->binding_level = current_binding_level;
14600}
5ff904cd 14601
c7e4ee3a
CB
14602static void
14603push_parm_decl (tree parm)
14604{
14605 int old_immediate_size_expand = immediate_size_expand;
5ff904cd 14606
c7e4ee3a 14607 /* Don't try computing parm sizes now -- wait till fn is called. */
5ff904cd 14608
c7e4ee3a 14609 immediate_size_expand = 0;
5ff904cd 14610
c7e4ee3a 14611 push_obstacks_nochange ();
5ff904cd 14612
c7e4ee3a 14613 /* Fill in arg stuff. */
5ff904cd 14614
c7e4ee3a
CB
14615 DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
14616 DECL_ARG_TYPE_AS_WRITTEN (parm) = TREE_TYPE (parm);
14617 TREE_READONLY (parm) = 1; /* All implementation args are read-only. */
5ff904cd 14618
c7e4ee3a
CB
14619 parm = pushdecl (parm);
14620
14621 immediate_size_expand = old_immediate_size_expand;
14622
14623 finish_decl (parm, NULL_TREE, FALSE);
5ff904cd
JL
14624}
14625
c7e4ee3a 14626/* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL, if appropriate. */
5ff904cd 14627
c7e4ee3a
CB
14628static tree
14629pushdecl_top_level (x)
14630 tree x;
14631{
14632 register tree t;
14633 register struct binding_level *b = current_binding_level;
14634 register tree f = current_function_decl;
5ff904cd 14635
c7e4ee3a
CB
14636 current_binding_level = global_binding_level;
14637 current_function_decl = NULL_TREE;
14638 t = pushdecl (x);
14639 current_binding_level = b;
14640 current_function_decl = f;
14641 return t;
14642}
14643
14644/* Store the list of declarations of the current level.
14645 This is done for the parameter declarations of a function being defined,
14646 after they are modified in the light of any missing parameters. */
14647
14648static tree
14649storedecls (decls)
14650 tree decls;
14651{
14652 return current_binding_level->names = decls;
14653}
14654
14655/* Store the parameter declarations into the current function declaration.
14656 This is called after parsing the parameter declarations, before
14657 digesting the body of the function.
14658
14659 For an old-style definition, modify the function's type
14660 to specify at least the number of arguments. */
5ff904cd
JL
14661
14662static void
c7e4ee3a 14663store_parm_decls (int is_main_program UNUSED)
5ff904cd
JL
14664{
14665 register tree fndecl = current_function_decl;
14666
c7e4ee3a
CB
14667 if (fndecl == error_mark_node)
14668 return;
5ff904cd 14669
c7e4ee3a
CB
14670 /* This is a chain of PARM_DECLs from old-style parm declarations. */
14671 DECL_ARGUMENTS (fndecl) = storedecls (nreverse (getdecls ()));
5ff904cd 14672
c7e4ee3a 14673 /* Initialize the RTL code for the function. */
5ff904cd 14674
c7e4ee3a 14675 init_function_start (fndecl, input_filename, lineno);
56a0044b 14676
c7e4ee3a 14677 /* Set up parameters and prepare for return, for the function. */
5ff904cd 14678
c7e4ee3a
CB
14679 expand_function_start (fndecl, 0);
14680}
5ff904cd 14681
c7e4ee3a
CB
14682static tree
14683start_decl (tree decl, bool is_top_level)
14684{
14685 register tree tem;
14686 bool at_top_level = (current_binding_level == global_binding_level);
14687 bool top_level = is_top_level || at_top_level;
5ff904cd 14688
c7e4ee3a
CB
14689 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
14690 level anyway. */
14691 assert (!is_top_level || !at_top_level);
5ff904cd 14692
c7e4ee3a
CB
14693 /* The corresponding pop_obstacks is in finish_decl. */
14694 push_obstacks_nochange ();
14695
14696 if (DECL_INITIAL (decl) != NULL_TREE)
14697 {
14698 assert (DECL_INITIAL (decl) == error_mark_node);
14699 assert (!DECL_EXTERNAL (decl));
56a0044b 14700 }
c7e4ee3a
CB
14701 else if (top_level)
14702 assert ((TREE_STATIC (decl) == 1) || DECL_EXTERNAL (decl) == 1);
5ff904cd 14703
c7e4ee3a
CB
14704 /* For Fortran, we by default put things in .common when possible. */
14705 DECL_COMMON (decl) = 1;
5ff904cd 14706
c7e4ee3a
CB
14707 /* Add this decl to the current binding level. TEM may equal DECL or it may
14708 be a previous decl of the same name. */
14709 if (is_top_level)
14710 tem = pushdecl_top_level (decl);
14711 else
14712 tem = pushdecl (decl);
14713
14714 /* For a local variable, define the RTL now. */
14715 if (!top_level
14716 /* But not if this is a duplicate decl and we preserved the rtl from the
14717 previous one (which may or may not happen). */
14718 && DECL_RTL (tem) == 0)
5ff904cd 14719 {
c7e4ee3a
CB
14720 if (TYPE_SIZE (TREE_TYPE (tem)) != 0)
14721 expand_decl (tem);
14722 else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
14723 && DECL_INITIAL (tem) != 0)
14724 expand_decl (tem);
5ff904cd
JL
14725 }
14726
c7e4ee3a 14727 if (DECL_INITIAL (tem) != NULL_TREE)
5ff904cd 14728 {
c7e4ee3a
CB
14729 /* When parsing and digesting the initializer, use temporary storage.
14730 Do this even if we will ignore the value. */
14731 if (at_top_level)
14732 temporary_allocation ();
5ff904cd 14733 }
c7e4ee3a
CB
14734
14735 return tem;
5ff904cd
JL
14736}
14737
c7e4ee3a
CB
14738/* Create the FUNCTION_DECL for a function definition.
14739 DECLSPECS and DECLARATOR are the parts of the declaration;
14740 they describe the function's name and the type it returns,
14741 but twisted together in a fashion that parallels the syntax of C.
5ff904cd 14742
c7e4ee3a
CB
14743 This function creates a binding context for the function body
14744 as well as setting up the FUNCTION_DECL in current_function_decl.
5ff904cd 14745
c7e4ee3a
CB
14746 Returns 1 on success. If the DECLARATOR is not suitable for a function
14747 (it defines a datum instead), we return 0, which tells
14748 yyparse to report a parse error.
5ff904cd 14749
c7e4ee3a
CB
14750 NESTED is nonzero for a function nested within another function. */
14751
14752static void
14753start_function (tree name, tree type, int nested, int public)
5ff904cd 14754{
c7e4ee3a
CB
14755 tree decl1;
14756 tree restype;
14757 int old_immediate_size_expand = immediate_size_expand;
5ff904cd 14758
c7e4ee3a
CB
14759 named_labels = 0;
14760 shadowed_labels = 0;
14761
14762 /* Don't expand any sizes in the return type of the function. */
14763 immediate_size_expand = 0;
14764
14765 if (nested)
5ff904cd 14766 {
c7e4ee3a
CB
14767 assert (!public);
14768 assert (current_function_decl != NULL_TREE);
14769 assert (DECL_CONTEXT (current_function_decl) == NULL_TREE);
14770 }
14771 else
14772 {
14773 assert (current_function_decl == NULL_TREE);
5ff904cd 14774 }
c7e4ee3a
CB
14775
14776 if (TREE_CODE (type) == ERROR_MARK)
14777 decl1 = current_function_decl = error_mark_node;
56a0044b 14778 else
5ff904cd 14779 {
c7e4ee3a
CB
14780 decl1 = build_decl (FUNCTION_DECL,
14781 name,
14782 type);
14783 TREE_PUBLIC (decl1) = public ? 1 : 0;
14784 if (nested)
14785 DECL_INLINE (decl1) = 1;
14786 TREE_STATIC (decl1) = 1;
14787 DECL_EXTERNAL (decl1) = 0;
5ff904cd 14788
c7e4ee3a 14789 announce_function (decl1);
5ff904cd 14790
c7e4ee3a
CB
14791 /* Make the init_value nonzero so pushdecl knows this is not tentative.
14792 error_mark_node is replaced below (in poplevel) with the BLOCK. */
14793 DECL_INITIAL (decl1) = error_mark_node;
5ff904cd 14794
c7e4ee3a
CB
14795 /* Record the decl so that the function name is defined. If we already have
14796 a decl for this name, and it is a FUNCTION_DECL, use the old decl. */
5ff904cd 14797
c7e4ee3a 14798 current_function_decl = pushdecl (decl1);
5ff904cd
JL
14799 }
14800
c7e4ee3a
CB
14801 if (!nested)
14802 ffecom_outer_function_decl_ = current_function_decl;
5ff904cd 14803
c7e4ee3a
CB
14804 pushlevel (0);
14805 current_binding_level->prep_state = 2;
5ff904cd 14806
c7e4ee3a
CB
14807 if (TREE_CODE (current_function_decl) != ERROR_MARK)
14808 {
14809 make_function_rtl (current_function_decl);
5ff904cd 14810
c7e4ee3a
CB
14811 restype = TREE_TYPE (TREE_TYPE (current_function_decl));
14812 DECL_RESULT (current_function_decl)
14813 = build_decl (RESULT_DECL, NULL_TREE, restype);
5ff904cd 14814 }
5ff904cd 14815
c7e4ee3a
CB
14816 if (!nested)
14817 /* Allocate further tree nodes temporarily during compilation of this
14818 function only. */
14819 temporary_allocation ();
5ff904cd 14820
c7e4ee3a
CB
14821 if (!nested && (TREE_CODE (current_function_decl) != ERROR_MARK))
14822 TREE_ADDRESSABLE (current_function_decl) = 1;
14823
14824 immediate_size_expand = old_immediate_size_expand;
14825}
14826\f
14827/* Here are the public functions the GNU back end needs. */
14828
14829tree
14830convert (type, expr)
14831 tree type, expr;
5ff904cd 14832{
c7e4ee3a
CB
14833 register tree e = expr;
14834 register enum tree_code code = TREE_CODE (type);
5ff904cd 14835
c7e4ee3a
CB
14836 if (type == TREE_TYPE (e)
14837 || TREE_CODE (e) == ERROR_MARK)
14838 return e;
14839 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
14840 return fold (build1 (NOP_EXPR, type, e));
14841 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
14842 || code == ERROR_MARK)
14843 return error_mark_node;
14844 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
14845 {
14846 assert ("void value not ignored as it ought to be" == NULL);
14847 return error_mark_node;
14848 }
14849 if (code == VOID_TYPE)
14850 return build1 (CONVERT_EXPR, type, e);
14851 if ((code != RECORD_TYPE)
14852 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
14853 e = ffecom_1 (REALPART_EXPR, TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e))),
14854 e);
14855 if (code == INTEGER_TYPE || code == ENUMERAL_TYPE)
14856 return fold (convert_to_integer (type, e));
14857 if (code == POINTER_TYPE)
14858 return fold (convert_to_pointer (type, e));
14859 if (code == REAL_TYPE)
14860 return fold (convert_to_real (type, e));
14861 if (code == COMPLEX_TYPE)
14862 return fold (convert_to_complex (type, e));
14863 if (code == RECORD_TYPE)
14864 return fold (ffecom_convert_to_complex_ (type, e));
5ff904cd 14865
c7e4ee3a
CB
14866 assert ("conversion to non-scalar type requested" == NULL);
14867 return error_mark_node;
14868}
5ff904cd 14869
c7e4ee3a
CB
14870/* integrate_decl_tree calls this function, but since we don't use the
14871 DECL_LANG_SPECIFIC field, this is a no-op. */
5ff904cd 14872
c7e4ee3a
CB
14873void
14874copy_lang_decl (node)
14875 tree node UNUSED;
14876{
5ff904cd
JL
14877}
14878
c7e4ee3a
CB
14879/* Return the list of declarations of the current level.
14880 Note that this list is in reverse order unless/until
14881 you nreverse it; and when you do nreverse it, you must
14882 store the result back using `storedecls' or you will lose. */
5ff904cd 14883
c7e4ee3a
CB
14884tree
14885getdecls ()
5ff904cd 14886{
c7e4ee3a 14887 return current_binding_level->names;
5ff904cd
JL
14888}
14889
c7e4ee3a 14890/* Nonzero if we are currently in the global binding level. */
5ff904cd 14891
c7e4ee3a
CB
14892int
14893global_bindings_p ()
5ff904cd 14894{
c7e4ee3a
CB
14895 return current_binding_level == global_binding_level;
14896}
5ff904cd 14897
c7e4ee3a
CB
14898/* Print an error message for invalid use of an incomplete type.
14899 VALUE is the expression that was used (or 0 if that isn't known)
14900 and TYPE is the type that was invalid. */
5ff904cd 14901
c7e4ee3a
CB
14902void
14903incomplete_type_error (value, type)
14904 tree value UNUSED;
14905 tree type;
14906{
14907 if (TREE_CODE (type) == ERROR_MARK)
14908 return;
5ff904cd 14909
c7e4ee3a
CB
14910 assert ("incomplete type?!?" == NULL);
14911}
14912
14913void
14914init_decl_processing ()
5ff904cd 14915{
c7e4ee3a
CB
14916 malloc_init ();
14917 ffe_init_0 ();
14918}
5ff904cd 14919
c7e4ee3a
CB
14920char *
14921init_parse (filename)
14922 char *filename;
14923{
14924#if BUILT_FOR_270
14925 extern void (*print_error_function) (char *);
14926#endif
5ff904cd 14927
c7e4ee3a
CB
14928 /* Open input file. */
14929 if (filename == 0 || !strcmp (filename, "-"))
5ff904cd 14930 {
c7e4ee3a
CB
14931 finput = stdin;
14932 filename = "stdin";
5ff904cd 14933 }
c7e4ee3a
CB
14934 else
14935 finput = fopen (filename, "r");
14936 if (finput == 0)
14937 pfatal_with_name (filename);
5ff904cd 14938
c7e4ee3a
CB
14939#ifdef IO_BUFFER_SIZE
14940 setvbuf (finput, (char *) xmalloc (IO_BUFFER_SIZE), _IOFBF, IO_BUFFER_SIZE);
14941#endif
5ff904cd 14942
c7e4ee3a
CB
14943 /* Make identifier nodes long enough for the language-specific slots. */
14944 set_identifier_size (sizeof (struct lang_identifier));
14945 decl_printable_name = lang_printable_name;
14946#if BUILT_FOR_270
14947 print_error_function = lang_print_error_function;
14948#endif
5ff904cd 14949
c7e4ee3a
CB
14950 return filename;
14951}
5ff904cd 14952
c7e4ee3a
CB
14953void
14954finish_parse ()
14955{
14956 fclose (finput);
14957}
14958
14959/* Delete the node BLOCK from the current binding level.
14960 This is used for the block inside a stmt expr ({...})
14961 so that the block can be reinserted where appropriate. */
14962
14963static void
14964delete_block (block)
14965 tree block;
14966{
14967 tree t;
14968 if (current_binding_level->blocks == block)
14969 current_binding_level->blocks = TREE_CHAIN (block);
14970 for (t = current_binding_level->blocks; t;)
14971 {
14972 if (TREE_CHAIN (t) == block)
14973 TREE_CHAIN (t) = TREE_CHAIN (block);
14974 else
14975 t = TREE_CHAIN (t);
14976 }
14977 TREE_CHAIN (block) = NULL;
14978 /* Clear TREE_USED which is always set by poplevel.
14979 The flag is set again if insert_block is called. */
14980 TREE_USED (block) = 0;
14981}
14982
14983void
14984insert_block (block)
14985 tree block;
14986{
14987 TREE_USED (block) = 1;
14988 current_binding_level->blocks
14989 = chainon (current_binding_level->blocks, block);
14990}
14991
14992int
14993lang_decode_option (argc, argv)
14994 int argc;
14995 char **argv;
14996{
14997 return ffe_decode_option (argc, argv);
5ff904cd
JL
14998}
14999
c7e4ee3a 15000/* used by print-tree.c */
5ff904cd 15001
c7e4ee3a
CB
15002void
15003lang_print_xnode (file, node, indent)
15004 FILE *file UNUSED;
15005 tree node UNUSED;
15006 int indent UNUSED;
5ff904cd 15007{
c7e4ee3a 15008}
5ff904cd 15009
c7e4ee3a
CB
15010void
15011lang_finish ()
15012{
15013 ffe_terminate_0 ();
5ff904cd 15014
c7e4ee3a
CB
15015 if (ffe_is_ffedebug ())
15016 malloc_pool_display (malloc_pool_image ());
5ff904cd
JL
15017}
15018
c7e4ee3a
CB
15019char *
15020lang_identify ()
5ff904cd 15021{
c7e4ee3a
CB
15022 return "f77";
15023}
5ff904cd 15024
c7e4ee3a
CB
15025void
15026lang_init_options ()
15027{
15028 /* Set default options for Fortran. */
15029 flag_move_all_movables = 1;
15030 flag_reduce_all_givs = 1;
15031 flag_argument_noalias = 2;
41af162c 15032 flag_errno_math = 0;
c64f913e 15033 flag_complex_divide_method = 1;
c7e4ee3a 15034}
5ff904cd 15035
c7e4ee3a
CB
15036void
15037lang_init ()
15038{
15039 /* If the file is output from cpp, it should contain a first line
15040 `# 1 "real-filename"', and the current design of gcc (toplev.c
15041 in particular and the way it sets up information relied on by
15042 INCLUDE) requires that we read this now, and store the
15043 "real-filename" info in master_input_filename. Ask the lexer
15044 to try doing this. */
15045 ffelex_hash_kludge (finput);
15046}
5ff904cd 15047
c7e4ee3a
CB
15048int
15049mark_addressable (exp)
15050 tree exp;
15051{
15052 register tree x = exp;
15053 while (1)
15054 switch (TREE_CODE (x))
15055 {
15056 case ADDR_EXPR:
15057 case COMPONENT_REF:
15058 case ARRAY_REF:
15059 x = TREE_OPERAND (x, 0);
15060 break;
5ff904cd 15061
c7e4ee3a
CB
15062 case CONSTRUCTOR:
15063 TREE_ADDRESSABLE (x) = 1;
15064 return 1;
5ff904cd 15065
c7e4ee3a
CB
15066 case VAR_DECL:
15067 case CONST_DECL:
15068 case PARM_DECL:
15069 case RESULT_DECL:
15070 if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x)
15071 && DECL_NONLOCAL (x))
15072 {
15073 if (TREE_PUBLIC (x))
15074 {
15075 assert ("address of global register var requested" == NULL);
15076 return 0;
15077 }
15078 assert ("address of register variable requested" == NULL);
15079 }
15080 else if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x))
15081 {
15082 if (TREE_PUBLIC (x))
15083 {
15084 assert ("address of global register var requested" == NULL);
15085 return 0;
15086 }
15087 assert ("address of register var requested" == NULL);
15088 }
15089 put_var_into_stack (x);
5ff904cd 15090
c7e4ee3a
CB
15091 /* drops in */
15092 case FUNCTION_DECL:
15093 TREE_ADDRESSABLE (x) = 1;
15094#if 0 /* poplevel deals with this now. */
15095 if (DECL_CONTEXT (x) == 0)
15096 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;
15097#endif
5ff904cd 15098
c7e4ee3a
CB
15099 default:
15100 return 1;
15101 }
5ff904cd
JL
15102}
15103
c7e4ee3a
CB
15104/* If DECL has a cleanup, build and return that cleanup here.
15105 This is a callback called by expand_expr. */
5ff904cd 15106
c7e4ee3a
CB
15107tree
15108maybe_build_cleanup (decl)
15109 tree decl UNUSED;
5ff904cd 15110{
c7e4ee3a
CB
15111 /* There are no cleanups in Fortran. */
15112 return NULL_TREE;
5ff904cd
JL
15113}
15114
c7e4ee3a
CB
15115/* Exit a binding level.
15116 Pop the level off, and restore the state of the identifier-decl mappings
15117 that were in effect when this level was entered.
5ff904cd 15118
c7e4ee3a
CB
15119 If KEEP is nonzero, this level had explicit declarations, so
15120 and create a "block" (a BLOCK node) for the level
15121 to record its declarations and subblocks for symbol table output.
5ff904cd 15122
c7e4ee3a
CB
15123 If FUNCTIONBODY is nonzero, this level is the body of a function,
15124 so create a block as if KEEP were set and also clear out all
15125 label names.
5ff904cd 15126
c7e4ee3a
CB
15127 If REVERSE is nonzero, reverse the order of decls before putting
15128 them into the BLOCK. */
5ff904cd 15129
c7e4ee3a
CB
15130tree
15131poplevel (keep, reverse, functionbody)
15132 int keep;
15133 int reverse;
15134 int functionbody;
5ff904cd 15135{
c7e4ee3a
CB
15136 register tree link;
15137 /* The chain of decls was accumulated in reverse order.
15138 Put it into forward order, just for cleanliness. */
15139 tree decls;
15140 tree subblocks = current_binding_level->blocks;
15141 tree block = 0;
15142 tree decl;
15143 int block_previously_created;
5ff904cd 15144
c7e4ee3a
CB
15145 /* Get the decls in the order they were written.
15146 Usually current_binding_level->names is in reverse order.
15147 But parameter decls were previously put in forward order. */
702edf1d 15148
c7e4ee3a
CB
15149 if (reverse)
15150 current_binding_level->names
15151 = decls = nreverse (current_binding_level->names);
15152 else
15153 decls = current_binding_level->names;
5ff904cd 15154
c7e4ee3a
CB
15155 /* Output any nested inline functions within this block
15156 if they weren't already output. */
5ff904cd 15157
c7e4ee3a
CB
15158 for (decl = decls; decl; decl = TREE_CHAIN (decl))
15159 if (TREE_CODE (decl) == FUNCTION_DECL
15160 && ! TREE_ASM_WRITTEN (decl)
15161 && DECL_INITIAL (decl) != 0
15162 && TREE_ADDRESSABLE (decl))
15163 {
15164 /* If this decl was copied from a file-scope decl
15165 on account of a block-scope extern decl,
15166 propagate TREE_ADDRESSABLE to the file-scope decl.
15167
15168 DECL_ABSTRACT_ORIGIN can be set to itself if warn_return_type is
15169 true, since then the decl goes through save_for_inline_copying. */
15170 if (DECL_ABSTRACT_ORIGIN (decl) != 0
15171 && DECL_ABSTRACT_ORIGIN (decl) != decl)
15172 TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
15173 else if (DECL_SAVED_INSNS (decl) != 0)
15174 {
15175 push_function_context ();
15176 output_inline_function (decl);
15177 pop_function_context ();
15178 }
15179 }
5ff904cd 15180
c7e4ee3a
CB
15181 /* If there were any declarations or structure tags in that level,
15182 or if this level is a function body,
15183 create a BLOCK to record them for the life of this function. */
5ff904cd 15184
c7e4ee3a
CB
15185 block = 0;
15186 block_previously_created = (current_binding_level->this_block != 0);
15187 if (block_previously_created)
15188 block = current_binding_level->this_block;
15189 else if (keep || functionbody)
15190 block = make_node (BLOCK);
15191 if (block != 0)
15192 {
15193 BLOCK_VARS (block) = decls;
15194 BLOCK_SUBBLOCKS (block) = subblocks;
15195 remember_end_note (block);
15196 }
5ff904cd 15197
c7e4ee3a 15198 /* In each subblock, record that this is its superior. */
5ff904cd 15199
c7e4ee3a
CB
15200 for (link = subblocks; link; link = TREE_CHAIN (link))
15201 BLOCK_SUPERCONTEXT (link) = block;
5ff904cd 15202
c7e4ee3a 15203 /* Clear out the meanings of the local variables of this level. */
5ff904cd 15204
c7e4ee3a 15205 for (link = decls; link; link = TREE_CHAIN (link))
5ff904cd 15206 {
c7e4ee3a
CB
15207 if (DECL_NAME (link) != 0)
15208 {
15209 /* If the ident. was used or addressed via a local extern decl,
15210 don't forget that fact. */
15211 if (DECL_EXTERNAL (link))
15212 {
15213 if (TREE_USED (link))
15214 TREE_USED (DECL_NAME (link)) = 1;
15215 if (TREE_ADDRESSABLE (link))
15216 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1;
15217 }
15218 IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = 0;
15219 }
5ff904cd 15220 }
5ff904cd 15221
c7e4ee3a
CB
15222 /* If the level being exited is the top level of a function,
15223 check over all the labels, and clear out the current
15224 (function local) meanings of their names. */
5ff904cd 15225
c7e4ee3a 15226 if (functionbody)
5ff904cd 15227 {
c7e4ee3a
CB
15228 /* If this is the top level block of a function,
15229 the vars are the function's parameters.
15230 Don't leave them in the BLOCK because they are
15231 found in the FUNCTION_DECL instead. */
15232
15233 BLOCK_VARS (block) = 0;
5ff904cd
JL
15234 }
15235
c7e4ee3a
CB
15236 /* Pop the current level, and free the structure for reuse. */
15237
15238 {
15239 register struct binding_level *level = current_binding_level;
15240 current_binding_level = current_binding_level->level_chain;
15241
15242 level->level_chain = free_binding_level;
15243 free_binding_level = level;
15244 }
15245
15246 /* Dispose of the block that we just made inside some higher level. */
15247 if (functionbody
15248 && current_function_decl != error_mark_node)
15249 DECL_INITIAL (current_function_decl) = block;
15250 else if (block)
5ff904cd 15251 {
c7e4ee3a
CB
15252 if (!block_previously_created)
15253 current_binding_level->blocks
15254 = chainon (current_binding_level->blocks, block);
5ff904cd 15255 }
c7e4ee3a
CB
15256 /* If we did not make a block for the level just exited,
15257 any blocks made for inner levels
15258 (since they cannot be recorded as subblocks in that level)
15259 must be carried forward so they will later become subblocks
15260 of something else. */
15261 else if (subblocks)
15262 current_binding_level->blocks
15263 = chainon (current_binding_level->blocks, subblocks);
5ff904cd 15264
c7e4ee3a
CB
15265 if (block)
15266 TREE_USED (block) = 1;
15267 return block;
5ff904cd
JL
15268}
15269
c7e4ee3a
CB
15270void
15271print_lang_decl (file, node, indent)
15272 FILE *file UNUSED;
15273 tree node UNUSED;
15274 int indent UNUSED;
15275{
15276}
5ff904cd 15277
c7e4ee3a
CB
15278void
15279print_lang_identifier (file, node, indent)
15280 FILE *file;
15281 tree node;
15282 int indent;
15283{
15284 print_node (file, "global", IDENTIFIER_GLOBAL_VALUE (node), indent + 4);
15285 print_node (file, "local", IDENTIFIER_LOCAL_VALUE (node), indent + 4);
15286}
5ff904cd 15287
c7e4ee3a
CB
15288void
15289print_lang_statistics ()
15290{
15291}
5ff904cd 15292
c7e4ee3a
CB
15293void
15294print_lang_type (file, node, indent)
15295 FILE *file UNUSED;
15296 tree node UNUSED;
15297 int indent UNUSED;
5ff904cd 15298{
c7e4ee3a 15299}
5ff904cd 15300
c7e4ee3a
CB
15301/* Record a decl-node X as belonging to the current lexical scope.
15302 Check for errors (such as an incompatible declaration for the same
15303 name already seen in the same scope).
5ff904cd 15304
c7e4ee3a
CB
15305 Returns either X or an old decl for the same name.
15306 If an old decl is returned, it may have been smashed
15307 to agree with what X says. */
5ff904cd 15308
c7e4ee3a
CB
15309tree
15310pushdecl (x)
15311 tree x;
15312{
15313 register tree t;
15314 register tree name = DECL_NAME (x);
15315 register struct binding_level *b = current_binding_level;
5ff904cd 15316
c7e4ee3a
CB
15317 if ((TREE_CODE (x) == FUNCTION_DECL)
15318 && (DECL_INITIAL (x) == 0)
15319 && DECL_EXTERNAL (x))
15320 DECL_CONTEXT (x) = NULL_TREE;
56a0044b 15321 else
c7e4ee3a
CB
15322 DECL_CONTEXT (x) = current_function_decl;
15323
15324 if (name)
56a0044b 15325 {
c7e4ee3a
CB
15326 if (IDENTIFIER_INVENTED (name))
15327 {
15328#if BUILT_FOR_270
15329 DECL_ARTIFICIAL (x) = 1;
15330#endif
15331 DECL_IN_SYSTEM_HEADER (x) = 1;
15332 }
5ff904cd 15333
c7e4ee3a 15334 t = lookup_name_current_level (name);
5ff904cd 15335
c7e4ee3a 15336 assert ((t == NULL_TREE) || (DECL_CONTEXT (x) == NULL_TREE));
5ff904cd 15337
c7e4ee3a
CB
15338 /* Don't push non-parms onto list for parms until we understand
15339 why we're doing this and whether it works. */
56a0044b 15340
c7e4ee3a
CB
15341 assert ((b == global_binding_level)
15342 || !ffecom_transform_only_dummies_
15343 || TREE_CODE (x) == PARM_DECL);
5ff904cd 15344
c7e4ee3a
CB
15345 if ((t != NULL_TREE) && duplicate_decls (x, t))
15346 return t;
5ff904cd 15347
c7e4ee3a
CB
15348 /* If we are processing a typedef statement, generate a whole new
15349 ..._TYPE node (which will be just an variant of the existing
15350 ..._TYPE node with identical properties) and then install the
15351 TYPE_DECL node generated to represent the typedef name as the
15352 TYPE_NAME of this brand new (duplicate) ..._TYPE node.
5ff904cd 15353
c7e4ee3a
CB
15354 The whole point here is to end up with a situation where each and every
15355 ..._TYPE node the compiler creates will be uniquely associated with
15356 AT MOST one node representing a typedef name. This way, even though
15357 the compiler substitutes corresponding ..._TYPE nodes for TYPE_DECL
15358 (i.e. "typedef name") nodes very early on, later parts of the
15359 compiler can always do the reverse translation and get back the
15360 corresponding typedef name. For example, given:
5ff904cd 15361
c7e4ee3a 15362 typedef struct S MY_TYPE; MY_TYPE object;
5ff904cd 15363
c7e4ee3a
CB
15364 Later parts of the compiler might only know that `object' was of type
15365 `struct S' if it were not for code just below. With this code
15366 however, later parts of the compiler see something like:
5ff904cd 15367
c7e4ee3a 15368 struct S' == struct S typedef struct S' MY_TYPE; struct S' object;
5ff904cd 15369
c7e4ee3a
CB
15370 And they can then deduce (from the node for type struct S') that the
15371 original object declaration was:
5ff904cd 15372
c7e4ee3a 15373 MY_TYPE object;
5ff904cd 15374
c7e4ee3a
CB
15375 Being able to do this is important for proper support of protoize, and
15376 also for generating precise symbolic debugging information which
15377 takes full account of the programmer's (typedef) vocabulary.
5ff904cd 15378
c7e4ee3a
CB
15379 Obviously, we don't want to generate a duplicate ..._TYPE node if the
15380 TYPE_DECL node that we are now processing really represents a
15381 standard built-in type.
5ff904cd 15382
c7e4ee3a
CB
15383 Since all standard types are effectively declared at line zero in the
15384 source file, we can easily check to see if we are working on a
15385 standard type by checking the current value of lineno. */
15386
15387 if (TREE_CODE (x) == TYPE_DECL)
15388 {
15389 if (DECL_SOURCE_LINE (x) == 0)
15390 {
15391 if (TYPE_NAME (TREE_TYPE (x)) == 0)
15392 TYPE_NAME (TREE_TYPE (x)) = x;
15393 }
15394 else if (TREE_TYPE (x) != error_mark_node)
15395 {
15396 tree tt = TREE_TYPE (x);
15397
15398 tt = build_type_copy (tt);
15399 TYPE_NAME (tt) = x;
15400 TREE_TYPE (x) = tt;
15401 }
15402 }
5ff904cd 15403
c7e4ee3a
CB
15404 /* This name is new in its binding level. Install the new declaration
15405 and return it. */
15406 if (b == global_binding_level)
15407 IDENTIFIER_GLOBAL_VALUE (name) = x;
15408 else
15409 IDENTIFIER_LOCAL_VALUE (name) = x;
15410 }
5ff904cd 15411
c7e4ee3a
CB
15412 /* Put decls on list in reverse order. We will reverse them later if
15413 necessary. */
15414 TREE_CHAIN (x) = b->names;
15415 b->names = x;
5ff904cd 15416
c7e4ee3a 15417 return x;
5ff904cd
JL
15418}
15419
c7e4ee3a 15420/* Nonzero if the current level needs to have a BLOCK made. */
5ff904cd 15421
c7e4ee3a
CB
15422static int
15423kept_level_p ()
5ff904cd 15424{
c7e4ee3a
CB
15425 tree decl;
15426
15427 for (decl = current_binding_level->names;
15428 decl;
15429 decl = TREE_CHAIN (decl))
15430 {
15431 if (TREE_USED (decl) || TREE_CODE (decl) != VAR_DECL
15432 || (DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl)))
15433 /* Currently, there aren't supposed to be non-artificial names
15434 at other than the top block for a function -- they're
15435 believed to always be temps. But it's wise to check anyway. */
15436 return 1;
15437 }
15438 return 0;
5ff904cd
JL
15439}
15440
c7e4ee3a
CB
15441/* Enter a new binding level.
15442 If TAG_TRANSPARENT is nonzero, do so only for the name space of variables,
15443 not for that of tags. */
5ff904cd
JL
15444
15445void
c7e4ee3a
CB
15446pushlevel (tag_transparent)
15447 int tag_transparent;
5ff904cd 15448{
c7e4ee3a 15449 register struct binding_level *newlevel = NULL_BINDING_LEVEL;
5ff904cd 15450
c7e4ee3a 15451 assert (! tag_transparent);
5ff904cd 15452
c7e4ee3a
CB
15453 if (current_binding_level == global_binding_level)
15454 {
15455 named_labels = 0;
15456 }
5ff904cd 15457
c7e4ee3a 15458 /* Reuse or create a struct for this binding level. */
5ff904cd 15459
c7e4ee3a 15460 if (free_binding_level)
77f77701 15461 {
c7e4ee3a
CB
15462 newlevel = free_binding_level;
15463 free_binding_level = free_binding_level->level_chain;
77f77701
DB
15464 }
15465 else
c7e4ee3a
CB
15466 {
15467 newlevel = make_binding_level ();
15468 }
77f77701 15469
c7e4ee3a
CB
15470 /* Add this level to the front of the chain (stack) of levels that
15471 are active. */
71b5e532 15472
c7e4ee3a
CB
15473 *newlevel = clear_binding_level;
15474 newlevel->level_chain = current_binding_level;
15475 current_binding_level = newlevel;
5ff904cd
JL
15476}
15477
c7e4ee3a
CB
15478/* Set the BLOCK node for the innermost scope
15479 (the one we are currently in). */
77f77701 15480
5ff904cd 15481void
c7e4ee3a
CB
15482set_block (block)
15483 register tree block;
5ff904cd 15484{
c7e4ee3a 15485 current_binding_level->this_block = block;
5ff904cd
JL
15486}
15487
c7e4ee3a 15488/* ~~gcc/tree.h *should* declare this, because toplev.c references it. */
5ff904cd 15489
c7e4ee3a 15490/* Can't 'yydebug' a front end not generated by yacc/bison! */
bc289659
ML
15491
15492void
c7e4ee3a
CB
15493set_yydebug (value)
15494 int value;
bc289659 15495{
c7e4ee3a
CB
15496 if (value)
15497 fprintf (stderr, "warning: no yacc/bison-generated output to debug!\n");
bc289659
ML
15498}
15499
c7e4ee3a
CB
15500tree
15501signed_or_unsigned_type (unsignedp, type)
15502 int unsignedp;
15503 tree type;
5ff904cd 15504{
c7e4ee3a 15505 tree type2;
5ff904cd 15506
c7e4ee3a
CB
15507 if (! INTEGRAL_TYPE_P (type))
15508 return type;
15509 if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node))
15510 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15511 if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
15512 return unsignedp ? unsigned_type_node : integer_type_node;
15513 if (TYPE_PRECISION (type) == TYPE_PRECISION (short_integer_type_node))
15514 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15515 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_integer_type_node))
15516 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15517 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_long_integer_type_node))
15518 return (unsignedp ? long_long_unsigned_type_node
15519 : long_long_integer_type_node);
5ff904cd 15520
c7e4ee3a
CB
15521 type2 = type_for_size (TYPE_PRECISION (type), unsignedp);
15522 if (type2 == NULL_TREE)
15523 return type;
f84639ba 15524
c7e4ee3a 15525 return type2;
5ff904cd
JL
15526}
15527
c7e4ee3a
CB
15528tree
15529signed_type (type)
15530 tree type;
5ff904cd 15531{
c7e4ee3a
CB
15532 tree type1 = TYPE_MAIN_VARIANT (type);
15533 ffeinfoKindtype kt;
15534 tree type2;
5ff904cd 15535
c7e4ee3a
CB
15536 if (type1 == unsigned_char_type_node || type1 == char_type_node)
15537 return signed_char_type_node;
15538 if (type1 == unsigned_type_node)
15539 return integer_type_node;
15540 if (type1 == short_unsigned_type_node)
15541 return short_integer_type_node;
15542 if (type1 == long_unsigned_type_node)
15543 return long_integer_type_node;
15544 if (type1 == long_long_unsigned_type_node)
15545 return long_long_integer_type_node;
15546#if 0 /* gcc/c-* files only */
15547 if (type1 == unsigned_intDI_type_node)
15548 return intDI_type_node;
15549 if (type1 == unsigned_intSI_type_node)
15550 return intSI_type_node;
15551 if (type1 == unsigned_intHI_type_node)
15552 return intHI_type_node;
15553 if (type1 == unsigned_intQI_type_node)
15554 return intQI_type_node;
15555#endif
5ff904cd 15556
c7e4ee3a
CB
15557 type2 = type_for_size (TYPE_PRECISION (type1), 0);
15558 if (type2 != NULL_TREE)
15559 return type2;
5ff904cd 15560
c7e4ee3a
CB
15561 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15562 {
15563 type2 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
5ff904cd 15564
c7e4ee3a
CB
15565 if (type1 == type2)
15566 return ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15567 }
15568
15569 return type;
5ff904cd
JL
15570}
15571
c7e4ee3a
CB
15572/* Prepare expr to be an argument of a TRUTH_NOT_EXPR,
15573 or validate its data type for an `if' or `while' statement or ?..: exp.
15574
15575 This preparation consists of taking the ordinary
15576 representation of an expression expr and producing a valid tree
15577 boolean expression describing whether expr is nonzero. We could
15578 simply always do build_binary_op (NE_EXPR, expr, integer_zero_node, 1),
15579 but we optimize comparisons, &&, ||, and !.
15580
15581 The resulting type should always be `integer_type_node'. */
5ff904cd
JL
15582
15583tree
c7e4ee3a
CB
15584truthvalue_conversion (expr)
15585 tree expr;
5ff904cd 15586{
c7e4ee3a
CB
15587 if (TREE_CODE (expr) == ERROR_MARK)
15588 return expr;
5ff904cd 15589
c7e4ee3a
CB
15590#if 0 /* This appears to be wrong for C++. */
15591 /* These really should return error_mark_node after 2.4 is stable.
15592 But not all callers handle ERROR_MARK properly. */
15593 switch (TREE_CODE (TREE_TYPE (expr)))
15594 {
15595 case RECORD_TYPE:
15596 error ("struct type value used where scalar is required");
15597 return integer_zero_node;
5ff904cd 15598
c7e4ee3a
CB
15599 case UNION_TYPE:
15600 error ("union type value used where scalar is required");
15601 return integer_zero_node;
5ff904cd 15602
c7e4ee3a
CB
15603 case ARRAY_TYPE:
15604 error ("array type value used where scalar is required");
15605 return integer_zero_node;
5ff904cd 15606
c7e4ee3a
CB
15607 default:
15608 break;
15609 }
15610#endif /* 0 */
5ff904cd 15611
c7e4ee3a
CB
15612 switch (TREE_CODE (expr))
15613 {
15614 /* It is simpler and generates better code to have only TRUTH_*_EXPR
15615 or comparison expressions as truth values at this level. */
15616#if 0
15617 case COMPONENT_REF:
15618 /* A one-bit unsigned bit-field is already acceptable. */
15619 if (1 == TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (expr, 1)))
15620 && TREE_UNSIGNED (TREE_OPERAND (expr, 1)))
15621 return expr;
15622 break;
15623#endif
15624
15625 case EQ_EXPR:
15626 /* It is simpler and generates better code to have only TRUTH_*_EXPR
15627 or comparison expressions as truth values at this level. */
15628#if 0
15629 if (integer_zerop (TREE_OPERAND (expr, 1)))
15630 return build_unary_op (TRUTH_NOT_EXPR, TREE_OPERAND (expr, 0), 0);
15631#endif
15632 case NE_EXPR: case LE_EXPR: case GE_EXPR: case LT_EXPR: case GT_EXPR:
15633 case TRUTH_ANDIF_EXPR:
15634 case TRUTH_ORIF_EXPR:
15635 case TRUTH_AND_EXPR:
15636 case TRUTH_OR_EXPR:
15637 case TRUTH_XOR_EXPR:
15638 TREE_TYPE (expr) = integer_type_node;
15639 return expr;
5ff904cd 15640
c7e4ee3a
CB
15641 case ERROR_MARK:
15642 return expr;
5ff904cd 15643
c7e4ee3a
CB
15644 case INTEGER_CST:
15645 return integer_zerop (expr) ? integer_zero_node : integer_one_node;
5ff904cd 15646
c7e4ee3a
CB
15647 case REAL_CST:
15648 return real_zerop (expr) ? integer_zero_node : integer_one_node;
5ff904cd 15649
c7e4ee3a
CB
15650 case ADDR_EXPR:
15651 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 0)))
15652 return build (COMPOUND_EXPR, integer_type_node,
15653 TREE_OPERAND (expr, 0), integer_one_node);
15654 else
15655 return integer_one_node;
5ff904cd 15656
c7e4ee3a
CB
15657 case COMPLEX_EXPR:
15658 return ffecom_2 ((TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
15659 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
15660 integer_type_node,
15661 truthvalue_conversion (TREE_OPERAND (expr, 0)),
15662 truthvalue_conversion (TREE_OPERAND (expr, 1)));
5ff904cd 15663
c7e4ee3a
CB
15664 case NEGATE_EXPR:
15665 case ABS_EXPR:
15666 case FLOAT_EXPR:
15667 case FFS_EXPR:
15668 /* These don't change whether an object is non-zero or zero. */
15669 return truthvalue_conversion (TREE_OPERAND (expr, 0));
5ff904cd 15670
c7e4ee3a
CB
15671 case LROTATE_EXPR:
15672 case RROTATE_EXPR:
15673 /* These don't change whether an object is zero or non-zero, but
15674 we can't ignore them if their second arg has side-effects. */
15675 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
15676 return build (COMPOUND_EXPR, integer_type_node, TREE_OPERAND (expr, 1),
15677 truthvalue_conversion (TREE_OPERAND (expr, 0)));
15678 else
15679 return truthvalue_conversion (TREE_OPERAND (expr, 0));
5ff904cd 15680
c7e4ee3a
CB
15681 case COND_EXPR:
15682 /* Distribute the conversion into the arms of a COND_EXPR. */
15683 return fold (build (COND_EXPR, integer_type_node, TREE_OPERAND (expr, 0),
15684 truthvalue_conversion (TREE_OPERAND (expr, 1)),
15685 truthvalue_conversion (TREE_OPERAND (expr, 2))));
5ff904cd 15686
c7e4ee3a
CB
15687 case CONVERT_EXPR:
15688 /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
15689 since that affects how `default_conversion' will behave. */
15690 if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE
15691 || TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE)
15692 break;
15693 /* fall through... */
15694 case NOP_EXPR:
15695 /* If this is widening the argument, we can ignore it. */
15696 if (TYPE_PRECISION (TREE_TYPE (expr))
15697 >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))
15698 return truthvalue_conversion (TREE_OPERAND (expr, 0));
15699 break;
5ff904cd 15700
c7e4ee3a
CB
15701 case MINUS_EXPR:
15702 /* With IEEE arithmetic, x - x may not equal 0, so we can't optimize
15703 this case. */
15704 if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
15705 && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE)
15706 break;
15707 /* fall through... */
15708 case BIT_XOR_EXPR:
15709 /* This and MINUS_EXPR can be changed into a comparison of the
15710 two objects. */
15711 if (TREE_TYPE (TREE_OPERAND (expr, 0))
15712 == TREE_TYPE (TREE_OPERAND (expr, 1)))
15713 return ffecom_2 (NE_EXPR, integer_type_node,
15714 TREE_OPERAND (expr, 0),
15715 TREE_OPERAND (expr, 1));
15716 return ffecom_2 (NE_EXPR, integer_type_node,
15717 TREE_OPERAND (expr, 0),
15718 fold (build1 (NOP_EXPR,
15719 TREE_TYPE (TREE_OPERAND (expr, 0)),
15720 TREE_OPERAND (expr, 1))));
15721
15722 case BIT_AND_EXPR:
15723 if (integer_onep (TREE_OPERAND (expr, 1)))
15724 return expr;
15725 break;
15726
15727 case MODIFY_EXPR:
15728#if 0 /* No such thing in Fortran. */
15729 if (warn_parentheses && C_EXP_ORIGINAL_CODE (expr) == MODIFY_EXPR)
15730 warning ("suggest parentheses around assignment used as truth value");
15731#endif
15732 break;
15733
15734 default:
15735 break;
5ff904cd
JL
15736 }
15737
c7e4ee3a
CB
15738 if (TREE_CODE (TREE_TYPE (expr)) == COMPLEX_TYPE)
15739 return (ffecom_2
15740 ((TREE_SIDE_EFFECTS (expr)
15741 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
15742 integer_type_node,
15743 truthvalue_conversion (ffecom_1 (REALPART_EXPR,
15744 TREE_TYPE (TREE_TYPE (expr)),
15745 expr)),
15746 truthvalue_conversion (ffecom_1 (IMAGPART_EXPR,
15747 TREE_TYPE (TREE_TYPE (expr)),
15748 expr))));
15749
15750 return ffecom_2 (NE_EXPR, integer_type_node,
15751 expr,
15752 convert (TREE_TYPE (expr), integer_zero_node));
15753}
15754
15755tree
15756type_for_mode (mode, unsignedp)
15757 enum machine_mode mode;
15758 int unsignedp;
15759{
15760 int i;
15761 int j;
15762 tree t;
5ff904cd 15763
c7e4ee3a
CB
15764 if (mode == TYPE_MODE (integer_type_node))
15765 return unsignedp ? unsigned_type_node : integer_type_node;
5ff904cd 15766
c7e4ee3a
CB
15767 if (mode == TYPE_MODE (signed_char_type_node))
15768 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
5ff904cd 15769
c7e4ee3a
CB
15770 if (mode == TYPE_MODE (short_integer_type_node))
15771 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
5ff904cd 15772
c7e4ee3a
CB
15773 if (mode == TYPE_MODE (long_integer_type_node))
15774 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
5ff904cd 15775
c7e4ee3a
CB
15776 if (mode == TYPE_MODE (long_long_integer_type_node))
15777 return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
5ff904cd 15778
c7e4ee3a
CB
15779 if (mode == TYPE_MODE (float_type_node))
15780 return float_type_node;
5ff904cd 15781
c7e4ee3a
CB
15782 if (mode == TYPE_MODE (double_type_node))
15783 return double_type_node;
5ff904cd 15784
c7e4ee3a
CB
15785 if (mode == TYPE_MODE (build_pointer_type (char_type_node)))
15786 return build_pointer_type (char_type_node);
5ff904cd 15787
c7e4ee3a
CB
15788 if (mode == TYPE_MODE (build_pointer_type (integer_type_node)))
15789 return build_pointer_type (integer_type_node);
5ff904cd 15790
c7e4ee3a
CB
15791 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
15792 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
15793 {
15794 if (((t = ffecom_tree_type[i][j]) != NULL_TREE)
15795 && (mode == TYPE_MODE (t)))
15796 {
15797 if ((i == FFEINFO_basictypeINTEGER) && unsignedp)
15798 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][j];
15799 else
15800 return t;
15801 }
15802 }
5ff904cd 15803
c7e4ee3a 15804 return 0;
5ff904cd
JL
15805}
15806
c7e4ee3a
CB
15807tree
15808type_for_size (bits, unsignedp)
15809 unsigned bits;
15810 int unsignedp;
5ff904cd 15811{
c7e4ee3a
CB
15812 ffeinfoKindtype kt;
15813 tree type_node;
5ff904cd 15814
c7e4ee3a
CB
15815 if (bits == TYPE_PRECISION (integer_type_node))
15816 return unsignedp ? unsigned_type_node : integer_type_node;
5ff904cd 15817
c7e4ee3a
CB
15818 if (bits == TYPE_PRECISION (signed_char_type_node))
15819 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
5ff904cd 15820
c7e4ee3a
CB
15821 if (bits == TYPE_PRECISION (short_integer_type_node))
15822 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
5ff904cd 15823
c7e4ee3a
CB
15824 if (bits == TYPE_PRECISION (long_integer_type_node))
15825 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
5ff904cd 15826
c7e4ee3a
CB
15827 if (bits == TYPE_PRECISION (long_long_integer_type_node))
15828 return (unsignedp ? long_long_unsigned_type_node
15829 : long_long_integer_type_node);
5ff904cd 15830
c7e4ee3a 15831 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
5ff904cd 15832 {
c7e4ee3a 15833 type_node = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
5ff904cd 15834
c7e4ee3a
CB
15835 if ((type_node != NULL_TREE) && (bits == TYPE_PRECISION (type_node)))
15836 return unsignedp ? ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt]
15837 : type_node;
15838 }
5ff904cd 15839
c7e4ee3a
CB
15840 return 0;
15841}
5ff904cd 15842
c7e4ee3a
CB
15843tree
15844unsigned_type (type)
15845 tree type;
15846{
15847 tree type1 = TYPE_MAIN_VARIANT (type);
15848 ffeinfoKindtype kt;
15849 tree type2;
5ff904cd 15850
c7e4ee3a
CB
15851 if (type1 == signed_char_type_node || type1 == char_type_node)
15852 return unsigned_char_type_node;
15853 if (type1 == integer_type_node)
15854 return unsigned_type_node;
15855 if (type1 == short_integer_type_node)
15856 return short_unsigned_type_node;
15857 if (type1 == long_integer_type_node)
15858 return long_unsigned_type_node;
15859 if (type1 == long_long_integer_type_node)
15860 return long_long_unsigned_type_node;
15861#if 0 /* gcc/c-* files only */
15862 if (type1 == intDI_type_node)
15863 return unsigned_intDI_type_node;
15864 if (type1 == intSI_type_node)
15865 return unsigned_intSI_type_node;
15866 if (type1 == intHI_type_node)
15867 return unsigned_intHI_type_node;
15868 if (type1 == intQI_type_node)
15869 return unsigned_intQI_type_node;
15870#endif
5ff904cd 15871
c7e4ee3a
CB
15872 type2 = type_for_size (TYPE_PRECISION (type1), 1);
15873 if (type2 != NULL_TREE)
15874 return type2;
5ff904cd 15875
c7e4ee3a
CB
15876 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15877 {
15878 type2 = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
5ff904cd 15879
c7e4ee3a
CB
15880 if (type1 == type2)
15881 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
15882 }
5ff904cd 15883
c7e4ee3a
CB
15884 return type;
15885}
5ff904cd 15886
c7e4ee3a
CB
15887#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
15888\f
15889#if FFECOM_GCC_INCLUDE
5ff904cd 15890
c7e4ee3a 15891/* From gcc/cccp.c, the code to handle -I. */
5ff904cd 15892
c7e4ee3a
CB
15893/* Skip leading "./" from a directory name.
15894 This may yield the empty string, which represents the current directory. */
5ff904cd 15895
c7e4ee3a
CB
15896static const char *
15897skip_redundant_dir_prefix (const char *dir)
15898{
15899 while (dir[0] == '.' && dir[1] == '/')
15900 for (dir += 2; *dir == '/'; dir++)
15901 continue;
15902 if (dir[0] == '.' && !dir[1])
15903 dir++;
15904 return dir;
15905}
5ff904cd 15906
c7e4ee3a
CB
15907/* The file_name_map structure holds a mapping of file names for a
15908 particular directory. This mapping is read from the file named
15909 FILE_NAME_MAP_FILE in that directory. Such a file can be used to
15910 map filenames on a file system with severe filename restrictions,
15911 such as DOS. The format of the file name map file is just a series
15912 of lines with two tokens on each line. The first token is the name
15913 to map, and the second token is the actual name to use. */
5ff904cd 15914
c7e4ee3a
CB
15915struct file_name_map
15916{
15917 struct file_name_map *map_next;
15918 char *map_from;
15919 char *map_to;
15920};
5ff904cd 15921
c7e4ee3a 15922#define FILE_NAME_MAP_FILE "header.gcc"
5ff904cd 15923
c7e4ee3a
CB
15924/* Current maximum length of directory names in the search path
15925 for include files. (Altered as we get more of them.) */
5ff904cd 15926
c7e4ee3a 15927static int max_include_len = 0;
5ff904cd 15928
c7e4ee3a
CB
15929struct file_name_list
15930 {
15931 struct file_name_list *next;
15932 char *fname;
15933 /* Mapping of file names for this directory. */
15934 struct file_name_map *name_map;
15935 /* Non-zero if name_map is valid. */
15936 int got_name_map;
15937 };
5ff904cd 15938
c7e4ee3a
CB
15939static struct file_name_list *include = NULL; /* First dir to search */
15940static struct file_name_list *last_include = NULL; /* Last in chain */
5ff904cd 15941
c7e4ee3a
CB
15942/* I/O buffer structure.
15943 The `fname' field is nonzero for source files and #include files
15944 and for the dummy text used for -D and -U.
15945 It is zero for rescanning results of macro expansion
15946 and for expanding macro arguments. */
15947#define INPUT_STACK_MAX 400
15948static struct file_buf {
15949 char *fname;
15950 /* Filename specified with #line command. */
15951 char *nominal_fname;
15952 /* Record where in the search path this file was found.
15953 For #include_next. */
15954 struct file_name_list *dir;
15955 ffewhereLine line;
15956 ffewhereColumn column;
15957} instack[INPUT_STACK_MAX];
5ff904cd 15958
c7e4ee3a
CB
15959static int last_error_tick = 0; /* Incremented each time we print it. */
15960static int input_file_stack_tick = 0; /* Incremented when status changes. */
5ff904cd 15961
c7e4ee3a
CB
15962/* Current nesting level of input sources.
15963 `instack[indepth]' is the level currently being read. */
15964static int indepth = -1;
5ff904cd 15965
c7e4ee3a 15966typedef struct file_buf FILE_BUF;
5ff904cd 15967
c7e4ee3a 15968typedef unsigned char U_CHAR;
5ff904cd 15969
c7e4ee3a
CB
15970/* table to tell if char can be part of a C identifier. */
15971U_CHAR is_idchar[256];
15972/* table to tell if char can be first char of a c identifier. */
15973U_CHAR is_idstart[256];
15974/* table to tell if c is horizontal space. */
15975U_CHAR is_hor_space[256];
15976/* table to tell if c is horizontal or vertical space. */
15977static U_CHAR is_space[256];
5ff904cd 15978
c7e4ee3a
CB
15979#define SKIP_WHITE_SPACE(p) do { while (is_hor_space[*p]) p++; } while (0)
15980#define SKIP_ALL_WHITE_SPACE(p) do { while (is_space[*p]) p++; } while (0)
5ff904cd 15981
c7e4ee3a
CB
15982/* Nonzero means -I- has been seen,
15983 so don't look for #include "foo" the source-file directory. */
15984static int ignore_srcdir;
5ff904cd 15985
c7e4ee3a
CB
15986#ifndef INCLUDE_LEN_FUDGE
15987#define INCLUDE_LEN_FUDGE 0
15988#endif
5ff904cd 15989
c7e4ee3a
CB
15990static void append_include_chain (struct file_name_list *first,
15991 struct file_name_list *last);
15992static FILE *open_include_file (char *filename,
15993 struct file_name_list *searchptr);
15994static void print_containing_files (ffebadSeverity sev);
15995static const char *skip_redundant_dir_prefix (const char *);
15996static char *read_filename_string (int ch, FILE *f);
15997static struct file_name_map *read_name_map (const char *dirname);
5ff904cd 15998
c7e4ee3a
CB
15999/* Append a chain of `struct file_name_list's
16000 to the end of the main include chain.
16001 FIRST is the beginning of the chain to append, and LAST is the end. */
5ff904cd 16002
c7e4ee3a
CB
16003static void
16004append_include_chain (first, last)
16005 struct file_name_list *first, *last;
5ff904cd 16006{
c7e4ee3a 16007 struct file_name_list *dir;
5ff904cd 16008
c7e4ee3a
CB
16009 if (!first || !last)
16010 return;
5ff904cd 16011
c7e4ee3a
CB
16012 if (include == 0)
16013 include = first;
16014 else
16015 last_include->next = first;
5ff904cd 16016
c7e4ee3a
CB
16017 for (dir = first; ; dir = dir->next) {
16018 int len = strlen (dir->fname) + INCLUDE_LEN_FUDGE;
16019 if (len > max_include_len)
16020 max_include_len = len;
16021 if (dir == last)
16022 break;
16023 }
16024
16025 last->next = NULL;
16026 last_include = last;
5ff904cd
JL
16027}
16028
c7e4ee3a
CB
16029/* Try to open include file FILENAME. SEARCHPTR is the directory
16030 being tried from the include file search path. This function maps
16031 filenames on file systems based on information read by
16032 read_name_map. */
16033
16034static FILE *
16035open_include_file (filename, searchptr)
16036 char *filename;
16037 struct file_name_list *searchptr;
5ff904cd 16038{
c7e4ee3a
CB
16039 register struct file_name_map *map;
16040 register char *from;
16041 char *p, *dir;
5ff904cd 16042
c7e4ee3a
CB
16043 if (searchptr && ! searchptr->got_name_map)
16044 {
16045 searchptr->name_map = read_name_map (searchptr->fname
16046 ? searchptr->fname : ".");
16047 searchptr->got_name_map = 1;
16048 }
5ff904cd 16049
c7e4ee3a
CB
16050 /* First check the mapping for the directory we are using. */
16051 if (searchptr && searchptr->name_map)
16052 {
16053 from = filename;
16054 if (searchptr->fname)
16055 from += strlen (searchptr->fname) + 1;
16056 for (map = searchptr->name_map; map; map = map->map_next)
16057 {
16058 if (! strcmp (map->map_from, from))
16059 {
16060 /* Found a match. */
16061 return fopen (map->map_to, "r");
16062 }
16063 }
16064 }
5ff904cd 16065
c7e4ee3a
CB
16066 /* Try to find a mapping file for the particular directory we are
16067 looking in. Thus #include <sys/types.h> will look up sys/types.h
16068 in /usr/include/header.gcc and look up types.h in
16069 /usr/include/sys/header.gcc. */
16070 p = rindex (filename, '/');
16071#ifdef DIR_SEPARATOR
16072 if (! p) p = rindex (filename, DIR_SEPARATOR);
16073 else {
16074 char *tmp = rindex (filename, DIR_SEPARATOR);
16075 if (tmp != NULL && tmp > p) p = tmp;
16076 }
16077#endif
16078 if (! p)
16079 p = filename;
16080 if (searchptr
16081 && searchptr->fname
16082 && strlen (searchptr->fname) == (size_t) (p - filename)
16083 && ! strncmp (searchptr->fname, filename, (int) (p - filename)))
16084 {
16085 /* FILENAME is in SEARCHPTR, which we've already checked. */
16086 return fopen (filename, "r");
16087 }
16088
16089 if (p == filename)
16090 {
16091 from = filename;
16092 map = read_name_map (".");
16093 }
16094 else
5ff904cd 16095 {
c7e4ee3a
CB
16096 dir = (char *) xmalloc (p - filename + 1);
16097 memcpy (dir, filename, p - filename);
16098 dir[p - filename] = '\0';
16099 from = p + 1;
16100 map = read_name_map (dir);
16101 free (dir);
5ff904cd 16102 }
c7e4ee3a
CB
16103 for (; map; map = map->map_next)
16104 if (! strcmp (map->map_from, from))
16105 return fopen (map->map_to, "r");
5ff904cd 16106
c7e4ee3a 16107 return fopen (filename, "r");
5ff904cd
JL
16108}
16109
c7e4ee3a
CB
16110/* Print the file names and line numbers of the #include
16111 commands which led to the current file. */
5ff904cd 16112
c7e4ee3a
CB
16113static void
16114print_containing_files (ffebadSeverity sev)
16115{
16116 FILE_BUF *ip = NULL;
16117 int i;
16118 int first = 1;
16119 const char *str1;
16120 const char *str2;
5ff904cd 16121
c7e4ee3a
CB
16122 /* If stack of files hasn't changed since we last printed
16123 this info, don't repeat it. */
16124 if (last_error_tick == input_file_stack_tick)
16125 return;
5ff904cd 16126
c7e4ee3a
CB
16127 for (i = indepth; i >= 0; i--)
16128 if (instack[i].fname != NULL) {
16129 ip = &instack[i];
16130 break;
16131 }
5ff904cd 16132
c7e4ee3a
CB
16133 /* Give up if we don't find a source file. */
16134 if (ip == NULL)
16135 return;
5ff904cd 16136
c7e4ee3a
CB
16137 /* Find the other, outer source files. */
16138 for (i--; i >= 0; i--)
16139 if (instack[i].fname != NULL)
16140 {
16141 ip = &instack[i];
16142 if (first)
16143 {
16144 first = 0;
16145 str1 = "In file included";
16146 }
16147 else
16148 {
16149 str1 = "... ...";
16150 }
5ff904cd 16151
c7e4ee3a
CB
16152 if (i == 1)
16153 str2 = ":";
16154 else
16155 str2 = "";
5ff904cd 16156
c7e4ee3a
CB
16157 ffebad_start_msg ("%A from %B at %0%C", sev);
16158 ffebad_here (0, ip->line, ip->column);
16159 ffebad_string (str1);
16160 ffebad_string (ip->nominal_fname);
16161 ffebad_string (str2);
16162 ffebad_finish ();
16163 }
5ff904cd 16164
c7e4ee3a
CB
16165 /* Record we have printed the status as of this time. */
16166 last_error_tick = input_file_stack_tick;
16167}
5ff904cd 16168
c7e4ee3a
CB
16169/* Read a space delimited string of unlimited length from a stdio
16170 file. */
5ff904cd 16171
c7e4ee3a
CB
16172static char *
16173read_filename_string (ch, f)
16174 int ch;
16175 FILE *f;
16176{
16177 char *alloc, *set;
16178 int len;
5ff904cd 16179
c7e4ee3a
CB
16180 len = 20;
16181 set = alloc = xmalloc (len + 1);
16182 if (! is_space[ch])
16183 {
16184 *set++ = ch;
16185 while ((ch = getc (f)) != EOF && ! is_space[ch])
16186 {
16187 if (set - alloc == len)
16188 {
16189 len *= 2;
16190 alloc = xrealloc (alloc, len + 1);
16191 set = alloc + len / 2;
16192 }
16193 *set++ = ch;
16194 }
16195 }
16196 *set = '\0';
16197 ungetc (ch, f);
16198 return alloc;
16199}
5ff904cd 16200
c7e4ee3a 16201/* Read the file name map file for DIRNAME. */
5ff904cd 16202
c7e4ee3a
CB
16203static struct file_name_map *
16204read_name_map (dirname)
16205 const char *dirname;
16206{
16207 /* This structure holds a linked list of file name maps, one per
16208 directory. */
16209 struct file_name_map_list
16210 {
16211 struct file_name_map_list *map_list_next;
16212 char *map_list_name;
16213 struct file_name_map *map_list_map;
16214 };
16215 static struct file_name_map_list *map_list;
16216 register struct file_name_map_list *map_list_ptr;
16217 char *name;
16218 FILE *f;
16219 size_t dirlen;
16220 int separator_needed;
5ff904cd 16221
c7e4ee3a 16222 dirname = skip_redundant_dir_prefix (dirname);
5ff904cd 16223
c7e4ee3a
CB
16224 for (map_list_ptr = map_list; map_list_ptr;
16225 map_list_ptr = map_list_ptr->map_list_next)
16226 if (! strcmp (map_list_ptr->map_list_name, dirname))
16227 return map_list_ptr->map_list_map;
5ff904cd 16228
c7e4ee3a
CB
16229 map_list_ptr = ((struct file_name_map_list *)
16230 xmalloc (sizeof (struct file_name_map_list)));
16231 map_list_ptr->map_list_name = xstrdup (dirname);
16232 map_list_ptr->map_list_map = NULL;
5ff904cd 16233
c7e4ee3a
CB
16234 dirlen = strlen (dirname);
16235 separator_needed = dirlen != 0 && dirname[dirlen - 1] != '/';
16236 name = (char *) xmalloc (dirlen + strlen (FILE_NAME_MAP_FILE) + 2);
16237 strcpy (name, dirname);
16238 name[dirlen] = '/';
16239 strcpy (name + dirlen + separator_needed, FILE_NAME_MAP_FILE);
16240 f = fopen (name, "r");
16241 free (name);
16242 if (!f)
16243 map_list_ptr->map_list_map = NULL;
16244 else
16245 {
16246 int ch;
5ff904cd 16247
c7e4ee3a
CB
16248 while ((ch = getc (f)) != EOF)
16249 {
16250 char *from, *to;
16251 struct file_name_map *ptr;
16252
16253 if (is_space[ch])
16254 continue;
16255 from = read_filename_string (ch, f);
16256 while ((ch = getc (f)) != EOF && is_hor_space[ch])
16257 ;
16258 to = read_filename_string (ch, f);
5ff904cd 16259
c7e4ee3a
CB
16260 ptr = ((struct file_name_map *)
16261 xmalloc (sizeof (struct file_name_map)));
16262 ptr->map_from = from;
5ff904cd 16263
c7e4ee3a
CB
16264 /* Make the real filename absolute. */
16265 if (*to == '/')
16266 ptr->map_to = to;
16267 else
16268 {
16269 ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
16270 strcpy (ptr->map_to, dirname);
16271 ptr->map_to[dirlen] = '/';
16272 strcpy (ptr->map_to + dirlen + separator_needed, to);
16273 free (to);
16274 }
5ff904cd 16275
c7e4ee3a
CB
16276 ptr->map_next = map_list_ptr->map_list_map;
16277 map_list_ptr->map_list_map = ptr;
5ff904cd 16278
c7e4ee3a
CB
16279 while ((ch = getc (f)) != '\n')
16280 if (ch == EOF)
16281 break;
16282 }
16283 fclose (f);
5ff904cd
JL
16284 }
16285
c7e4ee3a
CB
16286 map_list_ptr->map_list_next = map_list;
16287 map_list = map_list_ptr;
5ff904cd 16288
c7e4ee3a 16289 return map_list_ptr->map_list_map;
5ff904cd
JL
16290}
16291
c7e4ee3a
CB
16292static void
16293ffecom_file_ (char *name)
5ff904cd 16294{
c7e4ee3a 16295 FILE_BUF *fp;
5ff904cd 16296
c7e4ee3a
CB
16297 /* Do partial setup of input buffer for the sake of generating
16298 early #line directives (when -g is in effect). */
5ff904cd 16299
c7e4ee3a
CB
16300 fp = &instack[++indepth];
16301 memset ((char *) fp, 0, sizeof (FILE_BUF));
16302 if (name == NULL)
16303 name = "";
16304 fp->nominal_fname = fp->fname = name;
16305}
5ff904cd 16306
c7e4ee3a 16307/* Initialize syntactic classifications of characters. */
5ff904cd 16308
c7e4ee3a
CB
16309static void
16310ffecom_initialize_char_syntax_ ()
16311{
16312 register int i;
5ff904cd 16313
c7e4ee3a
CB
16314 /*
16315 * Set up is_idchar and is_idstart tables. These should be
16316 * faster than saying (is_alpha (c) || c == '_'), etc.
16317 * Set up these things before calling any routines tthat
16318 * refer to them.
16319 */
16320 for (i = 'a'; i <= 'z'; i++) {
16321 is_idchar[i - 'a' + 'A'] = 1;
16322 is_idchar[i] = 1;
16323 is_idstart[i - 'a' + 'A'] = 1;
16324 is_idstart[i] = 1;
16325 }
16326 for (i = '0'; i <= '9'; i++)
16327 is_idchar[i] = 1;
16328 is_idchar['_'] = 1;
16329 is_idstart['_'] = 1;
5ff904cd 16330
c7e4ee3a
CB
16331 /* horizontal space table */
16332 is_hor_space[' '] = 1;
16333 is_hor_space['\t'] = 1;
16334 is_hor_space['\v'] = 1;
16335 is_hor_space['\f'] = 1;
16336 is_hor_space['\r'] = 1;
5ff904cd 16337
c7e4ee3a
CB
16338 is_space[' '] = 1;
16339 is_space['\t'] = 1;
16340 is_space['\v'] = 1;
16341 is_space['\f'] = 1;
16342 is_space['\n'] = 1;
16343 is_space['\r'] = 1;
16344}
5ff904cd 16345
c7e4ee3a
CB
16346static void
16347ffecom_close_include_ (FILE *f)
16348{
16349 fclose (f);
5ff904cd 16350
c7e4ee3a
CB
16351 indepth--;
16352 input_file_stack_tick++;
5ff904cd 16353
c7e4ee3a
CB
16354 ffewhere_line_kill (instack[indepth].line);
16355 ffewhere_column_kill (instack[indepth].column);
16356}
5ff904cd 16357
c7e4ee3a
CB
16358static int
16359ffecom_decode_include_option_ (char *spec)
16360{
16361 struct file_name_list *dirtmp;
16362
16363 if (! ignore_srcdir && !strcmp (spec, "-"))
16364 ignore_srcdir = 1;
16365 else
16366 {
16367 dirtmp = (struct file_name_list *)
16368 xmalloc (sizeof (struct file_name_list));
16369 dirtmp->next = 0; /* New one goes on the end */
16370 if (spec[0] != 0)
16371 dirtmp->fname = spec;
16372 else
16373 fatal ("Directory name must immediately follow -I option with no intervening spaces, as in `-Idir', not `-I dir'");
16374 dirtmp->got_name_map = 0;
16375 append_include_chain (dirtmp, dirtmp);
16376 }
16377 return 1;
5ff904cd
JL
16378}
16379
c7e4ee3a
CB
16380/* Open INCLUDEd file. */
16381
16382static FILE *
16383ffecom_open_include_ (char *name, ffewhereLine l, ffewhereColumn c)
5ff904cd 16384{
c7e4ee3a
CB
16385 char *fbeg = name;
16386 size_t flen = strlen (fbeg);
16387 struct file_name_list *search_start = include; /* Chain of dirs to search */
16388 struct file_name_list dsp[1]; /* First in chain, if #include "..." */
16389 struct file_name_list *searchptr = 0;
16390 char *fname; /* Dynamically allocated fname buffer */
16391 FILE *f;
16392 FILE_BUF *fp;
5ff904cd 16393
c7e4ee3a
CB
16394 if (flen == 0)
16395 return NULL;
5ff904cd 16396
c7e4ee3a 16397 dsp[0].fname = NULL;
5ff904cd 16398
c7e4ee3a
CB
16399 /* If -I- was specified, don't search current dir, only spec'd ones. */
16400 if (!ignore_srcdir)
16401 {
16402 for (fp = &instack[indepth]; fp >= instack; fp--)
16403 {
16404 int n;
16405 char *ep;
16406 char *nam;
5ff904cd 16407
c7e4ee3a
CB
16408 if ((nam = fp->nominal_fname) != NULL)
16409 {
16410 /* Found a named file. Figure out dir of the file,
16411 and put it in front of the search list. */
16412 dsp[0].next = search_start;
16413 search_start = dsp;
16414#ifndef VMS
16415 ep = rindex (nam, '/');
16416#ifdef DIR_SEPARATOR
16417 if (ep == NULL) ep = rindex (nam, DIR_SEPARATOR);
16418 else {
16419 char *tmp = rindex (nam, DIR_SEPARATOR);
16420 if (tmp != NULL && tmp > ep) ep = tmp;
16421 }
16422#endif
16423#else /* VMS */
16424 ep = rindex (nam, ']');
16425 if (ep == NULL) ep = rindex (nam, '>');
16426 if (ep == NULL) ep = rindex (nam, ':');
16427 if (ep != NULL) ep++;
16428#endif /* VMS */
16429 if (ep != NULL)
16430 {
16431 n = ep - nam;
16432 dsp[0].fname = (char *) xmalloc (n + 1);
16433 strncpy (dsp[0].fname, nam, n);
16434 dsp[0].fname[n] = '\0';
16435 if (n + INCLUDE_LEN_FUDGE > max_include_len)
16436 max_include_len = n + INCLUDE_LEN_FUDGE;
16437 }
16438 else
16439 dsp[0].fname = NULL; /* Current directory */
16440 dsp[0].got_name_map = 0;
16441 break;
16442 }
16443 }
16444 }
5ff904cd 16445
c7e4ee3a
CB
16446 /* Allocate this permanently, because it gets stored in the definitions
16447 of macros. */
16448 fname = xmalloc (max_include_len + flen + 4);
16449 /* + 2 above for slash and terminating null. */
16450 /* + 2 added for '.h' on VMS (to support '#include filename') (NOT USED
16451 for g77 yet). */
5ff904cd 16452
c7e4ee3a 16453 /* If specified file name is absolute, just open it. */
5ff904cd 16454
c7e4ee3a
CB
16455 if (*fbeg == '/'
16456#ifdef DIR_SEPARATOR
16457 || *fbeg == DIR_SEPARATOR
16458#endif
16459 )
16460 {
16461 strncpy (fname, (char *) fbeg, flen);
16462 fname[flen] = 0;
16463 f = open_include_file (fname, NULL_PTR);
5ff904cd 16464 }
c7e4ee3a
CB
16465 else
16466 {
16467 f = NULL;
5ff904cd 16468
c7e4ee3a
CB
16469 /* Search directory path, trying to open the file.
16470 Copy each filename tried into FNAME. */
5ff904cd 16471
c7e4ee3a
CB
16472 for (searchptr = search_start; searchptr; searchptr = searchptr->next)
16473 {
16474 if (searchptr->fname)
16475 {
16476 /* The empty string in a search path is ignored.
16477 This makes it possible to turn off entirely
16478 a standard piece of the list. */
16479 if (searchptr->fname[0] == 0)
16480 continue;
16481 strcpy (fname, skip_redundant_dir_prefix (searchptr->fname));
16482 if (fname[0] && fname[strlen (fname) - 1] != '/')
16483 strcat (fname, "/");
16484 fname[strlen (fname) + flen] = 0;
16485 }
16486 else
16487 fname[0] = 0;
5ff904cd 16488
c7e4ee3a
CB
16489 strncat (fname, fbeg, flen);
16490#ifdef VMS
16491 /* Change this 1/2 Unix 1/2 VMS file specification into a
16492 full VMS file specification */
16493 if (searchptr->fname && (searchptr->fname[0] != 0))
16494 {
16495 /* Fix up the filename */
16496 hack_vms_include_specification (fname);
16497 }
16498 else
16499 {
16500 /* This is a normal VMS filespec, so use it unchanged. */
16501 strncpy (fname, (char *) fbeg, flen);
16502 fname[flen] = 0;
16503#if 0 /* Not for g77. */
16504 /* if it's '#include filename', add the missing .h */
16505 if (index (fname, '.') == NULL)
16506 strcat (fname, ".h");
5ff904cd 16507#endif
c7e4ee3a
CB
16508 }
16509#endif /* VMS */
16510 f = open_include_file (fname, searchptr);
16511#ifdef EACCES
16512 if (f == NULL && errno == EACCES)
16513 {
16514 print_containing_files (FFEBAD_severityWARNING);
16515 ffebad_start_msg ("At %0, INCLUDE file %A exists, but is not readable",
16516 FFEBAD_severityWARNING);
16517 ffebad_string (fname);
16518 ffebad_here (0, l, c);
16519 ffebad_finish ();
16520 }
16521#endif
16522 if (f != NULL)
16523 break;
16524 }
16525 }
5ff904cd 16526
c7e4ee3a 16527 if (f == NULL)
5ff904cd 16528 {
c7e4ee3a 16529 /* A file that was not found. */
5ff904cd 16530
c7e4ee3a
CB
16531 strncpy (fname, (char *) fbeg, flen);
16532 fname[flen] = 0;
16533 print_containing_files (ffebad_severity (FFEBAD_OPEN_INCLUDE));
16534 ffebad_start (FFEBAD_OPEN_INCLUDE);
16535 ffebad_here (0, l, c);
16536 ffebad_string (fname);
16537 ffebad_finish ();
5ff904cd
JL
16538 }
16539
c7e4ee3a
CB
16540 if (dsp[0].fname != NULL)
16541 free (dsp[0].fname);
5ff904cd 16542
c7e4ee3a
CB
16543 if (f == NULL)
16544 return NULL;
5ff904cd 16545
c7e4ee3a
CB
16546 if (indepth >= (INPUT_STACK_MAX - 1))
16547 {
16548 print_containing_files (FFEBAD_severityFATAL);
16549 ffebad_start_msg ("At %0, INCLUDE nesting too deep",
16550 FFEBAD_severityFATAL);
16551 ffebad_string (fname);
16552 ffebad_here (0, l, c);
16553 ffebad_finish ();
16554 return NULL;
16555 }
5ff904cd 16556
c7e4ee3a
CB
16557 instack[indepth].line = ffewhere_line_use (l);
16558 instack[indepth].column = ffewhere_column_use (c);
5ff904cd 16559
c7e4ee3a
CB
16560 fp = &instack[indepth + 1];
16561 memset ((char *) fp, 0, sizeof (FILE_BUF));
16562 fp->nominal_fname = fp->fname = fname;
16563 fp->dir = searchptr;
5ff904cd 16564
c7e4ee3a
CB
16565 indepth++;
16566 input_file_stack_tick++;
5ff904cd 16567
c7e4ee3a
CB
16568 return f;
16569}
16570#endif /* FFECOM_GCC_INCLUDE */
5ff904cd 16571
c7e4ee3a
CB
16572/**INDENT* (Do not reformat this comment even with -fca option.)
16573 Data-gathering files: Given the source file listed below, compiled with
16574 f2c I obtained the output file listed after that, and from the output
16575 file I derived the above code.
5ff904cd 16576
c7e4ee3a
CB
16577-------- (begin input file to f2c)
16578 implicit none
16579 character*10 A1,A2
16580 complex C1,C2
16581 integer I1,I2
16582 real R1,R2
16583 double precision D1,D2
16584C
16585 call getem(A1,A2,C1,C2,I1,I2,R1,R2,D1,D2)
16586c /
16587 call fooI(I1/I2)
16588 call fooR(R1/I1)
16589 call fooD(D1/I1)
16590 call fooC(C1/I1)
16591 call fooR(R1/R2)
16592 call fooD(R1/D1)
16593 call fooD(D1/D2)
16594 call fooD(D1/R1)
16595 call fooC(C1/C2)
16596 call fooC(C1/R1)
16597 call fooZ(C1/D1)
16598c **
16599 call fooI(I1**I2)
16600 call fooR(R1**I1)
16601 call fooD(D1**I1)
16602 call fooC(C1**I1)
16603 call fooR(R1**R2)
16604 call fooD(R1**D1)
16605 call fooD(D1**D2)
16606 call fooD(D1**R1)
16607 call fooC(C1**C2)
16608 call fooC(C1**R1)
16609 call fooZ(C1**D1)
16610c FFEINTRIN_impABS
16611 call fooR(ABS(R1))
16612c FFEINTRIN_impACOS
16613 call fooR(ACOS(R1))
16614c FFEINTRIN_impAIMAG
16615 call fooR(AIMAG(C1))
16616c FFEINTRIN_impAINT
16617 call fooR(AINT(R1))
16618c FFEINTRIN_impALOG
16619 call fooR(ALOG(R1))
16620c FFEINTRIN_impALOG10
16621 call fooR(ALOG10(R1))
16622c FFEINTRIN_impAMAX0
16623 call fooR(AMAX0(I1,I2))
16624c FFEINTRIN_impAMAX1
16625 call fooR(AMAX1(R1,R2))
16626c FFEINTRIN_impAMIN0
16627 call fooR(AMIN0(I1,I2))
16628c FFEINTRIN_impAMIN1
16629 call fooR(AMIN1(R1,R2))
16630c FFEINTRIN_impAMOD
16631 call fooR(AMOD(R1,R2))
16632c FFEINTRIN_impANINT
16633 call fooR(ANINT(R1))
16634c FFEINTRIN_impASIN
16635 call fooR(ASIN(R1))
16636c FFEINTRIN_impATAN
16637 call fooR(ATAN(R1))
16638c FFEINTRIN_impATAN2
16639 call fooR(ATAN2(R1,R2))
16640c FFEINTRIN_impCABS
16641 call fooR(CABS(C1))
16642c FFEINTRIN_impCCOS
16643 call fooC(CCOS(C1))
16644c FFEINTRIN_impCEXP
16645 call fooC(CEXP(C1))
16646c FFEINTRIN_impCHAR
16647 call fooA(CHAR(I1))
16648c FFEINTRIN_impCLOG
16649 call fooC(CLOG(C1))
16650c FFEINTRIN_impCONJG
16651 call fooC(CONJG(C1))
16652c FFEINTRIN_impCOS
16653 call fooR(COS(R1))
16654c FFEINTRIN_impCOSH
16655 call fooR(COSH(R1))
16656c FFEINTRIN_impCSIN
16657 call fooC(CSIN(C1))
16658c FFEINTRIN_impCSQRT
16659 call fooC(CSQRT(C1))
16660c FFEINTRIN_impDABS
16661 call fooD(DABS(D1))
16662c FFEINTRIN_impDACOS
16663 call fooD(DACOS(D1))
16664c FFEINTRIN_impDASIN
16665 call fooD(DASIN(D1))
16666c FFEINTRIN_impDATAN
16667 call fooD(DATAN(D1))
16668c FFEINTRIN_impDATAN2
16669 call fooD(DATAN2(D1,D2))
16670c FFEINTRIN_impDCOS
16671 call fooD(DCOS(D1))
16672c FFEINTRIN_impDCOSH
16673 call fooD(DCOSH(D1))
16674c FFEINTRIN_impDDIM
16675 call fooD(DDIM(D1,D2))
16676c FFEINTRIN_impDEXP
16677 call fooD(DEXP(D1))
16678c FFEINTRIN_impDIM
16679 call fooR(DIM(R1,R2))
16680c FFEINTRIN_impDINT
16681 call fooD(DINT(D1))
16682c FFEINTRIN_impDLOG
16683 call fooD(DLOG(D1))
16684c FFEINTRIN_impDLOG10
16685 call fooD(DLOG10(D1))
16686c FFEINTRIN_impDMAX1
16687 call fooD(DMAX1(D1,D2))
16688c FFEINTRIN_impDMIN1
16689 call fooD(DMIN1(D1,D2))
16690c FFEINTRIN_impDMOD
16691 call fooD(DMOD(D1,D2))
16692c FFEINTRIN_impDNINT
16693 call fooD(DNINT(D1))
16694c FFEINTRIN_impDPROD
16695 call fooD(DPROD(R1,R2))
16696c FFEINTRIN_impDSIGN
16697 call fooD(DSIGN(D1,D2))
16698c FFEINTRIN_impDSIN
16699 call fooD(DSIN(D1))
16700c FFEINTRIN_impDSINH
16701 call fooD(DSINH(D1))
16702c FFEINTRIN_impDSQRT
16703 call fooD(DSQRT(D1))
16704c FFEINTRIN_impDTAN
16705 call fooD(DTAN(D1))
16706c FFEINTRIN_impDTANH
16707 call fooD(DTANH(D1))
16708c FFEINTRIN_impEXP
16709 call fooR(EXP(R1))
16710c FFEINTRIN_impIABS
16711 call fooI(IABS(I1))
16712c FFEINTRIN_impICHAR
16713 call fooI(ICHAR(A1))
16714c FFEINTRIN_impIDIM
16715 call fooI(IDIM(I1,I2))
16716c FFEINTRIN_impIDNINT
16717 call fooI(IDNINT(D1))
16718c FFEINTRIN_impINDEX
16719 call fooI(INDEX(A1,A2))
16720c FFEINTRIN_impISIGN
16721 call fooI(ISIGN(I1,I2))
16722c FFEINTRIN_impLEN
16723 call fooI(LEN(A1))
16724c FFEINTRIN_impLGE
16725 call fooL(LGE(A1,A2))
16726c FFEINTRIN_impLGT
16727 call fooL(LGT(A1,A2))
16728c FFEINTRIN_impLLE
16729 call fooL(LLE(A1,A2))
16730c FFEINTRIN_impLLT
16731 call fooL(LLT(A1,A2))
16732c FFEINTRIN_impMAX0
16733 call fooI(MAX0(I1,I2))
16734c FFEINTRIN_impMAX1
16735 call fooI(MAX1(R1,R2))
16736c FFEINTRIN_impMIN0
16737 call fooI(MIN0(I1,I2))
16738c FFEINTRIN_impMIN1
16739 call fooI(MIN1(R1,R2))
16740c FFEINTRIN_impMOD
16741 call fooI(MOD(I1,I2))
16742c FFEINTRIN_impNINT
16743 call fooI(NINT(R1))
16744c FFEINTRIN_impSIGN
16745 call fooR(SIGN(R1,R2))
16746c FFEINTRIN_impSIN
16747 call fooR(SIN(R1))
16748c FFEINTRIN_impSINH
16749 call fooR(SINH(R1))
16750c FFEINTRIN_impSQRT
16751 call fooR(SQRT(R1))
16752c FFEINTRIN_impTAN
16753 call fooR(TAN(R1))
16754c FFEINTRIN_impTANH
16755 call fooR(TANH(R1))
16756c FFEINTRIN_imp_CMPLX_C
16757 call fooC(cmplx(C1,C2))
16758c FFEINTRIN_imp_CMPLX_D
16759 call fooZ(cmplx(D1,D2))
16760c FFEINTRIN_imp_CMPLX_I
16761 call fooC(cmplx(I1,I2))
16762c FFEINTRIN_imp_CMPLX_R
16763 call fooC(cmplx(R1,R2))
16764c FFEINTRIN_imp_DBLE_C
16765 call fooD(dble(C1))
16766c FFEINTRIN_imp_DBLE_D
16767 call fooD(dble(D1))
16768c FFEINTRIN_imp_DBLE_I
16769 call fooD(dble(I1))
16770c FFEINTRIN_imp_DBLE_R
16771 call fooD(dble(R1))
16772c FFEINTRIN_imp_INT_C
16773 call fooI(int(C1))
16774c FFEINTRIN_imp_INT_D
16775 call fooI(int(D1))
16776c FFEINTRIN_imp_INT_I
16777 call fooI(int(I1))
16778c FFEINTRIN_imp_INT_R
16779 call fooI(int(R1))
16780c FFEINTRIN_imp_REAL_C
16781 call fooR(real(C1))
16782c FFEINTRIN_imp_REAL_D
16783 call fooR(real(D1))
16784c FFEINTRIN_imp_REAL_I
16785 call fooR(real(I1))
16786c FFEINTRIN_imp_REAL_R
16787 call fooR(real(R1))
16788c
16789c FFEINTRIN_imp_INT_D:
16790c
16791c FFEINTRIN_specIDINT
16792 call fooI(IDINT(D1))
16793c
16794c FFEINTRIN_imp_INT_R:
16795c
16796c FFEINTRIN_specIFIX
16797 call fooI(IFIX(R1))
16798c FFEINTRIN_specINT
16799 call fooI(INT(R1))
16800c
16801c FFEINTRIN_imp_REAL_D:
16802c
16803c FFEINTRIN_specSNGL
16804 call fooR(SNGL(D1))
16805c
16806c FFEINTRIN_imp_REAL_I:
16807c
16808c FFEINTRIN_specFLOAT
16809 call fooR(FLOAT(I1))
16810c FFEINTRIN_specREAL
16811 call fooR(REAL(I1))
16812c
16813 end
16814-------- (end input file to f2c)
5ff904cd 16815
c7e4ee3a
CB
16816-------- (begin output from providing above input file as input to:
16817-------- `f2c | gcc -E -C - | sed -e "s:/[*]*://:g" -e "s:[*]*[/]://:g" \
16818-------- -e "s:^#.*$::g"')
5ff904cd 16819
c7e4ee3a
CB
16820// -- translated by f2c (version 19950223).
16821 You must link the resulting object file with the libraries:
16822 -lf2c -lm (in that order)
16823//
5ff904cd 16824
5ff904cd 16825
c7e4ee3a 16826// f2c.h -- Standard Fortran to C header file //
5ff904cd 16827
c7e4ee3a 16828/// barf [ba:rf] 2. "He suggested using FORTRAN, and everybody barfed."
5ff904cd 16829
c7e4ee3a 16830 - From The Shogakukan DICTIONARY OF NEW ENGLISH (Second edition) //
5ff904cd 16831
5ff904cd 16832
5ff904cd 16833
5ff904cd 16834
c7e4ee3a
CB
16835// F2C_INTEGER will normally be `int' but would be `long' on 16-bit systems //
16836// we assume short, float are OK //
16837typedef long int // long int // integer;
16838typedef char *address;
16839typedef short int shortint;
16840typedef float real;
16841typedef double doublereal;
16842typedef struct { real r, i; } complex;
16843typedef struct { doublereal r, i; } doublecomplex;
16844typedef long int // long int // logical;
16845typedef short int shortlogical;
16846typedef char logical1;
16847typedef char integer1;
16848// typedef long long longint; // // system-dependent //
5ff904cd 16849
5ff904cd 16850
5ff904cd 16851
5ff904cd 16852
c7e4ee3a 16853// Extern is for use with -E //
5ff904cd 16854
5ff904cd 16855
5ff904cd 16856
5ff904cd 16857
c7e4ee3a 16858// I/O stuff //
5ff904cd 16859
5ff904cd 16860
5ff904cd 16861
5ff904cd 16862
5ff904cd 16863
5ff904cd 16864
5ff904cd 16865
5ff904cd 16866
c7e4ee3a
CB
16867typedef long int // int or long int // flag;
16868typedef long int // int or long int // ftnlen;
16869typedef long int // int or long int // ftnint;
5ff904cd 16870
5ff904cd 16871
c7e4ee3a
CB
16872//external read, write//
16873typedef struct
16874{ flag cierr;
16875 ftnint ciunit;
16876 flag ciend;
16877 char *cifmt;
16878 ftnint cirec;
16879} cilist;
5ff904cd 16880
c7e4ee3a
CB
16881//internal read, write//
16882typedef struct
16883{ flag icierr;
16884 char *iciunit;
16885 flag iciend;
16886 char *icifmt;
16887 ftnint icirlen;
16888 ftnint icirnum;
16889} icilist;
5ff904cd 16890
c7e4ee3a
CB
16891//open//
16892typedef struct
16893{ flag oerr;
16894 ftnint ounit;
16895 char *ofnm;
16896 ftnlen ofnmlen;
16897 char *osta;
16898 char *oacc;
16899 char *ofm;
16900 ftnint orl;
16901 char *oblnk;
16902} olist;
5ff904cd 16903
c7e4ee3a
CB
16904//close//
16905typedef struct
16906{ flag cerr;
16907 ftnint cunit;
16908 char *csta;
16909} cllist;
5ff904cd 16910
c7e4ee3a
CB
16911//rewind, backspace, endfile//
16912typedef struct
16913{ flag aerr;
16914 ftnint aunit;
16915} alist;
5ff904cd 16916
c7e4ee3a
CB
16917// inquire //
16918typedef struct
16919{ flag inerr;
16920 ftnint inunit;
16921 char *infile;
16922 ftnlen infilen;
16923 ftnint *inex; //parameters in standard's order//
16924 ftnint *inopen;
16925 ftnint *innum;
16926 ftnint *innamed;
16927 char *inname;
16928 ftnlen innamlen;
16929 char *inacc;
16930 ftnlen inacclen;
16931 char *inseq;
16932 ftnlen inseqlen;
16933 char *indir;
16934 ftnlen indirlen;
16935 char *infmt;
16936 ftnlen infmtlen;
16937 char *inform;
16938 ftnint informlen;
16939 char *inunf;
16940 ftnlen inunflen;
16941 ftnint *inrecl;
16942 ftnint *innrec;
16943 char *inblank;
16944 ftnlen inblanklen;
16945} inlist;
5ff904cd 16946
5ff904cd 16947
5ff904cd 16948
c7e4ee3a
CB
16949union Multitype { // for multiple entry points //
16950 integer1 g;
16951 shortint h;
16952 integer i;
16953 // longint j; //
16954 real r;
16955 doublereal d;
16956 complex c;
16957 doublecomplex z;
16958 };
16959
16960typedef union Multitype Multitype;
5ff904cd 16961
c7e4ee3a 16962typedef long Long; // No longer used; formerly in Namelist //
5ff904cd 16963
c7e4ee3a
CB
16964struct Vardesc { // for Namelist //
16965 char *name;
16966 char *addr;
16967 ftnlen *dims;
16968 int type;
16969 };
16970typedef struct Vardesc Vardesc;
5ff904cd 16971
c7e4ee3a
CB
16972struct Namelist {
16973 char *name;
16974 Vardesc **vars;
16975 int nvars;
16976 };
16977typedef struct Namelist Namelist;
5ff904cd 16978
5ff904cd 16979
5ff904cd 16980
5ff904cd 16981
5ff904cd 16982
5ff904cd 16983
5ff904cd 16984
5ff904cd 16985
c7e4ee3a 16986// procedure parameter types for -A and -C++ //
5ff904cd 16987
5ff904cd 16988
5ff904cd 16989
5ff904cd 16990
c7e4ee3a
CB
16991typedef int // Unknown procedure type // (*U_fp)();
16992typedef shortint (*J_fp)();
16993typedef integer (*I_fp)();
16994typedef real (*R_fp)();
16995typedef doublereal (*D_fp)(), (*E_fp)();
16996typedef // Complex // void (*C_fp)();
16997typedef // Double Complex // void (*Z_fp)();
16998typedef logical (*L_fp)();
16999typedef shortlogical (*K_fp)();
17000typedef // Character // void (*H_fp)();
17001typedef // Subroutine // int (*S_fp)();
5ff904cd 17002
c7e4ee3a
CB
17003// E_fp is for real functions when -R is not specified //
17004typedef void C_f; // complex function //
17005typedef void H_f; // character function //
17006typedef void Z_f; // double complex function //
17007typedef doublereal E_f; // real function with -R not specified //
5ff904cd 17008
c7e4ee3a 17009// undef any lower-case symbols that your C compiler predefines, e.g.: //
5ff904cd 17010
5ff904cd 17011
c7e4ee3a
CB
17012// (No such symbols should be defined in a strict ANSI C compiler.
17013 We can avoid trouble with f2c-translated code by using
17014 gcc -ansi [-traditional].) //
17015
5ff904cd 17016
5ff904cd 17017
5ff904cd 17018
5ff904cd 17019
5ff904cd 17020
5ff904cd 17021
5ff904cd 17022
5ff904cd 17023
5ff904cd 17024
5ff904cd 17025
5ff904cd 17026
5ff904cd 17027
5ff904cd 17028
5ff904cd 17029
5ff904cd 17030
5ff904cd 17031
5ff904cd 17032
5ff904cd 17033
5ff904cd 17034
5ff904cd 17035
5ff904cd 17036
5ff904cd 17037
c7e4ee3a
CB
17038// Main program // MAIN__()
17039{
17040 // System generated locals //
17041 integer i__1;
17042 real r__1, r__2;
17043 doublereal d__1, d__2;
17044 complex q__1;
17045 doublecomplex z__1, z__2, z__3;
17046 logical L__1;
17047 char ch__1[1];
17048
17049 // Builtin functions //
17050 void c_div();
17051 integer pow_ii();
17052 double pow_ri(), pow_di();
17053 void pow_ci();
17054 double pow_dd();
17055 void pow_zz();
17056 double acos(), r_imag(), r_int(), log(), r_lg10(), r_mod(), r_nint(),
17057 asin(), atan(), atan2(), c_abs();
17058 void c_cos(), c_exp(), c_log(), r_cnjg();
17059 double cos(), cosh();
17060 void c_sin(), c_sqrt();
17061 double d_dim(), exp(), r_dim(), d_int(), d_lg10(), d_mod(), d_nint(),
17062 d_sign(), sin(), sinh(), sqrt(), tan(), tanh();
17063 integer i_dim(), i_dnnt(), i_indx(), i_sign(), i_len();
17064 logical l_ge(), l_gt(), l_le(), l_lt();
17065 integer i_nint();
17066 double r_sign();
17067
17068 // Local variables //
17069 extern // Subroutine // int fooa_(), fooc_(), food_(), fooi_(), foor_(),
17070 fool_(), fooz_(), getem_();
17071 static char a1[10], a2[10];
17072 static complex c1, c2;
17073 static doublereal d1, d2;
17074 static integer i1, i2;
17075 static real r1, r2;
17076
17077
17078 getem_(a1, a2, &c1, &c2, &i1, &i2, &r1, &r2, &d1, &d2, 10L, 10L);
17079// / //
17080 i__1 = i1 / i2;
17081 fooi_(&i__1);
17082 r__1 = r1 / i1;
17083 foor_(&r__1);
17084 d__1 = d1 / i1;
17085 food_(&d__1);
17086 d__1 = (doublereal) i1;
17087 q__1.r = c1.r / d__1, q__1.i = c1.i / d__1;
17088 fooc_(&q__1);
17089 r__1 = r1 / r2;
17090 foor_(&r__1);
17091 d__1 = r1 / d1;
17092 food_(&d__1);
17093 d__1 = d1 / d2;
17094 food_(&d__1);
17095 d__1 = d1 / r1;
17096 food_(&d__1);
17097 c_div(&q__1, &c1, &c2);
17098 fooc_(&q__1);
17099 q__1.r = c1.r / r1, q__1.i = c1.i / r1;
17100 fooc_(&q__1);
17101 z__1.r = c1.r / d1, z__1.i = c1.i / d1;
17102 fooz_(&z__1);
17103// ** //
17104 i__1 = pow_ii(&i1, &i2);
17105 fooi_(&i__1);
17106 r__1 = pow_ri(&r1, &i1);
17107 foor_(&r__1);
17108 d__1 = pow_di(&d1, &i1);
17109 food_(&d__1);
17110 pow_ci(&q__1, &c1, &i1);
17111 fooc_(&q__1);
17112 d__1 = (doublereal) r1;
17113 d__2 = (doublereal) r2;
17114 r__1 = pow_dd(&d__1, &d__2);
17115 foor_(&r__1);
17116 d__2 = (doublereal) r1;
17117 d__1 = pow_dd(&d__2, &d1);
17118 food_(&d__1);
17119 d__1 = pow_dd(&d1, &d2);
17120 food_(&d__1);
17121 d__2 = (doublereal) r1;
17122 d__1 = pow_dd(&d1, &d__2);
17123 food_(&d__1);
17124 z__2.r = c1.r, z__2.i = c1.i;
17125 z__3.r = c2.r, z__3.i = c2.i;
17126 pow_zz(&z__1, &z__2, &z__3);
17127 q__1.r = z__1.r, q__1.i = z__1.i;
17128 fooc_(&q__1);
17129 z__2.r = c1.r, z__2.i = c1.i;
17130 z__3.r = r1, z__3.i = 0.;
17131 pow_zz(&z__1, &z__2, &z__3);
17132 q__1.r = z__1.r, q__1.i = z__1.i;
17133 fooc_(&q__1);
17134 z__2.r = c1.r, z__2.i = c1.i;
17135 z__3.r = d1, z__3.i = 0.;
17136 pow_zz(&z__1, &z__2, &z__3);
17137 fooz_(&z__1);
17138// FFEINTRIN_impABS //
17139 r__1 = (doublereal)(( r1 ) >= 0 ? ( r1 ) : -( r1 )) ;
17140 foor_(&r__1);
17141// FFEINTRIN_impACOS //
17142 r__1 = acos(r1);
17143 foor_(&r__1);
17144// FFEINTRIN_impAIMAG //
17145 r__1 = r_imag(&c1);
17146 foor_(&r__1);
17147// FFEINTRIN_impAINT //
17148 r__1 = r_int(&r1);
17149 foor_(&r__1);
17150// FFEINTRIN_impALOG //
17151 r__1 = log(r1);
17152 foor_(&r__1);
17153// FFEINTRIN_impALOG10 //
17154 r__1 = r_lg10(&r1);
17155 foor_(&r__1);
17156// FFEINTRIN_impAMAX0 //
17157 r__1 = (real) (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
17158 foor_(&r__1);
17159// FFEINTRIN_impAMAX1 //
17160 r__1 = (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
17161 foor_(&r__1);
17162// FFEINTRIN_impAMIN0 //
17163 r__1 = (real) (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
17164 foor_(&r__1);
17165// FFEINTRIN_impAMIN1 //
17166 r__1 = (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
17167 foor_(&r__1);
17168// FFEINTRIN_impAMOD //
17169 r__1 = r_mod(&r1, &r2);
17170 foor_(&r__1);
17171// FFEINTRIN_impANINT //
17172 r__1 = r_nint(&r1);
17173 foor_(&r__1);
17174// FFEINTRIN_impASIN //
17175 r__1 = asin(r1);
17176 foor_(&r__1);
17177// FFEINTRIN_impATAN //
17178 r__1 = atan(r1);
17179 foor_(&r__1);
17180// FFEINTRIN_impATAN2 //
17181 r__1 = atan2(r1, r2);
17182 foor_(&r__1);
17183// FFEINTRIN_impCABS //
17184 r__1 = c_abs(&c1);
17185 foor_(&r__1);
17186// FFEINTRIN_impCCOS //
17187 c_cos(&q__1, &c1);
17188 fooc_(&q__1);
17189// FFEINTRIN_impCEXP //
17190 c_exp(&q__1, &c1);
17191 fooc_(&q__1);
17192// FFEINTRIN_impCHAR //
17193 *(unsigned char *)&ch__1[0] = i1;
17194 fooa_(ch__1, 1L);
17195// FFEINTRIN_impCLOG //
17196 c_log(&q__1, &c1);
17197 fooc_(&q__1);
17198// FFEINTRIN_impCONJG //
17199 r_cnjg(&q__1, &c1);
17200 fooc_(&q__1);
17201// FFEINTRIN_impCOS //
17202 r__1 = cos(r1);
17203 foor_(&r__1);
17204// FFEINTRIN_impCOSH //
17205 r__1 = cosh(r1);
17206 foor_(&r__1);
17207// FFEINTRIN_impCSIN //
17208 c_sin(&q__1, &c1);
17209 fooc_(&q__1);
17210// FFEINTRIN_impCSQRT //
17211 c_sqrt(&q__1, &c1);
17212 fooc_(&q__1);
17213// FFEINTRIN_impDABS //
17214 d__1 = (( d1 ) >= 0 ? ( d1 ) : -( d1 )) ;
17215 food_(&d__1);
17216// FFEINTRIN_impDACOS //
17217 d__1 = acos(d1);
17218 food_(&d__1);
17219// FFEINTRIN_impDASIN //
17220 d__1 = asin(d1);
17221 food_(&d__1);
17222// FFEINTRIN_impDATAN //
17223 d__1 = atan(d1);
17224 food_(&d__1);
17225// FFEINTRIN_impDATAN2 //
17226 d__1 = atan2(d1, d2);
17227 food_(&d__1);
17228// FFEINTRIN_impDCOS //
17229 d__1 = cos(d1);
17230 food_(&d__1);
17231// FFEINTRIN_impDCOSH //
17232 d__1 = cosh(d1);
17233 food_(&d__1);
17234// FFEINTRIN_impDDIM //
17235 d__1 = d_dim(&d1, &d2);
17236 food_(&d__1);
17237// FFEINTRIN_impDEXP //
17238 d__1 = exp(d1);
17239 food_(&d__1);
17240// FFEINTRIN_impDIM //
17241 r__1 = r_dim(&r1, &r2);
17242 foor_(&r__1);
17243// FFEINTRIN_impDINT //
17244 d__1 = d_int(&d1);
17245 food_(&d__1);
17246// FFEINTRIN_impDLOG //
17247 d__1 = log(d1);
17248 food_(&d__1);
17249// FFEINTRIN_impDLOG10 //
17250 d__1 = d_lg10(&d1);
17251 food_(&d__1);
17252// FFEINTRIN_impDMAX1 //
17253 d__1 = (( d1 ) >= ( d2 ) ? ( d1 ) : ( d2 )) ;
17254 food_(&d__1);
17255// FFEINTRIN_impDMIN1 //
17256 d__1 = (( d1 ) <= ( d2 ) ? ( d1 ) : ( d2 )) ;
17257 food_(&d__1);
17258// FFEINTRIN_impDMOD //
17259 d__1 = d_mod(&d1, &d2);
17260 food_(&d__1);
17261// FFEINTRIN_impDNINT //
17262 d__1 = d_nint(&d1);
17263 food_(&d__1);
17264// FFEINTRIN_impDPROD //
17265 d__1 = (doublereal) r1 * r2;
17266 food_(&d__1);
17267// FFEINTRIN_impDSIGN //
17268 d__1 = d_sign(&d1, &d2);
17269 food_(&d__1);
17270// FFEINTRIN_impDSIN //
17271 d__1 = sin(d1);
17272 food_(&d__1);
17273// FFEINTRIN_impDSINH //
17274 d__1 = sinh(d1);
17275 food_(&d__1);
17276// FFEINTRIN_impDSQRT //
17277 d__1 = sqrt(d1);
17278 food_(&d__1);
17279// FFEINTRIN_impDTAN //
17280 d__1 = tan(d1);
17281 food_(&d__1);
17282// FFEINTRIN_impDTANH //
17283 d__1 = tanh(d1);
17284 food_(&d__1);
17285// FFEINTRIN_impEXP //
17286 r__1 = exp(r1);
17287 foor_(&r__1);
17288// FFEINTRIN_impIABS //
17289 i__1 = (( i1 ) >= 0 ? ( i1 ) : -( i1 )) ;
17290 fooi_(&i__1);
17291// FFEINTRIN_impICHAR //
17292 i__1 = *(unsigned char *)a1;
17293 fooi_(&i__1);
17294// FFEINTRIN_impIDIM //
17295 i__1 = i_dim(&i1, &i2);
17296 fooi_(&i__1);
17297// FFEINTRIN_impIDNINT //
17298 i__1 = i_dnnt(&d1);
17299 fooi_(&i__1);
17300// FFEINTRIN_impINDEX //
17301 i__1 = i_indx(a1, a2, 10L, 10L);
17302 fooi_(&i__1);
17303// FFEINTRIN_impISIGN //
17304 i__1 = i_sign(&i1, &i2);
17305 fooi_(&i__1);
17306// FFEINTRIN_impLEN //
17307 i__1 = i_len(a1, 10L);
17308 fooi_(&i__1);
17309// FFEINTRIN_impLGE //
17310 L__1 = l_ge(a1, a2, 10L, 10L);
17311 fool_(&L__1);
17312// FFEINTRIN_impLGT //
17313 L__1 = l_gt(a1, a2, 10L, 10L);
17314 fool_(&L__1);
17315// FFEINTRIN_impLLE //
17316 L__1 = l_le(a1, a2, 10L, 10L);
17317 fool_(&L__1);
17318// FFEINTRIN_impLLT //
17319 L__1 = l_lt(a1, a2, 10L, 10L);
17320 fool_(&L__1);
17321// FFEINTRIN_impMAX0 //
17322 i__1 = (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
17323 fooi_(&i__1);
17324// FFEINTRIN_impMAX1 //
17325 i__1 = (integer) (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
17326 fooi_(&i__1);
17327// FFEINTRIN_impMIN0 //
17328 i__1 = (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
17329 fooi_(&i__1);
17330// FFEINTRIN_impMIN1 //
17331 i__1 = (integer) (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
17332 fooi_(&i__1);
17333// FFEINTRIN_impMOD //
17334 i__1 = i1 % i2;
17335 fooi_(&i__1);
17336// FFEINTRIN_impNINT //
17337 i__1 = i_nint(&r1);
17338 fooi_(&i__1);
17339// FFEINTRIN_impSIGN //
17340 r__1 = r_sign(&r1, &r2);
17341 foor_(&r__1);
17342// FFEINTRIN_impSIN //
17343 r__1 = sin(r1);
17344 foor_(&r__1);
17345// FFEINTRIN_impSINH //
17346 r__1 = sinh(r1);
17347 foor_(&r__1);
17348// FFEINTRIN_impSQRT //
17349 r__1 = sqrt(r1);
17350 foor_(&r__1);
17351// FFEINTRIN_impTAN //
17352 r__1 = tan(r1);
17353 foor_(&r__1);
17354// FFEINTRIN_impTANH //
17355 r__1 = tanh(r1);
17356 foor_(&r__1);
17357// FFEINTRIN_imp_CMPLX_C //
17358 r__1 = c1.r;
17359 r__2 = c2.r;
17360 q__1.r = r__1, q__1.i = r__2;
17361 fooc_(&q__1);
17362// FFEINTRIN_imp_CMPLX_D //
17363 z__1.r = d1, z__1.i = d2;
17364 fooz_(&z__1);
17365// FFEINTRIN_imp_CMPLX_I //
17366 r__1 = (real) i1;
17367 r__2 = (real) i2;
17368 q__1.r = r__1, q__1.i = r__2;
17369 fooc_(&q__1);
17370// FFEINTRIN_imp_CMPLX_R //
17371 q__1.r = r1, q__1.i = r2;
17372 fooc_(&q__1);
17373// FFEINTRIN_imp_DBLE_C //
17374 d__1 = (doublereal) c1.r;
17375 food_(&d__1);
17376// FFEINTRIN_imp_DBLE_D //
17377 d__1 = d1;
17378 food_(&d__1);
17379// FFEINTRIN_imp_DBLE_I //
17380 d__1 = (doublereal) i1;
17381 food_(&d__1);
17382// FFEINTRIN_imp_DBLE_R //
17383 d__1 = (doublereal) r1;
17384 food_(&d__1);
17385// FFEINTRIN_imp_INT_C //
17386 i__1 = (integer) c1.r;
17387 fooi_(&i__1);
17388// FFEINTRIN_imp_INT_D //
17389 i__1 = (integer) d1;
17390 fooi_(&i__1);
17391// FFEINTRIN_imp_INT_I //
17392 i__1 = i1;
17393 fooi_(&i__1);
17394// FFEINTRIN_imp_INT_R //
17395 i__1 = (integer) r1;
17396 fooi_(&i__1);
17397// FFEINTRIN_imp_REAL_C //
17398 r__1 = c1.r;
17399 foor_(&r__1);
17400// FFEINTRIN_imp_REAL_D //
17401 r__1 = (real) d1;
17402 foor_(&r__1);
17403// FFEINTRIN_imp_REAL_I //
17404 r__1 = (real) i1;
17405 foor_(&r__1);
17406// FFEINTRIN_imp_REAL_R //
17407 r__1 = r1;
17408 foor_(&r__1);
17409
17410// FFEINTRIN_imp_INT_D: //
17411
17412// FFEINTRIN_specIDINT //
17413 i__1 = (integer) d1;
17414 fooi_(&i__1);
17415
17416// FFEINTRIN_imp_INT_R: //
17417
17418// FFEINTRIN_specIFIX //
17419 i__1 = (integer) r1;
17420 fooi_(&i__1);
17421// FFEINTRIN_specINT //
17422 i__1 = (integer) r1;
17423 fooi_(&i__1);
17424
17425// FFEINTRIN_imp_REAL_D: //
5ff904cd 17426
c7e4ee3a
CB
17427// FFEINTRIN_specSNGL //
17428 r__1 = (real) d1;
17429 foor_(&r__1);
5ff904cd 17430
c7e4ee3a 17431// FFEINTRIN_imp_REAL_I: //
5ff904cd 17432
c7e4ee3a
CB
17433// FFEINTRIN_specFLOAT //
17434 r__1 = (real) i1;
17435 foor_(&r__1);
17436// FFEINTRIN_specREAL //
17437 r__1 = (real) i1;
17438 foor_(&r__1);
5ff904cd 17439
c7e4ee3a 17440} // MAIN__ //
5ff904cd 17441
c7e4ee3a 17442-------- (end output file from f2c)
5ff904cd 17443
c7e4ee3a 17444*/
This page took 2.690295 seconds and 5 git commands to generate.